Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_PowerPole.c
Go to the documentation of this file.
1[EntityEditorProps(category: "GameScripted/Power", description: "This is the power pole entity.", color: "0 255 0 255", visible: false, dynamicBox: true)]
3{
4 /*
5 Cable Slots
6 */
7
8 [Attribute(category: "[Prefab-Wide] Cable Slots")]
9 ref array<ref SCR_PoleCableSlotGroup> m_aCableSlotGroups; // since 2024-04-02
10}
11
12class SCR_PowerPole : PowerPoleEntity
13{
14 /*
15 [OLD] Power Cable Slots
16 */
17
18 [Attribute(uiwidget: UIWidgets.None, desc: "[OBSOLETE (use Cable Slot Groups above)] Slots for connecting with other power poles", category: "[OLD] Power Cable Slots")]
19 protected ref array<ref SCR_PowerPoleSlotBase> m_aSlots; // obsolete since 2024-04-02 - hidden since 2024-08-07
20
21 // Connected powerlines handling variables
22 protected static const float CONNECTED_POLE_SEARCH_RADIUS = 3.0; // meters to search for connected powerlines (matching building destruction pattern)
23
24#ifdef WORKBENCH
25
26 //------------------------------------------------------------------------------------------------
31 map<SCR_EPoleCableType, ref SCR_PoleCableSlotGroup> GetClosestCableSlotGroupsForEachCableType(vector worldPos, bool isSameLine)
32 {
33 map<SCR_EPoleCableType, ref SCR_PoleCableSlotGroup> result = new map<SCR_EPoleCableType, ref SCR_PoleCableSlotGroup>();
34 map<SCR_EPoleCableType, float> distancesSq = new map<SCR_EPoleCableType, float>();
35
36 SCR_PowerPoleClass prefabData = SCR_PowerPoleClass.Cast(GetPrefabData());
37 if (!prefabData)
38 return result;
39
40 foreach (SCR_PoleCableSlotGroup group : prefabData.m_aCableSlotGroups)
41 {
42 vector avgPos = vector.Zero;
43 int count = group.m_aSlots.Count();
44 if (count < 1)
45 continue;
46
47 if (group.m_eConnectivity != SCR_EPoleCableSlotConnectivity.ALL_LINES)
48 {
49 // SCR_EPoleCableSlotConnectivity.ALL_LINES = OK
50 // SCR_EPoleCableSlotConnectivity.SAME_LINE + isSameLine = OK
51 // SCR_EPoleCableSlotConnectivity.EXTERNAL_LINE + !isSameLine = OK
52 // anything else skips
53 if ((group.m_eConnectivity == SCR_EPoleCableSlotConnectivity.SAME_LINE) != isSameLine)
54 continue;
55 }
56
57 if (group.m_vAnchorOverride == vector.Zero)
58 {
59 foreach (SCR_PoleCableSlot slot : group.m_aSlots)
60 {
61 avgPos += slot.m_vPosition;
62 }
63
64 avgPos /= count;
65 }
66 else
67 {
68 avgPos = group.m_vAnchorOverride;
69 }
70
71 float distanceSq = vector.DistanceSq(worldPos, CoordToParent(avgPos));
72 float storedGroupDistanceSq = distancesSq.Get(group.m_eCableType);
73 if (storedGroupDistanceSq == 0) // not present - I believe faster than Contains, Get, Set/Insert
74 {
75 distancesSq.Insert(group.m_eCableType, distanceSq);
76 result.Insert(group.m_eCableType, group);
77 }
78 else
79 if (distanceSq < storedGroupDistanceSq)
80 {
81 distancesSq.Set(group.m_eCableType, distanceSq);
82 result.Set(group.m_eCableType, group);
83 }
84 }
85
86 return result;
87 }
88
89 //
90 // temp debug shapes for cable slot placement
91 //
92
93 protected static bool s_bDisplayCableSlots;
94 protected static ref SCR_DebugShapeManager s_DebugShapeManager;
95
96 protected static const float MIN_AVG_ANCHOR_DIST = 0.5;
97 protected static const int DEBUG_SLOT_POS_COLOUR_1 = Color.DARK_GREEN & 0x88FFFFFF;
98 protected static const int DEBUG_SLOT_POS_COLOUR_2 = Color.DARK_GREEN & 0x55FFFFFF;
99 protected static const int DEBUG_PRECISION_LINE_COLOUR = Color.RED;
100 protected static const float DEBUG_PRECISION_LINE_SIZE = 0.1;
101
102 protected static const int DEBUG_ANCHOR_POS_COLOUR = Color.ORANGE & 0xBBFFFFFF;
103 protected static const int DEBUG_ANCHOR_LINE_COLOUR = Color.ORANGE & 0x66FFFFFF;
104 protected static const float DEBUG_SLOT_POS_SIZE_1 = 0.05;
105 protected static const float DEBUG_SLOT_POS_SIZE_2 = 0.25;
106 protected static const float DEBUG_ANCHOR_POS = 0.075;
107
108 //------------------------------------------------------------------------------------------------
109 override bool _WB_OnKeyChanged(BaseContainer src, string key, BaseContainerList ownerContainers, IEntity parent)
110 {
111 bool result = super._WB_OnKeyChanged(src, key, ownerContainers, parent);
112 if (!src || _WB_GetEditorAPI().UndoOrRedoIsRestoring())
113 return result;
114
115 typename srcType = src.GetClassName().ToType();
116 if (
117 !srcType ||
118 (key != "m_vPosition" && key != "m_vAnchorOverride" && key != "m_eConnectivity") ||
119 (!srcType.IsInherited(SCR_PoleCableSlot) && !srcType.IsInherited(SCR_PoleCableSlotGroup)))
120 {
121 if (s_DebugShapeManager)
122 s_DebugShapeManager.Clear();
123
124 s_bDisplayCableSlots = false;
125 return result;
126 }
127
128 s_bDisplayCableSlots = true;
129
130 if (s_DebugShapeManager)
131 UpdateDebugShapes();
132
133 return result;
134 }
135
136// why these two do not work reliably, IDK
137// _WB_AfterWorldUpdate // sometimes doesn't work
138// thread // never works / crashes WB
139
140 //------------------------------------------------------------------------------------------------
141 override int _WB_GetAfterWorldUpdateSpecs(IEntitySource src)
142 {
143 return EEntityFrameUpdateSpecs.CALL_WHEN_ENTITY_VISIBLE;
144 }
145
146 //------------------------------------------------------------------------------------------------
147 override void _WB_AfterWorldUpdate(float timeSlice)
148 {
149 if (s_bDisplayCableSlots && _WB_GetEditorAPI() && _WB_GetEditorAPI().IsPrefabEditMode())
150 UpdateDebugShapes();
151 }
152
153 //------------------------------------------------------------------------------------------------
154 protected void UpdateDebugShapes()
155 {
156 SCR_PowerPoleClass prefabData = SCR_PowerPoleClass.Cast(GetPrefabData());
157 if (!prefabData)
158 return;
159
160 array<vector> lines = {
161 vector.FromYaw(45) * DEBUG_PRECISION_LINE_SIZE,
162 vector.Up * DEBUG_PRECISION_LINE_SIZE,
163 vector.FromYaw(-45) * DEBUG_PRECISION_LINE_SIZE,
164 };
165
166 s_DebugShapeManager.Clear();
167 foreach (SCR_PoleCableSlotGroup group : prefabData.m_aCableSlotGroups)
168 {
169 foreach (SCR_PoleCableSlot slot : group.m_aSlots)
170 {
171 s_DebugShapeManager.AddSphere(slot.m_vPosition, DEBUG_SLOT_POS_SIZE_1, DEBUG_SLOT_POS_COLOUR_1, ShapeFlags.DEPTH_DITHER | ShapeFlags.NOOUTLINE);
172 s_DebugShapeManager.AddSphere(slot.m_vPosition, DEBUG_SLOT_POS_SIZE_2, DEBUG_SLOT_POS_COLOUR_2, ShapeFlags.DEPTH_DITHER | ShapeFlags.NOOUTLINE);
173 foreach (vector line : lines)
174 {
175 s_DebugShapeManager.AddLine(slot.m_vPosition + line, slot.m_vPosition - line, DEBUG_PRECISION_LINE_COLOUR, ShapeFlags.DEPTH_DITHER);
176 }
177 }
178
179 vector anchor = group.m_vAnchorOverride;
180 int count = group.m_aSlots.Count();
181 bool drawAnchor = anchor != vector.Zero || count > 1;
182
183 if (anchor == vector.Zero && count > 1)
184 {
185 foreach (SCR_PoleCableSlot slot : group.m_aSlots)
186 {
187 anchor += slot.m_vPosition;
188 }
189
190 anchor /= count;
191
192 foreach (SCR_PoleCableSlot slot : group.m_aSlots)
193 {
194 if (vector.Distance(anchor, slot.m_vPosition) < MIN_AVG_ANCHOR_DIST)
195 {
196 drawAnchor = false;
197 break;
198 }
199 }
200 }
201
202 if (anchor != vector.Zero || count > 1)
203 {
204 if (drawAnchor)
205 s_DebugShapeManager.AddSphere(anchor, DEBUG_ANCHOR_POS, DEBUG_ANCHOR_POS_COLOUR, ShapeFlags.DEPTH_DITHER | ShapeFlags.NOOUTLINE);
206
207 // lines will be drawn
208 foreach (SCR_PoleCableSlot slot : group.m_aSlots)
209 {
210 s_DebugShapeManager.AddLine(slot.m_vPosition, anchor, DEBUG_ANCHOR_LINE_COLOUR, ShapeFlags.DEPTH_DITHER);
211 }
212 }
213 }
214 }
215
216#endif // WORKBENCH
217
218 //------------------------------------------------------------------------------------------------
220 override void OnStateChanged(int destructibleState, ScriptBitReader frameData, bool JIP)
221 {
222 super.OnStateChanged(destructibleState, frameData, JIP);
223
224 // Only handle connected powerlines on first destruction phase (state 1)
225 if (destructibleState == 1 && !JIP)
226 {
228 }
229 }
230
231 //------------------------------------------------------------------------------------------------
235 {
236 BaseWorld world = GetGame().GetWorld();
237 if (!world)
238 return;
239
240 // Get cable slot group positions like in SCR_DestructibleBuildingComponent
241 array<vector> polePositions = GetCableSlotGroupPositions();
242
243 // Query for powerlines around each cable slot group position and delete them
244 foreach (vector polePosition : polePositions)
245 {
246 world.QueryEntitiesBySphere(polePosition, CONNECTED_POLE_SEARCH_RADIUS, ProcessFoundPowerline, FilterPowerlineEntity);
247 }
248 }
249
250 //------------------------------------------------------------------------------------------------
252 protected array<vector> GetCableSlotGroupPositions()
253 {
254 array<vector> positions = {};
255
256 // Get prefab data to access cable slot groups
258 if (!prefabData || !prefabData.m_aCableSlotGroups)
259 {
260 // Fallback to entity origin if no cable slot groups
261 positions.Insert(GetOrigin());
262 return positions;
263 }
264
265 // Iterate through cable slot groups and average slot positions per group
266 foreach (SCR_PoleCableSlotGroup slotGroup : prefabData.m_aCableSlotGroups)
267 {
268 if (!slotGroup || !slotGroup.m_aSlots)
269 continue;
270
271 vector avgLocalPos = vector.Zero;
272 int validSlotCount = 0;
273
274 // Sum all slot positions in this group
275 foreach (SCR_PoleCableSlot slot : slotGroup.m_aSlots)
276 {
277 if (!slot)
278 continue;
279
280 avgLocalPos += slot.m_vPosition;
281 validSlotCount++;
282 }
283
284 // Calculate average and transform to world space
285 if (validSlotCount > 0)
286 {
287 avgLocalPos = avgLocalPos / validSlotCount;
288 vector avgWorldPos = CoordToParent(avgLocalPos);
289 positions.Insert(avgWorldPos);
290 }
291 }
292
293 return positions;
294 }
295
296 //------------------------------------------------------------------------------------------------
299 protected bool FilterPowerlineEntity(notnull IEntity entity)
300 {
301 return entity.Type() == PowerlineEntity;
302 }
303
304 //------------------------------------------------------------------------------------------------
307 protected bool ProcessFoundPowerline(notnull IEntity entity)
308 {
309 delete entity;
310 return true;
311 }
312
313
314 //------------------------------------------------------------------------------------------------
315 // constructor
319 {
320#ifdef WORKBENCH
321
322 if (_WB_GetEditorAPI() && _WB_GetEditorAPI().IsPrefabEditMode())
323 {
324 if (!s_DebugShapeManager)
325 s_DebugShapeManager = new SCR_DebugShapeManager();
326 }
327#endif // WORKBENCH
328 }
329}
ArmaReforgerScripted GetGame()
Definition game.c:1398
vector GetOrigin()
ref array< SCR_WeaponRackSlotEntity > m_aSlots
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
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 ...
override void OnStateChanged(int destructibleState, ScriptBitReader frameData, bool JIP)
void HandleConnectedPowerlines()
Cable Slots ref array< ref SCR_PoleCableSlotGroup > m_aCableSlotGroups
bool ProcessFoundPowerline(notnull IEntity entity)
array< vector > GetCableSlotGroupPositions()
Get cable slot group positions, following the exact pattern from SCR_DestructibleBuildingComponent.
void SCR_PowerPole(IEntitySource src, IEntity parent)
bool FilterPowerlineEntity(notnull IEntity entity)
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
SCR_VehicleDamageManagerComponentClass GetPrefabData()
enum EVehicleType IEntity
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute