worlddata.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. //! Keeps information about currently loaded world, like temperature
  2. class WorldData
  3. {
  4. const float SPAWN_CHANCE_CHOLERA_DEF = 50;
  5. const float COLD_AREA_TOOL_DMG_MODIF_DEF = 1;
  6. //! directly accesible (defined/overriden in Init())
  7. float m_TemperaturePerHeightReductionModifier; //! amount of °C reduced for each 100 meteres of height above water level
  8. float m_CloudsTemperatureEffectModifier; //! how many % of environment temperature can be lowered by clouds
  9. float m_TemperatureInsideBuildingsModifier
  10. float m_WaterContactTemperatureModifier
  11. protected float SUDDENCHANGE_TIME_MULTIPLIER = 0.2;
  12. protected float SUDDENCHANGE_LENGTH_MULTIPLIER = 0.4;
  13. protected float WIND_MAGNITUDE_TIME_MULTIPLIER = 0.1;
  14. protected float WIND_DIRECTION_TIME_MULTIPLIER = 0.05;
  15. protected Weather m_Weather;
  16. protected float m_EnvironmentTemperature;
  17. protected bool m_EnTempUpdated;
  18. protected float m_Timer;
  19. protected float m_MaxTemps[12];
  20. protected float m_MinTemps[12];
  21. protected float m_Sunrise_Jan;
  22. protected float m_Sunset_Jan;
  23. protected float m_Sunrise_Jul;
  24. protected float m_Sunset_Jul;
  25. protected ref array<vector> m_FiringPos; // Where we should fire from. On Init set the relevant data
  26. protected bool m_Pollution;
  27. protected ref CatchYieldBank m_YieldBank;
  28. protected ref WorldDataWeatherSettings m_WeatherDefaultSettings;
  29. protected ref WorldDataLiquidSettings m_LiquidSettings;
  30. protected ref TStringArray m_DefaultPlayerRestrictedAreas;
  31. //! weather related
  32. protected int m_BadWeatherChance;
  33. protected int m_ClearWeatherChance;
  34. protected bool m_IsSuddenChange;
  35. protected float m_WorldWindCoef;
  36. protected float m_UniversalTemperatureSourceCapModifier;
  37. //used at next weather calculation
  38. protected int m_SameWeatherCnt = 0;
  39. protected int m_StepValue = 5;
  40. protected int m_Chance = 50;
  41. protected int m_ChoosenWeather = 1;
  42. protected int m_LastWeather = 0;
  43. void WorldData()
  44. {
  45. Init();
  46. CreateYieldBank();
  47. InitYieldBank();
  48. UpdateBaseEnvTemperature(0);
  49. }
  50. void Init()
  51. {
  52. SetupWeatherSettings();
  53. SetupLiquidTemperatures();
  54. m_EnTempUpdated = false;
  55. m_Weather = g_Game.GetWeather();
  56. m_EnvironmentTemperature = 12.0;
  57. m_Timer = 0.0;
  58. m_Sunrise_Jan = 8.54;
  59. m_Sunset_Jan = 15.52;
  60. m_Sunrise_Jul = 3.26;
  61. m_Sunset_Jul = 20.73;
  62. m_MaxTemps = {3,5,7,14,19,24,26,25,21,16,10,5};
  63. m_MinTemps = {-3,-2,0,4,9,14,18,17,12,7,4,0};
  64. m_Pollution = EPollution.NONE;
  65. m_WorldWindCoef = 0.5;
  66. m_UniversalTemperatureSourceCapModifier = 0.0;
  67. m_TemperaturePerHeightReductionModifier = 0.02;
  68. m_CloudsTemperatureEffectModifier = 3.0;
  69. m_TemperatureInsideBuildingsModifier = 1.0;
  70. m_WaterContactTemperatureModifier = 20.0;
  71. m_ClearWeatherChance = m_WeatherDefaultSettings.m_ClearWeatherChance;
  72. m_BadWeatherChance = m_WeatherDefaultSettings.m_BadWeatherChance;
  73. m_DefaultPlayerRestrictedAreas = {};
  74. }
  75. float GetApproxSunriseTime( float monthday )
  76. {
  77. if ( monthday <= 8.0 )
  78. return ( ( m_Sunrise_Jan - m_Sunrise_Jul ) / ( 8 - 1 ) ) * ( 1 - monthday ) + m_Sunrise_Jan;
  79. else
  80. return ( ( ( monthday - 8 ) * ( m_Sunrise_Jan - m_Sunrise_Jul ) ) / ( 13 - 8 ) ) + m_Sunrise_Jul;
  81. }
  82. float GetApproxSunsetTime( float monthday )
  83. {
  84. if ( monthday <= 8.0 )
  85. return ( ( m_Sunset_Jan - m_Sunset_Jul ) / (8 - 1) ) * ( 1 - monthday ) + m_Sunset_Jan;
  86. else
  87. return ( ( ( monthday - 8 ) * ( m_Sunset_Jan - m_Sunset_Jul ) ) / ( 13 - 8 ) ) + m_Sunset_Jul;
  88. }
  89. int GetDaytime()
  90. {
  91. int year, month, day, hour, minute;
  92. GetGame().GetWorld().GetDate(year, month, day, hour, minute);
  93. float sunriseTimeStart = g_Game.GetMission().GetWorldData().GetApproxSunriseTime(month);
  94. float sunsetTimeStart = g_Game.GetMission().GetWorldData().GetApproxSunsetTime(month);
  95. if (hour >= sunriseTimeStart && hour < (sunriseTimeStart + 2))
  96. return WorldDataDaytime.DAWN;
  97. else if (hour >= (sunriseTimeStart + 2) && hour < sunsetTimeStart)
  98. return WorldDataDaytime.DAY;
  99. else if (hour >= sunsetTimeStart && hour < (sunsetTimeStart + 2))
  100. return WorldDataDaytime.DUSK;
  101. return WorldDataDaytime.NIGHT;
  102. }
  103. protected float CalcBaseEnvironmentTemperature( float monthday, float daytime )
  104. {
  105. float approxSunrise = GetApproxSunriseTime( monthday );
  106. float approxSunset = GetApproxSunsetTime( monthday );
  107. float dayLight = approxSunset - approxSunrise;
  108. float nightTime = 24.0 - dayLight;
  109. int tempArrayIndex = Math.Floor(monthday) - 1;
  110. int tempArrayIndexToLerp = tempArrayIndex + 1;
  111. if ( tempArrayIndexToLerp >= 12 )
  112. tempArrayIndexToLerp = 0;
  113. float tempArrayLerp = monthday - Math.Floor(monthday);
  114. float minTempA = m_MinTemps[tempArrayIndex];
  115. float minTempB = m_MinTemps[tempArrayIndexToLerp];
  116. float maxTempA = m_MaxTemps[tempArrayIndex];
  117. float maxTempB = m_MaxTemps[tempArrayIndexToLerp];
  118. float eveningMinA = minTempA + ( 0.5 * Math.AbsFloat( minTempA - maxTempA ) );
  119. float eveningMinB = minTempB + ( 0.5 * Math.AbsFloat( minTempB - maxTempB ) );
  120. if ( ( daytime >= approxSunrise ) && ( daytime <= approxSunset ) ) {
  121. if ( daytime <= ( approxSunrise + ( dayLight * 0.75 ) ) )
  122. return Math.Lerp(
  123. Math.Lerp( minTempA, minTempB, tempArrayLerp ),
  124. Math.Lerp( maxTempA, maxTempB, tempArrayLerp ),
  125. ( ( daytime - approxSunrise ) / ( dayLight * 0.75 ) ) );
  126. else
  127. return Math.Lerp(
  128. Math.Lerp( maxTempA, maxTempB, tempArrayLerp ),
  129. Math.Lerp( eveningMinA, eveningMinB, tempArrayLerp ),
  130. ( ( ( daytime - approxSunrise ) - ( dayLight * 0.75 ) ) / ( dayLight - ( dayLight * 0.75 ) ) ) );
  131. } else {
  132. if ( ( daytime > approxSunset ) && ( daytime < 24 ) )
  133. return Math.Lerp(
  134. Math.Lerp( eveningMinA, eveningMinB, tempArrayLerp ),
  135. Math.Lerp( minTempA, minTempB, tempArrayLerp ),
  136. ( ( daytime - approxSunset ) / ( 24 - approxSunset ) ) / 2.0 );
  137. else
  138. return Math.Lerp(
  139. Math.Lerp( eveningMinA, eveningMinB, tempArrayLerp ),
  140. Math.Lerp( minTempA, minTempB, tempArrayLerp ),
  141. ( ( ( daytime + ( 24 - approxSunset ) ) / nightTime ) / 2.0 ) + 0.5 );
  142. }
  143. }
  144. void UpdateBaseEnvTemperature(float timeslice)
  145. {
  146. m_Timer += timeslice;
  147. if (m_Timer > 30 || !m_EnTempUpdated)
  148. {
  149. int year, month, day, hour, minute;
  150. GetGame().GetWorld().GetDate( year, month, day, hour, minute );
  151. m_EnvironmentTemperature = CalcBaseEnvironmentTemperature( month + ( day / 32.0 ), hour + ( minute / 60.0 ) );
  152. m_Timer = 0;
  153. if (!m_EnTempUpdated)
  154. m_EnTempUpdated = true;
  155. }
  156. }
  157. /*!
  158. \brief Updates *local* weather effects.
  159. \param weather Weather instance
  160. \param timeslice Time delta since last update
  161. */
  162. void UpdateWeatherEffects( Weather weather, float timeslice )
  163. {
  164. float snowflakeScale = ComputeSnowflakeScale( weather );
  165. weather.SetSnowflakeScale( snowflakeScale );
  166. }
  167. /*!
  168. \brief Returns the desired snowflake scale based on weather simulation state.
  169. \param weather Weather instance
  170. */
  171. float ComputeSnowflakeScale( Weather weather )
  172. {
  173. float overcast01 = Math.Clamp( Math.InverseLerp( 0.4, 1.0, weather.GetOvercast().GetActual() ), 0.0, 1.0 ); // remap range to <0.4, 1.0> snowfall overcast threshold
  174. float wind01 = weather.GetWindSpeed() / weather.GetWindMaximumSpeed();
  175. float overcastScale = Math.Lerp( 0.50, 1.25, overcast01 );
  176. float windScale = Math.Lerp( 1.25, 1.00, wind01 );
  177. return Math.Clamp( overcastScale * windScale, 0.50, 1.25 );
  178. }
  179. // getter for the new base enviro temperature
  180. float GetBaseEnvTemperature()
  181. {
  182. return m_EnvironmentTemperature;
  183. }
  184. float GetBaseEnvTemperatureAtObject(notnull Object object)
  185. {
  186. return GetBaseEnvTemperatureAtPosition(object.GetPosition());
  187. }
  188. float GetBaseEnvTemperatureAtPosition(vector pos)
  189. {
  190. float terrainHeight = pos[1];
  191. float heightCorrection = Math.Max(0, (terrainHeight * m_TemperaturePerHeightReductionModifier));
  192. return m_EnvironmentTemperature - heightCorrection;
  193. }
  194. float GetBaseEnvTemperatureExact(int month, int day, int hour, int minute)
  195. {
  196. return CalcBaseEnvironmentTemperature( month + ( day / 32.0 ), hour + ( minute / 60.0 ) );
  197. }
  198. float GetLiquidTypeEnviroTemperature(int liquidType)
  199. {
  200. if (m_LiquidSettings.m_Temperatures.Count() > 0 && m_LiquidSettings.m_Temperatures.Contains(liquidType) != INDEX_NOT_FOUND)
  201. return m_LiquidSettings.m_Temperatures.Get(liquidType);
  202. #ifdef DEVELOPER
  203. ErrorEx("Undefined enviro temperature for liquid type: " + liquidType);
  204. #endif
  205. return m_EnvironmentTemperature;
  206. }
  207. bool WeatherOnBeforeChange( EWeatherPhenomenon type, float actual, float change, float time )
  208. {
  209. // default behaviour is same like setting MissionWeather (in Weather) to true
  210. return false;
  211. }
  212. // Used to return the artillery firing positions
  213. array<vector> GetArtyFiringPos()
  214. {
  215. return m_FiringPos;
  216. }
  217. // Returns chance percentage for selected agent to spawn, used with spawned loot
  218. float GetAgentSpawnChance(eAgents agent)
  219. {
  220. if (agent == eAgents.CHOLERA)
  221. return SPAWN_CHANCE_CHOLERA_DEF;
  222. return 0;
  223. }
  224. // Returns modifier which is added to the tool damage logic when player is in cold area
  225. float GetColdAreaToolDamageModifier()
  226. {
  227. return COLD_AREA_TOOL_DMG_MODIF_DEF;
  228. }
  229. // debug
  230. void BaseTempDebug(int month, int day)
  231. {
  232. Print("--------------------");
  233. for ( int i = 0; i < 24; i++ )
  234. {
  235. for ( int j = 0; j < 6; j++ )
  236. {
  237. int minute = ( j * 10 );
  238. Print(string.Format( "%1:%2 %3", i, minute, GetBaseEnvTemperatureExact( month, day, i, minute ) ) );
  239. }
  240. }
  241. }
  242. int GetPollution()
  243. {
  244. return m_Pollution;
  245. }
  246. float GetWindCoef()
  247. {
  248. return m_WorldWindCoef;
  249. }
  250. float GetUniversalTemperatureSourceCapModifier()
  251. {
  252. return m_UniversalTemperatureSourceCapModifier;
  253. }
  254. protected void CalculateWind(int newWeather, bool suddenChange, out float magnitude, out float direction);
  255. protected void CalculateVolFog(float lerpValue, float windMagnitude, float changeTime);
  256. protected void CreateYieldBank()
  257. {
  258. m_YieldBank = new CatchYieldBank();
  259. }
  260. //! override this to properly register world-specific yields
  261. protected void InitYieldBank()
  262. {
  263. GetDayZGame().GetYieldDataInitInvoker().Invoke(m_YieldBank); //injects defaults from 4_World and above
  264. }
  265. protected void SetupWeatherSettings()
  266. {
  267. m_WeatherDefaultSettings = new WorldDataWeatherSettings();
  268. }
  269. protected void SetupLiquidTemperatures()
  270. {
  271. m_LiquidSettings = new WorldDataLiquidSettings();
  272. m_LiquidSettings.m_Temperatures[LIQUID_SALTWATER] = 23.0;
  273. m_LiquidSettings.m_Temperatures[LIQUID_WATER] = 15.0;
  274. m_LiquidSettings.m_Temperatures[LIQUID_STILLWATER] = 15.0;
  275. m_LiquidSettings.m_Temperatures[LIQUID_RIVERWATER] = 15.0;
  276. m_LiquidSettings.m_Temperatures[LIQUID_FRESHWATER] = 15.0;
  277. m_LiquidSettings.m_Temperatures[LIQUID_CLEANWATER] = 10.0;
  278. m_LiquidSettings.m_Temperatures[LIQUID_SNOW] = -5.0;
  279. }
  280. CatchYieldBank GetCatchYieldBank()
  281. {
  282. return m_YieldBank;
  283. }
  284. TStringArray GetDefaultPRAPaths()
  285. {
  286. return m_DefaultPlayerRestrictedAreas;
  287. }
  288. //!
  289. //! DEPRECATED
  290. //!
  291. protected float m_DayTemperature = 10; // legacy, no longer used
  292. protected float m_NightTemperature = 6; // legacy, no longer used
  293. float GetDayTemperature()
  294. {
  295. return m_DayTemperature;
  296. }
  297. float GetNightTemperature()
  298. {
  299. return m_NightTemperature;
  300. }
  301. }
  302. class WorldDataWeatherConstants
  303. {
  304. const int CLEAR_WEATHER = 1;
  305. const int CLOUDY_WEATHER = 2;
  306. const int BAD_WEATHER = 3;
  307. }
  308. class WorldDataWeatherSettings
  309. {
  310. int m_OvercastMinTime = 600;
  311. int m_OvercastMaxTime = 900;
  312. int m_OvercastMinLength = 600;
  313. int m_OvercastMaxLength = 900;
  314. float m_RainThreshold = 0.6;
  315. int m_RainTimeMin = 60;
  316. int m_RainTimeMax = 120;
  317. int m_RainLengthMin = 60;
  318. int m_RainLengthMax = 120;
  319. float m_StormThreshold = 0.85;
  320. float m_ThundersnowThreshold = 0.98;
  321. float m_SnowfallThreshold = 0.3;
  322. int m_SnowfallTimeMin = 60;
  323. int m_SnowfallTimeMax = 120;
  324. int m_SnowfallLengthMin = 150;
  325. int m_SnowfallLengthMax = 300;
  326. int m_GlobalSuddenChance = 95;
  327. int m_ClearWeatherChance = 30;
  328. int m_BadWeatherChance = 80;
  329. int m_BadWeatherSuddenChance = 95;
  330. int m_FoggyMorningHeigthBiasLowLimit = 155;
  331. int m_DefaultHeigthBias = 170;
  332. int m_CalmAfterStormTimeMin = 480;
  333. int m_CalmAfterStormTimeMax = 600;
  334. }
  335. class WorldDataLiquidSettings
  336. {
  337. ref map<int, float> m_Temperatures = new map<int, float>();
  338. }
  339. class WorldDataDaytime
  340. {
  341. static int ANY = -1;
  342. static int NIGHT = 0;
  343. static int DAY = 1;
  344. static int DUSK = 2;
  345. static int DAWN = 3;
  346. static string ToString(int value)
  347. {
  348. switch (value)
  349. {
  350. case NIGHT:
  351. return "NIGHT";
  352. case DAY:
  353. return "DAY";
  354. case DUSK:
  355. return "DUSK";
  356. case DAWN:
  357. return "DAWN";
  358. }
  359. return "ANYTIME";
  360. }
  361. }