Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
environment.c
Go to the documentation of this file.
1
9
10class EnvironmentSnapshotData
11{
14}
15
17{
18 bool m_UseTemperatureSources = false;
19 float m_TemperatureSourceDistance = 1.0;
20}
21
26class Environment
27{
28 const float RAIN_LIMIT_LOW = 0.05;
29
30 protected const float SNOWFALL_LIMIT_LOW = 0.5;
31 protected const float SNOWFALL_WIND_COMBINED_THRESHOLD = 1.3;
32
33 const float WATER_LEVEL_HIGH = 1.5;
34 const float WATER_LEVEL_MID = 1.2;
35 const float WATER_LEVEL_LOW = 0.5;
36 const float WATER_LEVEL_NONE = 0.15;
37
38 protected float m_WetDryTick; //ticks passed since last clothing wetting or drying
39 protected float m_ItemsWetnessMax;
40 protected float m_RoofCheckTimer; // keeps info about tick time
41
42 //player
44 protected float m_PlayerHeightPos; // y position of player above water level (meters)
45 protected float m_PlayerSpeed; // 1-3 speed of player movement
46 protected float m_PlayerTemperature; //34-44
47 protected float m_PlayerHeat; //3-9 heatcomfort generated by entites movement
48 protected float m_HeatComfort;
49 protected float m_TargetHeatComfort;
50
51 //environment
52 protected float m_Rain = 0; // 0-1 amount of rain
53 protected float m_Snowfall = 0; // 0-1 amount of rain
54 protected float m_Wind = 0; // strength of wind
55 protected float m_Fog = 0; // 0-1 how foggy it is
56 protected float m_DayOrNight = 0; // 0-1 day(0) or night(1)
57 protected float m_Clouds = 0; // 0-1 how cloudy it is
58 protected float m_EnvironmentTemperature; //temperature of environment player is in
59 protected float m_Time = 0;
60 protected string m_SurfaceType;
61 protected int m_LiquidType;
62
63 //item temperatures
64 protected float m_ItemTemperatureCoef;
65
66 //
67 protected float m_WaterLevel;
68 protected bool m_IsUnderRoof;
69 private bool m_IsUnderRoofBuilding;
70 protected bool m_IsInWater;
71 protected bool m_IsTempSet;
72 //
73 protected float m_HeatBufferTimer;
74 protected float m_HeatBufferCapPrevious;
75
80
81 protected ref array<int> m_HeadParts;
82 protected ref array<int> m_BodyParts;
83 protected ref array<int> m_FeetParts;
84
86
88 protected float m_UTSAverageTemperature;
90 protected ref SimpleMovingAverage<float> m_UTSAverageTemperatureBuffer;
91 protected ref SimpleMovingAverage<float> m_AverageHeatComfortBuffer;
92
94
95 private bool m_Initialized;
96
97 #ifdef DIAG_DEVELOPER
98 bool m_Debug = false;
99 #endif
100
101 #ifdef ENABLE_LOGGING
102 bool m_DebugLogDryWet = false;
103 bool m_DebugLogItemHeat = false;
104 #endif
105
106 void Environment(PlayerBase pPlayer)
107 {
108 m_Player = pPlayer;
109 }
110
111 void Init()
112 {
113 m_PlayerSpeed = 0.0;
114 m_WetDryTick = 0.0;
115 m_RoofCheckTimer = 0.0;
116 m_WaterLevel = 0.0;
117 m_HeatComfort = m_Player.GetStatHeatComfort().Get();
118 m_WorldData = g_Game.GetMission().GetWorldData();
120
121 m_IsUnderRoof = false;
122 m_IsInWater = false;
123 m_SurfaceType = "cp_dirt";
124
125 m_HeatBufferTimer = 0.0;
126
129 m_UTSAverageTemperatureBuffer = new SimpleMovingAverage<float>(10, 0.0);
130 m_AverageHeatComfortBuffer = new SimpleMovingAverage<float>(20, m_HeatComfort);
131
135 InventorySlots.HEADGEAR,
136 InventorySlots.MASK,
137 InventorySlots.EYEWEAR,
138 InventorySlots.GLOVES,
139 InventorySlots.ARMBAND,
140 InventorySlots.BODY,
141 InventorySlots.HIPS,
142 InventorySlots.VEST,
143 InventorySlots.BACK,
144 InventorySlots.LEGS,
145 InventorySlots.FEET
146 };
150 InventorySlots.GLOVES,
151 InventorySlots.ARMBAND,
152 InventorySlots.BODY,
153 InventorySlots.HIPS,
154 InventorySlots.VEST,
155 InventorySlots.BACK,
156 InventorySlots.LEGS,
157 InventorySlots.FEET
158 };
162 InventorySlots.HIPS,
163 InventorySlots.LEGS,
164 InventorySlots.FEET
165 };
169 InventorySlots.FEET,
170 };
171
174 m_HeadParts = new array<int>();
175 m_HeadParts = {
176 InventorySlots.HEADGEAR,
177 InventorySlots.MASK,
178 };
179
180 m_BodyParts = new array<int>();
181 m_BodyParts = {
182 InventorySlots.GLOVES,
183 InventorySlots.HIPS,
184 InventorySlots.BODY,
185 InventorySlots.BACK,
186 InventorySlots.VEST,
187 InventorySlots.MELEE,
188 InventorySlots.SHOULDER
189 };
190
191 m_FeetParts = new array<int>();
192 m_FeetParts = {
193 InventorySlots.LEGS,
194 InventorySlots.FEET,
195 };
196
198 m_EnvironmentSnapshot = new EnvironmentSnapshotData();
199
200 m_Initialized = true;
201 }
202
203 // --------------------------------------------------------------------------------
204
208 void Update(float pDelta)
209 {
210 if (m_Player && m_Initialized)
211 {
212 m_RoofCheckTimer += pDelta;
214 if ( m_RoofCheckTimer >= GameConstants.ENVIRO_TICK_ROOF_RC_CHECK )
215 {
216 if ( !IsInsideBuilding() )
218
220 }
221
222 m_Time += pDelta;
223 if (m_Time >= GameConstants.ENVIRO_TICK_RATE)
224 {
225 m_Time = 0;
226 m_WetDryTick++; // Sets whether it is time to add wetness to items and clothing
227
232
235
241
245 else
247
249 if (m_WetDryTick >= GameConstants.ENVIRO_TICKS_TO_WETNESS_CALCULATION)
250 {
251 if (IsWaterContact())
252 {
254 }
255 else if ((IsRaining() || (IsSnowing() && MiscGameplayFunctions.GetCombinedSnowfallWindValue() > SNOWFALL_WIND_COMBINED_THRESHOLD)) && !IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}))
256 {
258 }
259 else
260 {
262 }
263
265 if ((m_ItemsWetnessMax < GameConstants.STATE_WET) && (m_Player.GetStatWet().Get() == 1))
266 {
267 m_Player.GetStatWet().Set(0);
268 }
269 else if ((m_ItemsWetnessMax >= GameConstants.STATE_WET) && (m_Player.GetStatWet().Get() == 0))
270 {
271 m_Player.GetStatWet().Set(1);
272 }
273
274 m_WetDryTick = 0;
276 }
277 }
278 }
279 }
280
281 // --------------------------------------------------------------------------------
282
286 bool IsTemperatureSet()
287 {
288 return m_IsTempSet;
289 }
290
295 protected float GetPlayerHeat()
296 {
297 float heat = m_PlayerSpeed * GameConstants.ENVIRO_DEFAULT_ENTITY_HEAT;
298 return heat;
299 }
300
306 {
307 return m_IsUnderRoof;
308 }
309
314 {
315 return m_Player.IsSoundInsideBuilding();
316 }
317
321 protected bool IsWaterContact()
322 {
323 return m_IsInWater;
324 }
325
330 private bool IsChildOfType(array<typename> typenames)
331 {
332 Object parent = Object.Cast(m_Player.GetParent());
333 if (parent)
334 return parent.IsAnyInherited(typenames);
335
336 return false;
337 }
338
343 private bool IsUnderRoofBuilding()
344 {
345 return m_IsUnderRoofBuilding;
346 }
347
351 protected bool IsRaining()
352 {
353 return m_Rain > RAIN_LIMIT_LOW;
354 }
355
359 protected bool IsSnowing()
360 {
362 }
363
370 {
371 if (IsChildOfType({Car}))
372 {
373 CarScript car = CarScript.Cast(m_Player.GetParent());
374 if (car && car.EngineIsOn())
375 {
377 return true;
378 }
379 }
380
382
383 return false;
384 }
385
386 // --------------------------------------------------------------------------------
387
391 protected void CheckUnderRoof()
392 {
394 if (IsChildOfType({Car}))
395 {
396 m_IsUnderRoof = false;
397 m_IsUnderRoofBuilding = false;
398 return;
399 }
400
401 float hitFraction;
402 vector hitPosition, hitNormal;
403 vector from = m_Player.GetPosition();
404 vector to = from + "0 25 0";
405 Object hitObject;
406 PhxInteractionLayers collisionLayerMask = PhxInteractionLayers.ITEM_LARGE|PhxInteractionLayers.BUILDING|PhxInteractionLayers.VEHICLE;
407
408 m_IsUnderRoof = DayZPhysics.RayCastBullet(from, to, collisionLayerMask, null, hitObject, hitPosition, hitNormal, hitFraction);
409
410 m_IsUnderRoofBuilding = hitObject && hitObject.IsInherited(House);
411 }
412
413 // --------------------------------------------------------------------------------
414
421 protected void CheckWaterContact(out float pWaterLevel)
422 {
423 string surfType;
424 int liquidType;
425
426 m_IsInWater = false;
427
428 if (m_Player.PhysicsGetLinkedEntity() || IsChildOfType({Transport}))
429 return;
430
431 if (m_Player.IsSwimming())
432 {
433 g_Game.SurfaceUnderObjectByBoneCorrectedLiquid(m_Player, SurfaceAnimationBone.RightFrontLimb, surfType, liquidType);
434 m_SurfaceType = surfType;
435 m_LiquidType = liquidType;
436
437 m_IsInWater = true;
438 m_Player.SetInWater(m_IsInWater);
439
440 HumanMovementState hms = new HumanMovementState();
441 m_Player.GetMovementState(hms);
442
443 pWaterLevel = WATER_LEVEL_MID;
444 if (hms.m_iMovement >= DayZPlayerConstants.MOVEMENTIDX_WALK)
445 pWaterLevel = WATER_LEVEL_HIGH;
446
447 return;
448 }
449
451 if (IsUnderRoofBuilding())
452 {
453 m_IsInWater = false;
454 return;
455 }
456
457 string impact;
458 g_Game.SurfaceUnderObjectExCorrectedLiquid(m_Player, surfType, impact, liquidType);
459
460 switch (liquidType)
461 {
462 case LIQUID_SALTWATER:
463 case LIQUID_WATER:
467 case LIQUID_HOTWATER:
468 pWaterLevel = m_Player.GetCurrentWaterLevel();
469 m_IsInWater = true;
470 break;
471 }
472
474 m_Player.SetInWater(m_IsInWater);
475
477 m_SurfaceType = surfType;
478 m_LiquidType = liquidType;
479
480 }
481
482 // --------------------------------------------------------------------------------
483
490 {
491 if (IsUnderRoofBuilding())
492 return 0.0;
493
494 return g_Game.ConfigGetFloat("CfgSurfaces " + m_SurfaceType + " windModifier");
495 }
496
498 {
500 }
501
503 {
504 return m_TargetHeatComfort;
505 }
506
507 // --------------------------------------------------------------------------------
508
518 {
520
521 if (IsWaterContact())
522 {
523 float waterBodyTemperature = m_WorldData.GetLiquidTypeEnviroTemperature(m_LiquidType);
524 temperature = waterBodyTemperature - m_WorldData.m_WaterContactTemperatureModifier;
525
526 return temperature;
527 }
528
529 if (IsInsideBuilding() || m_IsUnderRoofBuilding)
530 {
531 temperature += m_WorldData.m_TemperatureInsideBuildingsModifier;
532 }
533 else if (IsChildOfType({Car}))
534 {
535 temperature += Math.AbsFloat(temperature * GameConstants.ENVIRO_TEMPERATURE_INSIDE_VEHICLE_COEF);
536 return temperature;
537 }
538 else if (IsUnderRoof() && !m_IsUnderRoofBuilding)
539 {
541 temperature += WindEffectTemperatureValue(temperature) * GetWindModifierPerSurface() * GameConstants.ENVIRO_TEMPERATURE_UNDERROOF_COEF;
542 }
543 else
544 {
547 }
548
549 // incorporate temperature from temperature sources (buffer)
550 if (Math.AbsFloat(m_UTSAverageTemperature) > 0.0 && m_UTSAverageTemperature > temperature)
551 temperature = m_UTSAverageTemperature;
552
553 return temperature;
554 }
555
556 // --------------------------------------------------------------------------------
557
564 {
565 float wetDelta = 0;
566 if ( IsWaterContact() )
567 {
570 {
571 wetDelta = 1;
572 }
574 {
575 wetDelta = 0.66;
576 }
578 {
579 wetDelta = 0.66;
580 }
582 {
583 wetDelta = 0.33;
584 }
585 }
586 else if (!IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}))
587 {
588 if (IsRaining())
589 wetDelta = GameConstants.ENVIRO_WET_INCREMENT * GameConstants.ENVIRO_TICKS_TO_WETNESS_CALCULATION * (m_Rain) * (1 + (GameConstants.ENVIRO_WIND_EFFECT * m_Wind));
590
591 if (IsSnowing() && MiscGameplayFunctions.GetCombinedSnowfallWindValue() > SNOWFALL_WIND_COMBINED_THRESHOLD)
592 wetDelta = GameConstants.ENVIRO_WET_INCREMENT * GameConstants.ENVIRO_TICKS_TO_WETNESS_CALCULATION * (m_Snowfall - SNOWFALL_LIMIT_LOW) * GameConstants.ENVIRO_SNOW_WET_COEF * (1 + (GameConstants.ENVIRO_WIND_EFFECT * m_Wind));
593 }
594 else
595 {
597 float tempEffect = Math.Max(m_PlayerHeat + GetEnvironmentTemperature(), 1.0);
598
599 float weatherEffect = ((1 - (m_Fog * GameConstants.ENVIRO_FOG_DRY_EFFECT))) * (1 - (m_Clouds * GameConstants.ENVIRO_CLOUD_DRY_EFFECT));
600 if (weatherEffect <= 0)
601 {
602 weatherEffect = 1.0;
603 }
604
605 wetDelta = -(GameConstants.ENVIRO_DRY_INCREMENT * weatherEffect * tempEffect);
606 if (!IsInsideBuilding())
607 {
608 wetDelta *= 1 + (GameConstants.ENVIRO_WIND_EFFECT * m_Wind);
609 }
610 }
611
612 return wetDelta;
613 }
614
615 // --------------------------------------------------------------------------------
616
623 protected void CollectAndSetPlayerData()
624 {
625 vector playerPos = m_Player.GetPosition();
626 m_PlayerHeightPos = playerPos[1];
627
628 HumanCommandMove hcm = m_Player.GetCommand_Move();
629 if (hcm)
630 {
631 m_PlayerSpeed = hcm.GetCurrentMovementSpeed();
632 }
633
635 }
636
637 // Each tick updates current environment member variables
642 {
643 Weather weather = g_Game.GetWeather();
644 m_Rain = weather.GetRain().GetActual();
645 m_Snowfall = weather.GetSnowfall().GetActual();
646 m_DayOrNight = g_Game.GetMission().GetWorldData().GetDaytime();
647 m_Fog = weather.GetFog().GetActual();
648 m_Clouds = weather.GetOvercast().GetActual();
649 m_Wind = weather.GetWindMagnitude().GetActual();
650
653 }
654
655 // --------------------------------------------------------------------------------
656
662
667 {
668 float heigthCorrectedTemp = m_WorldData.GetBaseEnvTemperatureAtObject(m_Player);
669 m_Player.SetInColdArea(heigthCorrectedTemp <= GameConstants.COLD_AREA_TEMPERATURE_THRESHOLD);
670 }
671
676 protected void ProcessWetnessByWaterLevel(float pWaterLevel)
677 {
678 if (pWaterLevel >= WATER_LEVEL_HIGH)
680 else if (pWaterLevel >= WATER_LEVEL_MID && pWaterLevel < WATER_LEVEL_HIGH)
682 else if (pWaterLevel >= WATER_LEVEL_LOW && pWaterLevel < WATER_LEVEL_MID)
684 else if (pWaterLevel >= WATER_LEVEL_NONE && pWaterLevel < WATER_LEVEL_LOW)
686 }
687
688 // --------------------------------------------------------------------------------
689
694 protected void ProcessItemsWetness(array<int> pSlotIds)
695 {
696 EntityAI attachment;
697
698 int playerAttachmentCount = m_Player.GetInventory().AttachmentCount();
699
700 #ifdef ENABLE_LOGGING
701 LogDryWetProcess(string.Format("Environment :: ProcessItemsWetness (update interval=%1s)", GameConstants.ENVIRO_TICK_RATE));
702 #endif
703 for (int attIdx = 0; attIdx < playerAttachmentCount; ++attIdx)
704 {
705 attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
706 if (attachment.IsItemBase())
707 {
708 int attachmentSlotsCount = attachment.GetInventory().GetSlotIdCount();
709 for (int attachmentSlotId = 0; attachmentSlotId < attachmentSlotsCount; ++attachmentSlotId)
710 {
711 int attachmentSlot = attachment.GetInventory().GetSlotId(attachmentSlotId);
712 for (int i = 0; i < pSlotIds.Count(); ++i)
713 {
714 if (attachmentSlot == pSlotIds.Get(i))
715 {
716 ApplyWetnessToItem(ItemBase.Cast(attachment));
717 break;
718 }
719 }
720 }
721 }
722 }
723
724 if (m_Player.GetItemInHands())
725 ApplyWetnessToItem(m_Player.GetItemInHands());
726
727 #ifdef ENABLE_LOGGING
728 LogDryWetProcess("==========");
729 #endif
730 }
731
732 protected void ApplyWetnessToItem(ItemBase pItem)
733 {
734 if (pItem)
735 {
736 ItemBase parentItem;
737 bool isParentWet = false;
738 bool parentContainsLiquid = false;
740
741 if (pItem.GetInventory().GetCurrentInventoryLocation(iLoc))
742 {
743 EntityAI parent = iLoc.GetParent();
744 if (parent)
745 {
746 parentItem = ItemBase.Cast(parent);
747 if (parentItem)
748 {
749 if (parentItem.GetWet() >= GameConstants.STATE_SOAKING_WET)
750 isParentWet = true;
751
752 if ((parentItem.GetLiquidType() != 0) && (parentItem.GetQuantity() > 0))
753 parentContainsLiquid = true;
754 }
755 else
756 isParentWet = true;
757
758 if ((pItem.GetWet() > m_ItemsWetnessMax) && (parent == m_Player))
759 m_ItemsWetnessMax = pItem.GetWet();
760 }
761 }
762
763 if (isParentWet || parentContainsLiquid)
764 {
765 float soakingCoef = 0;
766 if (parentContainsLiquid)
767 {
768 soakingCoef = pItem.GetSoakingIncrement("parentWithLiquid");
769 #ifdef ENABLE_LOGGING
770 LogDryWetProcess(string.Format("%1 (soak coef=%2/s, current wetness=%3) [parent contains liquid]", pItem.GetDisplayName(), soakingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
771 #endif
772 }
773 else if (isParentWet && parentItem)
774 {
775 if (pItem.GetWet() < parentItem.GetWet())
776 soakingCoef = GetWetDelta();
777
778 #ifdef ENABLE_LOGGING
779 LogDryWetProcess(string.Format("%1 (soak coef=%2/s, current wetness=%3) [parent wet]", pItem.GetDisplayName(), soakingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
780 #endif
781 }
782 else
783 {
784 soakingCoef = GetWetDelta();
785 #ifdef ENABLE_LOGGING
786 LogDryWetProcess(string.Format("%1 (soak coef=%2/s, current wetness=%3) [normal]", pItem.GetDisplayName(), soakingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
787 #endif
788 }
789
790 pItem.AddWet(soakingCoef);
791
792 if (pItem.GetInventory().GetCargo())
793 {
794 int inItemCount = pItem.GetInventory().GetCargo().GetItemCount();
795 for (int i = 0; i < inItemCount; ++i)
796 {
797 ItemBase inItem;
798 if (Class.CastTo(inItem, pItem.GetInventory().GetCargo().GetItem(i)))
799 ApplyWetnessToItem(inItem);
800 }
801 }
802
803 int attCount = pItem.GetInventory().AttachmentCount();
804 if (attCount > 0)
805 {
806 for (int attIdx = 0; attIdx < attCount; ++attIdx)
807 {
808 EntityAI attachment = pItem.GetInventory().GetAttachmentFromIndex(attIdx);
809 ItemBase itemAtt = ItemBase.Cast(attachment);
810 if (itemAtt)
811 ApplyWetnessToItem(itemAtt);
812 }
813 }
814 }
815 }
816 }
817 // --------------------------------------------------------------------------------
818
822 protected void ProcessItemsDryness()
823 {
824 EntityAI attachment;
825 ItemBase item;
826
827 int attCount = m_Player.GetInventory().AttachmentCount();
828
829 #ifdef ENABLE_LOGGING
830 LogDryWetProcess(string.Format("Environment :: ProcessItemsDryness (update interval=%1s)", GameConstants.ENVIRO_TICK_RATE));
831 #endif
833 drynessData.m_UseTemperatureSources = m_HasTemperatureSources;
834
836 {
837 float distance = vector.Distance(m_UTemperatureSources[0].GetPosition(), m_Player.GetPosition());
838 distance = Math.Max(distance, 0.1);
839 drynessData.m_TemperatureSourceDistance = distance;
840 #ifdef ENABLE_LOGGING
841 LogDryWetProcess(string.Format("distance to heatsource: %1 m", distance));
842 #endif
843 }
844
845 for (int attIdx = 0; attIdx < attCount; ++attIdx)
846 {
847 attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
848 if (attachment && attachment.IsItemBase())
849 {
850 item = ItemBase.Cast(attachment);
851 if (item)
852 ApplyDrynessToItemEx(item, drynessData);
853 }
854 }
855
856 if (m_Player.GetItemInHands())
857 {
858 ApplyDrynessToItemEx(m_Player.GetItemInHands(), drynessData);
859 }
860
861 #ifdef ENABLE_LOGGING
862 LogDryWetProcess("==========");
863 #endif
864 }
865
866 protected void ApplyDrynessToItem(ItemBase pItem)
867 {
869 ApplyDrynessToItemEx(pItem, drynessData);
870 }
871
872 protected void ApplyDrynessToItemEx(ItemBase pItem, EnvironmentDrynessData pDrynessData)
873 {
874 if (pItem)
875 {
876 float dryingIncrement = pItem.GetDryingIncrement("player");
877 if (pDrynessData.m_UseTemperatureSources)
878 dryingIncrement = pItem.GetDryingIncrement("playerHeatSource");
879
880 ItemBase parentItem;
881 bool isParentWet = false;
882 bool parentContainsLiquid = false;
883
885 if (pItem.GetInventory().GetCurrentInventoryLocation(iLoc))
886 {
887 EntityAI parent = iLoc.GetParent();
888 if (parent)
889 {
890 parentItem = ItemBase.Cast(parent);
891 if (parentItem)
892 {
893 if (parentItem.GetWet() >= GameConstants.STATE_SOAKING_WET)
894 isParentWet = true;
895
896 if ((parentItem.GetLiquidType() != 0) && (parentItem.GetQuantity() > 0))
897 parentContainsLiquid = true;
898 }
899
900 if ((pItem.GetWet() > m_ItemsWetnessMax) && (parent == m_Player))
901 m_ItemsWetnessMax = pItem.GetWet();
902 }
903 }
904
905 float dryingCoef = 0;
906
907 if (!isParentWet && !parentContainsLiquid)
908 {
909
910 dryingCoef = (-1 * GameConstants.ENVIRO_TICK_RATE * dryingIncrement) / pDrynessData.m_TemperatureSourceDistance;
911 if (pItem.GetWet() >= GameConstants.STATE_DAMP)
912 {
913 #ifdef ENABLE_LOGGING
914 LogDryWetProcess(string.Format("%1 (dry coef=%2/s, current wetness=%3) [normal]", pItem.GetDisplayName(), dryingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
915 #endif
916 pItem.AddWet(dryingCoef);
917 }
918
919 if (pItem.GetInventory().GetCargo())
920 {
921 int inItemCount = pItem.GetInventory().GetCargo().GetItemCount();
922 for (int i = 0; i < inItemCount; ++i)
923 {
924 ItemBase inItem;
925 if (Class.CastTo(inItem, pItem.GetInventory().GetCargo().GetItem(i)))
926 ApplyDrynessToItemEx(inItem, pDrynessData);
927 }
928 }
929
930 int attCount = pItem.GetInventory().AttachmentCount();
931 if (attCount > 0)
932 {
933 for (int attIdx = 0; attIdx < attCount; ++attIdx)
934 {
935 EntityAI attachment = pItem.GetInventory().GetAttachmentFromIndex(attIdx);
936 ItemBase itemAtt;
937 if (ItemBase.CastTo(itemAtt, attachment))
938 ApplyDrynessToItemEx(itemAtt, pDrynessData);
939 }
940 }
941 }
942
943 if (parentContainsLiquid)
944 {
946 dryingCoef = (GameConstants.ENVIRO_TICK_RATE * pItem.GetSoakingIncrement("parentWithLiquid")) / pDrynessData.m_TemperatureSourceDistance;
947 #ifdef ENABLE_LOGGING
948 LogDryWetProcess(string.Format("%1 (dry coef=%2/s, current wetness=%3) [parent contains liquid]", pItem.GetDisplayName(), dryingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
949 #endif
950 pItem.AddWet(dryingCoef);
951 }
952
953 if (isParentWet)
954 {
956 dryingCoef = (GameConstants.ENVIRO_TICK_RATE * pItem.GetSoakingIncrement("wetParent")) / pDrynessData.m_TemperatureSourceDistance;
957 #ifdef ENABLE_LOGGING
958 LogDryWetProcess(string.Format("%1 (dry coef=%2/s, current wetness=%3) [parent wet]", pItem.GetDisplayName(), dryingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
959 #endif
960 pItem.AddWet(dryingCoef);
961 }
962 }
963 }
964
965 // --------------------------------------------------------------------------------
966
970 protected void ProcessHeatComfort()
971 {
972 float hcPenaltyTotal
973
974 // NEW body parts => splitted
975 float hcBodyPartTotal, hcBodyPart;
976 float hBodyPartTotal, hBodyPart;
977
978 float heatComfortSum = 0.0;
979 float heatItems = 0.0;
980
981 #ifdef ENABLE_LOGGING
982 LogItemHeat("====================");
983 #endif
984 BodyPartHeatProperties(InventorySlots.HEADGEAR, GameConstants.ENVIRO_HEATCOMFORT_HEADGEAR_WEIGHT, hcBodyPart, hBodyPart);
985 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
986 BodyPartHeatProperties(InventorySlots.MASK, GameConstants.ENVIRO_HEATCOMFORT_MASK_WEIGHT, hcBodyPart, hBodyPart);
987 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
988 BodyPartHeatProperties(InventorySlots.VEST, GameConstants.ENVIRO_HEATCOMFORT_VEST_WEIGHT, hcBodyPart, hBodyPart);
989 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
990 BodyPartHeatProperties(InventorySlots.BODY, GameConstants.ENVIRO_HEATCOMFORT_BODY_WEIGHT, hcBodyPart, hBodyPart);
991 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
992 BodyPartHeatProperties(InventorySlots.BACK, GameConstants.ENVIRO_HEATCOMFORT_BACK_WEIGHT, hcBodyPart, hBodyPart);
993 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
994 BodyPartHeatProperties(InventorySlots.GLOVES, GameConstants.ENVIRO_HEATCOMFORT_GLOVES_WEIGHT, hcBodyPart, hBodyPart);
995 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
996 BodyPartHeatProperties(InventorySlots.LEGS, GameConstants.ENVIRO_HEATCOMFORT_LEGS_WEIGHT, hcBodyPart, hBodyPart);
997 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
998 BodyPartHeatProperties(InventorySlots.FEET, GameConstants.ENVIRO_HEATCOMFORT_FEET_WEIGHT, hcBodyPart, hBodyPart);
999 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
1000 BodyPartHeatProperties(InventorySlots.HIPS, GameConstants.ENVIRO_HEATCOMFORT_HIPS_WEIGHT, hcBodyPart, hBodyPart);
1001 hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
1002
1003 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.HEADGEAR, GameConstants.ENVIRO_HEATCOMFORT_HEADGEAR_WEIGHT);
1004 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.MASK, GameConstants.ENVIRO_HEATCOMFORT_MASK_WEIGHT);
1005 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.BODY, GameConstants.ENVIRO_HEATCOMFORT_BODY_WEIGHT);
1006 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.GLOVES, GameConstants.ENVIRO_HEATCOMFORT_GLOVES_WEIGHT);
1007 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.LEGS, GameConstants.ENVIRO_HEATCOMFORT_LEGS_WEIGHT);
1008 hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.FEET, GameConstants.ENVIRO_HEATCOMFORT_FEET_WEIGHT);
1009
1010 heatItems = hBodyPartTotal;
1011 heatComfortSum = hcBodyPartTotal;
1012 heatComfortSum += hcPenaltyTotal;
1013
1015 {
1016 if (m_Player.GetStomach().GetStomachVolume() > 0.0)
1017 {
1018 float stomachContentTemperature = m_Player.GetStomach().GetStomachTemperature();
1019 if (stomachContentTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT)
1020 {
1021 stomachContentTemperature = Math.Remap(
1022 -10.0,
1023 GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT,
1024 -GameConstants.ENVIRO_STOMACH_WEIGHT,
1025 0.0,
1026 stomachContentTemperature,
1027 );
1028 }
1029 else if (stomachContentTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1030 {
1031 stomachContentTemperature = Math.Remap(
1032 GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT,
1033 70.0,
1034 0.0,
1035 GameConstants.ENVIRO_STOMACH_WEIGHT,
1036 stomachContentTemperature,
1037 );
1038 }
1039 else
1040 stomachContentTemperature = 0.0;
1041
1042 heatComfortSum += stomachContentTemperature * GameConstants.ENVIRO_STOMACH_WEIGHT;
1043 }
1044 }
1045
1046 float targetHeatComfort = (heatComfortSum + heatItems + (GetPlayerHeat() / 100)) + EnvTempToCoef(m_EnvironmentTemperature);
1047
1049 m_EnvironmentSnapshot.m_ClothingHeatComfort = hcBodyPartTotal;
1050 m_EnvironmentSnapshot.m_TargetHeatComfort = targetHeatComfort;
1052
1053 if (m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
1054 targetHeatComfort = Math.Clamp(targetHeatComfort, 0.0, m_Player.GetStatHeatComfort().GetMax());
1055 else
1056 targetHeatComfort = Math.Clamp(targetHeatComfort, m_Player.GetStatHeatComfort().GetMin(), m_Player.GetStatHeatComfort().GetMax());
1057
1058 targetHeatComfort = Math.Round(targetHeatComfort * 100) * 0.01;
1059
1060 float dynamicHeatComfort;
1061
1062 {
1063 float direction = 1.0;
1064 if (targetHeatComfort < 0.0)
1065 direction = -1.0;
1066
1067 if (Math.AbsFloat(targetHeatComfort - m_HeatComfort) <= GameConstants.ENVIRO_HEATCOMFORT_MAX_STEP_SIZE)
1068 dynamicHeatComfort = m_AverageHeatComfortBuffer.Add(targetHeatComfort);
1069 else
1070 dynamicHeatComfort = m_AverageHeatComfortBuffer.Add((Math.AbsFloat(targetHeatComfort) - GameConstants.ENVIRO_HEATCOMFORT_MAX_STEP_SIZE) * direction);
1071 }
1072
1073 dynamicHeatComfort = Math.Round(dynamicHeatComfort * 100) * 0.01;
1074
1075 m_HeatComfort = dynamicHeatComfort;
1076
1077 SetTargetHeatComfort(targetHeatComfort);
1078 m_Player.GetStatHeatComfort().Set(m_HeatComfort);
1079 }
1080
1081 protected void SetTargetHeatComfort(float value)
1082 {
1083 m_TargetHeatComfort = value;
1084 }
1085
1086 protected void SetHeatcomfortDirectly()
1087 {
1089 {
1090 float targetHeatComfort = 0.0;
1091 float dynamicHeatComfort = m_AverageHeatComfortBuffer.Add(targetHeatComfort);
1092
1093 m_HeatComfort = dynamicHeatComfort;
1094
1096 m_Player.GetStatHeatComfort().Set(dynamicHeatComfort);
1097 }
1098 }
1099
1100 // --------------------------------------------------------------------------------
1101
1102 protected void ProcessHeatBuffer(EnvironmentSnapshotData data)
1103 {
1105 {
1106 float applicableHeatbuffer = GetApplicableHeatbuffer();
1107
1109 float heatBufferCap = Math.InverseLerp(0.0, GameConstants.ENVIRO_HEATCOMFORT_WEIGHT_SUMMARY, data.m_ClothingHeatComfort);
1110 float heatBufferMax = GameConstants.ENVIRO_PLAYER_HEATBUFFER_CAPACITY_MIN + heatBufferCap * (1 - GameConstants.ENVIRO_PLAYER_HEATBUFFER_CAPACITY_MIN);
1111 m_Player.SetHeatBufferDynamicMax(heatBufferMax);
1112
1113 PlayerStat<float> heatBuffer = m_Player.GetStatHeatBuffer();
1114
1116 if (heatBufferCap < m_HeatBufferCapPrevious)
1117 {
1118 float heatBufferValueCorrection = GameConstants.ENVIRO_PLAYER_HEATBUFFER_INCREASE / (heatBufferMax * ((-GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
1119 heatBuffer.Add(-heatBufferValueCorrection);
1120 m_HeatBufferCapPrevious = heatBufferCap;
1121 }
1122
1123 float increaseRate = 0.0;
1124 float decreaseRate = 0.0;
1125
1126 {
1127 increaseRate = GameConstants.ENVIRO_PLAYER_HEATBUFFER_INCREASE / (heatBufferMax * (( -GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
1128 decreaseRate = GameConstants.ENVIRO_PLAYER_HEATBUFFER_DECREASE / (heatBufferMax * (( GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
1129
1130 float decreaseRateByHeatBufferStageCoef = 1;
1131
1132 if (heatBufferMax > HeatBufferMdfr.STAGE_THRESHOLDS[1])
1133 {
1134 float heatBufferMaxInversed = Math.InverseLerp(HeatBufferMdfr.STAGE_THRESHOLDS[1], 1.0, heatBufferMax);
1135 switch (m_Player.GetHeatBufferStage())
1136 {
1137 case 2:
1138 decreaseRateByHeatBufferStageCoef = Math.Lerp(
1139 GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[2][0],
1140 GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[2][1],
1141 heatBufferMaxInversed,
1142 );
1143 break;
1144 case 1:
1145 decreaseRateByHeatBufferStageCoef = Math.Lerp(
1146 GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][0],
1147 GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][1],
1148 heatBufferMaxInversed,
1149 );
1150 break;
1151 }
1152 }
1153 else
1154 {
1155 decreaseRateByHeatBufferStageCoef = GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][0];
1156 }
1157
1158 decreaseRate *= decreaseRateByHeatBufferStageCoef;
1159
1160 if (m_IsInWater)
1161 decreaseRate *= GameConstants.ENVIRO_PLAYER_HEATBUFFER_WATEREFFECT * m_WaterLevel;
1162 }
1163
1165 {
1166 if (m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
1167 {
1168 if (m_HeatBufferTimer >= 1.0)
1169 heatBuffer.Add(-decreaseRate);
1170 else
1171 m_HeatBufferTimer = 1.0;
1172 }
1173 else
1174 {
1175 m_HeatBufferTimer = 0.0;
1176 if (applicableHeatbuffer > 0.0)
1177 heatBuffer.Add(-decreaseRate);
1178 else if (applicableHeatbuffer != 0.0 && !m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
1179 heatBuffer.Set(0.0);
1180 }
1181 }
1182 else
1183 {
1184 if (m_HeatComfort > PlayerConstants.THRESHOLD_HEAT_COMFORT_MINUS_WARNING && m_UTSAverageTemperature > 0) // m_UTSAverageTemperature can be negative
1185 {
1186 if (applicableHeatbuffer < heatBufferMax)
1187 {
1188 heatBuffer.Add(increaseRate);
1189 m_HeatBufferCapPrevious = heatBufferCap;
1190 }
1191 }
1192 else if (applicableHeatbuffer > 0.0)
1193 heatBuffer.Add(-decreaseRate);
1194 else if (applicableHeatbuffer != 0.0 && !m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
1195 heatBuffer.Set(0.0);
1196
1197 m_HeatBufferTimer = 0.0;
1198 }
1199 }
1200 }
1201
1202 protected float GetApplicableHeatbuffer()
1203 {
1204 PlayerStat<float> heatBuffer = m_Player.GetStatHeatBuffer();
1205 float applicableHeatbuffer = Math.Round((heatBuffer.Get() / heatBuffer.GetMax()) * 1000) * 0.001;
1206
1207 return applicableHeatbuffer;
1208 }
1209
1210 // --------------------------------------------------------------------------------
1211
1216 protected void ProcessItemsTemperature(array<int> pBodyPartIds)
1217 {
1218 EntityAI attachment;
1219 ItemBase item;
1220
1221 int attCount = m_Player.GetInventory().AttachmentCount();
1222 for (int attIdx = 0; attIdx < attCount; ++attIdx)
1223 {
1224 attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
1225 item = ItemBase.Cast(attachment);
1226 int attachmentSlot = attachment.GetInventory().GetSlotId(0);
1227
1229 for (int i = 0; i < pBodyPartIds.Count(); ++i)
1230 {
1231 if (attachmentSlot == pBodyPartIds[i])
1232 {
1233 float heatPermCoef = item.GetHeatPermeabilityCoef();
1234 //first handle the item itself, if necessary
1235 if (item.CanHaveTemperature() && !item.IsSelfAdjustingTemperature())
1236 SetProcessedItemTemperature(item, heatPermCoef);
1237
1238 ProcessItemHierarchyRecursive(item, heatPermCoef);
1239 }
1240 }
1241 }
1242 }
1243
1248 {
1249 ItemBase item = m_Player.GetItemInHands();
1250 if (item)
1251 {
1252 float heatPermCoef = item.GetHeatPermeabilityCoef();
1253 //first handle the item itself, if necessary
1254 if (item.CanHaveTemperature() && !item.IsSelfAdjustingTemperature())
1255 SetProcessedItemTemperature(item,heatPermCoef);
1256
1257 ProcessItemHierarchyRecursive(item,heatPermCoef);
1258 }
1259 }
1260
1261 protected void ProcessItemHierarchyRecursive(ItemBase item, float heatPermeabilityCoef = 1.0)
1262 {
1263 float heatPermCoef = heatPermeabilityCoef;
1264
1265 // go through any attachments and cargo, recursive
1266 int inventoryAttCount = item.GetInventory().AttachmentCount();
1267 if (inventoryAttCount > 0)
1268 {
1269 ItemBase attachmentItem;
1270 for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
1271 {
1272 if (Class.CastTo(attachmentItem,item.GetInventory().GetAttachmentFromIndex(inAttIdx)))
1273 {
1274 heatPermCoef = heatPermeabilityCoef;
1275 heatPermCoef *= attachmentItem.GetHeatPermeabilityCoef();
1276
1277 if (attachmentItem.CanHaveTemperature() && !attachmentItem.IsSelfAdjustingTemperature())
1278 {
1279 SetProcessedItemTemperature(attachmentItem,heatPermCoef);
1280 }
1281
1282 ProcessItemHierarchyRecursive(attachmentItem,heatPermCoef);
1283 }
1284 }
1285 }
1286
1287 if (item.GetInventory().GetCargo())
1288 {
1289 int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
1290 if (inventoryItemCount > 0)
1291 {
1292 ItemBase inventoryItem;
1293 for (int j = 0; j < inventoryItemCount; ++j)
1294 {
1295 if (Class.CastTo(inventoryItem,item.GetInventory().GetCargo().GetItem(j)))
1296 {
1297 heatPermCoef = heatPermeabilityCoef;
1298 heatPermCoef *= inventoryItem.GetHeatPermeabilityCoef();
1299
1300 if (inventoryItem.CanHaveTemperature() && !inventoryItem.IsSelfAdjustingTemperature())
1301 {
1302 SetProcessedItemTemperature(inventoryItem,heatPermCoef);
1303 }
1304
1305 ProcessItemHierarchyRecursive(inventoryItem,heatPermCoef);
1306 }
1307 }
1308 }
1309 }
1310 }
1311
1312 protected void SetProcessedItemTemperature(ItemBase item, float heatPermeabilityCoef = 1.0)
1313 {
1314 float targetTemperature = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_MIDDLE;
1315 bool globalCooling = true;
1317 if (m_Player.IsSwimming())
1318 {
1319 SetItemHeatingCoef(GameConstants.TEMP_COEF_SWIMMING);
1321 globalCooling = false;
1322 }
1323
1324 if (item.GetTemperature() != targetTemperature || !item.IsFreezeThawProgressFinished())
1325 {
1326 TemperatureDataInterpolated temperatureData = new TemperatureDataInterpolated(
1327 targetTemperature,
1328 ETemperatureAccessTypes.ACCESS_INVENTORY,
1329 GameConstants.ENVIRO_TICK_RATE,
1331 heatPermeabilityCoef,
1332 );
1333 temperatureData.m_UseGlobalCooling = globalCooling;
1334
1335 item.SetTemperatureEx(temperatureData);
1336 }
1337 }
1338
1339 // --------------------------------------------------------------------------------
1340
1341 protected float EnvTempToCoef(float pTemp)
1342 {
1343 return (pTemp - GameConstants.ENVIRO_PLAYER_COMFORT_TEMP) / GameConstants.ENVIRO_TEMP_EFFECT_ON_PLAYER;
1344 }
1345
1353 protected void BodyPartHeatProperties(int pBodyPartId, float pCoef, out float pHeatComfort, out float pHeat)
1354 {
1355 pHeatComfort = 0;
1356 pHeat = 0;
1357
1358 int attCount = m_Player.GetInventory().AttachmentCount();
1359 for (int attIdx = 0; attIdx < attCount; ++attIdx)
1360 {
1361 EntityAI attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
1362 if (attachment.IsClothing())
1363 {
1364 ItemBase item = ItemBase.Cast(attachment);
1365 int attachmentSlot = attachment.GetInventory().GetSlotId(0);
1366
1367 if (attachmentSlot == pBodyPartId)
1368 {
1369 #ifdef ENABLE_LOGGING
1370 LogItemHeat(string.Format("BodyPartHeatProperties (%1)", EnumTools.EnumToString(InventorySlots, pBodyPartId)));
1371 #endif
1372
1373 float itemHeatcomfort = 0;
1374 float itemTemperature = 0;
1375
1376 // go through any attachments and cargo (only current level, ignore nested containers - they isolate)
1377 int inventoryAttCount = item.GetInventory().AttachmentCount();
1378 if (inventoryAttCount > 0)
1379 {
1380 #ifdef ENABLE_LOGGING
1381 LogItemHeat(string.Format("attachments:"), false);
1382 #endif
1383 for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
1384 {
1385 EntityAI inAttachment = item.GetInventory().GetAttachmentFromIndex(inAttIdx);
1386 ItemBase attachmentItem = ItemBase.Cast(inAttachment);
1387 if (attachmentItem && attachmentItem.CanHaveTemperature())
1388 {
1389 itemTemperature = attachmentItem.GetTemperature();
1390 if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1391 {
1392 itemHeatcomfort = NormalizedTemperature(itemTemperature) * attachmentItem.GetQuantityNormalizedScripted() * attachmentItem.GetTemperaturePerQuantityWeight();
1393 #ifdef ENABLE_LOGGING
1394 LogItemHeat(string.Format("%1: temperature=%2 heat=%3", attachmentItem, itemTemperature, pHeat), true);
1395 #endif
1396 pHeat += itemHeatcomfort;
1397 }
1398 }
1399 }
1400 }
1401 if (item.GetInventory().GetCargo())
1402 {
1403 int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
1404
1405 if (inventoryItemCount > 0)
1406 {
1407 #ifdef ENABLE_LOGGING
1408 LogItemHeat(string.Format("cargo:"), false);
1409 #endif
1410 for (int j = 0; j < inventoryItemCount; ++j)
1411 {
1412 ItemBase inventoryItem = ItemBase.Cast(item.GetInventory().GetCargo().GetItem(j));
1413 if (inventoryItem && inventoryItem.CanHaveTemperature())
1414 {
1415 itemTemperature = inventoryItem.GetTemperature();
1416 if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1417 {
1418 itemHeatcomfort = NormalizedTemperature(itemTemperature) * inventoryItem.GetQuantityNormalizedScripted() * inventoryItem.GetTemperaturePerQuantityWeight();
1419 #ifdef ENABLE_LOGGING
1420 LogItemHeat(string.Format("%1: temperature=%2 heat=%3", inventoryItem, itemTemperature, itemHeatcomfort), true);
1421 #endif
1422 pHeat += itemHeatcomfort;
1423 }
1424 }
1425 }
1426 }
1427 }
1428
1429 pHeatComfort = MiscGameplayFunctions.GetCurrentItemHeatIsolation(item) * pCoef;
1430
1431 #ifdef ENABLE_LOGGING
1432 LogItemHeat(string.Format("overall heat from items=%1 (coef applied)", pHeat));
1433 LogItemHeat("");
1434 #endif
1435
1436 break;
1437 }
1438 }
1439 }
1440 }
1441
1448 protected float NakedBodyPartHeatComfortPenalty(int pBodyPartSlotId, float pCoef)
1449 {
1450 float penalty = 0.0;
1451
1452 if (!IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}) && !IsWaterContact())
1453 {
1454 if (m_Rain > GameConstants.ENVIRO_NAKED_BODY_PENALTY_RAIN_MIN_VALUE || m_Snowfall > GameConstants.ENVIRO_NAKED_BODY_PENALTY_SNOWFALL_MIN_VALUE)
1455 {
1456 penalty += GameConstants.ENVIRO_ISOLATION_WETFACTOR_DRENCHED;
1457 penalty *= pCoef;
1458 }
1459 }
1460
1461 return penalty;
1462 }
1463
1464 // --------------------------------------------------------------------------------
1465
1470 {
1471 m_UTemperatureSources.Clear();
1472
1473 // Calculate min and max positions of the box
1474 vector pos = m_Player.GetPosition();
1475 vector minPos = pos - Vector(GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS / 2, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS);
1476 vector maxPos = pos + Vector(GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS / 2, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS);
1477
1478 array<EntityAI> nearestObjects = {};
1479 DayZPlayerUtils.SceneGetEntitiesInBox(minPos, maxPos, nearestObjects, QueryFlags.STATIC|QueryFlags.DYNAMIC); //STATIC catches area effects and other static (or 'static') sources
1480
1481 foreach (EntityAI nearestEntity : nearestObjects)
1482 {
1483 if (nearestEntity.IsUniversalTemperatureSource() && nearestEntity != m_Player)
1484 {
1486 if (!nearestEntity.GetUniversalTemperatureSource().GetLambda().AffectsPlayer())
1487 continue;
1488
1490 if (vector.DistanceSq(pos, nearestEntity.GetPosition()) > Math.SqrFloat(nearestEntity.GetUniversalTemperatureSource().GetMaxRange()))
1491 continue;
1492
1493 m_UTemperatureSources.Insert(nearestEntity.GetUniversalTemperatureSource());
1494 }
1495 }
1496
1497 if (m_Player.GetItemInHands() && m_Player.GetItemInHands().IsUniversalTemperatureSource())
1498 m_UTemperatureSources.Insert(m_Player.GetItemInHands().GetUniversalTemperatureSource());
1499 }
1500
1505 {
1506 int UTScount = m_UTemperatureSources.Count();
1507 if (UTScount == 0)
1508 {
1513 SetItemHeatingCoef(GameConstants.TEMP_COEF_INVENTORY);
1514
1515 return;
1516 }
1517
1518 array<float> utsTemperatures = new array<float>();
1519
1520 // get temperature from the source (based on distance), save it for min/max filtering
1521 float itemCoefAverage = 0.0;
1522 foreach (UTemperatureSource tempSource : m_UTemperatureSources)
1523 {
1524 utsTemperatures.Insert(CalcTemperatureFromTemperatureSource(tempSource));
1525 itemCoefAverage += tempSource.GetTemperatureItemCoef();
1526 }
1527 itemCoefAverage /= UTScount;
1528 SetItemHeatingCoef(itemCoefAverage);
1529
1530 float min = MiscGameplayFunctions.GetMinValue(utsTemperatures);
1531 float max = MiscGameplayFunctions.GetMaxValue(utsTemperatures);
1532
1533 if (max > 0 && min < 0)
1534 {
1537 }
1538 else
1539 {
1541 }
1542
1543 if (m_HasTemperatureSources == false)
1545
1547 }
1548
1549 protected void SetItemHeatingCoef(float val)
1550 {
1552 }
1553
1557 protected void OnTemperatureSourcesEnter();
1558
1563
1568
1569 float CalcTemperatureFromTemperatureSource(notnull UTemperatureSource uts)
1570 {
1571 float distance = vector.Distance(m_Player.GetPosition(), uts.GetPosition());
1572 distance = Math.Max(distance, 0.1); //min distance cannot be 0 (division by zero)
1573 float temperature = 0;
1574
1576 if (distance > uts.GetFullRange())
1577 {
1578 float distFactor = Math.InverseLerp(uts.GetMaxRange(), uts.GetFullRange(), distance);
1579 temperature = uts.GetTemperatureCap() * distFactor;
1580 }
1581 else
1582 {
1583 temperature = uts.GetTemperatureCap();
1584 }
1585
1586 return temperature;
1587 }
1588
1589 // --------------------------------------------------------------------------------
1590
1592 #ifdef DIAG_DEVELOPER
1593 EnvDebugData GetEnvDebugData()
1594 {
1595 EnvDebugData data = new EnvDebugData();
1596 data.Synch(this, m_Player);
1597 return data;
1598 }
1599
1600 void ShowEnvDebugPlayerInfo(bool enabled)
1601 {
1602 EnvDebugData data = GetEnvDebugData();
1603 DisplayEnvDebugPlayerInfo(enabled, data);
1604 }
1605
1606 static void DisplayEnvDebugPlayerInfo(bool enabled, EnvDebugData data)
1607 {
1608 int windowPosX = 10;
1609 int windowPosY = 200;
1610
1611 Object obj;
1612
1613 DbgUI.Begin("Player stats", windowPosX, windowPosY);
1614 if ( enabled )
1615 {
1616 DbgUI.Text(string.Format("Heat comfort(target): %1", data.m_PlayerData.m_HeatComfortTarget));
1617 DbgUI.Text(string.Format("Heat comfort(dynamic): %1", data.m_PlayerData.m_HeatComfortDynamic));
1618 DbgUI.Text(string.Format("Inside: %1 (%2)", data.m_PlayerData.m_Inside, data.m_PlayerData.m_Surface));
1619 DbgUI.Text(string.Format("Under roof: %1 (%2)", data.m_PlayerData.m_UnderRoof, data.m_PlayerData.m_UnderRoofTimer));
1620 if ( data.m_PlayerData.m_WaterLevel > 0 )
1621 {
1622 DbgUI.Text(string.Format("Water Level: %1", data.m_PlayerData.m_WaterLevel));
1623 }
1624
1625 }
1626 DbgUI.End();
1627
1628 DbgUI.Begin("Weather stats:", windowPosX, windowPosY + 200);
1629 if ( enabled )
1630 {
1631 DbgUI.Text(string.Format("Env temperature (base): %1", data.m_MiscData.m_TemperatureBase));
1632 DbgUI.Text(string.Format("Env temperature (height corrected): %1", data.m_MiscData.m_HeightCorrectedTemperature));
1633 DbgUI.Text(string.Format("Env temperature (modfied): %1", data.m_MiscData.m_TemperatureModified));
1634 DbgUI.Text(string.Format("Wind magnitude(surface mult): %1 (x%2)", data.m_WeatherData.m_Wind, data.m_WeatherData.m_WindModifier));
1635 DbgUI.Text(string.Format("Rain: %1", data.m_WeatherData.m_Rain));
1636 DbgUI.Text(string.Format("Snow: %1", data.m_WeatherData.m_Snowfall));
1637 DbgUI.Text(string.Format("Datetime: %1", WorldDataDaytime.ToString(g_Game.GetMission().GetWorldData().GetDaytime())));
1638 DbgUI.Text(string.Format("Fog: %1", data.m_WeatherData.m_Fog));
1639 DbgUI.Text(string.Format("Clouds: %1", data.m_WeatherData.m_Clouds));
1640 DbgUI.Text(string.Format("Wet delta: %1", data.m_MiscData.m_WetDelta));
1641 }
1642 DbgUI.End();
1643 }
1644
1645 void FillDebugWeatherData(EnvDebugWeatherData data)
1646 {
1647 data.m_Wind = m_Wind;
1648 data.m_WindModifier = GetWindModifierPerSurface();
1649 data.m_Rain = m_Rain;
1650 data.m_Snowfall = m_Snowfall;
1651 data.m_Fog = m_Fog;
1652 data.m_Clouds = m_Clouds;
1653 }
1654 #endif
1655
1657 {
1658 string message;
1659 message += "Player stats";
1660 message += "\nHeat comfort(target): " + GetTargetHeatComfort().ToString();
1661 message += "\nHeat comfort(dynamic): " + m_HeatComfort.ToString();
1662
1663 int liquidType;
1664 string impact, surfaceType;
1665 g_Game.SurfaceUnderObjectExCorrectedLiquid(m_Player, surfaceType, impact, liquidType);
1666
1667 message += "\nInside: " + IsInsideBuilding().ToString();
1668 message += "\nSurface: " + surfaceType;
1669 message += "\nLiquid: " + liquidType;
1670 message += "\nUnder roof: " + m_IsUnderRoof.ToString() + " (" + GetNextRoofCheck() + ")";
1672 {
1673 message += "\nWater Level: " + m_WaterLevel;
1674 }
1675
1676 message += "\n\nWeather stats";
1677 message += "\nEnv temperature (base): " + m_WorldData.GetBaseEnvTemperature().ToString();
1678 message += "\nEnv temperature (height corrected): " + m_WorldData.GetBaseEnvTemperatureAtObject(m_Player);
1679 message += "\nEnv temperature (modified): " + m_EnvironmentTemperature.ToString();
1680 message += "\nWind: " + m_Wind.ToString() + " (x" + GetWindModifierPerSurface() + ")";
1681 message += "\nRain: " + m_Rain.ToString();
1682 message += "\nSnow: " + m_Snowfall.ToString();
1683 message += "\nDatetime: " + WorldDataDaytime.ToString(m_DayOrNight);
1684 message += "\nFog: " + m_Fog.ToString();
1685 message += "\nClouds: " + m_Clouds.ToString();
1686 message += "\nWet delta: " + GetWetDelta().ToString();
1687
1688 return message;
1689 }
1690
1692 {
1693 return (GameConstants.ENVIRO_TICK_ROOF_RC_CHECK - m_RoofCheckTimer) + 1;
1694 }
1695
1697 {
1699 {
1700 return m_WaterLevel;
1701 }
1702
1703 return 0.0;
1704 }
1705
1706 private bool IsNeutralTemperature(float temperature, float lowerLimit = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT, float upperLimit = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1707 {
1708 if (temperature >= lowerLimit && temperature <= upperLimit)
1709 return true;
1710
1711 return false;
1712 }
1713
1714 private float NormalizedTemperature(float temperature, float lowerLimit = GameConstants.ENVIRO_LOW_TEMP_LIMIT, float upperLimit = GameConstants.ENVIRO_HIGH_TEMP_LIMIT)
1715 {
1716 if (temperature >= GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT && temperature <= GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1717 return 0.0;
1718
1719 if (temperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT)
1720 return Math.Clamp(Math.InverseLerp(lowerLimit, GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT, temperature), -1.0, -0.1);
1721
1722 if (temperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1723 return Math.Clamp(Math.InverseLerp(GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT, upperLimit, temperature), 0.1, 1.0);
1724
1725 // neutral zone
1726 return 0.0;
1727 }
1728
1729 #ifdef ENABLE_LOGGING
1730 private void LogDryWetProcess(string message, bool indented = false)
1731 {
1732 if (m_DebugLogDryWet)
1733 {
1734 string indentation = "";
1735 if (indented)
1736 indentation = "|--";
1737
1738 Debug.Log(string.Format("%1 %2", indentation, message));
1739 }
1740 }
1741 #endif
1742
1743 #ifdef ENABLE_LOGGING
1744 private void LogItemHeat(string message, bool indented = false)
1745 {
1746 if (m_DebugLogItemHeat)
1747 {
1748 string indentation = "";
1749 if (indented)
1750 indentation = "|--";
1751
1752 Debug.Log(string.Format("%1 %2", indentation, message));
1753 }
1754 }
1755 #endif
1756
1757 // --------------------------------------------------------------------------------
1758
1760 protected float m_HeatSourceTemp;
1761 protected ref SimpleMovingAverage<float> m_WindAverageBuffer;
1762 protected ref EnvironmentSnapshotData m_EnvironmentSnapshot;
1763
1764 void Init(PlayerBase pPlayer)
1765 {
1766 Init();
1767 }
1768
1769 protected bool OverridenHeatComfort(out float value);
1770 void AddToEnvironmentTemperature(float pTemperature);
1771
1772 protected void ProcessItemsHeat()
1773 {
1774 // for backward combatibility only
1776 }
1777
1778 protected void ProcessWetnessByRain()
1779 {
1781 }
1782
1783 // Returns amount of deg C air temperature should be lowered by, based on player's height above water level
1785 {
1786 float temperature_reduction = Math.Max(0, (m_PlayerHeightPos * m_WorldData.m_TemperaturePerHeightReductionModifier));
1787 return temperature_reduction;
1788 }
1789
1791 protected void BodyPartHeatProperties(array<int> pBodyPartIds, float pCoef, out float pHeatComfort, out float pHeat)
1792 {
1793 pHeatComfort = 0;
1794 pHeat = 0;
1795
1796 if (pBodyPartIds.Count() > 0)
1797 {
1798 #ifdef ENABLE_LOGGING
1799 LogItemHeat(string.Format("BodyPartHeatProperties (%1)", EnumTools.EnumToString(InventorySlots, pBodyPartIds[0])));
1800 #endif
1801
1802 int attCount = m_Player.GetInventory().AttachmentCount();
1803 for (int attIdx = 0; attIdx < attCount; ++attIdx)
1804 {
1805 EntityAI attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
1806 if (attachment.IsClothing())
1807 {
1808 ItemBase item = ItemBase.Cast(attachment);
1809 int attachmentSlot = attachment.GetInventory().GetSlotId(0);
1810
1812 for (int i = 0; i < pBodyPartIds.Count(); ++i)
1813 {
1814 if (attachmentSlot == pBodyPartIds[i])
1815 {
1816 float heatIsoMult = 1.0;
1817 if (attachmentSlot == InventorySlots.BACK)
1818 heatIsoMult = GameConstants.ENVIRO_HEATISOLATION_BACK_WEIGHT;
1819 else if (attachmentSlot == InventorySlots.VEST)
1820 heatIsoMult = GameConstants.ENVIRO_HEATISOLATION_VEST_WEIGHT;
1821
1822 pHeatComfort += heatIsoMult * MiscGameplayFunctions.GetCurrentItemHeatIsolation(item);
1823
1824 float itemHeatcomfort = 0;
1825 float itemTemperature = 0;
1826
1827 // go through any attachments and cargo (only current level, ignore nested containers - they isolate)
1828 int inventoryAttCount = item.GetInventory().AttachmentCount();
1829 if (inventoryAttCount > 0)
1830 {
1831 #ifdef ENABLE_LOGGING
1832 LogItemHeat(string.Format("attachments:"), false);
1833 #endif
1834 for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
1835 {
1836 EntityAI inAttachment = item.GetInventory().GetAttachmentFromIndex(inAttIdx);
1837 ItemBase attachmentItem = ItemBase.Cast(inAttachment);
1838 if (attachmentItem && attachmentItem.CanHaveTemperature())
1839 {
1840 itemTemperature = attachmentItem.GetTemperature();
1841 if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1842 {
1843 itemHeatcomfort = NormalizedTemperature(itemTemperature) * attachmentItem.GetQuantityNormalizedScripted() * attachmentItem.GetTemperaturePerQuantityWeight();
1844 #ifdef ENABLE_LOGGING
1845 LogItemHeat(string.Format("%1: temperature=%2 heat=%3", attachmentItem, itemTemperature, pHeat), true);
1846 pHeat += itemHeatcomfort;
1847 #endif
1848 }
1849 }
1850 }
1851 }
1852 if (item.GetInventory().GetCargo())
1853 {
1854 int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
1855
1856 if (inventoryItemCount > 0)
1857 {
1858 #ifdef ENABLE_LOGGING
1859 LogItemHeat(string.Format("cargo:"), false);
1860 #endif
1861 for (int j = 0; j < inventoryItemCount; ++j)
1862 {
1863 ItemBase inventoryItem = ItemBase.Cast(item.GetInventory().GetCargo().GetItem(j));
1864 if (inventoryItem && inventoryItem.CanHaveTemperature())
1865 {
1866 itemTemperature = inventoryItem.GetTemperature();
1867 if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
1868 {
1869 itemHeatcomfort = NormalizedTemperature(itemTemperature) * inventoryItem.GetQuantityNormalizedScripted() * inventoryItem.GetTemperaturePerQuantityWeight();
1870 #ifdef ENABLE_LOGGING
1871 LogItemHeat(string.Format("%1: temperature=%2 heat=%3", inventoryItem, itemTemperature, itemHeatcomfort), true);
1872 #endif
1873 pHeat += itemHeatcomfort;
1874 }
1875 }
1876 }
1877 }
1878 }
1879 }
1880 }
1881 }
1882 }
1883
1884 pHeatComfort += (pHeatComfort / pBodyPartIds.Count()) * pCoef;
1885
1886 #ifdef ENABLE_LOGGING
1887 LogItemHeat(string.Format("overall heat from items=%1 (coef applied)", pHeat));
1888 LogItemHeat("");
1889 #endif
1890 }
1891 }
1892
1894 {
1895 EnvironmentSnapshotData data = new EnvironmentSnapshotData();
1896 data.m_TargetHeatComfort = m_TargetHeatComfort;
1897
1898 m_EnvironmentSnapshot = data;
1899 }
1900
1902 protected void ProcessHeatBuffer(float heatComfortCloths)
1903 {
1904 m_EnvironmentSnapshot.m_ClothingHeatComfort = heatComfortCloths;
1905 m_EnvironmentSnapshot.m_TargetHeatComfort = m_TargetHeatComfort;
1906
1908 }
1909
1911 protected float WindEffectTemperatureValue(float temperatureInput)
1912 {
1913 float output = 0.0;
1914
1915 output = (temperatureInput - GameConstants.ENVIRO_WIND_CHILL_LIMIT) / (GameConstants.ENVIRO_WIND_EFFECT_SLOPE - GameConstants.ENVIRO_WIND_CHILL_LIMIT);
1916 output = output * m_Wind * m_WorldData.GetWindCoef();
1917
1918 return -output;
1919 }
1920
1922 {
1923 return m_DayOrNight;
1924 }
1925
1926 protected bool IsInsideVehicle()
1927 {
1928 return IsChildOfType({Car});
1929 }
1930}
1931
1932#ifdef DIAG_DEVELOPER
1933class EnvDebugPlayerData : Param
1934{
1935 float m_HeatComfortDynamic;
1936 float m_HeatComfortTarget;
1937 bool m_Inside;
1938 string m_Surface;
1939 bool m_UnderRoof;
1940 int m_UnderRoofTimer;
1941 float m_WaterLevel;
1942
1943 void Synch(Environment env, PlayerBase player)
1944 {
1945 m_HeatComfortTarget = env.GetTargetHeatComfort();
1946 m_HeatComfortDynamic = player.GetStatHeatComfort().Get();
1947 m_Inside = env.IsInsideBuilding();
1948 m_Surface = player.GetSurfaceType();
1949 m_UnderRoof = env.IsUnderRoof();
1950 m_UnderRoofTimer = env.GetNextRoofCheck();
1951 m_WaterLevel = env.GetWaterLevel();
1952 }
1953
1954 override bool Serialize(Serializer ctx)
1955 {
1956 return (
1957 ctx.Write(m_HeatComfortTarget) && ctx.Write(m_HeatComfortDynamic) && ctx.Write(m_Inside) && ctx.Write(m_Surface) && ctx.Write(m_UnderRoof) && ctx.Write(m_UnderRoofTimer) && ctx.Write(m_WaterLevel));
1958 }
1959
1960 override bool Deserializer(Serializer ctx)
1961 {
1962 return ctx.Write(m_HeatComfortTarget) && ctx.Read(m_HeatComfortDynamic) && ctx.Read(m_Inside) && ctx.Read(m_Surface) && ctx.Read(m_UnderRoof) && ctx.Read(m_UnderRoofTimer) && ctx.Read(m_WaterLevel);
1963 }
1964}
1965
1966class EnvDebugMiscData : Param
1967{
1968 float m_TemperatureBase;
1969 float m_TemperatureModified;
1970 float m_HeightCorrectedTemperature;
1971 float m_WetDelta;
1972
1973 void Synch(Environment env)
1974 {
1975 m_TemperatureBase = g_Game.GetMission().GetWorldData().GetBaseEnvTemperature();
1976 m_TemperatureModified = env.GetTemperature();
1977 m_HeightCorrectedTemperature = m_TemperatureBase - env.GetTemperatureHeightCorrection();
1978 m_WetDelta = env.GetWetDelta();
1979 }
1980
1981 override bool Serialize(Serializer ctx)
1982 {
1983 return ctx.Write(m_TemperatureBase) && ctx.Write(m_TemperatureModified) && ctx.Write(m_HeightCorrectedTemperature) && ctx.Write(m_WetDelta);
1984 }
1985
1986 override bool Deserializer(Serializer ctx)
1987 {
1988 return ctx.Read(m_TemperatureBase) && ctx.Read(m_TemperatureModified) && ctx.Read(m_HeightCorrectedTemperature) && ctx.Read(m_WetDelta);
1989 }
1990}
1991
1992class EnvDebugWeatherData : Param
1993{
1994 float m_Wind;
1995 float m_WindModifier;
1996 float m_Rain;
1997 float m_Snowfall;
1998 float m_Fog;
1999 float m_Clouds;
2000
2001 void Synch(Environment env)
2002 {
2003 env.FillDebugWeatherData(this);
2004 }
2005
2006 override bool Serialize(Serializer ctx)
2007 {
2008 return ctx.Write(m_Wind) && ctx.Write(m_WindModifier) && ctx.Write(m_Rain) && ctx.Write(m_Snowfall) && ctx.Write(m_Fog) && ctx.Write(m_Clouds);
2009 }
2010
2011 override bool Deserializer(Serializer ctx)
2012 {
2013 return ctx.Read(m_Wind) && ctx.Read(m_WindModifier) && ctx.Read(m_Rain) && ctx.Read(m_Snowfall) && ctx.Read(m_Fog) && ctx.Read(m_Clouds);
2014 }
2015}
2016
2017class EnvDebugData : Param
2018{
2019 ref EnvDebugPlayerData m_PlayerData = new EnvDebugPlayerData();
2020 ref EnvDebugMiscData m_MiscData = new EnvDebugMiscData();
2021 ref EnvDebugWeatherData m_WeatherData = new EnvDebugWeatherData();
2022
2023 void Synch(Environment env, PlayerBase player)
2024 {
2025 m_PlayerData.Synch(env, player);
2026 m_MiscData.Synch(env);
2027 m_WeatherData.Synch(env);
2028 }
2029
2030 override bool Serialize(Serializer ctx)
2031 {
2032 return m_PlayerData.Serialize(ctx) && m_MiscData.Serialize(ctx) && m_WeatherData.Serialize(ctx);
2033 }
2034
2035 override bool Deserializer(Serializer ctx)
2036 {
2037 return m_PlayerData.Deserializer(ctx) && m_MiscData.Deserializer(ctx) && m_WeatherData.Deserializer(ctx);
2038 }
2039}
2040#endif
bool m_Initialized
void Serialize()
Definition inventory.c:201
#define LIQUID_RIVERWATER
#define LIQUID_FRESHWATER
#define LIQUID_WATER
#define LIQUID_SALTWATER
#define LIQUID_HOTWATER
#define LIQUID_STILLWATER
Super root of all classes in Enforce script.
Definition enscript.c:11
override float GetCurrentWaterLevel()
Definition dbgui.c:60
Definition debug.c:2
InventoryLocation.
provides access to slot configuration
override bool IsSelfAdjustingTemperature()
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
Native class for boats - handles physics simulation.
Definition boat.c:28
Keeps information about currently loaded world, like temperature.
Definition worlddata.c:3
float GetTemperature(Object object, EEnvironmentTemperatureComponent properties=EEnvironmentTemperatureComponent.BASE)
Return actual temperature of environment based on provided parameters.
Definition worlddata.c:301
float GetBaseEnvTemperature()
Definition worlddata.c:206
float GetBaseEnvTemperatureAtObject(notnull Object object)
Definition worlddata.c:211
float GetWindCoef()
Definition worlddata.c:286
float GetLiquidTypeEnviroTemperature(int liquidType)
Definition worlddata.c:228
float GetTemperatureComponentValue(float temperatureIn, EEnvironmentTemperatureComponent properties=0)
Return value of queried EEnvironmentTemperatureComponent which can be used in future calculation(s)
Definition worlddata.c:326
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
DayZGame g_Game
Definition dayzgame.c:3868
override Widget Init()
Definition dayzgame.c:127
PhxInteractionLayers
Definition dayzphysics.c:2
DayZPlayerConstants
defined in C++
Definition dayzplayer.c:602
QueryFlags
eModifiers
Definition emodifiers.c:2
bool m_IsInWater
Definition environment.c:70
ref EnvironmentSnapshotData m_EnvironmentSnapshot
void CollectAndSetEnvironmentData()
Sets actual weather related values for further use (rain, snow, wind, etc.)
ref SimpleMovingAverage< float > m_UTSAverageTemperatureBuffer
Definition environment.c:90
ref array< UTemperatureSource > m_UTemperatureSources
Definition environment.c:89
void SetTargetHeatComfort(float value)
int GetNextRoofCheck()
float GetTemperatureHeightCorrection()
bool IsWaterContact()
Is character in contact with water body? (periodically checked - GameConstants.ENVIRO_TICK_RATE).
ref array< int > m_SlotIdsComplete
Definition environment.c:76
int m_HeatComfortBehaviorCategory
Definition environment.c:93
bool IsInsideBuilding()
Is character inside building? (periodically checked - GameConstants.ENVIRO_TICK_ROOF_RC_CHECK).
float m_HeatBufferTimer
Definition environment.c:73
float m_UTSAverageTemperature
Definition environment.c:88
float CalcTemperatureFromTemperatureSource(notnull UTemperatureSource uts)
float m_Time
Definition environment.c:59
void SetAreaGenericColdness()
Determines whether player is in cold area which restricts use of some actions (digging)
void ProcessTemperatureSources()
Processes registered UTSources and calculates resulting m_UTSAverageTemperature.
float m_PlayerTemperature
Definition environment.c:46
bool OverridenHeatComfort(out float value)
void CheckUnderRoof()
Checks whether character is sheltered and sets the information.
void AddToEnvironmentTemperature(float pTemperature)
float GetDayOrNight()
float m_ItemTemperatureCoef
Definition environment.c:64
const float SNOWFALL_LIMIT_LOW
Definition environment.c:30
float m_EnvironmentTemperature
Definition environment.c:58
ref array< int > m_HeadParts
Definition environment.c:81
void ApplyDrynessToItemEx(ItemBase pItem, EnvironmentDrynessData pDrynessData)
ref array< int > m_SlotIdsUpper
Definition environment.c:77
bool m_IsTempSet
Definition environment.c:71
float GetWaterLevel()
float m_PlayerSpeed
Definition environment.c:45
WorldData m_WorldData
Definition environment.c:85
void ProcessItemsWetness(array< int > pSlotIds)
Soak items at specific Slot ID(s)
float m_HeatSourceTemp
DEPRECATED.
float GetTemperature()
float GetWindModifierPerSurface()
Wind intensity (influence) modifier of temperature value.
float GetApplicableHeatbuffer()
ref array< int > m_SlotIdsLower
Definition environment.c:79
void ProcessItemsInHandsTemperature()
Process temperature of item in character hands and cool/warm it to neutral temparature.
void SetEnvironmentSnapshotData()
bool IsUnderRoof()
Is character under roof (periodically checked - GameConstants.ENVIRO_TICK_ROOF_RC_CHECK)....
ref SimpleMovingAverage< float > m_AverageHeatComfortBuffer
Definition environment.c:91
const float WATER_LEVEL_MID
Definition environment.c:34
float m_Rain
target value of heatcomfort (non-buffered)
Definition environment.c:52
float m_HeatComfort
Definition environment.c:48
float m_Snowfall
Definition environment.c:53
void ProcessWetnessByWaterLevel(float pWaterLevel)
Processes items wetness in player possession based on the current water level (the character is in)
int m_LiquidType
Definition environment.c:61
float WindEffectTemperatureValue(float temperatureInput)
backward compatibility [<1.28]
const float SNOWFALL_WIND_COMBINED_THRESHOLD
Definition environment.c:31
bool m_IsUnderRoof
Definition environment.c:68
void SetProcessedItemTemperature(ItemBase item, float heatPermeabilityCoef=1.0)
void CollectAndSetPlayerData()
Sets character related value for furher use.
enum EEnvironmentHeatcomfortBehaviorCategory m_ClothingHeatComfort
float m_Wind
Definition environment.c:54
void ProcessItemHierarchyRecursive(ItemBase item, float heatPermeabilityCoef=1.0)
float m_PlayerHeat
Definition environment.c:47
ref array< int > m_BodyParts
Definition environment.c:82
float m_DayOrNight
Definition environment.c:56
void SetItemHeatingCoef(float val)
void GatherTemperatureSources()
Checks characters proximity for usable Universal Temperature Sources and register them.
const float WATER_LEVEL_LOW
Definition environment.c:35
const float WATER_LEVEL_NONE
Definition environment.c:36
void OnTemperatureSourcesLeft()
Event fired when characters leave the UTSource proximity.
ref array< int > m_FeetParts
Definition environment.c:83
float m_WetDryTick
Definition environment.c:38
float EnvTempToCoef(float pTemp)
const float WATER_LEVEL_HIGH
Definition environment.c:33
EEnvironmentHeatcomfortBehaviorCategory
Categories that are changing behavior of Heat comfort processing.
Definition environment.c:5
@ DEFAULT
Definition environment.c:6
@ CAR_ENGINE_ON
Definition environment.c:7
ref SimpleMovingAverage< float > m_WindAverageBuffer
string GetDebugMessage()
debug
float GetWetDelta()
Calculates soaking/drying delta based on character's location and weather.
string m_SurfaceType
Definition environment.c:60
bool DetermineHeatcomfortBehavior()
Changes Heat Comfort curve behavior based on where the character is.
void ApplyWetnessToItem(ItemBase pItem)
void BodyPartHeatProperties(int pBodyPartId, float pCoef, out float pHeatComfort, out float pHeat)
Iterate through given body part and calculates heatcofort and item heat value.
float m_HeatBufferCapPrevious
reused as state toggle
Definition environment.c:74
bool IsRaining()
Rain phenomenon actual value > RAIN_LIMIT_LOW.
void SetEnvironmentTemperature()
ref array< int > m_SlotIdsBottom
Definition environment.c:78
float GetEnvironmentTemperature()
Calculations of temperarute for different situations.
float GetUniversalSourcesTemperageAverage()
float NakedBodyPartHeatComfortPenalty(int pBodyPartSlotId, float pCoef)
Calculates penalty value for heatcomfort - this simulates uncovered body part reaction.
void SetHeatcomfortDirectly()
void ProcessItemsHeat()
void ProcessWetnessByRain()
float m_WaterLevel
Definition environment.c:67
float m_ItemsWetnessMax
Definition environment.c:39
float m_PlayerHeightPos
Definition environment.c:44
void OnTemperatureSourcesEnter()
Event fired when characters enters into UTSource proximity.
void ApplyDrynessToItem(ItemBase pItem)
bool IsSnowing()
Snowfall phenomenon actual value > SNOWFALL_LIMIT_LOW.
float m_RoofCheckTimer
keeps wetness of most wet item in player's possesion
Definition environment.c:40
class EnvironmentDrynessData RAIN_LIMIT_LOW
Simulates influence of environment to character Takes input data from WorldData, Weather system and e...
void ProcessItemsDryness()
Dry items in player possession.
float m_Fog
Definition environment.c:55
float GetPlayerHeat()
Character's heat (calculated from movement speed multiplied by constant)
float m_TargetHeatComfort
player's heatcomfort (buffered, stored in player stats)
Definition environment.c:13
float m_Clouds
Definition environment.c:57
float GetTargetHeatComfort()
bool m_HasTemperatureSources
Definition environment.c:87
bool IsInsideVehicle()
void ProcessHeatComfort()
Calculates and process player's heatcomfort related to defined body parts.
void ProcessHeatBuffer(EnvironmentSnapshotData data)
void ProcessItemsTemperature(array< int > pBodyPartIds)
Iterate through items in player posession (by given body parts) and cool/warm them to neutral tempara...
void CheckWaterContact(out float pWaterLevel)
Checks player's contanct with water.
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
class JsonUndergroundAreaTriggerData GetPosition
DayZPlayer m_Player
Definition hand_events.c:42
string m_Surface
void PlayerStat(T min, T max, T init, string label, int flags)
class PresenceNotifierNoiseEvents windowPosX
dbgUI settings
const int windowPosY
void Synch(EntityAI victim)
keeping "step" here for consistency only
Definition trapbase.c:281