Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
dayzplayerimplementfalldamage.c
Go to the documentation of this file.
2{
3 int m_LandType;
4 float m_Height;
5 float m_HealthCoef;
6 float m_ShockCoef;
7 float m_BrokenLegsCoef;
8 float m_BleedingHandsCoef;
9 float m_BleedingFeetCoef;
10 float m_BleedingLegsCoef;
11 float m_GlovesHealthCoef;
12 float m_ShoesHealthCoef;
13 float m_PantsHealthCoef;
14 float m_BleedingChanceCoef;
15 float m_BleedingChanceLegsCoef;
16}
17
18class DayZPlayerImplementFallDamage
19{
20 static const string FALL_DAMAGE_AMMO_HEALTH = "FallDamageHealth";
21 static const string FALL_DAMAGE_AMMO_SHOCK = "FallDamageShock";
22
23 static const string FALL_DAMAGE_AMMO_HEALTH_ATTACHMENT = "FallDamageHealthAttachment";
24 static const string FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS = "FallDamageHealthOtherAttachments";
25
26 const float HEALTH_HEIGHT_LOW = 5;
27 const float HEALTH_HEIGHT_HIGH = 14;
28
29 private const float SHOCK_HEIGHT_LOW = 3;
30 private const float SHOCK_HEIGHT_HIGH = 12;
31 private const float BROKENLEGS_HEIGHT_LOW = 5;
32 private const float BROKENLEGS_HEIGHT_HIGH = 9;
33
34 private const float GLOVES_HEALTH_HEIGHT_LOW = 5;
35 private const float GLOVES_HEALTH_HEIGHT_HIGH = 15;
36 private const float SHOES_HEALTH_HEIGHT_LOW = 2;
37 private const float SHOES_HEALTH_HEIGHT_HIGH = 15;
38 private const float PANTS_HEALTH_HEIGHT_LOW = 5;
39 private const float PANTS_HEALTH_HEIGHT_HIGH = 16;
40
41 private const float BLEEDINGHANDS_HEIGHT_LOW = 5;
42 private const float BLEEDINGFEET_HEIGHT_LOW = 3;
43 private const float BLEEDINGLEGS_HEIGHT_LOW = 10;
44
45 private const float RANDOM_THRESHOLD_HEALTH_LOW = 0.05;
46 private const float RANDOM_THRESHOLD_HEALTH_HIGH = 0.1;
47 private const float RANDOM_THRESHOLD_LEGS_LOW = 0.05;
48 private const float RANDOM_THRESHOLD_LEGS_HIGH = 0.1;
49 private const float RANDOM_THRESHOLD_ATTACHMENTS_LOW = 0;
50 private const float RANDOM_THRESHOLD_ATTACHMENTS_HIGH = 0.2;
51
52 private const float BLEEDING_CHANCE_HEIGHT_LOW = 3;
53 private const float BLEEDING_CHANCE_HEIGHT_HIGH = 15;
54
55 private static const float BROKENLEGS_HEALTH_DAMAGE_MAX = 125;
56
57 private static const string BLEEDING_HANDS_SELECTIONS[2] = {"LeftForeArmRoll", "RightForeArmRoll"};
58 private static const string BLEEDING_FEET_SELECTIONS[2] = {"LeftFoot", "RightFoot"};
59 private static const string BLEEDING_LEGS_SELECTIONS[2] = {"LeftLeg", "RightLeg"};
60
61 private const int DAMAGE_TYPE_GLOBAL = 0;
62 private const int DAMAGE_TYPE_LEGS = 1;
63 private const int DAMAGE_TYPE_ATTACHMENTS = 2;
64
66 private ref FallDamageData m_FallDamageData;
67
68 #ifdef DIAG_DEVELOPER
69 bool m_Debug = false;
70 private static ref map<string, float> m_AmmoTypeData;
71 #endif
72
73 void DayZPlayerImplementFallDamage(DayZPlayer pPlayer)
74 {
75 m_Player = pPlayer;
76 m_FallDamageData = new FallDamageData();
77
78 #ifdef DIAG_DEVELOPER
79 PreloadAmmoTypeData();
80 #endif
81 }
82
83 float GetHeight()
84 {
85 return m_FallDamageData.m_Height;
86 }
87
88 int GetLandType()
89 {
90 return m_FallDamageData.m_LandType;
91 }
92
93 void HandleFallDamage(FallDamageData pData)
94 {
95 m_FallDamageData = pData;
96
97 m_FallDamageData.m_HealthCoef = Math.InverseLerp(HEALTH_HEIGHT_LOW, HEALTH_HEIGHT_HIGH, pData.m_Height);
98 m_FallDamageData.m_HealthCoef = Randomize(DAMAGE_TYPE_GLOBAL, m_FallDamageData.m_HealthCoef);
99 m_FallDamageData.m_HealthCoef = Math.Clamp(m_FallDamageData.m_HealthCoef, 0, 1);
100
101 m_FallDamageData.m_ShockCoef = Math.InverseLerp(SHOCK_HEIGHT_LOW, SHOCK_HEIGHT_HIGH, pData.m_Height);
102 m_FallDamageData.m_ShockCoef = Math.Clamp(m_FallDamageData.m_ShockCoef, 0, 1);
103
104 m_FallDamageData.m_BrokenLegsCoef = Math.InverseLerp(BROKENLEGS_HEIGHT_LOW, BROKENLEGS_HEIGHT_HIGH, pData.m_Height);
105 m_FallDamageData.m_BrokenLegsCoef = Randomize(DAMAGE_TYPE_LEGS, m_FallDamageData.m_BrokenLegsCoef);
106 m_FallDamageData.m_BrokenLegsCoef = Math.Clamp(m_FallDamageData.m_BrokenLegsCoef, 0, 1);
107
108 m_FallDamageData.m_BleedingHandsCoef = Math.InverseLerp(0, BLEEDINGHANDS_HEIGHT_LOW, pData.m_Height);
109 m_FallDamageData.m_BleedingHandsCoef = Math.Clamp(m_FallDamageData.m_BleedingHandsCoef, 0, 1);
110
111 m_FallDamageData.m_BleedingFeetCoef = Math.InverseLerp(0, BLEEDINGFEET_HEIGHT_LOW, pData.m_Height);
112 m_FallDamageData.m_BleedingFeetCoef = Math.Clamp(m_FallDamageData.m_BleedingFeetCoef, 0, 1);
113
114 m_FallDamageData.m_BleedingLegsCoef = Math.InverseLerp(0, BLEEDINGLEGS_HEIGHT_LOW, pData.m_Height);
115 m_FallDamageData.m_BleedingLegsCoef = Math.Clamp(m_FallDamageData.m_BleedingLegsCoef, 0, 1);
116
117 m_FallDamageData.m_GlovesHealthCoef = Math.InverseLerp(GLOVES_HEALTH_HEIGHT_LOW, GLOVES_HEALTH_HEIGHT_HIGH, pData.m_Height);
118 m_FallDamageData.m_GlovesHealthCoef = Randomize(DAMAGE_TYPE_ATTACHMENTS, m_FallDamageData.m_GlovesHealthCoef);
119 m_FallDamageData.m_GlovesHealthCoef = Math.Clamp(m_FallDamageData.m_GlovesHealthCoef, 0, 1);
120
121 m_FallDamageData.m_ShoesHealthCoef = Math.InverseLerp(SHOES_HEALTH_HEIGHT_LOW, SHOES_HEALTH_HEIGHT_HIGH, pData.m_Height);
122 m_FallDamageData.m_ShoesHealthCoef = Randomize(DAMAGE_TYPE_ATTACHMENTS, m_FallDamageData.m_ShoesHealthCoef);
123 m_FallDamageData.m_ShoesHealthCoef = Math.Clamp(m_FallDamageData.m_ShoesHealthCoef, 0, 1);
124
125 m_FallDamageData.m_PantsHealthCoef = Math.InverseLerp(PANTS_HEALTH_HEIGHT_LOW, PANTS_HEALTH_HEIGHT_HIGH, pData.m_Height);
126 m_FallDamageData.m_PantsHealthCoef = Randomize(DAMAGE_TYPE_ATTACHMENTS, m_FallDamageData.m_PantsHealthCoef);
127 m_FallDamageData.m_PantsHealthCoef = Math.Clamp(m_FallDamageData.m_PantsHealthCoef, 0, 1);
128
129 m_FallDamageData.m_BleedingChanceCoef = Math.InverseLerp(BLEEDING_CHANCE_HEIGHT_LOW, BLEEDING_CHANCE_HEIGHT_HIGH, pData.m_Height);
130 m_FallDamageData.m_BleedingChanceCoef = Math.Clamp(m_FallDamageData.m_BleedingChanceCoef, 0, 0.7);
131
132 m_FallDamageData.m_BleedingChanceLegsCoef = 0.15;
133
134 if (GetGame().IsServer())
135 {
136 PlayerBase playerBase = PlayerBase.Cast(m_Player);
137 if (playerBase)
138 {
139 AttachBleedingToZonesByHeight(playerBase);
140 DamageAttachedGear(playerBase);
141 playerBase.DamageAllLegs(BROKENLEGS_HEALTH_DAMAGE_MAX * m_FallDamageData.m_BrokenLegsCoef);
142 playerBase.ForceUpdateInjuredState();
143 }
144
145 m_Player.ProcessDirectDamage(DamageType.CUSTOM, m_Player, "", FALL_DAMAGE_AMMO_HEALTH, vector.Zero, m_FallDamageData.m_HealthCoef);
146 m_Player.ProcessDirectDamage(DamageType.CUSTOM, m_Player, "", FALL_DAMAGE_AMMO_SHOCK, vector.Zero, m_FallDamageData.m_ShockCoef);
147
148 }
149 }
150
151 private float Randomize(int pType, float pValue)
152 {
153 Math.Randomize(GetGame().GetTime());
154
155 int randomizedSign = -1;
156 if (Math.RandomIntInclusive(1, 2) % 2 == 1)
157 randomizedSign = 1;
158
159 float randomizationValue = 0;
160 switch (pType)
161 {
162 case DAMAGE_TYPE_GLOBAL:
163 randomizationValue = Math.RandomFloatInclusive(RANDOM_THRESHOLD_HEALTH_LOW, RANDOM_THRESHOLD_HEALTH_HIGH);
164 break;
165 case DAMAGE_TYPE_LEGS:
166 randomizationValue = Math.RandomFloatInclusive(RANDOM_THRESHOLD_LEGS_LOW, RANDOM_THRESHOLD_LEGS_HIGH);
167 break;
168 case DAMAGE_TYPE_ATTACHMENTS:
169 randomizationValue = Math.RandomFloatInclusive(RANDOM_THRESHOLD_ATTACHMENTS_LOW, RANDOM_THRESHOLD_ATTACHMENTS_HIGH);
170 break;
171 }
172
173 return pValue + (randomizedSign * pValue * randomizationValue);
174 }
175
176 private void AttachBleedingToZonesByHeight(notnull PlayerBase pPlayer)
177 {
178 Math.Randomize(GetGame().GetTime());
179
180 int bleedingSelectionIndex;
181 BleedingSourcesManagerServer bleedingManager = pPlayer.GetBleedingManagerServer();
182 if (Math.RandomFloatInclusive(0.0, 1.0) <= m_FallDamageData.m_BleedingChanceCoef && m_FallDamageData.m_BleedingHandsCoef == 1.0 && pPlayer.FindAttachmentBySlotName("Gloves") == null)
183 {
184 bleedingSelectionIndex = Math.RandomInt(0, 2);
185 bleedingManager.AttemptAddBleedingSourceBySelection(BLEEDING_HANDS_SELECTIONS[bleedingSelectionIndex]);
186 }
187
188 if (Math.RandomFloatInclusive(0.0, 1.0) <= m_FallDamageData.m_BleedingChanceCoef && m_FallDamageData.m_BleedingFeetCoef == 1.0 && pPlayer.FindAttachmentBySlotName("Feet") == null)
189 {
190
191 bleedingSelectionIndex = Math.RandomInt(0, 2);
192 bleedingManager.AttemptAddBleedingSourceBySelection(BLEEDING_FEET_SELECTIONS[bleedingSelectionIndex]);
193 }
194 if (Math.RandomFloatInclusive(0.0, 1.0) <= m_FallDamageData.m_BleedingChanceLegsCoef && m_FallDamageData.m_BleedingLegsCoef == 1.0)
195 {
196
197 bleedingSelectionIndex = Math.RandomInt(0, 2);
198 bleedingManager.AttemptAddBleedingSourceBySelection(BLEEDING_LEGS_SELECTIONS[bleedingSelectionIndex]);
199 }
200 }
201
202 private void DamageAttachedGear(notnull PlayerBase pPlayer)
203 {
204 EntityAI gloves = pPlayer.FindAttachmentBySlotName("Gloves");
205 if (gloves)
206 gloves.ProcessDirectDamage(DamageType.CUSTOM, pPlayer, "", FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS, gloves.WorldToModel(gloves.GetPosition()), m_FallDamageData.m_GlovesHealthCoef);
207
208 EntityAI shoes = pPlayer.FindAttachmentBySlotName("Feet");
209 if (shoes)
210 shoes.ProcessDirectDamage(DamageType.CUSTOM, pPlayer, "", FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS, shoes.WorldToModel(shoes.GetPosition()), m_FallDamageData.m_ShoesHealthCoef);
211
212 EntityAI pants = pPlayer.FindAttachmentBySlotName("Legs");
213 if (pants)
214 pants.ProcessDirectDamage(DamageType.CUSTOM, pPlayer, "", FALL_DAMAGE_AMMO_HEALTH_ATTACHMENT, pants.WorldToModel(pants.GetPosition()), m_FallDamageData.m_PantsHealthCoef);
215 }
216
217#ifdef DIAG_DEVELOPER
218 FallDamageDebugData GetFallDamageDebugData()
219 {
220 FallDamageDebugData data = new FallDamageDebugData();
221 data.Synch(this);
222
223 return data;
224 }
225
226 void ShowFallDamageDebugInfo(bool enabled)
227 {
228 FallDamageDebugData data = GetFallDamageDebugData();
229 DisplayFallDamageDebugInfo(enabled, data);
230 }
231
232 private static string LandTypeToString(int landType)
233 {
234 switch (landType)
235 {
236 case 1:
237 return "LIGHT";
238 case 2:
239 return "MEDIUM";
240 case 3:
241 return "HEAVY";
242 }
243
244 return "NONE";
245 }
246
247 private void PreloadAmmoTypeData()
248 {
249 if (m_AmmoTypeData == null)
250 m_AmmoTypeData = new map<string, float>();
251
252 m_AmmoTypeData.Insert(FALL_DAMAGE_AMMO_HEALTH, GetValuesFromAmmoType(FALL_DAMAGE_AMMO_HEALTH)[0]);
253 m_AmmoTypeData.Insert(FALL_DAMAGE_AMMO_SHOCK, GetValuesFromAmmoType(FALL_DAMAGE_AMMO_SHOCK)[2]);
254 m_AmmoTypeData.Insert(FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS, GetValuesFromAmmoType(FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS)[0]);
255 m_AmmoTypeData.Insert(FALL_DAMAGE_AMMO_HEALTH_ATTACHMENT, GetValuesFromAmmoType(FALL_DAMAGE_AMMO_HEALTH_ATTACHMENT)[0]);
256 }
257
258 private vector GetValuesFromAmmoType(string pAmmoType)
259 {
260 vector values = vector.Zero;
261 values[0] = GetGame().ConfigGetFloat(string.Format("CfgAmmo %1 DamageApplied Health damage", pAmmoType));
262 values[1] = GetGame().ConfigGetFloat(string.Format("CfgAmmo %1 DamageApplied Blood damage", pAmmoType));
263 values[2] = GetGame().ConfigGetFloat(string.Format("CfgAmmo %1 DamageApplied Shock damage", pAmmoType));
264
265 return values;
266 }
267
268 static void DisplayFallDamageDebugInfo(bool enabled, FallDamageDebugData data)
269 {
270 int windowPosX = 10;
271 int windowPosY = 200;
272
273 DbgUI.Begin("Fall Damage (last)", windowPosX, windowPosY);
274 if (enabled)
275 {
276 DbgUI.Text(string.Format("Height:\t%1", Math.Clamp(data.m_Height, 0, float.MAX)));
277 DbgUI.Text(string.Format("Land Type:\t%1 (%2)", data.m_LandType, LandTypeToString(data.m_LandType)));
278 DbgUI.Text("");
279 DbgUI.Text("Health");
280 DbgUI.Text(string.Format(" coef:%1 dmg:%2", data.m_HealthCoef, m_AmmoTypeData[FALL_DAMAGE_AMMO_HEALTH] * data.m_HealthCoef));
281 DbgUI.Text("Shock");
282 DbgUI.Text(string.Format(" coef:%1 dmg:%2", data.m_ShockCoef, m_AmmoTypeData[FALL_DAMAGE_AMMO_SHOCK] * data.m_ShockCoef));
283 DbgUI.Text("Broken Legs:");
284 DbgUI.Text(string.Format(" coef:%1 dmg:%2", data.m_BrokenLegsCoef, BROKENLEGS_HEALTH_DAMAGE_MAX * data.m_BrokenLegsCoef));
285 DbgUI.Text("Gloves damage:");
286 DbgUI.Text(string.Format(" coef:%1 dmg:%2", data.m_GlovesHealthCoef, m_AmmoTypeData[FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS] * data.m_GlovesHealthCoef));
287 DbgUI.Text("Shoes damage:");
288 DbgUI.Text(string.Format(" coef:%1 dmg:%2", data.m_ShoesHealthCoef, m_AmmoTypeData[FALL_DAMAGE_AMMO_HEALTH_OTHER_ATTACHMENTS] * data.m_ShoesHealthCoef));
289 DbgUI.Text("Pants damage:");
290 DbgUI.Text(string.Format(" coef:%1 dmg:%2" , data.m_PantsHealthCoef, m_AmmoTypeData[FALL_DAMAGE_AMMO_HEALTH_ATTACHMENT] * data.m_PantsHealthCoef));
291 DbgUI.Text("Bleeding coefs:");
292 DbgUI.Text(string.Format(" hands:%1", data.m_BleedingHandsCoef));
293 DbgUI.Text(string.Format(" feet:%1", data.m_BleedingFeetCoef));
294 DbgUI.Text(string.Format(" legs:%1", data.m_BleedingLegsCoef));
295 DbgUI.Text(string.Format(" H&F chance:%1", data.m_BleedingChanceCoef));
296
297
298 }
299 DbgUI.End();
300 }
301
302 void FillDebugFallDamageData(FallDamageDebugData data)
303 {
304 data.m_Height = m_FallDamageData.m_Height;
305 data.m_LandType = m_FallDamageData.m_LandType;
306 data.m_HealthCoef = m_FallDamageData.m_HealthCoef;
307 data.m_ShockCoef = m_FallDamageData.m_ShockCoef;
308 data.m_BrokenLegsCoef = m_FallDamageData.m_BrokenLegsCoef;
309 data.m_GlovesHealthCoef = m_FallDamageData.m_GlovesHealthCoef;
310 data.m_ShoesHealthCoef = m_FallDamageData.m_ShoesHealthCoef;
311 data.m_PantsHealthCoef = m_FallDamageData.m_PantsHealthCoef;
312
313 data.m_BleedingHandsCoef = m_FallDamageData.m_BleedingHandsCoef;
314 data.m_BleedingFeetCoef = m_FallDamageData.m_BleedingFeetCoef;
315 data.m_BleedingLegsCoef = m_FallDamageData.m_BleedingLegsCoef;
316 data.m_BleedingChanceCoef = m_FallDamageData.m_BleedingChanceCoef;
317 }
318#endif
319
323 const string FD_AMMO = "FallDamage";
324 const float FD_DMG_FROM_HEIGHT = 2.5;
325 const float FD_MAX_DMG_AT_HEIGHT = 15;
326 const float FD_MAX_HEIGHT_LEG_BREAK = 8;
327
328 void HandleFallDamage(float pHeight);
329 float DamageCoef(float pHeight);
330}
331
332#ifdef DIAG_DEVELOPER
333class FallDamageDebugData : Param
334{
335 int m_LandType;
336 float m_Height;
337 float m_HealthCoef;
338 float m_ShockCoef;
339 float m_BrokenLegsCoef;
340 float m_GlovesHealthCoef;
341 float m_ShoesHealthCoef;
342 float m_PantsHealthCoef;
343 float m_BleedingHandsCoef;
344 float m_BleedingFeetCoef;
345 float m_BleedingLegsCoef;
346 float m_BleedingChanceCoef;
347
348 void Synch(DayZPlayerImplementFallDamage fallDamage)
349 {
350 m_Height = fallDamage.GetHeight();
351 m_LandType = fallDamage.GetLandType();
352
353 fallDamage.FillDebugFallDamageData(this);
354 }
355
356 override bool Serialize(Serializer ctx)
357 {
358 return ctx.Write(m_Height) && ctx.Write(m_LandType) && ctx.Write(m_HealthCoef) && ctx.Write(m_ShockCoef) && ctx.Write(m_BrokenLegsCoef) && ctx.Write(m_GlovesHealthCoef) && ctx.Write(m_ShoesHealthCoef) && ctx.Write(m_PantsHealthCoef) && ctx.Write(m_BleedingHandsCoef) && ctx.Write(m_BleedingFeetCoef) && ctx.Write(m_BleedingLegsCoef);
359 }
360
361 override bool Deserializer(Serializer ctx)
362 {
363 return ctx.Read(m_Height) && ctx.Read(m_LandType) && ctx.Read(m_HealthCoef) && ctx.Read(m_ShockCoef) && ctx.Write(m_BrokenLegsCoef) && ctx.Read(m_GlovesHealthCoef) && ctx.Read(m_ShoesHealthCoef) && ctx.Read(m_PantsHealthCoef) && ctx.Read(m_BleedingHandsCoef) && ctx.Read(m_BleedingFeetCoef) && ctx.Read(m_BleedingLegsCoef);
364 }
365}
366#endif
void Serialize()
Definition inventory.c:201
Definition dbgui.c:60
Definition enmath.c:7
Base Param Class with no parameters. Used as general purpose parameter overloaded with Param1 to Para...
Definition param.c:12
Serialization general interface. Serializer API works with:
Definition serializer.c:56
DamageType
exposed from C++ (do not change)
class FallDamageData FALL_DAMAGE_AMMO_HEALTH
const float HEALTH_HEIGHT_LOW
const float HEALTH_HEIGHT_HIGH
proto native CGame GetGame()
DayZPlayer m_Player
Definition hand_events.c:42
float GetTime()
class PresenceNotifierNoiseEvents windowPosX
dbgUI settings
const int windowPosY
void Synch(EntityAI victim)
keeping "step" here for consistency only
Definition trapbase.c:281