123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040 |
- /**
- * \brief Categories that are changing behavior of Heat comfort processing
- */
- enum EEnvironmentHeatcomfortBehaviorCategory
- {
- DEFAULT,
- CAR_ENGINE_ON
- }
- class EnvironmentSnapshotData
- {
- float m_ClothingHeatComfort;
- float m_TargetHeatComfort;
- }
- class EnvironmentDrynessData
- {
- bool m_UseTemperatureSources = false;
- float m_TemperatureSourceDistance = 1.0;
- }
- /**
- * \brief Simulates influence of environment to character
- * Takes input data from WorldData, Weather system and entities simulating temperature and wetness.
- */
- class Environment
- {
- const float RAIN_LIMIT_LOW = 0.05;
-
- protected const float SNOWFALL_LIMIT_LOW = 0.5;
- protected const float SNOWFALL_WIND_COMBINED_THRESHOLD = 1.3;
- const float WATER_LEVEL_HIGH = 1.5;
- const float WATER_LEVEL_MID = 1.2;
- const float WATER_LEVEL_LOW = 0.5;
- const float WATER_LEVEL_NONE = 0.15;
-
- protected float m_WetDryTick; //ticks passed since last clothing wetting or drying
- protected float m_ItemsWetnessMax; //! keeps wetness of most wet item in player's possesion
- protected float m_RoofCheckTimer; // keeps info about tick time
- //player
- protected PlayerBase m_Player;
- protected float m_PlayerHeightPos; // y position of player above water level (meters)
- protected float m_PlayerSpeed; // 1-3 speed of player movement
- protected float m_PlayerTemperature; //34-44
- protected float m_PlayerHeat; //3-9 heatcomfort generated by entites movement
- protected float m_HeatComfort; //! player's heatcomfort (buffered, stored in player stats)
- protected float m_TargetHeatComfort; //! target value of heatcomfort (non-buffered)
- //environment
- protected float m_Rain = 0; // 0-1 amount of rain
- protected float m_Snowfall = 0; // 0-1 amount of rain
- protected float m_Wind = 0; // strength of wind
- protected float m_Fog = 0; // 0-1 how foggy it is
- protected float m_DayOrNight = 0; // 0-1 day(0) or night(1)
- protected float m_Clouds = 0; // 0-1 how cloudy it is
- protected float m_EnvironmentTemperature; //temperature of environment player is in
- protected float m_Time = 0;
- protected string m_SurfaceType;
- protected int m_LiquidType;
-
- //item temperatures
- protected float m_ItemTemperatureCoef;
-
- //
- protected float m_WaterLevel;
- protected bool m_IsUnderRoof;
- private bool m_IsUnderRoofBuilding;
- protected bool m_IsInWater;
- protected bool m_IsTempSet;
- //
- protected float m_HeatBufferTimer; //! reused as state toggle
- protected float m_HeatBufferCapPrevious;
-
- protected ref array<int> m_SlotIdsComplete;
- protected ref array<int> m_SlotIdsUpper;
- protected ref array<int> m_SlotIdsBottom;
- protected ref array<int> m_SlotIdsLower;
-
- protected ref array<int> m_HeadParts;
- protected ref array<int> m_BodyParts;
- protected ref array<int> m_FeetParts;
-
- protected WorldData m_WorldData;
- protected bool m_HasTemperatureSources;
- protected float m_UTSAverageTemperature;
- protected ref array<UTemperatureSource> m_UTemperatureSources;
- protected ref SimpleMovingAverage<float> m_UTSAverageTemperatureBuffer;
- protected ref SimpleMovingAverage<float> m_AverageHeatComfortBuffer;
-
- protected int m_HeatComfortBehaviorCategory;
-
- private bool m_Initialized;
-
- #ifdef DIAG_DEVELOPER
- bool m_Debug = false;
- #endif
- #ifdef ENABLE_LOGGING
- bool m_DebugLogDryWet = false;
- bool m_DebugLogItemHeat = false;
- #endif
-
- void Environment(PlayerBase pPlayer)
- {
- m_Player = pPlayer;
- }
-
- void Init()
- {
- m_PlayerSpeed = 0.0;
- m_WetDryTick = 0.0;
- m_RoofCheckTimer = 0.0;
- m_WaterLevel = 0.0;
- m_HeatComfort = m_Player.GetStatHeatComfort().Get();
- m_WorldData = g_Game.GetMission().GetWorldData();
- m_EnvironmentTemperature = m_WorldData.GetBaseEnvTemperatureAtObject(m_Player);
-
- m_IsUnderRoof = false;
- m_IsInWater = false;
- m_SurfaceType = "cp_dirt";
- m_HeatBufferTimer = 0.0;
-
- m_UTSAverageTemperature = 0.0;
- m_UTemperatureSources = new array<UTemperatureSource>();
- m_UTSAverageTemperatureBuffer = new SimpleMovingAverage<float>(10, 0.0);
- m_AverageHeatComfortBuffer = new SimpleMovingAverage<float>(20, m_HeatComfort);
-
- //! whole body slots
- m_SlotIdsComplete = new array<int>();
- m_SlotIdsComplete = {
- InventorySlots.HEADGEAR,
- InventorySlots.MASK,
- InventorySlots.EYEWEAR,
- InventorySlots.GLOVES,
- InventorySlots.ARMBAND,
- InventorySlots.BODY,
- InventorySlots.HIPS,
- InventorySlots.VEST,
- InventorySlots.BACK,
- InventorySlots.LEGS,
- InventorySlots.FEET
- };
- //! upper body part slots
- m_SlotIdsUpper = new array<int>();
- m_SlotIdsUpper = {
- InventorySlots.GLOVES,
- InventorySlots.ARMBAND,
- InventorySlots.BODY,
- InventorySlots.HIPS,
- InventorySlots.VEST,
- InventorySlots.BACK,
- InventorySlots.LEGS,
- InventorySlots.FEET
- };
- //! bottom body part slots
- m_SlotIdsBottom = new array<int>();
- m_SlotIdsBottom = {
- InventorySlots.HIPS,
- InventorySlots.LEGS,
- InventorySlots.FEET
- };
- //! lower body part slots
- m_SlotIdsLower = new array<int>();
- m_SlotIdsLower = {
- InventorySlots.FEET,
- };
- //! --------------------------
- //! heat comfort related slots
- m_HeadParts = new array<int>();
- m_HeadParts = {
- InventorySlots.HEADGEAR,
- InventorySlots.MASK,
- };
-
- m_BodyParts = new array<int>();
- m_BodyParts = {
- InventorySlots.GLOVES,
- InventorySlots.HIPS,
- InventorySlots.BODY,
- InventorySlots.BACK,
- InventorySlots.VEST,
- InventorySlots.MELEE,
- InventorySlots.SHOULDER
- };
-
- m_FeetParts = new array<int>();
- m_FeetParts = {
- InventorySlots.LEGS,
- InventorySlots.FEET,
- };
-
- m_HeatComfortBehaviorCategory = EEnvironmentHeatcomfortBehaviorCategory.DEFAULT;
- m_EnvironmentSnapshot = new EnvironmentSnapshotData();
-
- m_Initialized = true;
- }
- // --------------------------------------------------------------------------------
- /**
- * \brief Main loop that runs calculations for various Environment parts (wetness, heatcomfort, watercontact, etc.)
- */
- void Update(float pDelta)
- {
- if (m_Player && m_Initialized)
- {
- m_RoofCheckTimer += pDelta;
- //! check if player is under roof (only if the Building check is false)
- if ( m_RoofCheckTimer >= GameConstants.ENVIRO_TICK_ROOF_RC_CHECK )
- {
- if ( !IsInsideBuilding() )
- CheckUnderRoof();
-
- m_RoofCheckTimer = 0;
- }
- m_Time += pDelta;
- if (m_Time >= GameConstants.ENVIRO_TICK_RATE)
- {
- m_Time = 0;
- m_WetDryTick++; // Sets whether it is time to add wetness to items and clothing
- //! Updates data
- CheckWaterContact(m_WaterLevel);
- CollectAndSetPlayerData();
- CollectAndSetEnvironmentData();
- GatherTemperatureSources();
- ProcessTemperatureSources();
-
- //! Process temperatures
- ProcessItemsTemperature(m_HeadParts);
- ProcessItemsTemperature(m_BodyParts);
- ProcessItemsTemperature(m_FeetParts);
- ProcessItemsInHandsTemperature();
- //! heat comfort calculation
- if (DetermineHeatcomfortBehavior())
- SetHeatcomfortDirectly();
- else
- ProcessHeatComfort();
- //! Process item wetness/dryness
- if (m_WetDryTick >= GameConstants.ENVIRO_TICKS_TO_WETNESS_CALCULATION)
- {
- if (IsWaterContact())
- {
- ProcessWetnessByWaterLevel(m_WaterLevel);
- }
- else if ((IsRaining() || (IsSnowing() && MiscGameplayFunctions.GetCombinedSnowfallWindValue() > SNOWFALL_WIND_COMBINED_THRESHOLD)) && !IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}))
- {
- ProcessItemsWetness(m_SlotIdsComplete);
- }
- else
- {
- ProcessItemsDryness();
- }
- //! setting of wetness/dryiness of player
- if ((m_ItemsWetnessMax < GameConstants.STATE_WET) && (m_Player.GetStatWet().Get() == 1))
- {
- m_Player.GetStatWet().Set(0);
- }
- else if ((m_ItemsWetnessMax >= GameConstants.STATE_WET) && (m_Player.GetStatWet().Get() == 0))
- {
- m_Player.GetStatWet().Set(1);
- }
- m_WetDryTick = 0;
- m_ItemsWetnessMax = 0; //! reset item wetness counter;
- }
- }
- }
- }
- // --------------------------------------------------------------------------------
- /**
- * \brief For safe-guards, waiting for the proper temperature to be set
- */
- bool IsTemperatureSet()
- {
- return m_IsTempSet;
- }
- /**
- * \brief Character's heat (calculated from movement speed multiplied by constant)
- * \return generated heat value
- */
- protected float GetPlayerHeat()
- {
- float heat = m_PlayerSpeed * GameConstants.ENVIRO_DEFAULT_ENTITY_HEAT;
- return heat;
- }
- /**
- * \brief Is character under roof (periodically checked - GameConstants.ENVIRO_TICK_ROOF_RC_CHECK).
- * Runs when player is not inside of building
- */
- bool IsUnderRoof()
- {
- return m_IsUnderRoof;
- }
- /**
- * \brief Is character inside building? (periodically checked - GameConstants.ENVIRO_TICK_ROOF_RC_CHECK).
- */
- bool IsInsideBuilding()
- {
- return m_Player.IsSoundInsideBuilding();
- }
-
- /**
- * \brief Is character in contact with water body? (periodically checked - GameConstants.ENVIRO_TICK_RATE).
- */
- protected bool IsWaterContact()
- {
- return m_IsInWater;
- }
-
- /**
- * \brief Returns true if character is child of given parent type(s)
- * @param typenames list of types to check against
- */
- private bool IsChildOfType(array<typename> typenames)
- {
- Object parent = Object.Cast(m_Player.GetParent());
- if (parent)
- return parent.IsAnyInherited(typenames);
-
- return false;
- }
- /**
- * \brief Is character under building's roof (periodically checked - GameConstants.ENVIRO_TICK_ROOF_RC_CHECK).
- * There might be situations where the surface under is external, but character is inside building
- */
- private bool IsUnderRoofBuilding()
- {
- return m_IsUnderRoofBuilding;
- }
- /**
- * \brief Rain phenomenon actual value > RAIN_LIMIT_LOW
- */
- protected bool IsRaining()
- {
- return m_Rain > RAIN_LIMIT_LOW;
- }
- /**
- * \brief Snowfall phenomenon actual value > SNOWFALL_LIMIT_LOW
- */
- protected bool IsSnowing()
- {
- return m_Snowfall > SNOWFALL_LIMIT_LOW;
- }
- /**
- * \brief Changes Heat Comfort curve behavior based on where the character is
- *
- * \return true if the behavior is altered otherwise false
- */
- protected bool DetermineHeatcomfortBehavior()
- {
- if (IsChildOfType({Car}))
- {
- CarScript car = CarScript.Cast(m_Player.GetParent());
- if (car && car.EngineIsOn())
- {
- m_HeatComfortBehaviorCategory = EEnvironmentHeatcomfortBehaviorCategory.CAR_ENGINE_ON;
- return true;
- }
- }
-
- m_HeatComfortBehaviorCategory = EEnvironmentHeatcomfortBehaviorCategory.DEFAULT;
-
- return false;
- }
-
- // --------------------------------------------------------------------------------
-
- /**
- * \brief Checks whether character is sheltered and sets the information
- */
- protected void CheckUnderRoof()
- {
- //! if inside vehicle return immediatelly
- if (IsChildOfType({Car}))
- {
- m_IsUnderRoof = false;
- m_IsUnderRoofBuilding = false;
- return;
- }
-
- float hitFraction;
- vector hitPosition, hitNormal;
- vector from = m_Player.GetPosition();
- vector to = from + "0 25 0";
- Object hitObject;
- PhxInteractionLayers collisionLayerMask = PhxInteractionLayers.ITEM_LARGE|PhxInteractionLayers.BUILDING|PhxInteractionLayers.VEHICLE;
-
- m_IsUnderRoof = DayZPhysics.RayCastBullet(from, to, collisionLayerMask, null, hitObject, hitPosition, hitNormal, hitFraction);
- m_IsUnderRoofBuilding = hitObject && hitObject.IsInherited(House);
- }
-
- // --------------------------------------------------------------------------------
-
- /**
- * \brief Checks player's contanct with water
- * @param[out] pWaterLevel water level height
- *
- * \return Nothing
- */
- protected void CheckWaterContact(out float pWaterLevel)
- {
- string surfType;
- int liquidType;
- m_IsInWater = false;
-
- if (m_Player.PhysicsGetLinkedEntity() || IsChildOfType({Transport}))
- return;
-
- if (m_Player.IsSwimming())
- {
- g_Game.SurfaceUnderObjectByBoneCorrectedLiquid(m_Player, SurfaceAnimationBone.RightFrontLimb, surfType, liquidType);
- m_SurfaceType = surfType;
- m_LiquidType = liquidType;
-
- m_IsInWater = true;
- m_Player.SetInWater(m_IsInWater);
-
- HumanMovementState hms = new HumanMovementState();
- m_Player.GetMovementState(hms);
-
- pWaterLevel = WATER_LEVEL_MID;
- if (hms.m_iMovement >= DayZPlayerConstants.MOVEMENTIDX_WALK)
- pWaterLevel = WATER_LEVEL_HIGH;
- return;
- }
-
- //! no valid surface under character
- if (IsUnderRoofBuilding())
- {
- m_IsInWater = false;
- return;
- }
-
- string impact;
- g_Game.SurfaceUnderObjectExCorrectedLiquid(m_Player, surfType, impact, liquidType);
-
- switch (liquidType)
- {
- case LIQUID_SALTWATER:
- case LIQUID_WATER:
- case LIQUID_RIVERWATER:
- case LIQUID_FRESHWATER:
- case LIQUID_STILLWATER:
- case LIQUID_HOTWATER:
- pWaterLevel = m_Player.GetCurrentWaterLevel();
- m_IsInWater = true;
- break;
- }
- //! sync info about water contact to player
- m_Player.SetInWater(m_IsInWater);
- //! update active surface
- m_SurfaceType = surfType;
- m_LiquidType = liquidType;
- }
-
- // --------------------------------------------------------------------------------
- /**
- * \brief Wind intensity (influence) modifier of temperature value
- *
- * \return float modifier used in temperature calculations
- */
- float GetWindModifierPerSurface()
- {
- if (IsUnderRoofBuilding())
- return 0.0;
- return g_Game.ConfigGetFloat("CfgSurfaces " + m_SurfaceType + " windModifier");
- }
-
- float GetTemperature()
- {
- return m_EnvironmentTemperature;
- }
- float GetTargetHeatComfort()
- {
- return m_TargetHeatComfort;
- }
-
- // --------------------------------------------------------------------------------
-
- /**
- * \brief Calculations of temperarute for different situations
- * - in water
- * - inside building / inside vehicle / under roof
- * - influence of UniversalTemperatureSource
- *
- * \return Resulting temperature of the environment
- */
- protected float GetEnvironmentTemperature()
- {
- float temperature = m_WorldData.GetTemperature(m_Player, EEnvironmentTemperatureComponent.ALTITUDE | EEnvironmentTemperatureComponent.OVERCAST);
-
- if (IsWaterContact())
- {
- float waterBodyTemperature = m_WorldData.GetLiquidTypeEnviroTemperature(m_LiquidType);
- temperature = waterBodyTemperature - m_WorldData.m_WaterContactTemperatureModifier;
-
- return temperature;
- }
-
- if (IsInsideBuilding() || m_IsUnderRoofBuilding)
- {
- temperature += m_WorldData.m_TemperatureInsideBuildingsModifier;
- }
- else if (IsChildOfType({Car}))
- {
- temperature += Math.AbsFloat(temperature * GameConstants.ENVIRO_TEMPERATURE_INSIDE_VEHICLE_COEF);
- return temperature;
- }
- else if (IsUnderRoof() && !m_IsUnderRoofBuilding)
- {
- temperature = m_WorldData.GetTemperature(m_Player, EEnvironmentTemperatureComponent.ALTITUDE | EEnvironmentTemperatureComponent.OVERCAST|EEnvironmentTemperatureComponent.FOG);
- temperature += WindEffectTemperatureValue(temperature) * GetWindModifierPerSurface() * GameConstants.ENVIRO_TEMPERATURE_UNDERROOF_COEF;
- }
- else
- {
- temperature = m_WorldData.GetTemperature(m_Player, EEnvironmentTemperatureComponent.ALTITUDE | EEnvironmentTemperatureComponent.OVERCAST|EEnvironmentTemperatureComponent.FOG);
- temperature += m_WorldData.GetTemperatureComponentValue(temperature, EEnvironmentTemperatureComponent.WIND) * GetWindModifierPerSurface();
- }
- // incorporate temperature from temperature sources (buffer)
- if (Math.AbsFloat(m_UTSAverageTemperature) > 0.0 && m_UTSAverageTemperature > temperature)
- temperature = m_UTSAverageTemperature;
-
- return temperature;
- }
-
- // --------------------------------------------------------------------------------
- /**
- * \brief Calculates soaking/drying delta based on character's location and weather
- *
- * \return Resulting wet delta modifier
- */
- float GetWetDelta()
- {
- float wetDelta = 0;
- if ( IsWaterContact() )
- {
- //! player is getting wet by movement/swimming in water (+differentiate wetDelta by water level)
- if (m_WaterLevel >= WATER_LEVEL_HIGH)
- {
- wetDelta = 1;
- }
- else if (m_WaterLevel >= WATER_LEVEL_MID && m_WaterLevel < WATER_LEVEL_HIGH)
- {
- wetDelta = 0.66;
- }
- else if (m_WaterLevel >= WATER_LEVEL_LOW && m_WaterLevel < WATER_LEVEL_MID)
- {
- wetDelta = 0.66;
- }
- else if (m_WaterLevel >= WATER_LEVEL_NONE && m_WaterLevel < WATER_LEVEL_LOW)
- {
- wetDelta = 0.33;
- }
- }
- else if (!IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}))
- {
- if (IsRaining())
- wetDelta = GameConstants.ENVIRO_WET_INCREMENT * GameConstants.ENVIRO_TICKS_TO_WETNESS_CALCULATION * (m_Rain) * (1 + (GameConstants.ENVIRO_WIND_EFFECT * m_Wind));
- if (IsSnowing() && MiscGameplayFunctions.GetCombinedSnowfallWindValue() > SNOWFALL_WIND_COMBINED_THRESHOLD)
- 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));
- }
- else
- {
- //! player is drying
- float tempEffect = Math.Max(m_PlayerHeat + GetEnvironmentTemperature(), 1.0);
- float weatherEffect = ((1 - (m_Fog * GameConstants.ENVIRO_FOG_DRY_EFFECT))) * (1 - (m_Clouds * GameConstants.ENVIRO_CLOUD_DRY_EFFECT));
- if (weatherEffect <= 0)
- {
- weatherEffect = 1.0;
- }
-
- wetDelta = -(GameConstants.ENVIRO_DRY_INCREMENT * weatherEffect * tempEffect);
- if (!IsInsideBuilding())
- {
- wetDelta *= 1 + (GameConstants.ENVIRO_WIND_EFFECT * m_Wind);
- }
- }
- return wetDelta;
- }
-
- // --------------------------------------------------------------------------------
- /**
- * \brief Sets character related value for furher use
- * - position
- * - movement speed
- * - player heat (actual speed * heat constant)
- */
- protected void CollectAndSetPlayerData()
- {
- vector playerPos = m_Player.GetPosition();
- m_PlayerHeightPos = playerPos[1];
- HumanCommandMove hcm = m_Player.GetCommand_Move();
- if (hcm)
- {
- m_PlayerSpeed = hcm.GetCurrentMovementSpeed();
- }
- m_PlayerHeat = GetPlayerHeat();
- }
-
- // Each tick updates current environment member variables
- /**
- * \brief Sets actual weather related values for further use (rain, snow, wind, etc.)
- */
- protected void CollectAndSetEnvironmentData()
- {
- Weather weather = g_Game.GetWeather();
- m_Rain = weather.GetRain().GetActual();
- m_Snowfall = weather.GetSnowfall().GetActual();
- m_DayOrNight = g_Game.GetMission().GetWorldData().GetDaytime();
- m_Fog = weather.GetFog().GetActual();
- m_Clouds = weather.GetOvercast().GetActual();
- m_Wind = weather.GetWindMagnitude().GetActual();
- SetEnvironmentTemperature();
- SetAreaGenericColdness();
- }
- // --------------------------------------------------------------------------------
-
- void SetEnvironmentTemperature()
- {
- m_IsTempSet = true;
- m_EnvironmentTemperature = GetEnvironmentTemperature();
- }
-
- /**
- * \brief Determines whether player is in cold area which restricts use of some actions (digging)
- */
- void SetAreaGenericColdness()
- {
- float heigthCorrectedTemp = m_WorldData.GetBaseEnvTemperatureAtObject(m_Player);
- m_Player.SetInColdArea(heigthCorrectedTemp <= GameConstants.COLD_AREA_TEMPERATURE_THRESHOLD);
- }
- /**
- * \brief Processes items wetness in player possession based on the current water level (the character is in)
- * @param pWaterLevel Water level height
- */
- protected void ProcessWetnessByWaterLevel(float pWaterLevel)
- {
- if (pWaterLevel >= WATER_LEVEL_HIGH)
- ProcessItemsWetness(m_SlotIdsComplete);
- else if (pWaterLevel >= WATER_LEVEL_MID && pWaterLevel < WATER_LEVEL_HIGH)
- ProcessItemsWetness(m_SlotIdsUpper);
- else if (pWaterLevel >= WATER_LEVEL_LOW && pWaterLevel < WATER_LEVEL_MID)
- ProcessItemsWetness(m_SlotIdsBottom);
- else if (pWaterLevel >= WATER_LEVEL_NONE && pWaterLevel < WATER_LEVEL_LOW)
- ProcessItemsWetness(m_SlotIdsLower);
- }
-
- // --------------------------------------------------------------------------------
- /**
- * \brief Soak items at specific Slot ID(s)
- * @param pSlotIds Inventory Slot IDs to process
- */
- protected void ProcessItemsWetness(array<int> pSlotIds)
- {
- EntityAI attachment;
-
- int playerAttachmentCount = m_Player.GetInventory().AttachmentCount();
-
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("Environment :: ProcessItemsWetness (update interval=%1s)", GameConstants.ENVIRO_TICK_RATE));
- #endif
- for (int attIdx = 0; attIdx < playerAttachmentCount; ++attIdx)
- {
- attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
- if (attachment.IsItemBase())
- {
- int attachmentSlotsCount = attachment.GetInventory().GetSlotIdCount();
- for (int attachmentSlotId = 0; attachmentSlotId < attachmentSlotsCount; ++attachmentSlotId)
- {
- int attachmentSlot = attachment.GetInventory().GetSlotId(attachmentSlotId);
- for (int i = 0; i < pSlotIds.Count(); ++i)
- {
- if (attachmentSlot == pSlotIds.Get(i))
- {
- ApplyWetnessToItem(ItemBase.Cast(attachment));
- break;
- }
- }
- }
- }
- }
-
- if (m_Player.GetItemInHands())
- ApplyWetnessToItem(m_Player.GetItemInHands());
- #ifdef ENABLE_LOGGING
- LogDryWetProcess("==========");
- #endif
- }
- protected void ApplyWetnessToItem(ItemBase pItem)
- {
- if (pItem)
- {
- ItemBase parentItem;
- bool isParentWet = false;
- bool parentContainsLiquid = false;
- InventoryLocation iLoc = new InventoryLocation();
- if (pItem.GetInventory().GetCurrentInventoryLocation(iLoc))
- {
- EntityAI parent = iLoc.GetParent();
- if (parent)
- {
- parentItem = ItemBase.Cast(parent);
- if (parentItem)
- {
- if (parentItem.GetWet() >= GameConstants.STATE_SOAKING_WET)
- isParentWet = true;
- if ((parentItem.GetLiquidType() != 0) && (parentItem.GetQuantity() > 0))
- parentContainsLiquid = true;
- }
- else
- isParentWet = true;
-
- if ((pItem.GetWet() > m_ItemsWetnessMax) && (parent == m_Player))
- m_ItemsWetnessMax = pItem.GetWet();
- }
- }
- if (isParentWet || parentContainsLiquid)
- {
- float soakingCoef = 0;
- if (parentContainsLiquid)
- {
- soakingCoef = pItem.GetSoakingIncrement("parentWithLiquid");
- #ifdef ENABLE_LOGGING
- 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);
- #endif
- }
- else if (isParentWet && parentItem)
- {
- if (pItem.GetWet() < parentItem.GetWet())
- soakingCoef = GetWetDelta();
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("%1 (soak coef=%2/s, current wetness=%3) [parent wet]", pItem.GetDisplayName(), soakingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
- #endif
- }
- else
- {
- soakingCoef = GetWetDelta();
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("%1 (soak coef=%2/s, current wetness=%3) [normal]", pItem.GetDisplayName(), soakingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
- #endif
- }
- pItem.AddWet(soakingCoef);
- if (pItem.GetInventory().GetCargo())
- {
- int inItemCount = pItem.GetInventory().GetCargo().GetItemCount();
- for (int i = 0; i < inItemCount; ++i)
- {
- ItemBase inItem;
- if (Class.CastTo(inItem, pItem.GetInventory().GetCargo().GetItem(i)))
- ApplyWetnessToItem(inItem);
- }
- }
-
- int attCount = pItem.GetInventory().AttachmentCount();
- if (attCount > 0)
- {
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- EntityAI attachment = pItem.GetInventory().GetAttachmentFromIndex(attIdx);
- ItemBase itemAtt = ItemBase.Cast(attachment);
- if (itemAtt)
- ApplyWetnessToItem(itemAtt);
- }
- }
- }
- }
- }
- // --------------------------------------------------------------------------------
- /**
- * \brief Dry items in player possession
- */
- protected void ProcessItemsDryness()
- {
- EntityAI attachment;
- ItemBase item;
-
- int attCount = m_Player.GetInventory().AttachmentCount();
-
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("Environment :: ProcessItemsDryness (update interval=%1s)", GameConstants.ENVIRO_TICK_RATE));
- #endif
- EnvironmentDrynessData drynessData = new EnvironmentDrynessData();
- drynessData.m_UseTemperatureSources = m_HasTemperatureSources;
- if (m_HasTemperatureSources)
- {
- float distance = vector.Distance(m_UTemperatureSources[0].GetPosition(), m_Player.GetPosition());
- distance = Math.Max(distance, 0.1);
- drynessData.m_TemperatureSourceDistance = distance;
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("distance to heatsource: %1 m", distance));
- #endif
- }
-
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
- if (attachment && attachment.IsItemBase())
- {
- item = ItemBase.Cast(attachment);
- if (item)
- ApplyDrynessToItemEx(item, drynessData);
- }
- }
- if (m_Player.GetItemInHands())
- {
- ApplyDrynessToItemEx(m_Player.GetItemInHands(), drynessData);
- }
-
- #ifdef ENABLE_LOGGING
- LogDryWetProcess("==========");
- #endif
- }
-
- protected void ApplyDrynessToItem(ItemBase pItem)
- {
- EnvironmentDrynessData drynessData = new EnvironmentDrynessData();
- ApplyDrynessToItemEx(pItem, drynessData);
- }
-
- protected void ApplyDrynessToItemEx(ItemBase pItem, EnvironmentDrynessData pDrynessData)
- {
- if (pItem)
- {
- float dryingIncrement = pItem.GetDryingIncrement("player");
- if (pDrynessData.m_UseTemperatureSources)
- dryingIncrement = pItem.GetDryingIncrement("playerHeatSource");
-
- ItemBase parentItem;
- bool isParentWet = false;
- bool parentContainsLiquid = false;
-
- InventoryLocation iLoc = new InventoryLocation();
- if (pItem.GetInventory().GetCurrentInventoryLocation(iLoc))
- {
- EntityAI parent = iLoc.GetParent();
- if (parent)
- {
- parentItem = ItemBase.Cast(parent);
- if (parentItem)
- {
- if (parentItem.GetWet() >= GameConstants.STATE_SOAKING_WET)
- isParentWet = true;
-
- if ((parentItem.GetLiquidType() != 0) && (parentItem.GetQuantity() > 0))
- parentContainsLiquid = true;
- }
-
- if ((pItem.GetWet() > m_ItemsWetnessMax) && (parent == m_Player))
- m_ItemsWetnessMax = pItem.GetWet();
- }
- }
-
- float dryingCoef = 0;
-
- if (!isParentWet && !parentContainsLiquid)
- {
-
- dryingCoef = (-1 * GameConstants.ENVIRO_TICK_RATE * dryingIncrement) / pDrynessData.m_TemperatureSourceDistance;
- if (pItem.GetWet() >= GameConstants.STATE_DAMP)
- {
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("%1 (dry coef=%2/s, current wetness=%3) [normal]", pItem.GetDisplayName(), dryingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
- #endif
- pItem.AddWet(dryingCoef);
- }
-
- if (pItem.GetInventory().GetCargo())
- {
- int inItemCount = pItem.GetInventory().GetCargo().GetItemCount();
- for (int i = 0; i < inItemCount; ++i)
- {
- ItemBase inItem;
- if (Class.CastTo(inItem, pItem.GetInventory().GetCargo().GetItem(i)))
- ApplyDrynessToItemEx(inItem, pDrynessData);
- }
- }
-
- int attCount = pItem.GetInventory().AttachmentCount();
- if (attCount > 0)
- {
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- EntityAI attachment = pItem.GetInventory().GetAttachmentFromIndex(attIdx);
- ItemBase itemAtt;
- if (ItemBase.CastTo(itemAtt, attachment))
- ApplyDrynessToItemEx(itemAtt, pDrynessData);
- }
- }
- }
-
- if (parentContainsLiquid)
- {
- //! adds wetness to item inside parent item containing liquid
- dryingCoef = (GameConstants.ENVIRO_TICK_RATE * pItem.GetSoakingIncrement("parentWithLiquid")) / pDrynessData.m_TemperatureSourceDistance;
- #ifdef ENABLE_LOGGING
- 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);
- #endif
- pItem.AddWet(dryingCoef);
- }
-
- if (isParentWet)
- {
- //! adds wetness to item inside wet parent item
- dryingCoef = (GameConstants.ENVIRO_TICK_RATE * pItem.GetSoakingIncrement("wetParent")) / pDrynessData.m_TemperatureSourceDistance;
- #ifdef ENABLE_LOGGING
- LogDryWetProcess(string.Format("%1 (dry coef=%2/s, current wetness=%3) [parent wet]", pItem.GetDisplayName(), dryingCoef / GameConstants.ENVIRO_TICK_RATE, pItem.GetWet()), parentItem != null);
- #endif
- pItem.AddWet(dryingCoef);
- }
- }
- }
- // --------------------------------------------------------------------------------
- /**
- * \brief Calculates and process player's heatcomfort related to defined body parts
- */
- protected void ProcessHeatComfort()
- {
- float hcPenaltyTotal //! Heat Comfort Penalty
-
- // NEW body parts => splitted
- float hcBodyPartTotal, hcBodyPart;
- float hBodyPartTotal, hBodyPart;
-
- float heatComfortSum = 0.0;
- float heatItems = 0.0;
-
- #ifdef ENABLE_LOGGING
- LogItemHeat("====================");
- #endif
- BodyPartHeatProperties(InventorySlots.HEADGEAR, GameConstants.ENVIRO_HEATCOMFORT_HEADGEAR_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.MASK, GameConstants.ENVIRO_HEATCOMFORT_MASK_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.VEST, GameConstants.ENVIRO_HEATCOMFORT_VEST_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.BODY, GameConstants.ENVIRO_HEATCOMFORT_BODY_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.BACK, GameConstants.ENVIRO_HEATCOMFORT_BACK_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.GLOVES, GameConstants.ENVIRO_HEATCOMFORT_GLOVES_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.LEGS, GameConstants.ENVIRO_HEATCOMFORT_LEGS_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.FEET, GameConstants.ENVIRO_HEATCOMFORT_FEET_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
- BodyPartHeatProperties(InventorySlots.HIPS, GameConstants.ENVIRO_HEATCOMFORT_HIPS_WEIGHT, hcBodyPart, hBodyPart);
- hcBodyPartTotal += hcBodyPart; hBodyPartTotal += hBodyPart;
-
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.HEADGEAR, GameConstants.ENVIRO_HEATCOMFORT_HEADGEAR_WEIGHT);
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.MASK, GameConstants.ENVIRO_HEATCOMFORT_MASK_WEIGHT);
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.BODY, GameConstants.ENVIRO_HEATCOMFORT_BODY_WEIGHT);
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.GLOVES, GameConstants.ENVIRO_HEATCOMFORT_GLOVES_WEIGHT);
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.LEGS, GameConstants.ENVIRO_HEATCOMFORT_LEGS_WEIGHT);
- hcPenaltyTotal += NakedBodyPartHeatComfortPenalty(InventorySlots.FEET, GameConstants.ENVIRO_HEATCOMFORT_FEET_WEIGHT);
- heatItems = hBodyPartTotal;
- heatComfortSum = hcBodyPartTotal;
- heatComfortSum += hcPenaltyTotal; //! heatcomfort body parts penalties
- //! Stomach temperature influence to heatcomfort
- {
- if (m_Player.GetStomach().GetStomachVolume() > 0.0)
- {
- float stomachContentTemperature = m_Player.GetStomach().GetStomachTemperature();
- if (stomachContentTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT)
- {
- stomachContentTemperature = Math.Remap(
- -10.0,
- GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT,
- -GameConstants.ENVIRO_STOMACH_WEIGHT,
- 0.0,
- stomachContentTemperature,
- );
- }
- else if (stomachContentTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- stomachContentTemperature = Math.Remap(
- GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT,
- 70.0,
- 0.0,
- GameConstants.ENVIRO_STOMACH_WEIGHT,
- stomachContentTemperature,
- );
- }
- else
- stomachContentTemperature = 0.0;
- heatComfortSum += stomachContentTemperature * GameConstants.ENVIRO_STOMACH_WEIGHT;
- }
- }
- float targetHeatComfort = (heatComfortSum + heatItems + (GetPlayerHeat() / 100)) + EnvTempToCoef(m_EnvironmentTemperature);
-
- //! uses the raw targetHeatComfort data
- m_EnvironmentSnapshot.m_ClothingHeatComfort = hcBodyPartTotal;
- m_EnvironmentSnapshot.m_TargetHeatComfort = targetHeatComfort;
- ProcessHeatBuffer(m_EnvironmentSnapshot);
-
- if (m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
- targetHeatComfort = Math.Clamp(targetHeatComfort, 0.0, m_Player.GetStatHeatComfort().GetMax());
- else
- targetHeatComfort = Math.Clamp(targetHeatComfort, m_Player.GetStatHeatComfort().GetMin(), m_Player.GetStatHeatComfort().GetMax());
- targetHeatComfort = Math.Round(targetHeatComfort * 100) * 0.01;
-
- float dynamicHeatComfort;
-
- {
- float direction = 1.0;
- if (targetHeatComfort < 0.0)
- direction = -1.0;
-
- if (Math.AbsFloat(targetHeatComfort - m_HeatComfort) <= GameConstants.ENVIRO_HEATCOMFORT_MAX_STEP_SIZE)
- dynamicHeatComfort = m_AverageHeatComfortBuffer.Add(targetHeatComfort);
- else
- dynamicHeatComfort = m_AverageHeatComfortBuffer.Add((Math.AbsFloat(targetHeatComfort) - GameConstants.ENVIRO_HEATCOMFORT_MAX_STEP_SIZE) * direction);
- }
-
- dynamicHeatComfort = Math.Round(dynamicHeatComfort * 100) * 0.01;
- m_HeatComfort = dynamicHeatComfort;
- SetTargetHeatComfort(targetHeatComfort);
- m_Player.GetStatHeatComfort().Set(m_HeatComfort);
- }
-
- protected void SetTargetHeatComfort(float value)
- {
- m_TargetHeatComfort = value;
- }
-
- protected void SetHeatcomfortDirectly()
- {
- if (m_HeatComfortBehaviorCategory == EEnvironmentHeatcomfortBehaviorCategory.CAR_ENGINE_ON)
- {
- float targetHeatComfort = 0.0;
- float dynamicHeatComfort = m_AverageHeatComfortBuffer.Add(targetHeatComfort);
-
- m_HeatComfort = dynamicHeatComfort;
-
- SetTargetHeatComfort(0.0);
- m_Player.GetStatHeatComfort().Set(dynamicHeatComfort);
- }
- }
-
- // --------------------------------------------------------------------------------
- protected void ProcessHeatBuffer(EnvironmentSnapshotData data)
- {
- if (m_HeatComfortBehaviorCategory == EEnvironmentHeatcomfortBehaviorCategory.DEFAULT)
- {
- float applicableHeatbuffer = GetApplicableHeatbuffer();
-
- //! dynamic HB cap based on actual heatcomfort (from cloths)
- float heatBufferCap = Math.InverseLerp(0.0, GameConstants.ENVIRO_HEATCOMFORT_WEIGHT_SUMMARY, data.m_ClothingHeatComfort);
- float heatBufferMax = GameConstants.ENVIRO_PLAYER_HEATBUFFER_CAPACITY_MIN + heatBufferCap * (1 - GameConstants.ENVIRO_PLAYER_HEATBUFFER_CAPACITY_MIN);
- m_Player.SetHeatBufferDynamicMax(heatBufferMax);
-
- PlayerStat<float> heatBuffer = m_Player.GetStatHeatBuffer();
- //! deplete the heat buffer if there is difference in HB capacity (eg.: cloths were removed)
- if (heatBufferCap < m_HeatBufferCapPrevious)
- {
- float heatBufferValueCorrection = GameConstants.ENVIRO_PLAYER_HEATBUFFER_INCREASE / (heatBufferMax * ((-GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
- heatBuffer.Add(-heatBufferValueCorrection);
- m_HeatBufferCapPrevious = heatBufferCap;
- }
-
- float increaseRate = 0.0;
- float decreaseRate = 0.0;
- {
- increaseRate = GameConstants.ENVIRO_PLAYER_HEATBUFFER_INCREASE / (heatBufferMax * (( -GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
- decreaseRate = GameConstants.ENVIRO_PLAYER_HEATBUFFER_DECREASE / (heatBufferMax * (( GameConstants.ENVIRO_PLAYER_HEATBUFFER_TEMP_AFFECT * data.m_TargetHeatComfort) + 1 ));
-
- float decreaseRateByHeatBufferStageCoef = 1;
-
- if (heatBufferMax > HeatBufferMdfr.STAGE_THRESHOLDS[1])
- {
- float heatBufferMaxInversed = Math.InverseLerp(HeatBufferMdfr.STAGE_THRESHOLDS[1], 1.0, heatBufferMax);
- switch (m_Player.GetHeatBufferStage())
- {
- case 2:
- decreaseRateByHeatBufferStageCoef = Math.Lerp(
- GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[2][0],
- GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[2][1],
- heatBufferMaxInversed,
- );
- break;
- case 1:
- decreaseRateByHeatBufferStageCoef = Math.Lerp(
- GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][0],
- GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][1],
- heatBufferMaxInversed,
- );
- break;
- }
- }
- else
- {
- decreaseRateByHeatBufferStageCoef = GameConstants.ENVIRO_PLAYER_HEATBUFFER_STAGE_RATELIMIT[1][0];
- }
-
- decreaseRate *= decreaseRateByHeatBufferStageCoef;
-
- if (m_IsInWater)
- decreaseRate *= GameConstants.ENVIRO_PLAYER_HEATBUFFER_WATEREFFECT * m_WaterLevel;
- }
- if (!m_HasTemperatureSources)
- {
- if (m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
- {
- if (m_HeatBufferTimer >= 1.0)
- heatBuffer.Add(-decreaseRate);
- else
- m_HeatBufferTimer = 1.0;
- }
- else
- {
- m_HeatBufferTimer = 0.0;
- if (applicableHeatbuffer > 0.0)
- heatBuffer.Add(-decreaseRate);
- else if (applicableHeatbuffer != 0.0 && !m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
- heatBuffer.Set(0.0);
- }
- }
- else
- {
- if (m_HeatComfort > PlayerConstants.THRESHOLD_HEAT_COMFORT_MINUS_WARNING && m_UTSAverageTemperature > 0) // m_UTSAverageTemperature can be negative
- {
- if (applicableHeatbuffer < heatBufferMax)
- {
- heatBuffer.Add(increaseRate);
- m_HeatBufferCapPrevious = heatBufferCap;
- }
- }
- else if (applicableHeatbuffer > 0.0)
- heatBuffer.Add(-decreaseRate);
- else if (applicableHeatbuffer != 0.0 && !m_Player.GetModifiersManager().IsModifierActive(eModifiers.MDF_HEATBUFFER))
- heatBuffer.Set(0.0);
-
- m_HeatBufferTimer = 0.0;
- }
- }
- }
-
- protected float GetApplicableHeatbuffer()
- {
- PlayerStat<float> heatBuffer = m_Player.GetStatHeatBuffer();
- float applicableHeatbuffer = Math.Round((heatBuffer.Get() / heatBuffer.GetMax()) * 1000) * 0.001;
- return applicableHeatbuffer;
- }
-
- // --------------------------------------------------------------------------------
- /**
- * \brief Iterate through items in player posession (by given body parts) and cool/warm them to neutral temparature
- * @param pBodyPartIds List of body parts to iterate through (see InventorySlots)
- */
- protected void ProcessItemsTemperature(array<int> pBodyPartIds)
- {
- EntityAI attachment;
- ItemBase item;
-
- int attCount = m_Player.GetInventory().AttachmentCount();
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
- item = ItemBase.Cast(attachment);
- int attachmentSlot = attachment.GetInventory().GetSlotId(0);
-
- //! go through all body parts we've defined for that zone (ex.: head, body, feet)
- for (int i = 0; i < pBodyPartIds.Count(); ++i)
- {
- if (attachmentSlot == pBodyPartIds[i])
- {
- float heatPermCoef = item.GetHeatPermeabilityCoef();
- //first handle the item itself, if necessary
- if (item.CanHaveTemperature() && !item.IsSelfAdjustingTemperature())
- SetProcessedItemTemperature(item, heatPermCoef);
-
- ProcessItemHierarchyRecursive(item, heatPermCoef);
- }
- }
- }
- }
- /**
- * \brief Process temperature of item in character hands and cool/warm it to neutral temparature
- */
- protected void ProcessItemsInHandsTemperature()
- {
- ItemBase item = m_Player.GetItemInHands();
- if (item)
- {
- float heatPermCoef = item.GetHeatPermeabilityCoef();
- //first handle the item itself, if necessary
- if (item.CanHaveTemperature() && !item.IsSelfAdjustingTemperature())
- SetProcessedItemTemperature(item,heatPermCoef);
-
- ProcessItemHierarchyRecursive(item,heatPermCoef);
- }
- }
-
- protected void ProcessItemHierarchyRecursive(ItemBase item, float heatPermeabilityCoef = 1.0)
- {
- float heatPermCoef = heatPermeabilityCoef;
-
- // go through any attachments and cargo, recursive
- int inventoryAttCount = item.GetInventory().AttachmentCount();
- if (inventoryAttCount > 0)
- {
- ItemBase attachmentItem;
- for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
- {
- if (Class.CastTo(attachmentItem,item.GetInventory().GetAttachmentFromIndex(inAttIdx)))
- {
- heatPermCoef = heatPermeabilityCoef;
- heatPermCoef *= attachmentItem.GetHeatPermeabilityCoef();
-
- if (attachmentItem.CanHaveTemperature() && !attachmentItem.IsSelfAdjustingTemperature())
- {
- SetProcessedItemTemperature(attachmentItem,heatPermCoef);
- }
-
- ProcessItemHierarchyRecursive(attachmentItem,heatPermCoef);
- }
- }
- }
-
- if (item.GetInventory().GetCargo())
- {
- int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
- if (inventoryItemCount > 0)
- {
- ItemBase inventoryItem;
- for (int j = 0; j < inventoryItemCount; ++j)
- {
- if (Class.CastTo(inventoryItem,item.GetInventory().GetCargo().GetItem(j)))
- {
- heatPermCoef = heatPermeabilityCoef;
- heatPermCoef *= inventoryItem.GetHeatPermeabilityCoef();
-
- if (inventoryItem.CanHaveTemperature() && !inventoryItem.IsSelfAdjustingTemperature())
- {
- SetProcessedItemTemperature(inventoryItem,heatPermCoef);
- }
-
- ProcessItemHierarchyRecursive(inventoryItem,heatPermCoef);
- }
- }
- }
- }
- }
-
- protected void SetProcessedItemTemperature(ItemBase item, float heatPermeabilityCoef = 1.0)
- {
- float targetTemperature = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_MIDDLE;
- bool globalCooling = true;
- //! swimming special behavior
- if (m_Player.IsSwimming())
- {
- SetItemHeatingCoef(GameConstants.TEMP_COEF_SWIMMING);
- targetTemperature = m_WorldData.GetLiquidTypeEnviroTemperature(m_LiquidType);
- globalCooling = false;
- }
- if (item.GetTemperature() != targetTemperature || !item.IsFreezeThawProgressFinished())
- {
- TemperatureDataInterpolated temperatureData = new TemperatureDataInterpolated(
- targetTemperature,
- ETemperatureAccessTypes.ACCESS_INVENTORY,
- GameConstants.ENVIRO_TICK_RATE,
- m_ItemTemperatureCoef,
- heatPermeabilityCoef,
- );
- temperatureData.m_UseGlobalCooling = globalCooling;
- item.SetTemperatureEx(temperatureData);
- }
- }
-
- // --------------------------------------------------------------------------------
-
- protected float EnvTempToCoef(float pTemp)
- {
- return (pTemp - GameConstants.ENVIRO_PLAYER_COMFORT_TEMP) / GameConstants.ENVIRO_TEMP_EFFECT_ON_PLAYER;
- }
- /**
- * \brief Iterate through given body part and calculates heatcofort and item heat value
- * @param pBodyPartIds List of body parts to iterate through (see InventorySlots)
- * @param pCoef Multiplier used for heatcomfort enhancing
- * @param[out] pHeatComfort overall heatcomfort from items of given body part
- * @param[out] pHeat overall heat from items for given body part
- */
- protected void BodyPartHeatProperties(int pBodyPartId, float pCoef, out float pHeatComfort, out float pHeat)
- {
- pHeatComfort = 0;
- pHeat = 0;
- int attCount = m_Player.GetInventory().AttachmentCount();
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- EntityAI attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
- if (attachment.IsClothing())
- {
- ItemBase item = ItemBase.Cast(attachment);
- int attachmentSlot = attachment.GetInventory().GetSlotId(0);
- if (attachmentSlot == pBodyPartId)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("BodyPartHeatProperties (%1)", EnumTools.EnumToString(InventorySlots, pBodyPartId)));
- #endif
- float itemHeatcomfort = 0;
- float itemTemperature = 0;
-
- // go through any attachments and cargo (only current level, ignore nested containers - they isolate)
- int inventoryAttCount = item.GetInventory().AttachmentCount();
- if (inventoryAttCount > 0)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("attachments:"), false);
- #endif
- for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
- {
- EntityAI inAttachment = item.GetInventory().GetAttachmentFromIndex(inAttIdx);
- ItemBase attachmentItem = ItemBase.Cast(inAttachment);
- if (attachmentItem && attachmentItem.CanHaveTemperature())
- {
- itemTemperature = attachmentItem.GetTemperature();
- if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- itemHeatcomfort = NormalizedTemperature(itemTemperature) * attachmentItem.GetQuantityNormalizedScripted() * attachmentItem.GetTemperaturePerQuantityWeight();
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("%1: temperature=%2 heat=%3", attachmentItem, itemTemperature, pHeat), true);
- #endif
- pHeat += itemHeatcomfort;
- }
- }
- }
- }
- if (item.GetInventory().GetCargo())
- {
- int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
-
- if (inventoryItemCount > 0)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("cargo:"), false);
- #endif
- for (int j = 0; j < inventoryItemCount; ++j)
- {
- ItemBase inventoryItem = ItemBase.Cast(item.GetInventory().GetCargo().GetItem(j));
- if (inventoryItem && inventoryItem.CanHaveTemperature())
- {
- itemTemperature = inventoryItem.GetTemperature();
- if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- itemHeatcomfort = NormalizedTemperature(itemTemperature) * inventoryItem.GetQuantityNormalizedScripted() * inventoryItem.GetTemperaturePerQuantityWeight();
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("%1: temperature=%2 heat=%3", inventoryItem, itemTemperature, itemHeatcomfort), true);
- #endif
- pHeat += itemHeatcomfort;
- }
- }
- }
- }
- }
-
- pHeatComfort = MiscGameplayFunctions.GetCurrentItemHeatIsolation(item) * pCoef;
-
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("overall heat from items=%1 (coef applied)", pHeat));
- LogItemHeat("");
- #endif
- break;
- }
- }
- }
- }
- /**
- * \brief Calculates penalty value for heatcomfort - this simulates uncovered body part reaction
- * @param pBodyPartSlotId InventorySlot ID to check
- * @param pCoef external coefficient used for that slot
- * \return Value of penalty for given slot ID
- */
- protected float NakedBodyPartHeatComfortPenalty(int pBodyPartSlotId, float pCoef)
- {
- float penalty = 0.0;
-
- if (!IsInsideBuilding() && !IsUnderRoof() && !IsChildOfType({Car}) && !IsWaterContact())
- {
- if (m_Rain > GameConstants.ENVIRO_NAKED_BODY_PENALTY_RAIN_MIN_VALUE || m_Snowfall > GameConstants.ENVIRO_NAKED_BODY_PENALTY_SNOWFALL_MIN_VALUE)
- {
- penalty += GameConstants.ENVIRO_ISOLATION_WETFACTOR_DRENCHED;
- penalty *= pCoef;
- }
- }
-
- return penalty;
- }
- // --------------------------------------------------------------------------------
- /**
- * \brief Checks characters proximity for usable Universal Temperature Sources and register them
- */
- protected void GatherTemperatureSources()
- {
- m_UTemperatureSources.Clear();
-
- // Calculate min and max positions of the box
- vector pos = m_Player.GetPosition();
- vector minPos = pos - Vector(GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS / 2, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS);
- vector maxPos = pos + Vector(GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS / 2, GameConstants.ENVIRO_TEMP_SOURCES_LOOKUP_RADIUS);
- array<EntityAI> nearestObjects = {};
- DayZPlayerUtils.SceneGetEntitiesInBox(minPos, maxPos, nearestObjects, QueryFlags.STATIC|QueryFlags.DYNAMIC); //STATIC catches area effects and other static (or 'static') sources
-
- foreach (EntityAI nearestEntity : nearestObjects)
- {
- if (nearestEntity.IsUniversalTemperatureSource() && nearestEntity != m_Player)
- {
- //! skip - Temperature Source is not affecting player entities
- if (!nearestEntity.GetUniversalTemperatureSource().GetLambda().AffectsPlayer())
- continue;
- //! skip - Temperature Source is too far
- if (vector.DistanceSq(pos, nearestEntity.GetPosition()) > Math.SqrFloat(nearestEntity.GetUniversalTemperatureSource().GetMaxRange()))
- continue;
- m_UTemperatureSources.Insert(nearestEntity.GetUniversalTemperatureSource());
- }
- }
- if (m_Player.GetItemInHands() && m_Player.GetItemInHands().IsUniversalTemperatureSource())
- m_UTemperatureSources.Insert(m_Player.GetItemInHands().GetUniversalTemperatureSource());
- }
-
- /**
- * \brief Processes registered UTSources and calculates resulting m_UTSAverageTemperature
- */
- protected void ProcessTemperatureSources()
- {
- int UTScount = m_UTemperatureSources.Count();
- if (UTScount == 0)
- {
- m_HasTemperatureSources = false;
- OnTemperatureSourcesLeft();
- m_UTSAverageTemperatureBuffer.Add(0.0);
- m_UTSAverageTemperature = 0.0;
- SetItemHeatingCoef(GameConstants.TEMP_COEF_INVENTORY);
- return;
- }
- array<float> utsTemperatures = new array<float>();
-
- // get temperature from the source (based on distance), save it for min/max filtering
- float itemCoefAverage = 0.0;
- foreach (UTemperatureSource tempSource : m_UTemperatureSources)
- {
- utsTemperatures.Insert(CalcTemperatureFromTemperatureSource(tempSource));
- itemCoefAverage += tempSource.GetTemperatureItemCoef();
- }
- itemCoefAverage /= UTScount;
- SetItemHeatingCoef(itemCoefAverage);
-
- float min = MiscGameplayFunctions.GetMinValue(utsTemperatures);
- float max = MiscGameplayFunctions.GetMaxValue(utsTemperatures);
- if (max > 0 && min < 0)
- {
- //! adds average of 2 most significat sources to buffer
- m_UTSAverageTemperature = m_UTSAverageTemperatureBuffer.Add((max + min) * 0.5);
- }
- else
- {
- m_UTSAverageTemperature = m_UTSAverageTemperatureBuffer.Add(max);
- }
- if (m_HasTemperatureSources == false)
- OnTemperatureSourcesEnter();
- m_HasTemperatureSources = true;
- }
-
- protected void SetItemHeatingCoef(float val)
- {
- m_ItemTemperatureCoef = val;
- }
-
- /**
- * \brief Event fired when characters enters into UTSource proximity
- */
- protected void OnTemperatureSourcesEnter();
-
- /**
- * \brief Event fired when characters leave the UTSource proximity
- */
- protected void OnTemperatureSourcesLeft();
-
- float GetUniversalSourcesTemperageAverage()
- {
- return m_UTSAverageTemperature;
- }
-
- float CalcTemperatureFromTemperatureSource(notnull UTemperatureSource uts)
- {
- float distance = vector.Distance(m_Player.GetPosition(), uts.GetPosition());
- distance = Math.Max(distance, 0.1); //min distance cannot be 0 (division by zero)
- float temperature = 0;
- //! heat transfer through air to player (env temperature)
- if (distance > uts.GetFullRange())
- {
- float distFactor = Math.InverseLerp(uts.GetMaxRange(), uts.GetFullRange(), distance);
- temperature = uts.GetTemperatureCap() * distFactor;
- }
- else
- {
- temperature = uts.GetTemperatureCap();
- }
- return temperature;
- }
-
- // --------------------------------------------------------------------------------
- //! debug
- #ifdef DIAG_DEVELOPER
- EnvDebugData GetEnvDebugData()
- {
- EnvDebugData data = new EnvDebugData();
- data.Synch(this, m_Player);
- return data;
- }
-
- void ShowEnvDebugPlayerInfo(bool enabled)
- {
- EnvDebugData data = GetEnvDebugData();
- DisplayEnvDebugPlayerInfo(enabled, data);
- }
-
- static void DisplayEnvDebugPlayerInfo(bool enabled, EnvDebugData data)
- {
- int windowPosX = 10;
- int windowPosY = 200;
- Object obj;
- DbgUI.Begin("Player stats", windowPosX, windowPosY);
- if ( enabled )
- {
- DbgUI.Text(string.Format("Heat comfort(target): %1", data.m_PlayerData.m_HeatComfortTarget));
- DbgUI.Text(string.Format("Heat comfort(dynamic): %1", data.m_PlayerData.m_HeatComfortDynamic));
- DbgUI.Text(string.Format("Inside: %1 (%2)", data.m_PlayerData.m_Inside, data.m_PlayerData.m_Surface));
- DbgUI.Text(string.Format("Under roof: %1 (%2)", data.m_PlayerData.m_UnderRoof, data.m_PlayerData.m_UnderRoofTimer));
- if ( data.m_PlayerData.m_WaterLevel > 0 )
- {
- DbgUI.Text(string.Format("Water Level: %1", data.m_PlayerData.m_WaterLevel));
- }
-
- }
- DbgUI.End();
-
- DbgUI.Begin("Weather stats:", windowPosX, windowPosY + 200);
- if ( enabled )
- {
- DbgUI.Text(string.Format("Env temperature (base): %1", data.m_MiscData.m_TemperatureBase));
- DbgUI.Text(string.Format("Env temperature (height corrected): %1", data.m_MiscData.m_HeightCorrectedTemperature));
- DbgUI.Text(string.Format("Env temperature (modfied): %1", data.m_MiscData.m_TemperatureModified));
- DbgUI.Text(string.Format("Wind magnitude(surface mult): %1 (x%2)", data.m_WeatherData.m_Wind, data.m_WeatherData.m_WindModifier));
- DbgUI.Text(string.Format("Rain: %1", data.m_WeatherData.m_Rain));
- DbgUI.Text(string.Format("Snow: %1", data.m_WeatherData.m_Snowfall));
- DbgUI.Text(string.Format("Datetime: %1", WorldDataDaytime.ToString(g_Game.GetMission().GetWorldData().GetDaytime())));
- DbgUI.Text(string.Format("Fog: %1", data.m_WeatherData.m_Fog));
- DbgUI.Text(string.Format("Clouds: %1", data.m_WeatherData.m_Clouds));
- DbgUI.Text(string.Format("Wet delta: %1", data.m_MiscData.m_WetDelta));
- }
- DbgUI.End();
- }
-
- void FillDebugWeatherData(EnvDebugWeatherData data)
- {
- data.m_Wind = m_Wind;
- data.m_WindModifier = GetWindModifierPerSurface();
- data.m_Rain = m_Rain;
- data.m_Snowfall = m_Snowfall;
- data.m_Fog = m_Fog;
- data.m_Clouds = m_Clouds;
- }
- #endif
- string GetDebugMessage()
- {
- string message;
- message += "Player stats";
- message += "\nHeat comfort(target): " + GetTargetHeatComfort().ToString();
- message += "\nHeat comfort(dynamic): " + m_HeatComfort.ToString();
-
- int liquidType;
- string impact, surfaceType;
- g_Game.SurfaceUnderObjectExCorrectedLiquid(m_Player, surfaceType, impact, liquidType);
-
- message += "\nInside: " + IsInsideBuilding().ToString();
- message += "\nSurface: " + surfaceType;
- message += "\nLiquid: " + liquidType;
- message += "\nUnder roof: " + m_IsUnderRoof.ToString() + " (" + GetNextRoofCheck() + ")";
- if (IsWaterContact() && m_WaterLevel > WATER_LEVEL_NONE)
- {
- message += "\nWater Level: " + m_WaterLevel;
- }
- message += "\n\nWeather stats";
- message += "\nEnv temperature (base): " + m_WorldData.GetBaseEnvTemperature().ToString();
- message += "\nEnv temperature (height corrected): " + m_WorldData.GetBaseEnvTemperatureAtObject(m_Player);
- message += "\nEnv temperature (modified): " + m_EnvironmentTemperature.ToString();
- message += "\nWind: " + m_Wind.ToString() + " (x" + GetWindModifierPerSurface() + ")";
- message += "\nRain: " + m_Rain.ToString();
- message += "\nSnow: " + m_Snowfall.ToString();
- message += "\nDatetime: " + WorldDataDaytime.ToString(m_DayOrNight);
- message += "\nFog: " + m_Fog.ToString();
- message += "\nClouds: " + m_Clouds.ToString();
- message += "\nWet delta: " + GetWetDelta().ToString();
-
- return message;
- }
-
- int GetNextRoofCheck()
- {
- return (GameConstants.ENVIRO_TICK_ROOF_RC_CHECK - m_RoofCheckTimer) + 1;
- }
-
- float GetWaterLevel()
- {
- if (IsWaterContact() && m_WaterLevel > WATER_LEVEL_NONE)
- {
- return m_WaterLevel;
- }
- return 0.0;
- }
-
- private bool IsNeutralTemperature(float temperature, float lowerLimit = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT, float upperLimit = GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- if (temperature >= lowerLimit && temperature <= upperLimit)
- return true;
- return false;
- }
-
- private float NormalizedTemperature(float temperature, float lowerLimit = GameConstants.ENVIRO_LOW_TEMP_LIMIT, float upperLimit = GameConstants.ENVIRO_HIGH_TEMP_LIMIT)
- {
- if (temperature >= GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT && temperature <= GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- return 0.0;
- if (temperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT)
- return Math.Clamp(Math.InverseLerp(lowerLimit, GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT, temperature), -1.0, -0.1);
-
- if (temperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- return Math.Clamp(Math.InverseLerp(GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT, upperLimit, temperature), 0.1, 1.0);
-
- // neutral zone
- return 0.0;
- }
-
- #ifdef ENABLE_LOGGING
- private void LogDryWetProcess(string message, bool indented = false)
- {
- if (m_DebugLogDryWet)
- {
- string indentation = "";
- if (indented)
- indentation = "|--";
- Debug.Log(string.Format("%1 %2", indentation, message));
- }
- }
- #endif
- #ifdef ENABLE_LOGGING
- private void LogItemHeat(string message, bool indented = false)
- {
- if (m_DebugLogItemHeat)
- {
- string indentation = "";
- if (indented)
- indentation = "|--";
- Debug.Log(string.Format("%1 %2", indentation, message));
- }
- }
- #endif
-
- // --------------------------------------------------------------------------------
-
- //! DEPRECATED
- protected float m_HeatSourceTemp;
- protected ref SimpleMovingAverage<float> m_WindAverageBuffer;
- protected ref EnvironmentSnapshotData m_EnvironmentSnapshot; //! used for calculations before the data modification
-
- void Init(PlayerBase pPlayer)
- {
- Init();
- }
- protected bool OverridenHeatComfort(out float value);
- void AddToEnvironmentTemperature(float pTemperature);
-
- protected void ProcessItemsHeat()
- {
- // for backward combatibility only
- ProcessHeatComfort();
- }
- protected void ProcessWetnessByRain()
- {
- ProcessItemsWetness(m_SlotIdsComplete);
- }
-
- // Returns amount of deg C air temperature should be lowered by, based on player's height above water level
- float GetTemperatureHeightCorrection()
- {
- float temperature_reduction = Math.Max(0, (m_PlayerHeightPos * m_WorldData.m_TemperaturePerHeightReductionModifier));
- return temperature_reduction;
- }
-
- //! returns weighted avg heat comfort for bodypart
- protected void BodyPartHeatProperties(array<int> pBodyPartIds, float pCoef, out float pHeatComfort, out float pHeat)
- {
- pHeatComfort = 0;
- pHeat = 0;
-
- if (pBodyPartIds.Count() > 0)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("BodyPartHeatProperties (%1)", EnumTools.EnumToString(InventorySlots, pBodyPartIds[0])));
- #endif
-
- int attCount = m_Player.GetInventory().AttachmentCount();
- for (int attIdx = 0; attIdx < attCount; ++attIdx)
- {
- EntityAI attachment = m_Player.GetInventory().GetAttachmentFromIndex(attIdx);
- if (attachment.IsClothing())
- {
- ItemBase item = ItemBase.Cast(attachment);
- int attachmentSlot = attachment.GetInventory().GetSlotId(0);
-
- //! go through all body parts we've defined for that zone (ex.: head, body, feet)
- for (int i = 0; i < pBodyPartIds.Count(); ++i)
- {
- if (attachmentSlot == pBodyPartIds[i])
- {
- float heatIsoMult = 1.0;
- if (attachmentSlot == InventorySlots.BACK)
- heatIsoMult = GameConstants.ENVIRO_HEATISOLATION_BACK_WEIGHT;
- else if (attachmentSlot == InventorySlots.VEST)
- heatIsoMult = GameConstants.ENVIRO_HEATISOLATION_VEST_WEIGHT;
-
- pHeatComfort += heatIsoMult * MiscGameplayFunctions.GetCurrentItemHeatIsolation(item);
-
- float itemHeatcomfort = 0;
- float itemTemperature = 0;
-
- // go through any attachments and cargo (only current level, ignore nested containers - they isolate)
- int inventoryAttCount = item.GetInventory().AttachmentCount();
- if (inventoryAttCount > 0)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("attachments:"), false);
- #endif
- for (int inAttIdx = 0; inAttIdx < inventoryAttCount; ++inAttIdx)
- {
- EntityAI inAttachment = item.GetInventory().GetAttachmentFromIndex(inAttIdx);
- ItemBase attachmentItem = ItemBase.Cast(inAttachment);
- if (attachmentItem && attachmentItem.CanHaveTemperature())
- {
- itemTemperature = attachmentItem.GetTemperature();
- if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- itemHeatcomfort = NormalizedTemperature(itemTemperature) * attachmentItem.GetQuantityNormalizedScripted() * attachmentItem.GetTemperaturePerQuantityWeight();
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("%1: temperature=%2 heat=%3", attachmentItem, itemTemperature, pHeat), true);
- pHeat += itemHeatcomfort;
- #endif
- }
- }
- }
- }
- if (item.GetInventory().GetCargo())
- {
- int inventoryItemCount = item.GetInventory().GetCargo().GetItemCount();
-
- if (inventoryItemCount > 0)
- {
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("cargo:"), false);
- #endif
- for (int j = 0; j < inventoryItemCount; ++j)
- {
- ItemBase inventoryItem = ItemBase.Cast(item.GetInventory().GetCargo().GetItem(j));
- if (inventoryItem && inventoryItem.CanHaveTemperature())
- {
- itemTemperature = inventoryItem.GetTemperature();
- if (itemTemperature < GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_LOWER_LIMIT || itemTemperature > GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_UPPER_LIMIT)
- {
- itemHeatcomfort = NormalizedTemperature(itemTemperature) * inventoryItem.GetQuantityNormalizedScripted() * inventoryItem.GetTemperaturePerQuantityWeight();
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("%1: temperature=%2 heat=%3", inventoryItem, itemTemperature, itemHeatcomfort), true);
- #endif
- pHeat += itemHeatcomfort;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- pHeatComfort += (pHeatComfort / pBodyPartIds.Count()) * pCoef;
-
- #ifdef ENABLE_LOGGING
- LogItemHeat(string.Format("overall heat from items=%1 (coef applied)", pHeat));
- LogItemHeat("");
- #endif
- }
- }
-
- protected void SetEnvironmentSnapshotData()
- {
- EnvironmentSnapshotData data = new EnvironmentSnapshotData();
- data.m_TargetHeatComfort = m_TargetHeatComfort;
-
- m_EnvironmentSnapshot = data;
- }
-
- //! backward compatibility [<1.27]
- protected void ProcessHeatBuffer(float heatComfortCloths)
- {
- m_EnvironmentSnapshot.m_ClothingHeatComfort = heatComfortCloths;
- m_EnvironmentSnapshot.m_TargetHeatComfort = m_TargetHeatComfort;
-
- ProcessHeatBuffer(m_EnvironmentSnapshot);
- }
-
- //! backward compatibility [<1.28]
- protected float WindEffectTemperatureValue(float temperatureInput)
- {
- float output = 0.0;
- output = (temperatureInput - GameConstants.ENVIRO_WIND_CHILL_LIMIT) / (GameConstants.ENVIRO_WIND_EFFECT_SLOPE - GameConstants.ENVIRO_WIND_CHILL_LIMIT);
- output = output * m_Wind * m_WorldData.GetWindCoef();
-
- return -output;
- }
-
- float GetDayOrNight()
- {
- return m_DayOrNight;
- }
-
- protected bool IsInsideVehicle()
- {
- return IsChildOfType({Car});
- }
- }
- #ifdef DIAG_DEVELOPER
- class EnvDebugPlayerData : Param
- {
- float m_HeatComfortDynamic;
- float m_HeatComfortTarget;
- bool m_Inside;
- string m_Surface;
- bool m_UnderRoof;
- int m_UnderRoofTimer;
- float m_WaterLevel;
-
- void Synch(Environment env, PlayerBase player)
- {
- m_HeatComfortTarget = env.GetTargetHeatComfort();
- m_HeatComfortDynamic = player.GetStatHeatComfort().Get();
- m_Inside = env.IsInsideBuilding();
- m_Surface = player.GetSurfaceType();
- m_UnderRoof = env.IsUnderRoof();
- m_UnderRoofTimer = env.GetNextRoofCheck();
- m_WaterLevel = env.GetWaterLevel();
- }
-
- override bool Serialize(Serializer ctx)
- {
- return (
- 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));
- }
-
- override bool Deserializer(Serializer ctx)
- {
- 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);
- }
- }
- class EnvDebugMiscData : Param
- {
- float m_TemperatureBase;
- float m_TemperatureModified;
- float m_HeightCorrectedTemperature;
- float m_WetDelta;
-
- void Synch(Environment env)
- {
- m_TemperatureBase = g_Game.GetMission().GetWorldData().GetBaseEnvTemperature();
- m_TemperatureModified = env.GetTemperature();
- m_HeightCorrectedTemperature = m_TemperatureBase - env.GetTemperatureHeightCorrection();
- m_WetDelta = env.GetWetDelta();
- }
-
- override bool Serialize(Serializer ctx)
- {
- return ctx.Write(m_TemperatureBase) && ctx.Write(m_TemperatureModified) && ctx.Write(m_HeightCorrectedTemperature) && ctx.Write(m_WetDelta);
- }
-
- override bool Deserializer(Serializer ctx)
- {
- return ctx.Read(m_TemperatureBase) && ctx.Read(m_TemperatureModified) && ctx.Read(m_HeightCorrectedTemperature) && ctx.Read(m_WetDelta);
- }
- }
- class EnvDebugWeatherData : Param
- {
- float m_Wind;
- float m_WindModifier;
- float m_Rain;
- float m_Snowfall;
- float m_Fog;
- float m_Clouds;
-
- void Synch(Environment env)
- {
- env.FillDebugWeatherData(this);
- }
-
- override bool Serialize(Serializer ctx)
- {
- 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);
- }
-
- override bool Deserializer(Serializer ctx)
- {
- 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);
- }
- }
- class EnvDebugData : Param
- {
- ref EnvDebugPlayerData m_PlayerData = new EnvDebugPlayerData();
- ref EnvDebugMiscData m_MiscData = new EnvDebugMiscData();
- ref EnvDebugWeatherData m_WeatherData = new EnvDebugWeatherData();
-
- void Synch(Environment env, PlayerBase player)
- {
- m_PlayerData.Synch(env, player);
- m_MiscData.Synch(env);
- m_WeatherData.Synch(env);
- }
-
- override bool Serialize(Serializer ctx)
- {
- return m_PlayerData.Serialize(ctx) && m_MiscData.Serialize(ctx) && m_WeatherData.Serialize(ctx);
- }
-
- override bool Deserializer(Serializer ctx)
- {
- return m_PlayerData.Deserializer(ctx) && m_MiscData.Deserializer(ctx) && m_WeatherData.Deserializer(ctx);
- }
- }
- #endif
|