Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_PushVehicleAction.c
Go to the documentation of this file.
2{
3 protected const float FORCE_SCALE = 1.0;
4 protected const float COUNTERFORCE_SCALE = -1.5;
5
6 [Attribute(defvalue: "1", desc: "Mass to force\n[N per kg]", params: "0.01 inf 0.01")]
7 protected float m_fMassToForce;
8
9 [Attribute(defvalue: "1000", desc: "Force limit\n[N]", params: "1 100000 1")]
10 protected float m_fForceLimit;
11
12 [Attribute(defvalue: "3", desc: "Maximum speed\n[m/s]")]
13 protected float m_fLinearSpeedLimit;
14
15 [Attribute(defvalue: "2", desc: "Maximum angular speed\n[rad/s]", params: "0 inf")]
16 protected float m_fAngularSpeedLimit;
17
18 [Attribute(defvalue: "0", desc: "Pull if enabled, otherwise push", params: "0 inf")]
19 protected bool m_bPull;
20
21 [Attribute(defvalue: "5", desc: "How many times per second server should try to apply this force to the vehicle", params: "1 30 1")]
23
24 [Attribute(defvalue: "1.5", desc: "Multiplies the offset used for the position of the counter force.\nThis makes it easier to apply rotational force without pushing away the object from the user.", params: "0.1 inf")]
26
27 protected float m_fApplicationInterval;
28 protected float m_fApplicationDeltaTime;
29 protected RplComponent m_Rpl;
30#ifdef ENABLE_DIAG
31 protected ref array<ref Shape> m_aShapes = {};
32
33 //------------------------------------------------------------------------------------------------
34 void ClearDebug()
35 {
36 m_aShapes.Clear();
37 }
38#endif
39
40 //------------------------------------------------------------------------------------------------
42 override void Init(IEntity pOwnerEntity, GenericComponent pManagerComponent)
43 {
44 m_Rpl = RplComponent.Cast(pOwnerEntity.GetRootParent().FindComponent(RplComponent));
46#ifdef ENABLE_DIAG
47 DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_VEHICLES_UNFLIP, "", "Visualize push force", "Vehicles");
48#endif
49 }
50
51 //------------------------------------------------------------------------------------------------
53 override bool CanBeShownScript(IEntity user)
54 {
55 if (!super.CanBeShownScript(user))
56 return false;
57
59 if (!character)
60 return false;
61
62 if (character.IsInVehicle())
63 return false;
64
65 CharacterControllerComponent controller = character.GetCharacterController();
66 if (!controller)
67 return false;
68
69 if (controller.IsSwimming())
70 return false;
71
72 if (controller.GetStance() == ECharacterStance.PRONE)
73 return false;
74
75 IEntity owner = GetOwner().GetRootParent();
76 CharacterAnimationComponent characterAnimationComp = controller.GetAnimationComponent();
77 if (!characterAnimationComp || characterAnimationComp.GetLinkedEntity() == owner)
78 return false;
79
80 Physics physics = owner.GetPhysics();
81 if (!physics)
82 return false;
83
84 if (m_fLinearSpeedLimit > 0 && physics.GetVelocity().LengthSq() > m_fLinearSpeedLimit * m_fLinearSpeedLimit)
85 return false;
86
87 if (m_fAngularSpeedLimit > 0 && physics.GetAngularVelocity().LengthSq() > m_fAngularSpeedLimit * m_fAngularSpeedLimit)
88 return false;
89
90 return true;
91 }
92
93 //------------------------------------------------------------------------------------------------
95 protected float GetAdditionalForce();
96
97 //------------------------------------------------------------------------------------------------
99 protected float GetMaxForceToMassFactor()
100 {
101 return 1;
102 }
103
104 //------------------------------------------------------------------------------------------------
105 protected void ApplyForce(IEntity rootEntity, IEntity pUserEntity, float timeSlice, vector forceOffset = vector.Zero)
106 {
107 // Only run where vehicle is being simulated
108 if (!m_Rpl || m_Rpl.Role() != RplRole.Authority && !m_Rpl.IsOwnerProxy())
109 return;
110
111 ChimeraCharacter character = ChimeraCharacter.Cast(pUserEntity);
112 if (!character)
113 return;
114
115 m_fApplicationDeltaTime += timeSlice;
117 return;
118
119 // Get force origin, target and direction
120 vector forceOrigin = character.EyePosition();
121 Physics physics = rootEntity.GetPhysics();
122 vector forceTarget = rootEntity.CoordToParent(physics.GetCenterOfMass());
123 //equal Y to ensure that foce vector isnt going to have odd angle because of the distance between the player and the vehicle
124 forceOrigin[1] = forceTarget[1];
125 vector forceDirection = vector.Direction(forceTarget, forceOrigin);
126 //normalized to prevent force scaling based on how far player is away from the vehicle
127 forceDirection.Normalize();
128
129 float mass = physics.GetMass();
130 float force = Math.Min(m_fMassToForce * mass, m_fForceLimit);
131
132 // limit the amount of force to prevent f.e. S105 from being flipped into space, as without that a ~850kg car, could expirience a 16200 impulse when unflipped with support station
133 force = Math.Min(force + GetAdditionalForce(), mass * GetMaxForceToMassFactor());
134
135 if (!m_bPull)
136 force *= -1;
137
138 float linearSpeedFactor = 1;
139 if (m_fLinearSpeedLimit > 0)
140 linearSpeedFactor -= Math.Clamp(physics.GetVelocity().LengthSq() / (m_fLinearSpeedLimit * m_fLinearSpeedLimit), 0, 1);
141
142 float angularSpeedFactor = 1;
143 if (m_fAngularSpeedLimit > 0)
144 angularSpeedFactor -= Math.Clamp(physics.GetAngularVelocity().LengthSq() / (m_fAngularSpeedLimit * m_fAngularSpeedLimit), 0, 1);
145
146 vector impulse = (m_fApplicationDeltaTime * force * linearSpeedFactor * angularSpeedFactor) * forceDirection;
148 // Apply force above and below center of mass for best efficiency
149 physics.ApplyImpulseAt(forceTarget + forceOffset, impulse * FORCE_SCALE);
150
151 if (forceOffset != vector.Zero)
152 physics.ApplyImpulseAt(forceTarget - (forceOffset * m_fCounterForceOffsetMultiplier), impulse * COUNTERFORCE_SCALE);//lowered by another 50% to reduce sliding
153
154#ifdef ENABLE_DIAG
155 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_VEHICLES_UNFLIP))
156 {
157 m_aShapes.Clear();
158 ShapeFlags shapeFlags = ShapeFlags.NOZBUFFER | ShapeFlags.TRANSP | ShapeFlags.DOUBLESIDE | ShapeFlags.NOOUTLINE;
159 m_aShapes.Insert(Shape.CreateArrow(forceTarget, forceTarget + forceOffset, 0.1, Color.BLUE, shapeFlags));
160 m_aShapes.Insert(Shape.CreateArrow(forceOrigin, forceOrigin - forceDirection, 0.1, Color.RED, shapeFlags));
161 m_aShapes.Insert(Shape.CreateArrow(forceTarget + forceOffset, forceTarget + forceOffset + impulse, 1, Color.GREEN, shapeFlags));
162 if (forceOffset != vector.Zero)
163 {
164 m_aShapes.Insert(Shape.CreateArrow(forceTarget, forceTarget - (forceOffset * m_fCounterForceOffsetMultiplier), 0.1, Color.PINK, shapeFlags));
165 m_aShapes.Insert(Shape.CreateArrow(forceTarget - (forceOffset * m_fCounterForceOffsetMultiplier), forceTarget - (forceOffset * m_fCounterForceOffsetMultiplier) + (impulse * COUNTERFORCE_SCALE), 1, Color.BLACK, shapeFlags));
166 }
167 }
168#endif
169 }
170
171 //------------------------------------------------------------------------------------------------
173 override void PerformContinuousAction(IEntity pOwnerEntity, IEntity pUserEntity, float timeSlice)
174 {
175 ApplyForce(pOwnerEntity.GetRootParent(), pUserEntity, timeSlice);
176 }
177
178 //------------------------------------------------------------------------------------------------
181 override void OnActionStart(IEntity pUserEntity)
182 {
183 super.OnActionStart(pUserEntity);
185 }
186
187 //------------------------------------------------------------------------------------------------
190 override void OnActionCanceled(IEntity pOwnerEntity, IEntity pUserEntity)
191 {
192#ifdef ENABLE_DIAG
193 if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_VEHICLES_UNFLIP))
194 {
195 GetGame().GetCallqueue().CallLater(ClearDebug, 10000);
196 }
197#endif
198 super.OnActionCanceled(pOwnerEntity, pUserEntity);
200 }
201
202 //------------------------------------------------------------------------------------------------
204 override float GetActionProgressScript(float fProgress, float timeSlice)
205 {
206 return fProgress + timeSlice;
207 }
208
209 //------------------------------------------------------------------------------------------------
211 override bool CanBroadcastScript()
212 {
213 return false;
214 }
215}
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition DebugMenuID.c:4
ArmaReforgerScripted GetGame()
Definition game.c:1398
SCR_DestructibleTreeV2Class impulse
ref array< ref Shape > m_aShapes
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
proto external IEntity GetOwner()
Returns the parent entity of this action.
Definition Color.c:13
Diagnostic and developer menu system.
Definition DiagMenu.c:18
proto external Managed FindComponent(typename typeName)
proto external Physics GetPhysics()
proto external vector CoordToParent(vector coord)
proto external IEntity GetRootParent()
Definition Math.c:13
override void OnActionStart(IEntity pUserEntity)
override float GetActionProgressScript(float fProgress, float timeSlice)
Returns the progress of this action in seconds.
override void Init(IEntity pOwnerEntity, GenericComponent pManagerComponent)
Called when object is initialized and registered to actions manager.
override bool CanBroadcastScript()
If HasLocalEffectOnly() is false this method tells if the server is supposed to broadcast this action...
override void OnActionCanceled(IEntity pOwnerEntity, IEntity pUserEntity)
override bool CanBeShownScript(IEntity user)
Can this action be shown in the UI to the provided user entity?
void ApplyForce(IEntity rootEntity, IEntity pUserEntity, float timeSlice, vector forceOffset=vector.Zero)
override void PerformContinuousAction(IEntity pOwnerEntity, IEntity pUserEntity, float timeSlice)
Called when someone tries to perform the continuous action, user entity is typically character.
A scripted action class having optional logic to check if vehicle is valid.
Instance of created debug visualizer.
Definition Shape.c:14
ECharacterStance
ShapeFlags
Definition ShapeFlags.c:13
SCR_FieldOfViewSettings Attribute
RplRole
Role of replicated node (and all items in it) within the replication system.
Definition RplRole.c:14