Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_MultiPartDeployableItemComponent.c
Go to the documentation of this file.
1[ComponentEditorProps(category: "GameScripted/Misc", description: "")]
3{
4 [Attribute(defvalue: "7", desc: "Radius (meters) in which game will look for items", params: "0 inf", category: "Validation")]
5 protected int m_iSearchRadius;
6
7 [Attribute(defvalue: "15", desc: "Height in meters that will be used to check if deployment position is under something.\nNot used if deployment user action is not selected to prevent indoors placement", params: "0 inf 0.01", category: "Validation")]
8 protected float m_fIndoorsCheckHeight;
9
10 [Attribute(defvalue: "1", desc: "If this entity should be deleted when it is deployed", category: "Setup")]
12
13 [Attribute(desc: "If only currently loaded magazines should be dropped when this entity is deleted", category: "Setup")]
15
16 [Attribute(desc: "If all stored items should be dropped when this entity is deleted", category: "Setup")]
18
19 [Attribute(desc: "Variants", category: "Setup")]
20 protected ref array<ref SCR_DeployableVariantContainer> m_aVariants;
21
22 [Attribute(defvalue: SCR_ESurfaceMonitoringBehaviour.DONT_MONITOR.ToString(), desc: "How this entity should react if the object on which it was deployed was deleted/destroyed/dismantled.", uiwidget: UIWidgets.ComboBox, enumType: SCR_ESurfaceMonitoringBehaviour)]
24
25 [Attribute(desc: "If forward vector of spawned entity should face the player (by default it will face away from player)", category: "Setup")]
26 protected bool m_bFrontTowardPlayer;
27
29 protected int m_iPreviewVariant = -1;
31
32 protected const LocalizedString REASON_NO_SPACE = "#AR-UserAction_Assemble_NoSpace";
33 protected const LocalizedString REASON_NO_SPACE_TERRAIN = "#AR-UserAction_Assemble_BlockedByTerrain";
34 protected const LocalizedString REASON_OBSTRUCTED_BY = "#AR-UserAction_Assemble_ObstructedBy";
35
36 //------------------------------------------------------------------------------------------------
38 array<ref SCR_DeployableVariantContainer> GetVariants()
39 {
40 return m_aVariants;
41 }
42
43 //------------------------------------------------------------------------------------------------
47 {
48 if (!m_aVariants || m_aVariants.IsEmpty())
49 return null;
50
52 {
53 if (variant.GetVariantId() == variantId)
54 return variant;
55 }
56
57 return null;
58 }
59
60 //------------------------------------------------------------------------------------------------
66
67 //------------------------------------------------------------------------------------------------
70 {
71 return m_iSearchRadius;
72 }
73
74 //------------------------------------------------------------------------------------------------
77 {
79 }
80
81 //------------------------------------------------------------------------------------------------
87
88 //------------------------------------------------------------------------------------------------
94
95 //------------------------------------------------------------------------------------------------
101
102 //------------------------------------------------------------------------------------------------
104 {
106 }
107
108 //------------------------------------------------------------------------------------------------
110 void SetPreviewEntity(notnull IEntity ent, int variantId)
111 {
112 if (variantId == m_iPreviewVariant && ent && m_PreviewEntity)
113 return;
114
115 SCR_EntityHelper.DeleteEntityAndChildren(m_PreviewEntity);
116 m_PreviewEntity = ent;
117 if (ent)
118 m_iPreviewVariant = variantId;
119 else
121 }
122
123 //------------------------------------------------------------------------------------------------
126 {
127 return m_PreviewEntity;
128 }
129
130 //------------------------------------------------------------------------------------------------
133 {
134 return m_iPreviewVariant;
135 }
136
137 //------------------------------------------------------------------------------------------------
143
144 //------------------------------------------------------------------------------------------------
147 {
148 m_ePreviewState = newState;
149 }
150
151 //------------------------------------------------------------------------------------------------
155 {
156 if (GenericTerrainEntity.Cast(collidingBody))
158
159 IEntity topMostParent = collidingBody.GetRootParent();
160 InventoryItemComponent iic = InventoryItemComponent.Cast(collidingBody.FindComponent(InventoryItemComponent));
161 if (iic)
162 {
163 UIInfo uiInfo = iic.GetUIInfo();
164 if (uiInfo && uiInfo.GetName().IsEmpty())
165 uiInfo = null;
166
167 if (uiInfo)
168 return WidgetManager.Translate(REASON_OBSTRUCTED_BY, uiInfo.GetName());
169 }
170
171 SCR_EditableEntityComponent editableEntityComp = SCR_EditableEntityComponent.Cast(collidingBody.FindComponent(SCR_EditableEntityComponent));
172 if (!editableEntityComp)
173 return REASON_NO_SPACE;
174
175 SCR_UIInfo scriptedUiInfo = editableEntityComp.GetInfo(collidingBody);
176 if (!scriptedUiInfo || scriptedUiInfo.GetName().IsEmpty())
177 return REASON_NO_SPACE;
178
179 return WidgetManager.Translate(REASON_OBSTRUCTED_BY, scriptedUiInfo.GetName());
180 }
181
182 //------------------------------------------------------------------------------------------------
183 // destructor
185 {
186 //This is only called when all instances are destroyed
187 SCR_EntityHelper.DeleteEntityAndChildren(m_PreviewEntity);
188 }
189}
190
191class SCR_MultiPartDeployableItemComponent : SCR_BaseDeployableInventoryItemComponent
192{
194 protected ref array<ref SCR_RequiredDeployablePart> m_aFoundElements;
196 protected int m_iCurrentVariant = -1;
197
198 protected static const LocalizedString SEARCH_FAIL_REASON_MISSING_PART = "#AR-UserAction_Assemble_MissingPart";
199
200 protected static const ResourceName CAN_BUILD_MATERIAL = "{56EBF5038622AC95}Assets/Conflict/CanBuild.emat";
201 protected static const ResourceName CANNOT_BUILD_MATERIAL = "{14A9DCEA57D1C381}Assets/Conflict/CannotBuild.emat";
202 protected static const ResourceName TRANSPARENT_MATERIAL = "{8FBC3A6E946F056E}Common/Materials/Default_Transparent.emat";
203
204 protected static const float MINOR_SAFETY_OFFSET = 0.05;
205
206#ifdef ENABLE_DIAG
208 protected ref SCR_DebugShapeManager m_DebugShapeMgr = new SCR_DebugShapeManager();
209#endif
210#ifdef WORKBENCH
211 protected static bool s_bShowBoundingBoxDebug;
212
213 //------------------------------------------------------------------------------------------------
214 override array<ref WB_UIMenuItem> _WB_GetContextMenuItems(IEntity owner)
215 {
216 array<ref WB_UIMenuItem> items = { new WB_UIMenuItem("Toggle replacement prefabs bounding box visibility", 0) };
217
218 return items;
219 }
220
221 //------------------------------------------------------------------------------------------------
222 override void _WB_OnContextMenu(IEntity owner, int id)
223 {
224 switch (id)
225 {
226 case 0:
227 s_bShowBoundingBoxDebug = !s_bShowBoundingBoxDebug;
228 GenericWorldEntity world = GetGame().GetWorldEntity();
229 if (!world)
230 return;
231
232 IEntity child = world.GetChildren();
233 SCR_MultiPartDeployableItemComponent comp;
234 while (child)
235 {
236 comp = SCR_MultiPartDeployableItemComponent.Cast(child.FindComponent(SCR_MultiPartDeployableItemComponent));
237 if (comp)
238 DrawBoundingBoxDebug(child);
239
240 child = child.GetSibling();
241 }
242
243 break;
244
245 default:
246 break;
247 }
248 }
249
250 //------------------------------------------------------------------------------------------------
253 void DrawBoundingBoxDebug(notnull IEntity owner)
254 {
255 if (GetGame().InPlayMode())
256 return;
257
258 m_DebugShapeMgr.Clear();
259 if (!s_bShowBoundingBoxDebug)
260 return;
261
262 SCR_MultiPartDeployableItemComponentClass data = SCR_MultiPartDeployableItemComponentClass.Cast(GetComponentData(GetOwner()));
263 if (!data)
264 return;
265
266 int r, g, b;
267 const int a = 1;
268 Color color = new Color(r, g, b, a);
269 vector mat[4];
270 array<ref SCR_DeployableVariantContainer> variants = data.GetVariants();
271 foreach (int i, SCR_DeployableVariantContainer variant : variants)
272 {
273 m_VariantContainer = variant;
274
275 vector mins, maxs;
276 m_VariantContainer.GetReplacementPrefabBoundingBox(mins, maxs);
277 if (mins == vector.Zero && maxs == vector.Zero)
278 continue;
279
280 owner.GetTransform(mat);
281 mat[3] = mat[3] + owner.VectorToParent(m_VariantContainer.GetAdditionaPlacementOffset());
282 if (!m_VariantContainer.IsUsingPartPositionAndRotation())
283 ComputeTransform(mat, owner.GetYawPitchRoll());
284
285 mat[3] = mat[3] + MINOR_SAFETY_OFFSET * mat[1];
286 ShapeFlags shapeFlags = ShapeFlags.ONCE | ShapeFlags.WIREFRAME;
287 Shape shape = Shape.Create(ShapeType.BBOX, color.PackToInt(), shapeFlags, mins, maxs);
288 if (shape)
289 {
290 shape.SetMatrix(mat);
291 m_DebugShapeMgr.Add(shape);
292 }
293
294 switch (Math.Mod(i, 3))
295 {
296 case 0:
297 r = Math.Min(r + 51, 255);
298 break;
299
300 case 1:
301 g = Math.Min(g + 51, 255);
302 break;
303
304 case 2:
305 b = Math.Min(b + 51, 255);
306 break;
307 }
308
309 color = new Color(r, g, b, a);
310 }
311
312 m_VariantContainer = null;
313 }
314
315 //------------------------------------------------------------------------------------------------
316 override void _WB_AfterWorldUpdate(IEntity owner, float timeSlice)
317 {
318 DrawBoundingBoxDebug(owner);
319 }
320#endif
321
322 //------------------------------------------------------------------------------------------------
325 {
326 return m_VariantContainer && m_VariantContainer.IsUsingPartPositionAndRotation();
327 }
328
329 //------------------------------------------------------------------------------------------------
332 {
333 if (m_VariantContainer && !m_VariantContainer.IsUsingPartPositionAndRotation())
334 return m_VariantContainer.GetAdditionaPlacementOffset();
335
336 return vector.Zero;
337 }
338
339 //------------------------------------------------------------------------------------------------
342 {
343 if (m_VariantContainer && !m_VariantContainer.IsUsingPartPositionAndRotation())
344 return m_VariantContainer.GetAdditionaPlacementRotation();
345
346 return vector.Zero;
347 }
348
349 //------------------------------------------------------------------------------------------------
352 {
354 if (!data)
355 return false;
356
357 return data.IsFrontFacingPlayer();
358 }
359
360 //------------------------------------------------------------------------------------------------
366
367 //------------------------------------------------------------------------------------------------
369 void SetReplacmentPrefabHealthScaled(float newHealthValue)
370 {
371 m_fReplacementPrefabHealthScaled = Math.Clamp(newHealthValue, 0, 1);
372 }
373
374 //------------------------------------------------------------------------------------------------
378 bool FetchVariantData(int variant)
379 {
381 if (!data)
382 return false;
383
384 m_VariantContainer = data.GetVariantContainer(variant);
385 m_iCurrentVariant = variant;
386 return m_VariantContainer != null;
387 }
388
389 //------------------------------------------------------------------------------------------------
392 {
394 m_VariantContainer = null;
395 }
396
397 //------------------------------------------------------------------------------------------------
400 {
401 return m_iCurrentVariant;
402 }
403
404 //------------------------------------------------------------------------------------------------
409 bool CheckSurfaceTilt(vector up, bool useDataFromOwnerPosition = false)
410 {
412 return false;
413
414 float maxTilt = m_VariantContainer.GetMaxAllowedTilt();
415 if (maxTilt < 0)
416 return true;
417
418 if (useDataFromOwnerPosition)
419 {
420 IEntity owner = GetOwner();
421 TraceParam param = new TraceParam();
422 param.Exclude = owner;
423
424 vector transform[4];
425 SCR_TerrainHelper.GetTerrainBasis(owner.GetOrigin() + vector.Up * 0.1, transform, owner.GetWorld(), false, param);
426 up = transform[1];
427 }
428
429 return Math.Acos(vector.Dot(up, vector.Up)) * Math.RAD2DEG < maxTilt;
430 }
431
432 //------------------------------------------------------------------------------------------------
443 bool IsSurfaceValid(IEntity surfaceEnt, vector worldPosition, vector surfaceNorm, int nodeIndex, int colliderIndex, SurfaceProperties surfaceProps, string surfaceMaterial, string colliderName)
444 {
446 return false;
447
448 return m_VariantContainer.IsSurfaceValid(surfaceEnt, worldPosition, surfaceNorm, nodeIndex, colliderIndex, surfaceProps, surfaceMaterial, colliderName);
449 }
450
451 //------------------------------------------------------------------------------------------------
456 bool FindRequiredElements(out string failReason, vector position = -vector.One)
457 {
459 return false;
460
461 IEntity owner = GetOwner();
463 if (!data)
464 return false;
465
466 if (!m_aFoundElements)
467 m_aFoundElements = {};
468
469 m_aFoundElements.Clear();
470 if (m_VariantContainer.GetRequiredElements(m_aFoundElements) < 1)
471 return true;
472
473 BaseWorld world = owner.GetWorld();
474 if (position == -vector.One)
475 position = owner.GetOrigin();
476
477 world.QueryEntitiesBySphere(position, data.GetSearchRadius(), EvaluateFoundEntity);
479 {
480 int difference;
481 if (!partReq.IsRequirementMet(difference))
482 {
483 failReason = WidgetManager.Translate(SEARCH_FAIL_REASON_MISSING_PART, difference.ToString(), partReq.GetMissingPartName());
484 return false;
485 }
486 }
487
488 return true;
489 }
490
491 //------------------------------------------------------------------------------------------------
495 protected bool EvaluateFoundEntity(IEntity ent)
496 {
497 if (!m_aFoundElements || m_aFoundElements.IsEmpty())
498 return false;
499
500 if (!ent)
501 return true;
502
503 if (ent == GetOwner())
504 return true;
505
506 if (ent.GetParent())
507 return true;//skip items that are not on the ground
508
509 if (!ent.GetPrefabData())
510 return true;//f.e. particles dont have prefab data
511
512 if (ChimeraCharacter.Cast(ent))
513 return true;//character cannot be a required element
514
515 BaseContainer foundPrefab = ent.GetPrefabData().GetPrefab();
516 vector origin = GetOwner().GetOrigin();
517 float distToEnt = vector.DistanceSq(origin, ent.GetOrigin());
519 {
520 if (partReq.EvaluateFoundEntity(origin, distToEnt, foundPrefab, ent))
521 return true;
522 }
523
524 return true;
525 }
526
527 //------------------------------------------------------------------------------------------------
533 bool CheckAvailableSpace(inout vector transform[4], vector direction = vector.Zero, out LocalizedString reason = string.Empty)
534 {
536 return false;
537
538 IEntity owner = GetOwner();
540 if (!data)
541 return false;
542
543 TraceOBB paramOBB = new TraceOBB();
544 if (!m_VariantContainer.GetReplacementPrefabBoundingBox(paramOBB.Mins, paramOBB.Maxs))
545 return true;//no volume to check thus skip this requirement
546
547 vector mat[4] = transform;//because attributes that are static arrays are passed as a reference thus we need to copy it
548 if (!m_VariantContainer.IsUsingPartPositionAndRotation())
550
551 array<IEntity> excludeArray = {owner, data.GetPreviewEntity()};
553 {
555 {
556 if (partReq.GetFoundEntities())
557 excludeArray.InsertAll(partReq.GetFoundEntities());
558 }
559 }
560
561 paramOBB.Mat[0] = mat[0];
562 paramOBB.Mat[1] = mat[1];
563 paramOBB.Mat[2] = mat[2];
564 paramOBB.Start = mat[3] + MINOR_SAFETY_OFFSET * paramOBB.Mat[1];//+5cm to ensure that we wont collide with the ground due to minor unevenness
565 paramOBB.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
566 paramOBB.ExcludeArray = excludeArray;
567 paramOBB.LayerMask = EPhysicsLayerPresets.Projectile;
568
569 owner.GetWorld().TracePosition(paramOBB, FilterTracedEntities);
570
571#ifdef ENABLE_DIAG
572 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_ITEM_PLACEMENT_VISUALIZATION))
573 {
574 m_DebugShapeMgr.Clear();
575 ShapeFlags shapeFlags = ShapeFlags.WIREFRAME;
576
577 int color = Color.RED;
578 if (!paramOBB.TraceEnt)
579 color = Color.GREEN;
580
581 Shape shape = Shape.Create(ShapeType.BBOX, color, shapeFlags, paramOBB.Mins, paramOBB.Maxs);
582 if (shape)
583 {
584 mat[0] = paramOBB.Mat[0];
585 mat[1] = paramOBB.Mat[1];
586 mat[2] = paramOBB.Mat[2];
587 mat[3] = paramOBB.Start;
588 shape.SetMatrix(mat);
589 m_DebugShapeMgr.Add(shape);
590 }
591 }
592#endif
593 if (!paramOBB.TraceEnt)
594 return true;
595
596 reason = data.GetSpaceValidationFailureReason(paramOBB.TraceEnt);
597 return false;
598 }
599
600 //------------------------------------------------------------------------------------------------
602 bool CheckIfPositionIsIndoors(inout vector transform[4])
603 {
604 IEntity owner = GetOwner();
606
607 TraceParam traceParam = new TraceParam();
608 traceParam.Start = transform[3] + (vector.Up * MINOR_SAFETY_OFFSET);//+5cm to ensure that we wont collide with the ground
609 traceParam.End = traceParam.Start + (vector.Up * data.GetIndoorsCheckHeight());
610 traceParam.Flags = TraceFlags.WORLD | TraceFlags.ENTS;
611 traceParam.LayerMask = EPhysicsLayerPresets.Projectile;
612 traceParam.Exclude = owner;
613 owner.GetWorld().TraceMove(traceParam, FilterTracedEntities);
614
615 return traceParam.TraceEnt;
616 }
617
618 //------------------------------------------------------------------------------------------------
622 void VisualizeReplacementEntity(inout vector transform[4], vector direction = vector.Zero)
623 {
625 return;
626
627 IEntity owner = GetOwner();
629 if (!data)
630 return;
631
632 IEntity previewEnt = data.GetPreviewEntity();
633 if (!previewEnt || data.GetPreviewVariantId() != m_iCurrentVariant)
634 {
635 ResourceName replacementPrefab = m_VariantContainer.GetPreviewResource();
636 if (replacementPrefab.IsEmpty())
637 return;
638
639 Resource resource = Resource.Load(replacementPrefab);
640 if (!resource.IsValid())
641 return;
642
643 BaseResourceObject resourceObject = resource.GetResource();
644 if (!resourceObject)
645 return;
646
647 BaseWorld world = owner.GetWorld();
648 VObject vObj = resourceObject.ToVObject();
649 if (vObj)
650 {
651 previewEnt = GetGame().SpawnEntity(GenericEntity, world);
652 previewEnt.SetObject(vObj, string.Empty);
653 }
654 else
655 {
656 previewEnt = GetGame().SpawnEntityPrefab(resource, world);
657 }
658
659 if (!previewEnt)
660 return;
661
662 SCR_Global.SetMaterial(previewEnt, CAN_BUILD_MATERIAL);
663 data.SetPreviewEntity(previewEnt, m_iCurrentVariant);
664 data.SetPreviewState(SCR_EPreviewState.PLACEABLE);
665 previewEnt.ClearFlags(EntityFlags.TRACEABLE | EntityFlags.ACTIVE, true);
666 }
667
668 vector mat[4] = transform;//because attributes that are static arrays are passed as a reference thus we need to copy it
669 if (!m_VariantContainer.IsUsingPartPositionAndRotation())
671
672 if (!(previewEnt.GetFlags() & EntityFlags.VISIBLE))
673 previewEnt.SetFlags(EntityFlags.VISIBLE, true);
674
675 previewEnt.SetTransform(mat);
676 previewEnt.Update();
677 }
678
679 //------------------------------------------------------------------------------------------------
682 {
684 if (!data)
685 return;
686
687 if (!m_VariantContainer || m_iCurrentVariant != data.GetPreviewVariantId())
688 return;
689
690 IEntity previewEnt = data.GetPreviewEntity();
691 if (!previewEnt)
692 return;
693
694 if (data.GetPreviewState() == state)
695 return;
696
697 switch (state)
698 {
699 case SCR_EPreviewState.PLACEABLE:
700 SCR_Global.SetMaterial(previewEnt, CAN_BUILD_MATERIAL);
701 break;
702
703 case SCR_EPreviewState.BLOCKED:
704 SCR_Global.SetMaterial(previewEnt, CANNOT_BUILD_MATERIAL);
705 break;
706
707 case SCR_EPreviewState.NONE:
708#ifdef ENABLE_DIAG
709 m_DebugShapeMgr.Clear();
710#endif
711 SCR_Global.SetMaterial(previewEnt, TRANSPARENT_MATERIAL);
712 break;
713 }
714
715 data.SetPreviewState(state);
716 }
717
718 //------------------------------------------------------------------------------------------------
724 bool FilterTracedEntities(notnull IEntity e, vector start = "0 0 0", vector dir = "0 0 0")
725 {
726 if (!e)
727 return false;
728
729 if (e.GetRootParent() == GetOwner())
730 return false;
731
732 if (ChimeraCharacter.Cast(e))
733 return false;//ignore characters
734
735 if (e && ChimeraCharacter.Cast(e.GetRootParent()))
736 return false;//ignore character equipment
737
738 if (SCR_BaseDebrisSmallEntity.Cast(e))
739 return false;//ignore debris
740
741 if (!e.GetPrefabData())
742 return false;//ignore f.e. particles or managers
743
744 return true;
745 }
746
747 //------------------------------------------------------------------------------------------------
753 void Deploy(int variantId, IEntity userEntity = null, vector direction = vector.Zero, bool reload = false, bool state = true)
754 {
755 if (!m_RplComponent || m_RplComponent.IsProxy())
756 return;
757
758 if (m_bIsDeployed)
759 return;
760
761 if (!m_VariantContainer || variantId != m_VariantContainer.GetVariantId())
762 return;
763
764 IEntity owner = GetOwner();
765 vector position = owner.GetOrigin() + vector.Up * 0.1;
766 if (!m_VariantContainer.IsUsingPartPositionAndRotation())
767 position += owner.VectorToParent(m_VariantContainer.GetAdditionaPlacementOffset());
768
769 TraceParam param = new TraceParam();
770 array<IEntity> excludeArray = {owner, userEntity};
771 param.ExcludeArray = excludeArray;
772 param.LayerMask = EPhysicsLayerPresets.Projectile;
773 SCR_TerrainHelper.GetTerrainBasis(position, m_aOriginalTransform, GetGame().GetWorld(), false, param);
774
775 if (!m_VariantContainer.IsUsingPartPositionAndRotation())
776 {
777 ComputeTransform(m_aOriginalTransform, direction);
778 if (!IsSurfaceValid(param.TraceEnt, m_aOriginalTransform[3], param.TraceNorm, param.NodeIndex, param.ColliderIndex, param.SurfaceProps, param.TraceMaterial, param.ColliderName))
779 return;
780 }
781
783 params.Transform = m_aOriginalTransform;
784 params.TransformMode = ETransformMode.WORLD;
785
786 Resource resource = Resource.Load(m_VariantContainer.GetReplacementPrefab());
787 if (!resource.IsValid())
788 return;
789
790 m_ReplacementEntity = GetGame().SpawnEntityPrefab(resource, GetGame().GetWorld(), params);
791 if (!m_ReplacementEntity)
792 return;
793
794 m_PreviousOwner = userEntity;
795
796 PlayerManager playerMgr = GetGame().GetPlayerManager();
797 int playerID = playerMgr.GetPlayerIdFromControlledEntity(userEntity);
798 SetAuthor(m_ReplacementEntity, playerID);
799
800 if (param.TraceEnt)
801 {
802 SCR_MultiPartDeployableItemComponent deployableComp = SCR_MultiPartDeployableItemComponent.Cast(m_ReplacementEntity.FindComponent(SCR_MultiPartDeployableItemComponent));
803 if (deployableComp)
804 deployableComp.SurfaceMonitoringInit(param.TraceEnt);
805 }
806
807 array<ref SCR_AdditionalDeployablePart> additionalPartsToSpawn = m_VariantContainer.GetAdditionalPrefabList();
808 if (additionalPartsToSpawn)
809 {
810 vector spawnedMat[4];
811 IEntity spawnedEntity;
812 InventoryItemComponent spawnedIIC;
813 SCR_DeployableInventoryItemInventoryComponent spawnedDIIC;
814 foreach (SCR_AdditionalDeployablePart additionalPrefab : additionalPartsToSpawn)
815 {
816 additionalPrefab.SpawnPrefabs(playerID, userEntity, params);
817 }
818 }
819
820 m_bIsDeployed = state;
821 Replication.BumpMe();
822
824 if (data && data.IsSoundEnabled() && !reload)
825 {
828 }
829
830 if (m_OnDeployedStateChanged)
831 m_OnDeployedStateChanged.Invoke(m_bIsDeployed, this);
832
833 DeleteParts();
835 }
836
837 //------------------------------------------------------------------------------------------------
841 static void SetAuthor(notnull IEntity ent, int playerID)
842 {
843 SCR_EditableEntityComponent editableComp = SCR_EditableEntityComponent.Cast(ent.FindComponent(SCR_EditableEntityComponent));
844 if (!editableComp)
845 return;
846
847 editableComp.SetAuthor(playerID);
848 }
849
850 //------------------------------------------------------------------------------------------------
853 void SurfaceMonitoringInit(notnull IEntity surface)
854 {
855 IEntity owner = GetOwner();
857 if (!data || data.GetMonitoringBehaviour() == SCR_ESurfaceMonitoringBehaviour.DONT_MONITOR)
858 return;
859
861 if (deployableComp)
863
864 HitZoneContainerComponent parentDamageManager = HitZoneContainerComponent.Cast(surface.FindComponent(HitZoneContainerComponent));
865 if (parentDamageManager)
866 {
867 SCR_HitZone hitZone = SCR_HitZone.Cast(parentDamageManager.GetDefaultHitZone());
868 if (hitZone && !parentDamageManager.IsInherited(SCR_DestructibleBuildingComponent)) // destructible building component has its own logic for this
870 }
871
872 SCR_EditableEntityComponent editableComponent = SCR_EditableEntityComponent.Cast(surface.FindComponent(SCR_EditableEntityComponent));
873 if (editableComponent)
874 editableComponent.GetOnDeleted().Insert(OnMonitoredSurfaceDeleted);
875 }
876
877 //------------------------------------------------------------------------------------------------
882 protected void StopMonitoringSurface(IEntity ent, SCR_HitZone observedHitZone = null, SCR_BaseDeployableInventoryItemComponent deployableComp = null)
883 {
884 if (!deployableComp)
886
887 if (deployableComp)
889
890 if (!observedHitZone)
891 {
893 if (surfaceDamageManager)
894 observedHitZone = SCR_HitZone.Cast(surfaceDamageManager.GetDefaultHitZone());
895 }
896
897 if (observedHitZone && !observedHitZone.GetHitZoneContainer().IsInherited(SCR_DestructibleBuildingComponent)) // destructible building component has its own logic for this
898 observedHitZone.GetOnDamageStateChanged().Remove(OnMonitoredSurfaceDamageStateChanged);
899
901 if (editableComponent)
902 editableComponent.GetOnDeleted().Remove(OnMonitoredSurfaceDeleted);
903 }
904
905 //------------------------------------------------------------------------------------------------
909 {
910 IEntity owner = GetOwner();
912 if (!data)
913 return;
914
915 if (beaviour == -1)
916 beaviour = data.GetMonitoringBehaviour();
917
918 switch (beaviour)
919 {
920 case SCR_ESurfaceMonitoringBehaviour.DISMANTLE:
921 ClearCache();
923 Deploy(0);
924 return;
925
928 if (!dmgMgrComp)
929 {
931 return;
932 }
933
934 vector outMat[3];
935 SCR_DamageContext damageContext = new SCR_DamageContext(EDamageType.TRUE, dmgMgrComp.GetMaxHealth(), outMat, GetOwner(), null, Instigator.CreateInstigator(null), null, -1, -1);
936 damageContext.damageEffect = new SCR_InstantDamageEffect();
937 dmgMgrComp.HandleDamage(damageContext);
938 return;
939
941 // if something is deployed on top of this object, then lets inform them via deployment, because this component doesnt have a deletion invoker
942 if (m_OnDeployedStateChanged)
943 m_OnDeployedStateChanged.Invoke(!m_bIsDeployed, this);
944
945 RplComponent.DeleteRplEntity(owner, false);
946 return;
947 }
948 }
949
950 //------------------------------------------------------------------------------------------------
954 {
955 if (damagedHitZone.GetDamageState() != EDamageState.DESTROYED)
956 return;
957
958 StopMonitoringSurface(damagedHitZone.GetOwner(), damagedHitZone);
960 }
961
962 //------------------------------------------------------------------------------------------------
967 {
968 StopMonitoringSurface(component.GetOwner(), deployableComp: component);
970 }
971
972 //------------------------------------------------------------------------------------------------
976 {
978 }
979
980 //------------------------------------------------------------------------------------------------
984 void ComputeTransform(inout vector transform[4], vector direction)
985 {
986 vector directionTrans[4];
987 direction += m_VariantContainer.GetAdditionaPlacementRotation();
988
989 Math3D.AnglesToMatrix(direction, directionTrans);
990
991 vector right = transform[1] * directionTrans[0];
992 vector forward = transform[1] * right;
993 right.Normalize();
994 forward.Normalize();
995
997 if (data && data.IsFrontFacingPlayer())
998 {
999 transform[0] = forward;
1000 transform[2] = right;
1001 }
1002 else
1003 {
1004 transform[0] = -forward;
1005 transform[2] = -right;
1006 }
1007 }
1008
1009 //------------------------------------------------------------------------------------------------
1012 protected void DeleteParts()
1013 {
1015 {
1016 if (!partReq.ShouldDeleteFoundEntities())
1017 continue;
1018
1019 for (int i = partReq.GetNumberOfFoundEntities() - 1; i >= 0; i--)
1020 {
1021 if (!partReq.DeleteFoundEntity(i, m_PreviousOwner))
1022 Print("WARNING: SCR_MultiPartDeployableItemComponent => Deletion of required entity failed as this entity doesnt exist anymore", LogLevel.WARNING);
1023 }
1024 }
1025
1027
1028 IEntity owner = GetOwner();
1030 if (!data)
1031 return;
1032
1033 if (data.IsDeletedWhenDeployed())
1034 {
1035 if (data.MustDropAllStoredItems())
1036 {
1037 TryRemoveAllItemsFromStorage(owner, m_PreviousOwner);
1038 TryRemoveMagazineFromWeapons(owner, m_PreviousOwner);//because removing from storage doesnt removed currently attached magazines
1039 }
1040 else if (data.MustDropLoadedMagazines())
1041 {
1042 TryRemoveMagazineFromWeapons(owner, m_PreviousOwner);
1043 }
1044
1045 GetGame().GetCallqueue().CallLater(DelayedDeletion);//delay to allow other replicated logic to be executed on clients
1046 }
1047 }
1048
1049 //------------------------------------------------------------------------------------------------
1051 protected void TransferDamageValues()
1052 {
1053 DamageManagerComponent damageMgr = DamageManagerComponent.Cast(m_ReplacementEntity.FindComponent(DamageManagerComponent));
1054 if (!float.AlmostEqual(m_fReplacementPrefabHealthScaled, 1) && damageMgr)
1055 {
1056 if (damageMgr)
1057 damageMgr.SetHealthScaled(m_fReplacementPrefabHealthScaled);
1058 }
1059
1060 damageMgr = DamageManagerComponent.Cast(GetOwner().FindComponent(DamageManagerComponent));
1061 if (damageMgr && !float.AlmostEqual(damageMgr.GetHealthScaled(), 1))
1062 {
1063 SCR_MultiPartDeployableItemComponent deployableComp = SCR_MultiPartDeployableItemComponent.Cast(m_ReplacementEntity.FindComponent(SCR_MultiPartDeployableItemComponent));
1064 if (deployableComp)
1065 deployableComp.SetReplacmentPrefabHealthScaled(damageMgr.GetHealthScaled());
1066 }
1067 }
1068
1069 //------------------------------------------------------------------------------------------------
1071 static void TryRemoveMagazineFromWeapons(notnull IEntity owner, notnull IEntity user)
1072 {
1073 InventoryStorageManagerComponent storage = InventoryStorageManagerComponent.Cast(user.FindComponent(InventoryStorageManagerComponent));
1074 if (!storage)
1075 return;
1076
1077 BaseMuzzleComponent muzzleComp = BaseMuzzleComponent.Cast(owner.FindComponent(BaseMuzzleComponent));
1078 if (muzzleComp && !muzzleComp.IsDisposable())
1079 {
1080 BaseMagazineComponent currentMagazine = muzzleComp.GetMagazine();
1081 InventoryItemComponent magIIC;
1082 if (currentMagazine)
1083 magIIC = InventoryItemComponent.Cast(currentMagazine.GetOwner().FindComponent(InventoryItemComponent));
1084
1085 InventoryStorageSlot parentSlot;
1086 if (magIIC)
1087 parentSlot = magIIC.GetParentSlot();
1088
1089 BaseInventoryStorageComponent magContainer;
1090 if (parentSlot)
1091 magContainer = parentSlot.GetStorage();
1092
1093 if (magContainer)
1094 storage.TryRemoveItemFromStorage(currentMagazine.GetOwner(), magContainer);
1095 }
1096
1097 array<Managed> weaponSlots = {};
1098 owner.FindComponents(WeaponSlotComponent, weaponSlots);
1099 if (weaponSlots.IsEmpty())
1100 return;
1101
1102 IEntity weapon;
1103 WeaponSlotComponent weaponSlot;
1104 InventoryStorageSlot slot;
1105 foreach (Managed managedComp : weaponSlots)
1106 {
1107 weaponSlot = WeaponSlotComponent.Cast(managedComp);
1108 if (!weaponSlot)
1109 continue;
1110
1111 slot = weaponSlot.GetSlotInfo();
1112 if (!slot)
1113 continue;
1114
1115 weapon = slot.GetAttachedEntity();
1116 if (!weapon)
1117 continue;
1118
1119 TryRemoveMagazineFromWeapons(weapon, user);
1120 }
1121 }
1122
1123 //------------------------------------------------------------------------------------------------
1125 static void TryRemoveAllItemsFromStorage(notnull IEntity owner, notnull IEntity user)
1126 {
1127 InventoryStorageManagerComponent storageMgr = InventoryStorageManagerComponent.Cast(user.FindComponent(InventoryStorageManagerComponent));
1128 if (!storageMgr)
1129 return;
1130
1131 BaseInventoryStorageComponent storage = BaseInventoryStorageComponent.Cast(owner.FindComponent(BaseInventoryStorageComponent));
1132 if (!storage)
1133 return;
1134
1135 array<IEntity> outItems = {};
1136 storage.GetAll(outItems);
1137 foreach (IEntity item : outItems)
1138 {
1139 storageMgr.TryRemoveItemFromStorage(item, storage);
1140 }
1141 }
1142
1143 //------------------------------------------------------------------------------------------------
1146 {
1147 SCR_EntityHelper.DeleteEntityAndChildren(GetOwner());
1148 }
1149
1150 //------------------------------------------------------------------------------------------------
1151 protected override void OnDelete(IEntity owner)
1152 {
1154 {
1156 ClearCache();
1157 }
1158
1160 if (!data)
1161 return;
1162
1163 if (data.IsDeletedWhenDeployed())
1164 m_ReplacementEntity = null;//break the connection to prevent the deletion of deployed entity
1165
1166 super.OnDelete(owner);
1167 }
1168
1169 //------------------------------------------------------------------------------------------------
1170 protected override void RPC_PlaySoundOnDeployBroadcast(bool deploy)
1171 {
1172 IEntity ent = GetOwner();
1174 if (!data)
1175 return;
1176
1177 if (data.IsDeletedWhenDeployed() && m_ReplacementEntity)
1178 ent = m_ReplacementEntity;
1179
1180 if (!ent)
1181 return;
1182
1184 if (soundComp)
1185 {
1186 if (deploy)
1187 soundComp.SoundEvent(SCR_SoundEvent.SOUND_DEPLOY);
1188 else
1189 soundComp.SoundEvent(SCR_SoundEvent.SOUND_UNDEPLOY);
1190
1191 return;
1192 }
1193
1194 SCR_SoundManagerModule soundMan = SCR_SoundManagerModule.GetInstance(ent.GetWorld());
1195 if (!soundMan)
1196 return;
1197
1198 if (deploy)
1199 soundMan.CreateAndPlayAudioSource(ent, SCR_SoundEvent.SOUND_DEPLOY);
1200 else
1201 soundMan.CreateAndPlayAudioSource(ent, SCR_SoundEvent.SOUND_UNDEPLOY);
1202 }
1203
1204 //------------------------------------------------------------------------------------------------
1205 protected override bool RplSave(ScriptBitWriter writer)
1206 {
1207 bool hasData = !float.AlmostEqual(m_fReplacementPrefabHealthScaled, 1);
1208 writer.WriteBool(hasData);
1209 if (hasData)
1210 writer.WriteFloat01(m_fReplacementPrefabHealthScaled);
1211
1212 return true;
1213 }
1214
1215 //------------------------------------------------------------------------------------------------
1216 protected override bool RplLoad(ScriptBitReader reader)
1217 {
1218 bool hasData;
1219 reader.ReadBool(hasData);
1220 if (hasData)
1221 reader.ReadFloat01(m_fReplacementPrefabHealthScaled);
1222
1223 return true;
1224 }
1225}
void SCR_BaseDebrisSmallEntity(IEntitySource src, IEntity parent)
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ArmaReforgerScripted GetGame()
Definition game.c:1398
override bool RplLoad(ScriptBitReader reader)
enum EAIGroupCombatMode ComponentEditorProps(category:"GameScripted/AI", description:"Component for utility AI system for groups")
override bool RplSave(ScriptBitWriter writer)
RplComponent m_RplComponent
bool Deploy(SCR_EMobileAssemblyStatus status, int playerId=0, bool silent=false)
SCR_CharacterSoundComponentClass GetComponentData()
vector direction
vector position
Get all prefabs that have the spawner data
void VisualizeReplacementEntity(inout vector transform[4], vector direction=vector.Zero)
SCR_MultiPartDeployableItemComponentClass m_VariantContainer
void OnMonitoredSurfaceDeleted(IEntity deletedEntity)
void OnMonitoredSurfaceDamageStateChanged(SCR_HitZone damagedHitZone)
bool CheckSurfaceTilt(vector up, bool useDataFromOwnerPosition=false)
void ComputeTransform(inout vector transform[4], vector direction)
void SetPreviewState(SCR_EPreviewState state)
vector GetAdditionaPlacementOffset()
bool CheckAvailableSpace(inout vector transform[4], vector direction=vector.Zero, out LocalizedString reason=string.Empty)
bool FindRequiredElements(out string failReason, vector position=-vector.One)
vector GetAdditionaPlacementRotation()
bool FetchVariantData(int variant)
bool EvaluateFoundEntity(IEntity ent)
void DelayedDeletion()
Method used to delte this entity but after some delay to ensure that other logic can execute correctl...
bool IsUsingPartPositionAndRotation()
bool FilterTracedEntities(notnull IEntity e, vector start="0 0 0", vector dir="0 0 0")
void SetReplacmentPrefabHealthScaled(float newHealthValue)
0-1 scaled amount of health that replacement prefab will have upon deployment
void TransferDamageValues()
Method meant to be used to transfer information about health between this entity and deployed entity.
ref array< ref SCR_RequiredDeployablePart > m_aFoundElements
void OnMonitoredSurfaceDismantled(bool newState, SCR_BaseDeployableInventoryItemComponent component)
void SurfaceMonitoringInit(notnull IEntity surface)
float GetReplacementPrefabHealthScaled()
bool IsSurfaceValid(IEntity surfaceEnt, vector worldPosition, vector surfaceNorm, int nodeIndex, int colliderIndex, SurfaceProperties surfaceProps, string surfaceMaterial, string colliderName)
void StopMonitoringSurface(IEntity ent, SCR_HitZone observedHitZone=null, SCR_BaseDeployableInventoryItemComponent deployableComp=null)
void ExecuteObservationBehaviour(SCR_ESurfaceMonitoringBehaviour beaviour=-1)
bool CheckIfPositionIsIndoors(inout vector transform[4])
Method that is meant to be called by clients to check if spawn position will be under something.
void ClearCache()
Clears the information about currently handled variant.
override void RPC_PlaySoundOnDeployBroadcast(bool deploy)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum EVehicleType IEntity
Definition Color.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
event void _WB_OnContextMenu(IEntity owner, int id)
User has chosen any of your menu item from editor's "Component" menu which you have recently provided...
event array< ref WB_UIMenuItem > _WB_GetContextMenuItems(IEntity owner)
An opportunity to append items into editor's "Component" context menu. Do not call editor API here!
proto external EntityFlags GetFlags()
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external int Update()
proto external BaseWorld GetWorld()
proto external bool SetTransform(vector mat[4])
proto external EntityFlags SetFlags(EntityFlags flags, bool recursively=false)
proto external EntityPrefabData GetPrefabData()
proto external IEntity GetParent()
proto external EntityFlags ClearFlags(EntityFlags flags, bool recursively=false)
proto external IEntity GetSibling()
proto external vector VectorToParent(vector vec)
proto external IEntity GetRootParent()
Definition Math.c:13
Main replication API.
Definition Replication.c:14
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
Base class which all deployable inventory items inherit from.
SCR_UIInfo GetInfo(IEntity owner=null)
static void SetMaterial(IEntity entity, ResourceName material, bool recursively=true)
Definition Functions.c:1793
ScriptInvoker GetOnDamageStateChanged(bool createNew=true)
Definition SCR_HitZone.c:32
IEntity GetOwner()
Definition SCR_HitZone.c:42
array< ref SCR_DeployableVariantContainer > GetVariants()
LocalizedString GetSpaceValidationFailureReason(notnull IEntity collidingBody)
SCR_DeployableVariantContainer GetVariantContainer(int variantId)
ref array< ref SCR_DeployableVariantContainer > m_aVariants
void SetPreviewEntity(notnull IEntity ent, int variantId)
static bool GetTerrainBasis(vector pos, out vector result[4], BaseWorld world=null, bool noUnderwater=false, TraceParam trace=null)
Instance of created debug visualizer.
Definition Shape.c:14
UIInfo - allows to define UI elements.
Definition UIInfo.c:14
Visual object.
Definition VObject.c:14
void EntitySpawnParams()
Definition gameLib.c:130
EPhysicsLayerPresets
Enum is filled by C++ by data in project config PhysicsSettings.LayerPresets.
Definition gameLib.c:19
IEntity GetOwner()
Owner entity of the fuel tank.
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
ShapeType
Definition ShapeType.c:13
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute
EntityFlags
Various entity flags.
Definition EntityFlags.c:14
EDamageType
Definition EDamageType.c:13
EDamageState
TraceFlags
Definition TraceFlags.c:13