2[WorkbenchToolAttribute(
3 name:
"Destruction indices assign tool",
4 description:
"Automatically assigns response indices to destructible objects\n\n" +
5 "- button 1 = Fix phases\n" +
6 "- button 2 = Print all destructible resource names\n" +
7 "- button 3 = Revert to parent\n" +
8 "- button 4 = Update Prefabs\n" +
9 "- button 5 = Remove phases\n" +
10 "- button 6 = Filter Prefabs\n" +
11 "- button 7 = Show Mass\n" +
12 "- button 8 = Convert Prefabs\n" +
13 "- button 9 = Assign Indices\n" +
14 "- button 10 = Set building destruction effects - TODO",
15 awesomeFontCode: 0xF7E4)]
16class SCR_DestructionIndicesAssignTool : WorldEditorTool
19 protected ref array<ref SCR_MassResponseIndexPair> m_aPairs;
22 protected ref array<string> m_aProperties;
24 protected const ref array<string> EXTENSIONS = {
"et" };
25 protected const ref array<string> DESTRUCTIBLE_COMPONENT_CLASSES = {
"SCR_DestructionDamageManagerComponent",
"SCR_DestructionMultiPhaseComponent" };
26 protected const string DESTRUCTION_COMPONENT_CLASS =
"SCR_DestructionMultiPhaseComponent";
27 protected const string PHYSICS_COMPONENT =
"RigidBody";
31 protected void FixPhasesButton()
33 m_API.BeginEntityAction();
34 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS);
37 BaseResourceObject baseResourceObject;
38 BaseContainer baseContainer, parent;
39 IEntitySource parentEntitySource, entitySource;
40 IEntityComponentSource destructionComponent;
41 BaseContainerList parentPhasesList, phasesList;
42 BaseContainerList parentOldPhasesList, oldPhasesList;
43 int count = resourceNames.Count();
46 for (
int i = count - 1; i >= 0; i--)
49 if (!resourceNames[i].
Contains(
"Prefabs/"))
52 resourceNames.Remove(i);
57 resource = Resource.Load(resourceNames[i]);
61 resourceNames.Remove(i);
66 baseResourceObject = resource.GetResource();
67 if (!baseResourceObject)
70 resourceNames.Remove(i);
75 baseContainer = baseResourceObject.ToBaseContainer();
79 resourceNames.Remove(i);
84 if (baseContainer.GetClassName() !=
"SCR_DestructibleEntity")
87 resourceNames.Remove(i);
91 entitySource = baseContainer.ToEntitySource();
92 destructionComponent = FindComponent(entitySource,
"SCR_DestructionMultiPhaseComponent");
94 parent = entitySource.GetAncestor();
99 resourceNames.Remove(i);
103 if (parent.GetClassName() ==
"SCR_DestructibleEntity" && resourceNames.Find(parent.GetResourceName()) != -1)
106 if (resourceNames[i] ==
"{A00A15B03B48A2AF}Prefabs/Structures/Walls/Brick/BrickWall_01/BrickWall_01_8m.et")
109 parentEntitySource = parent.ToEntitySource();
110 phasesList = baseContainer.GetObjectArray(
"DamagePhases");
111 parentPhasesList = parent.GetObjectArray(
"DamagePhases");
113 if (resourceNames[i] ==
"{A00A15B03B48A2AF}Prefabs/Structures/Walls/Brick/BrickWall_01/BrickWall_01_8m.et")
115 Print(parentPhasesList.Count());
116 Print(parent.GetResourceName());
119 if (parentPhasesList && parentPhasesList.Count() != 0)
125 ConvertPhases(entitySource, destructionComponent);
135 resourceNames.Remove(i);
140 m_API.EndEntityAction();
144 protected void ConvertPhases(IEntitySource source, IEntityComponentSource componentSource)
146 array<ref SCR_DamagePhaseData> parentDamagePhases;
147 BaseContainer parentContainer = source.GetAncestor();
150 parentDamagePhases = {};
151 FindComponent(parentContainer.ToEntitySource(),
"SCR_DestructionMultiPhaseComponent").Get(
"m_aDamagePhases", parentDamagePhases);
154 array<ref SCR_DamagePhaseData> damagePhases = {};
155 componentSource.Get(
"m_aDamagePhases", damagePhases);
156 int damagePhasesCount = damagePhases.Count();
159 float totalHealth = GetPhasesTotalHealth(componentSource, damagePhases);
160 float healthNormalized = 1;
161 float currentPhaseHealth;
162 componentSource.Get(
"m_fBaseHealth", currentPhaseHealth);
164 healthNormalized -= currentPhaseHealth / totalHealth;
166 array<ref ContainerIdPathEntry>
path = {};
167 bool phaseExists =
false;
168 for (
int j = 0; j < damagePhasesCount; j++)
170 if (j == damagePhasesCount - 1)
174 if (parentDamagePhases && parentDamagePhases.IsIndexValid(j))
176 for (
int k = parentDamagePhases.Count() - 1; k >= 0; k--)
178 if (parentDamagePhases[k].m_fPhaseHealth == damagePhases[j].m_fPhaseHealth)
189 m_API.CreateObjectArrayVariableMember(source,
path,
"DamagePhases",
"SCR_BaseDestructionPhase", j);
195 if (parentDamagePhases && parentDamagePhases.IsIndexValid(j))
197 if (parentDamagePhases[j].m_PhaseModel != damagePhases[j].m_PhaseModel)
198 m_API.SetVariableValue(source,
path,
"m_sPhaseModel", damagePhases[j].m_PhaseModel);
201 m_API.SetVariableValue(source,
path,
"Threshold", healthNormalized.ToString());
202 healthNormalized -= damagePhases[j].m_fPhaseHealth / totalHealth;
207 if (j + 1 < damagePhasesCount)
209 foreach (
int k, SCR_BaseSpawnable spawnObject : damagePhases[j + 1].m_PhaseDestroySpawnObjects)
211 spawnObject.CopyToSource(m_API, source,
path, k,
"m_aPhaseDestroySpawnObjects");
216 array<ref SCR_BaseSpawnable> destroySpawnObjects = {};
217 componentSource.Get(
"m_DestroySpawnObjects", destroySpawnObjects);
219 foreach (
int k, SCR_BaseSpawnable destroySpawnObject : destroySpawnObjects)
221 destroySpawnObject.CopyToSource(m_API, source,
path, k,
"m_aPhaseDestroySpawnObjects");
231 protected void PrintAllDestructibleResourceNamesButton()
233 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"$ArmaReforger:Prefabs");
236 BaseResourceObject baseResourceObject;
237 BaseContainer baseContainer;
238 IEntitySource entitySource;
239 IEntityComponentSource destructionComponent;
244 if (!resource.IsValid())
248 baseResourceObject = resource.GetResource();
249 if (!baseResourceObject)
253 baseContainer = baseResourceObject.ToBaseContainer();
258 if (!HasComponent(baseResourceObject,
"SCR_DestructionMultiPhaseComponent",
true))
261 entitySource = baseContainer.ToEntitySource();
262 if (!entitySource || entitySource.GetClassName() !=
"SCR_DestructibleEntity")
272 protected float CalculateDensity(notnull
IEntity entity)
274 Physics physics = entity.GetPhysics();
278 array<SurfaceProperties> surfaces = {};
279 GameMaterial gameMaterial;
280 BallisticInfo ballisticInfo;
283 int j, densitiesCount;
285 for (
int i = physics.GetNumGeoms() - 1; i >= 0; i--)
288 physics.GetGeomSurfaces(i, surfaces);
290 for (j = surfaces.Count() - 1; i >= 0; i--)
292 gameMaterial = surfaces[j];
296 ballisticInfo = gameMaterial.GetBallisticInfo();
300 totalDensity += ballisticInfo.GetDensity();
305 if (densitiesCount != 0)
306 return totalDensity / densitiesCount;
313 protected void RevertToParentButton()
315 m_API.BeginEntityAction();
316 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"Prefabs");
322 BaseResourceObject baseResourceObject;
323 BaseContainer baseContainer;
324 IEntitySource entitySource;
325 IEntityComponentSource destructionComponent;
326 BaseContainer parent;
327 string parentValue, childValue, defaultValue;
328 for (
int i = resourceNames.Count() - 1; i >= 0; i--)
331 if (!resourceNames[i].
Contains(
"Prefabs/"))
333 resourceNames.Remove(i);
338 resource = Resource.Load(resourceNames[i]);
341 resourceNames.Remove(i);
346 baseResourceObject = resource.GetResource();
347 if (!baseResourceObject)
349 resourceNames.Remove(i);
354 baseContainer = baseResourceObject.ToBaseContainer();
357 resourceNames.Remove(i);
362 entitySource = baseContainer.ToEntitySource();
363 if (!entitySource || entitySource.GetClassName() !=
"SCR_DestructibleEntity")
365 resourceNames.Remove(i);
370 if (!HasComponent(baseResourceObject,
"SCR_DestructionMultiPhaseComponent",
false))
372 resourceNames.Remove(i);
376 parent = entitySource.GetAncestor();
378 foreach (
int j,
string property : m_aProperties)
380 if (!entitySource.IsVariableSetDirectly(property))
383 entitySource.Get(property, childValue);
384 entitySource.GetDefaultAsString(property, defaultValue);
386 if (resourceNames[i] ==
"{B31031F1F682586E}Prefabs/Props/Furniture/BenchWooden_02_Base.et")
388 if (property ==
"MaxHealth")
395 if (childValue == defaultValue)
397 m_API.ClearVariableValue(entitySource, null, property);
404 if (parent && parent.GetClassName() ==
"SCR_DestructibleEntity")
406 parent.Get(property, parentValue);
407 if (childValue == parentValue)
408 m_API.ClearVariableValue(entitySource, null, property);
416 if (entitySource.IsVariableSetDirectly(
"FirstDestructionPhase") && parent.IsVariableSetDirectly(
"FirstDestructionPhase"))
417 m_API.ClearVariableValue(entitySource, null,
"FirstDestructionPhase");
418 if (entitySource.IsVariableSetDirectly(
"LastDestructionPhase") && parent.IsVariableSetDirectly(
"LastDestructionPhase"))
419 m_API.ClearVariableValue(entitySource, null,
"LastDestructionPhase");
422 m_API.EndEntityAction();
428 protected void UpdatePrefabsButton()
430 m_API.BeginEntityAction();
431 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"Prefabs");
434 BaseResourceObject baseResourceObject;
435 BaseContainer baseContainer;
436 IEntitySource entitySource;
437 IEntityComponentSource destructionComponent;
438 for (
int i = resourceNames.Count() - 1; i >= 0; i--)
441 if (!resourceNames[i].
Contains(
"Prefabs/"))
443 resourceNames.Remove(i);
448 resource = Resource.Load(resourceNames[i]);
451 resourceNames.Remove(i);
456 baseResourceObject = resource.GetResource();
457 if (!baseResourceObject)
459 resourceNames.Remove(i);
464 baseContainer = baseResourceObject.ToBaseContainer();
467 resourceNames.Remove(i);
472 entitySource = baseContainer.ToEntitySource();
473 if (!entitySource || entitySource.GetClassName() !=
"SCR_DestructibleEntity")
475 resourceNames.Remove(i);
480 if (!HasComponent(baseResourceObject,
"SCR_DestructionMultiPhaseComponent",
false))
482 resourceNames.Remove(i);
486 destructionComponent = FindComponent(entitySource,
"SCR_DestructionMultiPhaseComponent");
489 array<ref ContainerIdPathEntry>
path = {};
490 array<ref SCR_DamagePhaseData> damagePhases = {};
491 destructionComponent.Get(
"m_aDamagePhases", damagePhases);
492 int damagePhasesCount = damagePhases.Count();
494 BaseContainer phaseObject;
496 if (damagePhasesCount > 0)
499 phaseObject = entitySource.GetObject(
"FirstDestructionPhase");
500 ClearArrayOfPhaseEffects(phaseObject,
path, entitySource);
502 foreach (
int j, SCR_BaseSpawnable spawnObject : damagePhases[0].m_PhaseDestroySpawnObjects)
504 spawnObject.CopyToSource(m_API, entitySource,
path, j,
"m_aPhaseDestroySpawnObjects");
510 if (damagePhasesCount == 0)
512 array<ref SCR_BaseSpawnable> destroySpawnObjects = {};
513 destructionComponent.Get(
"m_DestroySpawnObjects", destroySpawnObjects);
517 phaseObject = entitySource.GetObject(
"LastDestructionPhase");
518 ClearArrayOfPhaseEffects(phaseObject,
path, entitySource);
520 foreach (
int j, SCR_BaseSpawnable spawnObject : destroySpawnObjects)
522 spawnObject.CopyToSource(m_API, entitySource,
path, j,
"m_aPhaseDestroySpawnObjects");
528 BaseContainerList phasesList;
529 phasesList = entitySource.GetObjectArray(
"DamagePhases");
530 for (
int j = 0; j < damagePhasesCount; j++)
532 if (j == damagePhasesCount - 1)
540 if (j + 1 < damagePhasesCount)
543 phaseObject = phasesList.Get(j);
544 ClearArrayOfPhaseEffects(phaseObject,
path, entitySource);
546 foreach (
int k, SCR_BaseSpawnable spawnObject : damagePhases[j + 1].m_PhaseDestroySpawnObjects)
548 spawnObject.CopyToSource(m_API, entitySource,
path, k,
"m_aPhaseDestroySpawnObjects");
553 array<ref SCR_BaseSpawnable> destroySpawnObjects = {};
554 destructionComponent.Get(
"m_DestroySpawnObjects", destroySpawnObjects);
557 phaseObject = phasesList.Get(j);
558 ClearArrayOfPhaseEffects(phaseObject,
path, entitySource);
560 foreach (
int k, SCR_BaseSpawnable spawnObject : destroySpawnObjects)
562 spawnObject.CopyToSource(m_API, entitySource,
path, k,
"m_aPhaseDestroySpawnObjects");
571 m_API.EndEntityAction();
578 protected void RemovePhasesButton()
580 m_API.BeginEntityAction();
581 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"Prefabs");
584 BaseResourceObject baseResourceObject;
585 BaseContainer baseContainer;
586 IEntitySource entitySource;
587 IEntityComponentSource destructionComponent;
588 for (
int i = resourceNames.Count() - 1; i >= 0; i--)
591 if (!resourceNames[i].
Contains(
"Prefabs/"))
593 resourceNames.Remove(i);
598 resource = Resource.Load(resourceNames[i]);
601 resourceNames.Remove(i);
606 baseResourceObject = resource.GetResource();
607 if (!baseResourceObject)
609 resourceNames.Remove(i);
614 baseContainer = baseResourceObject.ToBaseContainer();
617 resourceNames.Remove(i);
622 entitySource = baseContainer.ToEntitySource();
623 if (!entitySource || entitySource.GetClassName() !=
"SCR_DestructibleEntity")
625 resourceNames.Remove(i);
630 if (!HasComponent(baseResourceObject,
"SCR_DestructionMultiPhaseComponent",
false))
632 resourceNames.Remove(i);
636 array<ref ContainerIdPathEntry>
path = {};
637 BaseContainer phaseObject;
638 BaseContainerList phasesList;
639 phasesList = entitySource.GetObjectArray(
"DamagePhases");
640 int phasesCount = phasesList.Count();
642 array<float> thresholds = {};
643 ResourceName phaseModel;
644 array<ResourceName> phaseModels = {};
645 bool recalculate =
false;
647 for (
int j = 0; j < phasesCount; j++)
649 phaseObject = phasesList.Get(j);
650 phaseObject.Get(
"Threshold", threshold);
652 phaseObject.Get(
"m_sPhaseModel", phaseModel);
654 if (phaseModels.Contains(phaseModel))
656 m_API.RemoveObjectArrayVariableMember(entitySource,
path,
"DamagePhases", j);
657 phasesList = entitySource.GetObjectArray(
"DamagePhases");
658 phasesCount = phasesList.Count();
663 phaseModels.Insert(phaseModel);
665 if (thresholds.Contains(threshold))
668 thresholds.Insert(threshold);
674 destructionComponent = FindComponent(entitySource,
"SCR_DestructionMultiPhaseComponent");
675 array<ref SCR_DamagePhaseData> damagePhases = {};
676 destructionComponent.Get(
"m_aDamagePhases", damagePhases);
677 float totalHealth = GetPhasesTotalHealth(destructionComponent, damagePhases);
678 float healthNormalized = 1;
681 for (
int j = 0; j < phasesCount; j++)
684 healthNormalized -= damagePhases[j].m_fPhaseHealth / totalHealth;
685 m_API.SetVariableValue(entitySource,
path,
"Threshold", healthNormalized.ToString());
690 m_API.EndEntityAction();
694 void ClearArrayOfPhaseEffects(BaseContainer phaseObject, array<ref ContainerIdPathEntry>
path, IEntitySource entitySource)
699 BaseContainerList effectsList = phaseObject.GetObjectArray(
"m_aPhaseDestroySpawnObjects");
703 for (
int i = effectsList.Count() - 1; i >= 0; --i)
705 m_API.RemoveObjectArrayVariableMember(entitySource,
path,
"m_aPhaseDestroySpawnObjects", 0);
711 protected void FilterPrefabsButton()
713 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"Prefabs");
715 array<string> componentClassNames = {};
716 componentClassNames.Insert(
"SCR_DestructionMultiPhaseComponent");
718 array<ResourceName> outResourceNames = {};
719 FilterByComponents(resourceNames, outResourceNames, componentClassNames,
false,
true);
722 componentClassNames = {};
723 componentClassNames.Insert(
"ActionsManagerComponent");
724 FilterByComponents(outResourceNames, resourceNames, componentClassNames,
true);
726 Print(
"" + resourceNames.Count() +
" resources",
LogLevel.NORMAL);
734 int length = endIndex - startIndex;
741 protected void ShowMassButton()
743 IEntitySource entitySource = m_API.GetSelectedEntity();
744 IEntity entity = m_API.SourceToEntity(entitySource);
745 float volume = MeshObjectVolumeCalculator.GetVolumeFromColliders(entity, EPhysicsLayerDefs.FireGeometry);
746 float density = CalculateDensity(entity);
747 Print(density * 1000 * volume);
752 protected void ConvertPrefabsButton()
754 m_API.BeginEntityAction();
755 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS, rootPath:
"Prefabs");
757 array<string> componentClassNames = {};
758 componentClassNames.Insert(
"SCR_DestructionMultiPhaseComponent");
760 array<ResourceName> outResourceNames = {};
762 FilterByClass(resourceNames, outResourceNames,
"SCR_DestructibleEntity");
765 BaseResourceObject baseResource;
766 IEntitySource source;
767 IEntityComponentSource componentSource;
768 BaseContainer defaultHitZone;
769 array<ref ContainerIdPathEntry>
path = {};
770 bool deleteAfterFinalPhase =
false;
771 SCR_EMaterialSoundTypeBreak materialSoundType;
772 float momentumToDamage;
779 baseResource = resource.GetResource();
780 source = baseResource.ToEntitySource();
782 for (
int j = source.GetComponentCount() - 1; j >= 0; j--)
784 componentSource = source.GetComponent(j);
785 if (componentSource.GetClassName() != DESTRUCTION_COMPONENT_CLASS)
791 if (!componentSource)
794 if (source.GetClassName() !=
"SCR_DestructibleEntity")
796 Print(
"The following prefab is not SCR_DestructibleEntity type!");
797 Print(
"Cannot convert!");
798 Print(source.GetClassName());
799 Print(source.GetResourceName());
803 array<ref SCR_DamagePhaseData> damagePhases = {};
804 componentSource.Get(
"m_aDamagePhases", damagePhases);
806 array<ref SCR_BaseDestructionPhase> newPhases = {};
807 SCR_BaseDestructionPhase newPhase;
808 for (
int j = damagePhases.Count() - 1; j >= 0; j--)
810 newPhase =
new SCR_BaseDestructionPhase();
811 newPhase.m_sPhaseModel = damagePhases[j].m_PhaseModel;
812 newPhase.m_aPhaseDestroySpawnObjects = {};
813 CopySpawnObjectsArray(newPhase.m_aPhaseDestroySpawnObjects, damagePhases[j].m_PhaseDestroySpawnObjects);
816 newPhases.Insert(newPhase);
823 defaultHitZone = GetHitZone(source);
827 defaultHitZone.Get(
"Collision multiplier", multiplier);
828 m_API.SetVariableValue(source,
path,
"Collision multiplier", multiplier.ToString());
830 defaultHitZone.Get(
"Melee multiplier", multiplier);
831 m_API.SetVariableValue(source,
path,
"Melee multiplier", multiplier.ToString());
833 defaultHitZone.Get(
"Kinetic multiplier", multiplier);
834 m_API.SetVariableValue(source,
path,
"Kinetic multiplier", multiplier.ToString());
836 defaultHitZone.Get(
"Fragmentation multiplier", multiplier);
837 m_API.SetVariableValue(source,
path,
"Fragmentation multiplier", multiplier.ToString());
839 defaultHitZone.Get(
"Explosive multiplier", multiplier);
840 m_API.SetVariableValue(source,
path,
"Explosive multiplier", multiplier.ToString());
842 defaultHitZone.Get(
"Incendiary multiplier", multiplier);
843 m_API.SetVariableValue(source,
path,
"Incendiary multiplier", multiplier.ToString());
845 defaultHitZone.Get(
"BaseDamageMultiplier", multiplier);
846 m_API.SetVariableValue(source,
path,
"BaseDamageMultiplier", multiplier.ToString());
848 defaultHitZone.Get(
"DamageReduction", multiplier);
849 m_API.SetVariableValue(source,
path,
"DamageReduction", multiplier.ToString());
851 defaultHitZone.Get(
"DamageThreshold", multiplier);
852 m_API.SetVariableValue(source,
path,
"DamageThreshold", multiplier.ToString());
857 componentSource.Get(
"m_bDeleteAfterFinalPhase", deleteAfterFinalPhase);
858 m_API.SetVariableValue(source,
path,
"DestroyAtNoHealth", deleteAfterFinalPhase.ToString(
true));
860 componentSource.Get(
"m_eMaterialSoundType", materialSoundType);
861 m_API.SetVariableValue(source,
path,
"m_eMaterialSoundType", materialSoundType.ToString());
863 componentSource.Get(
"m_fMomentumToDamageScale", momentumToDamage);
864 m_API.SetVariableValue(source,
path,
"m_fMomentumToDamageScale", momentumToDamage.ToString());
868 int damagePhasesCount = damagePhases.Count();
869 IEntityComponentSource meshObject = FindComponent(source,
"MeshObject");
870 ResourceName firstPhaseResourceName;
872 meshObject.Get(
"Object", firstPhaseResourceName);
874 m_API.CreateObjectVariableMember(source,
path,
"FirstDestructionPhase",
"SCR_BaseDestructionPhase");
877 m_API.SetVariableValue(source,
path,
"m_sPhaseModel", firstPhaseResourceName);
879 if (damagePhasesCount > 0)
881 foreach (
int k, SCR_BaseSpawnable spawnObject : damagePhases[0].m_PhaseDestroySpawnObjects)
883 spawnObject.CopyToSource(m_API, source,
path, k,
"m_aPhaseDestroySpawnObjects");
889 float totalHealth = GetPhasesTotalHealth(componentSource, damagePhases);
890 float healthNormalized = 1;
891 float currentPhaseHealth;
892 componentSource.Get(
"m_fBaseHealth", currentPhaseHealth);
894 healthNormalized -= currentPhaseHealth / totalHealth;
897 m_API.SetVariableValue(source,
path,
"MaxHealth", totalHealth.ToString());
898 if (damagePhasesCount == 0)
900 m_API.CreateObjectVariableMember(source,
path,
"LastDestructionPhase",
"SCR_BaseDestructionPhase");
902 array<ref SCR_BaseSpawnable> destroySpawnObjects = {};
903 componentSource.Get(
"m_DestroySpawnObjects", destroySpawnObjects);
906 foreach (
int j, SCR_BaseSpawnable spawnObject : destroySpawnObjects)
908 spawnObject.CopyToSource(m_API, source,
path, j,
"m_aPhaseDestroySpawnObjects");
911 m_API.SetVariableValue(source,
path,
"Threshold",
"0");
916 for (
int j = 0; j < damagePhasesCount; j++)
918 if (j == damagePhasesCount - 1)
921 m_API.CreateObjectVariableMember(source,
path,
"LastDestructionPhase",
"SCR_BaseDestructionPhase");
924 healthNormalized = 0;
929 m_API.CreateObjectArrayVariableMember(source,
path,
"DamagePhases",
"SCR_BaseDestructionPhase", j);
936 m_API.SetVariableValue(source,
path,
"m_sPhaseModel", damagePhases[j].m_PhaseModel);
938 m_API.SetVariableValue(source,
path,
"Threshold", healthNormalized.ToString());
939 healthNormalized -= damagePhases[j].m_fPhaseHealth / totalHealth;
942 if (j + 1 < damagePhasesCount)
944 foreach (
int k, SCR_BaseSpawnable spawnObject : damagePhases[j + 1].m_PhaseDestroySpawnObjects)
946 spawnObject.CopyToSource(m_API, source,
path, k,
"m_aPhaseDestroySpawnObjects");
951 array<ref SCR_BaseSpawnable> destroySpawnObjects = {};
952 componentSource.Get(
"m_DestroySpawnObjects", destroySpawnObjects);
954 foreach (
int k, SCR_BaseSpawnable spawnObject : destroySpawnObjects)
956 spawnObject.CopyToSource(m_API, source,
path, k,
"m_aPhaseDestroySpawnObjects");
965 m_API.SetVariableValue(source,
path,
"Enabled",
"0");
969 m_API.SetVariableValue(source,
path,
"Enabled",
"0");
973 m_API.EndEntityAction();
977 BaseContainer GetHitZone(IEntitySource source)
979 IEntityComponentSource componentSource;
980 for (
int i = source.GetComponentCount() - 1; i >= 0; i--)
982 componentSource = source.GetComponent(i);
983 if (componentSource.GetClassName() != DESTRUCTION_COMPONENT_CLASS)
989 BaseContainerList hitZonesList = componentSource.GetObjectArray(
"Additional hit zones");
990 if (!hitZonesList || hitZonesList.Count() == 0)
993 return hitZonesList[0];
997 float GetPhasesTotalHealth(IEntityComponentSource componentSource, array<ref SCR_DamagePhaseData> phases)
1000 componentSource.Get(
"m_fBaseHealth", health);
1002 foreach (SCR_DamagePhaseData phase : phases)
1004 health += phase.m_fPhaseHealth;
1011 IEntityComponentSource FindComponent(IEntitySource source,
string componentType)
1013 for (
int i = source.GetComponentCount() - 1; i >= 0; i--)
1015 if (source.GetComponent(i).GetClassName() == componentType)
1016 return source.GetComponent(i);
1023 void CopySpawnObjectsArray(out array<ref SCR_BaseSpawnable> to, array<ref SCR_BaseSpawnable> from)
1025 foreach (SCR_BaseSpawnable
object : from)
1032 protected bool HasComponent(BaseResourceObject baseResource,
string componentClassName,
bool checkEnabled)
1034 IEntitySource source = baseResource.ToEntitySource();
1035 string currentComponentClassName;
1036 for (
int i = source.GetComponentCount() - 1; i >= 0; i--)
1038 currentComponentClassName = source.GetComponent(i).GetClassName();
1039 if (currentComponentClassName == componentClassName)
1046 source.GetComponent(i).Get(
"Enabled", enabled);
1057 protected void FilterByClass(notnull array<ResourceName> resourceNames, notnull out array<ResourceName> outResourceNames,
string className)
1060 BaseResourceObject baseResource;
1061 IEntitySource source;
1068 baseResource = resource.GetResource();
1072 source = baseResource.ToEntitySource();
1073 if (source && source.GetClassName() == className)
1079 protected void FilterByComponents(notnull array<ResourceName> resourceNames, notnull out array<ResourceName> outResourceNames, notnull array<string> componentClassNames,
bool removeWithComponent =
false,
bool checkEnabled =
false)
1082 BaseResourceObject baseResource;
1083 IEntitySource entitySource;
1084 IEntityComponentSource component;
1086 for (
int i = resourceNames.Count() - 1; i >= 0; i--)
1088 resource = Resource.Load(resourceNames[i]);
1089 baseResource = resource.GetResource();
1092 resourceNames.Remove(i);
1096 entitySource = baseResource.ToEntitySource();
1098 if (!entitySource || entitySource.GetNumChildren() > 0 || entitySource.GetParent())
1100 resourceNames.Remove(i);
1104 for (
int j = componentClassNames.Count() - 1; j >= 0; j--)
1106 if (HasComponent(baseResource, componentClassNames[j], checkEnabled))
1108 if (removeWithComponent)
1111 outResourceNames.Insert(resourceNames[i]);
1115 if (removeWithComponent)
1116 outResourceNames.Insert(resourceNames[i]);
1126 protected void AssignIndicesButton()
1128 Debug.BeginTimeMeasure();
1130 array<ResourceName> resourceNames = SCR_WorkbenchHelper.SearchWorkbenchResources(EXTENSIONS);
1133 BaseResourceObject baseResource;
1134 IEntitySource source;
1135 IEntitySource runtimeSource;
1136 string componentClassName;
1140 bool hasDestruction, hasPhysics;
1141 int componentClassesCount = DESTRUCTIBLE_COMPONENT_CLASSES.Count();
1145 int pairsCount = m_aPairs.Count();
1148 IEntityComponentSource physicsSource;
1152 m_API.BeginEntityAction();
1154 for (
int i = resourceNames.Count() - 1; i >= 0; i--)
1156 hasDestruction =
false;
1158 resource = Resource.Load(resourceNames[i]);
1159 baseResource = resource.GetResource();
1162 resourceNames.Remove(i);
1166 source = baseResource.ToEntitySource();
1167 componentCount = source.GetComponentCount();
1168 for (j = componentCount - 1; j >= 0; j--)
1170 componentClassName = source.GetComponent(j).GetClassName();
1171 if (!hasPhysics && componentClassName == PHYSICS_COMPONENT)
1174 for (k = componentClassesCount - 1; k >= 0; k--)
1176 if (componentClassName == DESTRUCTIBLE_COMPONENT_CLASSES[k])
1178 physicsSource = source.GetComponent(j);
1179 hasDestruction =
true;
1184 if (hasPhysics && hasDestruction)
1188 if (!hasDestruction || !hasPhysics)
1191 runtimeSource = m_API.CreateEntity(resourceNames[i],
"", 0, null, vector.Zero, vector.Zero);
1195 entity = m_API.SourceToEntity(runtimeSource);
1197 volume = MeshObjectVolumeCalculator.GetVolumeFromColliders(entity, EPhysicsLayerDefs.FireGeometry);
1199 density = CalculateDensity(entity);
1201 mass = density * 1000 * volume;
1203 for (l = 0; l < pairsCount; l++)
1205 if (mass < m_aPairs[l].
m_fMass)
1207 indexName = m_aPairs[l].m_sIndexName;
1210 else if (l == pairsCount - 1)
1212 indexName = SCR_DamageManagerComponent.MAX_DESTRUCTION_RESPONSE_INDEX_NAME;
1217 m_API.SetVariableValue(source, entryPath,
"ResponseIndex", indexName);
1219 m_API.DeleteEntity(runtimeSource);
1222 m_API.EndEntityAction();
1224 Debug.EndTimeMeasure(
"Assigning done");
1229 protected void SetBuildingDestructionEffectButton()
1236class SCR_MassResponseIndexPair
1238 [
Attribute(
desc:
"Objects with smaller weight will have this index. [kg]")]
1241 [
Attribute(
desc:
"Refer to physics settings of the project.")]
1244 [
Attribute(
desc:
"Refer to physics settings of the project.")]
1245 string m_sIndexName;
void ContainerIdPathEntry(string propertyName, int index=-1)
SCR_HybridPhysicsComponentClass m_fMass
Class for storing physics setup info for SCR_HybridPhysicsComponent.
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
ResourceName resourceName
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum EVehicleType IEntity
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
SCR_FieldOfViewSettings Attribute
proto bool Contains(T value)