Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ConvexPolygonDamageAreaShape.c
Go to the documentation of this file.
2{
3 [Attribute(desc: "List of poin infos defining the convex boundry area")]
4 private ref array<ref SCR_BoundsPosition> m_aBounds;
5
6 [Attribute(defvalue: "1", desc: "Height of the boundries", params: "0.1 inf 0.01")]
7 protected float m_fHeight;
8
9 protected ref array<vector> m_aSimpleBoundsLS;
10 protected float m_fDiameter;
11
12#ifdef ENABLE_DIAG
13 static bool s_bSupressChangedPropertyWarnings;
14 const string PROPERTY_OFFSET = "Offset";
15 const string PROPERTY_BOUNDS = "m_aBounds";
16 const string PROPERTY_HEIGHT = "m_fHeight";
17
18 //------------------------------------------------------------------------------------------------
19 override void DrawDebug(IEntity owner, inout SCR_DebugShapeManager shapeMgr, bool runtime = false)
20 {
22 return;
23
24 array<vector> positions = {};
25 foreach (vector point : m_aSimpleBoundsLS)
26 {
27 positions.Insert(owner.CoordToParent(point));
28 }
29
30 if (positions.Count() < 3)
31 return;
32
33 ShapeFlags flag;
34 int color = Color.RED;
35 if (runtime)
36 flag = ShapeFlags.ONCE; // once as in runtime it is called every frame and we dont have a nice point to clear them, thus they are disposable
37 else
38 color = Color.WHITE;
39
40 vector mat[4];
41 owner.GetTransform(mat);
42
43 shapeMgr.AddBounds(positions, m_fHeight, mat[1], color, additionalFlags: flag);
44 }
45
46 //------------------------------------------------------------------------------------------------
47 override bool _WB_OnKeyChanged(IEntity owner, BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
48 {
49 if (s_bSupressChangedPropertyWarnings)
50 return false;
51
52 if (key.IsEmpty())
53 return false;
54
55 if (key != PROPERTY_OFFSET && key != PROPERTY_BOUNDS && key != PROPERTY_HEIGHT)
56 return false;
57
58 Print("SCR_ConvexPolygonDamageAreaShape -> NOTICE! After you are finished adjusting the bounds, use World Editor -> Plugins -> Optimize Damage Area Shapes", LogLevel.WARNING);
59 return false;
60 }
61
62 //------------------------------------------------------------------------------------------------
63 override bool OptimizeShape(notnull IEntitySource ownerSource, inout notnull WorldEditorAPI api, notnull array<ref ContainerIdPathEntry> shapePath, out vector offset)
64 {
66 return false;
67
68 const int numberOfPoints = m_aSimpleBoundsLS.Count();
69 if (numberOfPoints < 1)
70 return false; // nothing to recenter
71
72 // Find lowest and highest point
73 float low = float.MAX;
74 float high = int.MIN;
75 foreach (vector point : m_aSimpleBoundsLS)
76 {
77 if (point[1] < low)
78 low = point[1];
79
80 if (point[1] > high)
81 high = point[1];
82 }
83
84 // Recalculate the max height based on the lowest point
85 m_fHeight = high - low + m_fHeight; // total height
86
87 // Readjust their positions and find their center
88 foreach (int i, vector point : m_aSimpleBoundsLS)
89 {
90 point[1] = low; // set all of them to the same Y position
91 m_aSimpleBoundsLS[i] = point;
92 offset += point;
93 offset += point + vector.Up * m_fHeight;
94 }
95
96 if (offset == vector.Zero ||
97 (float.AlmostEqual(offset[0], 0) && float.AlmostEqual(offset[1], 0) && float.AlmostEqual(offset[2], 0))) // if its off by float point precision then we dont care
98 return false; // its already centered
99
100 // Actual center in local space
101 offset /= numberOfPoints * 2;
102
103 array<ref ContainerIdPathEntry> finalPath = {};
104 foreach (ContainerIdPathEntry pathEntry : shapePath)
105 {
106 finalPath.Insert(ContainerIdPathEntry.Cast(pathEntry.Clone()));
107 }
108
109 // Disable printing that something has changed in this prefab to not spam
110 SCR_ConvexPolygonDamageAreaShape.s_bSupressChangedPropertyWarnings = true;
111
112 // Update entity properties for this shape
113 api.SetVariableValue(ownerSource, finalPath, PROPERTY_HEIGHT, m_fHeight.ToString());
114
115 finalPath.Insert(new ContainerIdPathEntry(PROPERTY_BOUNDS));
116 int lastElementId = finalPath.Count() - 1;
117 foreach (int entryId, vector oldPos : m_aSimpleBoundsLS)
118 {
119 finalPath[lastElementId].Index = entryId;
120
121 vector newPos = oldPos - offset;
122 api.SetVariableValue(ownerSource, finalPath, PROPERTY_OFFSET, newPos.ToString(false));
123 }
124
125 SCR_ConvexPolygonDamageAreaShape.s_bSupressChangedPropertyWarnings = false;
126 return true;
127 }
128
129 //------------------------------------------------------------------------------------------------
130 override void Diag_DrawArea(int color)
131 {
132 if (!GetGame().InPlayMode())
133 return;
134
135 IEntity owner = GetDamageArea().GetParent();
136 SCR_DamageAreaComponent dmgAreaComp = SCR_DamageAreaComponent.Cast(owner.FindComponent(SCR_DamageAreaComponent));
137 SCR_DebugShapeManager shapeMgr = dmgAreaComp.GetDebugShapeMgr();
138 DrawDebug(owner, shapeMgr, true);
139 }
140#endif
141
142 //------------------------------------------------------------------------------------------------
143 override void Init(IEntity owner)
144 {
145 if (!m_aBounds)
146 return;
147
148 vector pos;
149
150 float maxDistanceSq, currentDistSq;
152 foreach (SCR_BoundsPosition point : m_aBounds)
153 {
154 if (!point)
155 continue;
156
157 // transfer from point infos to simple vectors for smaller memory footprint
158 pos = point.Offset;
159 m_aSimpleBoundsLS.Insert(pos);
160
161 currentDistSq = pos.LengthSq();
162 if (currentDistSq > maxDistanceSq)
163 maxDistanceSq = currentDistSq;
164
165 vector upperCorner = pos + vector.Up * m_fHeight;
166 currentDistSq = upperCorner.LengthSq();
167 if (currentDistSq > maxDistanceSq)
168 maxDistanceSq = currentDistSq;
169 }
170
171 m_fDiameter = Math.Sqrt(maxDistanceSq) * 2;
172 m_aBounds = null;
173 }
174
175 //------------------------------------------------------------------------------------------------
176 override float GetDiameter()
177 {
178 return m_fDiameter;
179 }
180
181 //------------------------------------------------------------------------------------------------
182 override bool ShouldAffectEntity(IEntity entityToAffect)
183 {
184 vector worldPos;
185 ChimeraCharacter character = ChimeraCharacter.Cast(entityToAffect);
186 if (character)
187 {
188 worldPos = character.AimingPosition();
189 }
190 else
191 {
192 Physics phys = entityToAffect.GetPhysics();
193 if (phys)
194 worldPos = phys.GetCenterOfMass();
195 else
196 worldPos = entityToAffect.GetOrigin();
197 }
198
199 return AffectsPosition(worldPos);
200 }
201
202 //------------------------------------------------------------------------------------------------
206 {
207 const IEntity owner = GetDamageArea().GetParent();
208 // translate to local space for easier evaluation with vectors from m_aSimpleBoundsLS
209 const vector positionCopy = owner.CoordToLocal(position);
210
211 // all shapes should be optimized with the puling, which will make the entity to be in the center of the shape
212 // thus half height determines if Y component is outside of the area of influence
213 const float halfHeight = m_fHeight * 0.5;
214 if (positionCopy[1] > halfHeight || positionCopy[1] < -halfHeight)
215 return false;
216
217 const vector upOffset = {0, m_fHeight, 0};
218
219 vector previousCorner, nextCorner, previousPlaneDir, nextPlaneDir, previousNormal, nextNormal, directionToPoint;
220 float previousDot, nextDot;
221 int lastPointId = m_aSimpleBoundsLS.Count() - 1;
222
223 // check if point is on the right side of the previous plane, and on the left side of the next plane
224 // to ensure that point is within the wedge
225 foreach (int i, vector corner : m_aSimpleBoundsLS)
226 {
227 if (i > 0)
228 previousCorner = m_aSimpleBoundsLS[i - 1];
229 else
230 previousCorner = m_aSimpleBoundsLS[lastPointId];
231
232 if (i < lastPointId)
233 nextCorner = m_aSimpleBoundsLS[i + 1];
234 else
235 nextCorner = m_aSimpleBoundsLS[0];
236
237 previousPlaneDir = previousCorner - corner;
238 nextPlaneDir = nextCorner - corner;
239 previousNormal = SCR_Math3D.Cross(upOffset, previousPlaneDir, true);
240 nextNormal = SCR_Math3D.Cross(upOffset, nextPlaneDir, true);
241 directionToPoint = positionCopy - corner;
242 previousDot = vector.Dot(previousNormal, directionToPoint);
243 nextDot = vector.Dot(nextNormal, directionToPoint);
244
245 // if both dots have the same sign, then the point is on the wrong side for one of them
246 if (previousDot * nextDot > 0)
247 return false; // its outside of the wedge
248 }
249
250 return true; // its somewhere inside of the shape
251 }
252}
void ContainerIdPathEntry(string propertyName, int index=-1)
Definition worldEditor.c:30
ArmaReforgerScripted GetGame()
Definition game.c:1398
override bool _WB_OnKeyChanged(IEntity owner, BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
Any property value has been changed. You can use editor API here and do some additional edit actions ...
vector position
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum EVehicleType IEntity
Definition Color.c:13
proto external Managed FindComponent(typename typeName)
proto external vector GetOrigin()
proto external Physics GetPhysics()
proto external void GetTransform(out vector mat[])
proto external IEntity GetParent()
proto external vector CoordToParent(vector coord)
proto external vector CoordToLocal(vector coord)
Definition Math.c:13
override bool ShouldAffectEntity(IEntity entityToAffect)
Contains various scripted 3D math functions.
Definition SCR_Math3D.c:3
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute