Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_CompassComponent.c
Go to the documentation of this file.
1//------------------------------------------------------------------------------------------------
4{
5 SY183, // US
6 ADRIANOV // Soviet
7}
8
10[EntityEditorProps(category: "GameScripted/Gadgets", description: "Compass", color: "0 0 255 255")]
11class SCR_CompassComponentClass : SCR_GadgetComponentClass
13 [Attribute(defvalue: "0", UIWidgets.ComboBox, "Set compass type", "", ParamEnumArray.FromEnum(SCR_ECompassType), category: "Compass")]
14 int m_iCompassType;
15
16 [Attribute(defvalue: "1", uiwidget: UIWidgets.CheckBox, desc: "Approximate time (in seconds) for the needle to reach a new direction", params: "0.1 10 0.1", category: "Compass")]
17 float m_fDirectionChangeTime;
18
19 [Attribute(defvalue: "25", uiwidget: UIWidgets.Slider, desc: "Percentage overshoot of the needle when settling", params: "0 95 0.1", category: "Compass")]
20 float m_fDirectionOvershootPercentage;
21
22 [Attribute(defvalue: "2", UIWidgets.CheckBox, desc: "Frequency (in hertz) of the vertical shaking of the needle", params: "0.1 5 0.1", category: "Compass")]
23 float m_fShakeFrequency;
24
25 [Attribute(defvalue: "15", uiwidget: UIWidgets.Slider, desc: "Percentage overshoot the vertical needle shaking", params: "0 95 0.1", category: "Compass")]
26 float m_fShakeOvershootPercentage;
27
28 [Attribute(defvalue: "3", UIWidgets.CheckBox, desc: "Maximum angle (in degrees) of the shaking", params: "0 15 0.1", category: "Compass")]
29 float m_fShakeMaximumAngle;
30
31 [Attribute("0 0.3 0", UIWidgets.Coords, desc: "camera position when displayed in map UI mode", category: "Compass")]
32 vector m_vMapCameraPos;
33
34 [Attribute("{72691366C26BD901}Prefabs/Items/Equipment/Compass/Compass_SY183_Map.et", desc: "Compass prefab used for display within 2D map", category: "Compass")]
35 ResourceName m_sMapResource;
36
37 // signals
38 bool m_bSignalInit = false;
39 int m_iSignalNeedle = -1;
40 int m_iSignalShake = -1;
41 int m_iSignalInHand = -1;
42 int m_iSignalInMap = -1;
43 int m_iSignalClose = -1;
44
45 //------------------------------------------------------------------------------------------------
47 void InitSignals(IEntity owner)
48 {
50 if (!signalMgr)
51 return;
52
53 // cache signals
54 m_iSignalNeedle = signalMgr.FindSignal("Needle");
55 m_iSignalShake = signalMgr.FindSignal("Shake");
56 m_iSignalInHand = signalMgr.FindSignal("InHand");
57 m_iSignalInMap = signalMgr.FindSignal("InMap");
58 m_iSignalClose = signalMgr.FindSignal("Close");
59
60 if (m_iSignalNeedle != -1 && m_iSignalShake != -1 && m_iSignalInHand != -1)
61 m_bSignalInit = true;
62 }
63}
64
66class SCR_CompassComponent : SCR_GadgetComponent
67{
68 static const float E = 2.71828182845904;
69
70 // Derived from m_fDirectionChangeTime and m_fDirectionOvershootPercentage:
71 protected float m_fNeedleAccelerationConstant = 0;
72 protected float m_fNeedleDragConstant = 0;
73
74 // The current position and velocity:
75 protected float m_fNeedleAngle = 0;
76 protected float m_fNeedleVelocity = 0;
77
78 // Derived from m_fShakeFrequency and m_fShakeOvershootPercentage:
79 protected float m_fShakeAccelerationConstant = 0;
80 protected float m_fShakeDragConstant = 0;
81
82 // The current shake angle and velocity:
83 protected float m_fShakeAngle = 0;
84 protected float m_fShakeVelocity = 0;
85
86 // The shake is induced by the rotation since the last frame:
88
89 // Various:
90 protected bool m_bIsInMapMode;
91
93 protected ref SCR_CompassComponentClass m_PrefabData;
94
95 //------------------------------------------------------------------------------------------------
99 {
100 return m_PrefabData.m_sMapResource;
101 }
102
103 //------------------------------------------------------------------------------------------------
106 protected void UpdateNeedleDirection(float timeSlice)
107 {
109 float northDirection = -angles[0];
110
111 float magneticTorque = Math.Sin((northDirection - m_fNeedleAngle) * Math.DEG2RAD);
112
113 float acceleration = magneticTorque * m_fNeedleAccelerationConstant;
115
116 float cappedTimeSlice = Math.Min(timeSlice, 1);
117
118 m_fNeedleVelocity += (acceleration - drag) * cappedTimeSlice;
119 m_fNeedleAngle += m_fNeedleVelocity * cappedTimeSlice;
120
122 if (m_fNeedleAngle > 180) m_fNeedleAngle -= 360;
123
124 if (m_SignalManager)
125 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalNeedle, m_fNeedleAngle);
126 }
127
128 //------------------------------------------------------------------------------------------------
131 protected void UpdateNeedleShake(float timeSlice)
132 {
134 vector deltaAngles = (m_vPreviousFrameAngles - angles);
135
137
138 float acceleration = -m_fShakeAngle * m_fShakeAccelerationConstant;
140
141 float cappedTimeSlice = Math.Min(timeSlice, 1);
142
143 m_fShakeVelocity += (acceleration - drag) * cappedTimeSlice;
144
145 // The pitch change is added to the angle (as if the needle stayed still as the compass was
146 // rotated around the X axis) and yaw is added as shake when you spin around quickly:
147 m_fShakeAngle += m_fShakeVelocity * cappedTimeSlice + deltaAngles[0] + deltaAngles[1];
148
149 // The needle hit the glass or base below it, and stopped:
150 if (m_fShakeAngle > m_PrefabData.m_fShakeMaximumAngle)
151 {
153 m_fShakeAngle = m_PrefabData.m_fShakeMaximumAngle;
154 }
155
156 if (m_fShakeAngle < -m_PrefabData.m_fShakeMaximumAngle)
157 {
159 m_fShakeAngle = -m_PrefabData.m_fShakeMaximumAngle;
160 }
161
162 if (m_SignalManager)
163 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalShake, m_fShakeAngle);
164 }
165
166 //------------------------------------------------------------------------------------------------
169 {
170 // Perturb the compass a bit:
171 m_fShakeAngle = m_PrefabData.m_fShakeMaximumAngle;
173
174 // Initial set
176 m_fNeedleAngle = -angles[0] + Math.RandomInt(-10, 10);
177
178 if (m_SignalManager)
179 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalNeedle, m_fNeedleAngle);
180 }
181
182 //------------------------------------------------------------------------------------------------
185 {
186 // Perturb the compass a bit:
187 m_fShakeAngle = m_PrefabData.m_fShakeMaximumAngle;
189 }
190
191 //------------------------------------------------------------------------------------------------
194 {
195 m_iMode = EGadgetMode.IN_HAND;
196 m_bActivated = true;
197 m_bIsInMapMode = true;
198
200 }
201
202 //------------------------------------------------------------------------------------------------
205 {
206 return m_PrefabData.m_vMapCameraPos;
207 }
208
209 //------------------------------------------------------------------------------------------------
211 protected void UpdateCompassState()
212 {
213 if (System.IsConsoleApp())
214 return;
215
216 if (m_bActivated)
218 else
220
221 if (!m_PrefabData.m_bSignalInit)
222 m_PrefabData.InitSignals(GetOwner());
223
224 if (m_SignalManager)
225 {
226 // Map
227 if (m_bIsInMapMode)
228 {
229 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalInMap, 1);
230 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalInHand, 0);
231
232 if (m_PrefabData.m_iCompassType == SCR_ECompassType.SY183)
233 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalClose, 0);
234 }
235 // Hand
236 else if (m_iMode != EGadgetMode.IN_SLOT)
237 {
238 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalInHand, 1);
239
240 if (m_PrefabData.m_iCompassType == SCR_ECompassType.SY183)
241 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalClose, 0);
242 }
243 // Ground
244 else
245 {
246 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalInHand, 0);
247
248 if (m_PrefabData.m_iCompassType == SCR_ECompassType.SY183)
249 m_SignalManager.SetSignalValue(m_PrefabData.m_iSignalClose, 1);
250 }
251 }
252 }
253
254 //------------------------------------------------------------------------------------------------
257 protected float GetDampingRatio(float overshootPercentage)
258 {
259 float logOvershoot = Math.Log2(Math.Max(0.001, overshootPercentage / 100.0)) / Math.Log2(E);
260 float zeta = -logOvershoot / Math.Sqrt(Math.PI * Math.PI + logOvershoot * logOvershoot);
261
262 return zeta;
263 }
264
265 //------------------------------------------------------------------------------------------------
267 protected void CalculateConstants()
268 {
269 // Calculate the needle constants:
270 float zeta = GetDampingRatio(m_PrefabData.m_fDirectionOvershootPercentage);
271 float naturalFrequency = Math.PI / Math.Max(0.1, m_PrefabData.m_fDirectionChangeTime);
272
273 m_fNeedleAccelerationConstant = naturalFrequency * naturalFrequency * Math.RAD2DEG;
274 m_fNeedleDragConstant = 2 * naturalFrequency * zeta;
275
276 // Calculate the shake constants:
277 zeta = GetDampingRatio(m_PrefabData.m_fShakeOvershootPercentage);
278 naturalFrequency = m_PrefabData.m_fShakeFrequency;
279
280 m_fShakeAccelerationConstant = naturalFrequency * naturalFrequency * Math.RAD2DEG;
281 m_fShakeDragConstant = 2 * naturalFrequency * zeta;
282 }
283
284
285 //------------------------------------------------------------------------------------------------
286 override void ModeSwitch(EGadgetMode mode, IEntity charOwner)
287 {
288 super.ModeSwitch(mode, charOwner);
289
290 if (mode == EGadgetMode.IN_HAND)
291 {
292 m_bActivated = true;
294 }
295 }
296
297 //------------------------------------------------------------------------------------------------
298 override void ModeClear(EGadgetMode mode)
299 {
300 super.ModeClear(mode);
301
302 if (mode == EGadgetMode.IN_HAND)
303 {
304 m_bActivated = false;
306 }
307 }
308
309 //------------------------------------------------------------------------------------------------
310 override void ActivateGadgetUpdate()
311 {
312 super.ActivateGadgetUpdate();
313
315 if (itemComponent)
316 itemComponent.ActivateOwner(true); // required for the procedural animations to function
317 }
318
319 //------------------------------------------------------------------------------------------------
321 {
322 super.DeactivateGadgetUpdate();
323
325 if (itemComponent)
326 itemComponent.ActivateOwner(false);
327 }
328
329 //------------------------------------------------------------------------------------------------
330 override EGadgetType GetType()
331 {
332 return EGadgetType.COMPASS;
333 }
334
335 //------------------------------------------------------------------------------------------------
336 override bool CanBeRaised()
337 {
338 return true;
339 }
340
341 //------------------------------------------------------------------------------------------------
342 override bool IsUsingADSControls()
343 {
344 return true;
345 }
346
347 //------------------------------------------------------------------------------------------------
348 override bool RplSave(ScriptBitWriter writer)
349 {
350 if (!super.RplSave(writer))
351 return false;
352
353 writer.WriteBool(m_bActivated);
354
355 return true;
356 }
357
358 //------------------------------------------------------------------------------------------------
359 override bool RplLoad(ScriptBitReader reader)
360 {
361 if (!super.RplLoad(reader))
362 return false;
363
364 reader.ReadBool(m_bActivated);
365
367
368 return true;
369 }
370
371 //------------------------------------------------------------------------------------------------
372 override void Update(float timeSlice)
373 {
374 UpdateNeedleDirection(timeSlice);
375 UpdateNeedleShake(timeSlice);
376 }
377
378 //------------------------------------------------------------------------------------------------
379 override void OnPostInit(IEntity owner)
380 {
381 super.OnPostInit(owner);
382
383 m_PrefabData = SCR_CompassComponentClass.Cast( GetComponentData(owner) );
385 if (!m_SignalManager)
386 Print(string.Format("Missing SingalsManagerComponent on compass entity: %1", owner), LogLevel.WARNING);
387
390 }
391}
ref array< string > angles
SCR_CharacterSoundComponentClass GetComponentData()
enum SCR_ECompassType EntityEditorProps(category:"GameScripted/Gadgets", description:"Compass", color:"0 0 255 255")
Prefab data class for compass component.
SCR_ECompassType
Compass type.
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
proto external Managed FindComponent(typename typeName)
proto external vector GetYawPitchRoll()
Definition Math.c:13
void UpdateNeedleShake(float timeSlice)
void CalculateConstants()
Init configurables.
override void ActivateGadgetUpdate()
override void ModeClear(EGadgetMode mode)
override void OnPostInit(IEntity owner)
ResourceName GetMapPrefabResource()
override bool RplSave(ScriptBitWriter writer)
vector GetMapCamPosition()
Get compass in map UI camera position configuration.
void UpdateCompassState()
Update state of compass active/inactive.
override EGadgetType GetType()
override void DeactivateGadgetUpdate()
override void ModeSwitch(EGadgetMode mode, IEntity charOwner)
SignalsManagerComponent m_SignalManager
override bool RplLoad(ScriptBitReader reader)
void SetMapMode()
Activate in a map UI mode.
override bool IsUsingADSControls()
void DragMapCompass()
MapCompassUI drag activation, simulating movement.
void UpdateNeedleDirection(float timeSlice)
override void Update(float timeSlice)
void Init2DMapCompass()
Init for 2D map compass UI.
float GetDampingRatio(float overshootPercentage)
ref SCR_CompassComponentClass m_PrefabData
static float fmod(float dividend, float divisor)
Definition SCR_Math.c:114
IEntity GetOwner()
Owner entity of the fuel tank.
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
SCR_FieldOfViewSettings Attribute