undergroundhandlerclient.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. enum EUndergroundPresence
  2. {
  3. NONE,//player is not interacting with underground at any level
  4. OUTER,//player is on the outskirts of the underdound, some effects are already in effect, while others might not be
  5. TRANSITIONING,//player has entered underground and is in the process of screen darkening transition
  6. FULL//the player is now fully entered underground
  7. }
  8. class UndergroundHandlerClient
  9. {
  10. const float LIGHT_BLEND_SPEED_IN = 5;
  11. const float LIGHT_BLEND_SPEED_OUT = 1.75;
  12. const float MAX_RATIO = 0.9;//how much max ratio between 0..1 can a single breadcrumb occupy
  13. const float RATIO_CUTOFF = 0;//what's the minimum ratio a breadcrumb needs to have to be considered when calculatiing accommodation
  14. const float DISTANCE_CUTOFF = 5;//we ignore breadcrumbs further than this distance
  15. const float ACCO_MODIFIER = 1;//when we calculate eye accommodation between 0..1 based on the breadcrumbs values and distances, we multiply the result by this modifier to get the final eye accommodation value
  16. const float DEFAULT_INTERPOLATION_SPEED = 7;
  17. const string UNDERGROUND_LIGHTING = "dz\\data\\lighting\\lighting_underground.txt";
  18. protected ref AnimationTimer m_AnimTimerLightBlend;
  19. protected PlayerBase m_Player;
  20. protected PPERUndergroundAcco m_Requester;
  21. protected PPERequester_CameraNV m_NVRequester;
  22. protected ref set<UndergroundTrigger> m_InsideTriggers = new set<UndergroundTrigger>();
  23. protected float m_EyeAccoTarget = 1;
  24. protected float m_AccoInterpolationSpeed;
  25. protected float m_EyeAcco = 1;
  26. protected float m_LightingLerpTarget;
  27. protected float m_LightingLerp;
  28. protected string m_AmbientController; // active sound controlelr for ambient
  29. protected EffectSound m_AmbientSound;
  30. protected UndergroundTrigger m_TransitionalTrigger;
  31. void UndergroundHandlerClient(PlayerBase player)
  32. {
  33. GetGame().GetWorld().LoadUserLightingCfg(UNDERGROUND_LIGHTING, "Underground");
  34. m_Player = player;
  35. m_NVRequester = PPERequester_CameraNV.Cast(PPERequesterBank.GetRequester( PPERequesterBank.REQ_CAMERANV));
  36. }
  37. void ~UndergroundHandlerClient()
  38. {
  39. if (GetGame())
  40. {
  41. GetGame().GetWorld().SetExplicitVolumeFactor_EnvSounds2D(1, 0.5);
  42. GetGame().GetWeather().SuppressLightningSimulation(false);
  43. GetGame().GetWorld().SetUserLightingLerp(0);
  44. if (m_AmbientSound)
  45. m_AmbientSound.Stop();
  46. }
  47. }
  48. protected PPERUndergroundAcco GetRequester()
  49. {
  50. if (!m_Requester)
  51. {
  52. m_Requester = PPERUndergroundAcco.Cast(PPERequesterBank.GetRequester( PPERequesterBank.REQ_UNDERGROUND));
  53. m_Requester.Start();
  54. }
  55. return m_Requester;
  56. }
  57. void OnTriggerEnter(UndergroundTrigger trigger)
  58. {
  59. m_InsideTriggers.Insert(trigger);
  60. OnTriggerInsiderUpdate();
  61. }
  62. void OnTriggerLeave(UndergroundTrigger trigger)
  63. {
  64. int index = m_InsideTriggers.Find(trigger);
  65. if (index != -1)
  66. {
  67. m_InsideTriggers.Remove(index);
  68. }
  69. OnTriggerInsiderUpdate();
  70. }
  71. protected void CalculateEyeAccoTarget()
  72. {
  73. if (!m_TransitionalTrigger)
  74. return;
  75. if (m_TransitionalTrigger.m_Data.UseLinePointFade && m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
  76. {
  77. CalculateLinePointFade();
  78. }
  79. else if (m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
  80. {
  81. CalculateBreadCrumbs();
  82. }
  83. }
  84. protected void CalculateBreadCrumbs()
  85. {
  86. float closestDist = float.MAX;
  87. array<float> distances = new array<float>();
  88. array<float> distancesInverted = new array<float>();
  89. int excludeMask = 0;
  90. foreach (int indx, auto crumb:m_TransitionalTrigger.m_Data.Breadcrumbs)
  91. {
  92. if (indx > 32)//error handling for exceeding this limit is handled elsewhere
  93. break;
  94. float dist = vector.Distance(m_Player.GetPosition(), crumb.GetPosition());
  95. float crumbRadius = m_TransitionalTrigger.m_Data.Breadcrumbs[indx].Radius;
  96. float maxRadiusAllowed = DISTANCE_CUTOFF;
  97. if (crumbRadius != -1)
  98. maxRadiusAllowed = crumbRadius;
  99. if (dist > maxRadiusAllowed)
  100. excludeMask = (excludeMask | (1 << indx));
  101. else if (m_TransitionalTrigger.m_Data.Breadcrumbs[indx].UseRaycast)
  102. {
  103. int idx = m_Player.GetBoneIndexByName("Head");
  104. vector rayStart = m_Player.GetBonePositionWS(idx);
  105. vector rayEnd = crumb.GetPosition();
  106. vector hitPos, hitNormal;
  107. float hitFraction;
  108. Object hitObj;
  109. if (DayZPhysics.RayCastBullet(rayStart, rayEnd,PhxInteractionLayers.TERRAIN | PhxInteractionLayers.ROADWAY| PhxInteractionLayers.BUILDING, null, hitObj, hitPos, hitNormal, hitFraction))
  110. {
  111. excludeMask = (excludeMask | (1 << indx));
  112. }
  113. }
  114. distances.Insert(dist);
  115. #ifdef DIAG_DEVELOPER
  116. if ( DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
  117. Debug.DrawSphere(crumb.GetPosition(),0.1, COLOR_RED, ShapeFlags.ONCE);
  118. #endif
  119. }
  120. float baseDst = distances[0];
  121. float sum = 0;
  122. foreach (float dst:distances)
  123. {
  124. if (dst == 0)
  125. dst = 0.1;
  126. float dstInv = (baseDst / dst) * baseDst;
  127. sum += dstInv;
  128. distancesInverted.Insert(dstInv);
  129. }
  130. float sumCheck = 0;
  131. float eyeAcco = 0;
  132. foreach (int i, float dstInvert:distancesInverted)
  133. {
  134. if ((1 << i) & excludeMask)
  135. continue;
  136. float ratio = dstInvert / sum;
  137. if (ratio > MAX_RATIO)
  138. ratio = MAX_RATIO;
  139. if (ratio > RATIO_CUTOFF)
  140. {
  141. #ifdef DIAG_DEVELOPER
  142. if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
  143. {
  144. float intensity = (1-ratio) * 255;
  145. Debug.DrawLine(GetGame().GetPlayer().GetPosition() + "0 1 0", m_TransitionalTrigger.m_Data.Breadcrumbs[i].GetPosition(),ARGB(0,255,intensity,intensity),ShapeFlags.ONCE);
  146. }
  147. #endif
  148. eyeAcco += ratio * m_TransitionalTrigger.m_Data.Breadcrumbs[i].EyeAccommodation;
  149. }
  150. }
  151. m_EyeAccoTarget = eyeAcco * ACCO_MODIFIER;
  152. }
  153. protected void CalculateLinePointFade()
  154. {
  155. array<ref JsonUndergroundAreaBreadcrumb> points = m_TransitionalTrigger.m_Data.Breadcrumbs;
  156. JsonUndergroundAreaBreadcrumb startPoint = points[0];
  157. JsonUndergroundAreaBreadcrumb endPoint = points[points.Count() - 1];
  158. vector playerPos = m_Player.GetPosition();
  159. bool forceAcco;
  160. float acco;
  161. float accoMax = m_TransitionalTrigger.m_Data.Breadcrumbs[0].EyeAccommodation;
  162. float accoMin = endPoint.EyeAccommodation;
  163. JsonUndergroundAreaBreadcrumb closestPoint;
  164. JsonUndergroundAreaBreadcrumb secondaryPoint;
  165. float distanceToClosest;
  166. float distanceToSecondary;
  167. float distanceBetweenPoints;
  168. foreach (JsonUndergroundAreaBreadcrumb point : points) //identify closest segment
  169. {
  170. float dist = vector.DistanceSq(playerPos, point.GetPosition());
  171. if (!closestPoint || dist < distanceToClosest)
  172. {
  173. if (closestPoint)
  174. {
  175. secondaryPoint = closestPoint;
  176. distanceToSecondary = distanceToClosest;
  177. }
  178. closestPoint = point;
  179. distanceToClosest = dist;
  180. }
  181. else if (!secondaryPoint || dist < secondaryPoint)
  182. {
  183. secondaryPoint = point;
  184. distanceToSecondary = dist;
  185. }
  186. #ifdef DIAG_DEVELOPER
  187. if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB))
  188. Debug.DrawSphere(point.GetPosition(),0.1, COLOR_RED, ShapeFlags.ONCE);
  189. #endif
  190. }
  191. distanceBetweenPoints = vector.DistanceSq(closestPoint.GetPosition(), secondaryPoint.GetPosition());
  192. if (closestPoint == startPoint && secondaryPoint == points[1] && distanceToSecondary > distanceBetweenPoints) // before first point, do nothing
  193. acco = accoMax;
  194. else if (closestPoint == endPoint && secondaryPoint == points[points.Count() - 2] && distanceToSecondary > distanceBetweenPoints) // past second point, do nothing
  195. acco = accoMin;
  196. else // between the two points, lerp
  197. {
  198. if (closestPoint == endPoint)
  199. secondaryPoint = points[points.Count() - 2];
  200. else if (closestPoint == startPoint)
  201. secondaryPoint = points[1];
  202. else if (distanceBetweenPoints < distanceToClosest || distanceBetweenPoints < distanceToSecondary)
  203. {
  204. JsonUndergroundAreaBreadcrumb nexPoint = points[points.Find(closestPoint) + 1];
  205. if (vector.DistanceSq(playerPos, nexPoint.GetPosition()) < vector.DistanceSq(closestPoint.GetPosition(), nexPoint.GetPosition()))
  206. secondaryPoint = nexPoint;
  207. else
  208. {
  209. acco = closestPoint.EyeAccommodation;
  210. forceAcco = true;
  211. }
  212. }
  213. if (!forceAcco)
  214. {
  215. distanceToSecondary = vector.DistanceSq(playerPos, secondaryPoint.GetPosition());
  216. acco = distanceToSecondary / (distanceToClosest + distanceToSecondary); // progress
  217. acco = Math.Lerp(secondaryPoint.EyeAccommodation, closestPoint.EyeAccommodation, acco);
  218. if (points.Find(closestPoint) > points.Find(secondaryPoint))
  219. m_LightingLerpTarget = closestPoint.LightLerp;
  220. else
  221. m_LightingLerpTarget = secondaryPoint.LightLerp;
  222. }
  223. }
  224. m_EyeAccoTarget = acco * ACCO_MODIFIER;
  225. if (m_LightingLerpTarget != m_LightingLerp && (!m_AnimTimerLightBlend || !m_AnimTimerLightBlend.IsRunning()))
  226. {
  227. if (m_LightingLerpTarget == 1)
  228. {
  229. m_AnimTimerLightBlend = new AnimationTimer();
  230. m_AnimTimerLightBlend.Run(1, this, "OnUpdateTimerIn", "OnUpdateTimerEnd",0, false, LIGHT_BLEND_SPEED_IN);
  231. }
  232. else
  233. {
  234. m_AnimTimerLightBlend = new AnimationTimer();
  235. m_AnimTimerLightBlend.Run(0, this, "OnUpdateTimerOut", "OnUpdateTimerEnd",m_LightingLerp, false, LIGHT_BLEND_SPEED_OUT);
  236. }
  237. }
  238. #ifdef DIAG_DEVELOPER
  239. if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB))
  240. {
  241. Debug.DrawLine(m_Player.GetPosition() + "0 1 0", closestPoint.GetPosition(), COLOR_YELLOW, ShapeFlags.ONCE);
  242. if (acco != accoMin && acco != accoMax)
  243. Debug.DrawLine(closestPoint.GetPosition(), secondaryPoint.GetPosition(), COLOR_RED, ShapeFlags.ONCE);
  244. DbgUI.Begin(String("Underground Areas"), 20, 20);
  245. DbgUI.Text(String("Closest point id: " + points.Find(closestPoint)));
  246. DbgUI.Text(String("Second closest id: " + points.Find(secondaryPoint)));
  247. DbgUI.End();
  248. }
  249. #endif
  250. }
  251. protected void ProcessEyeAcco(float timeSlice)
  252. {
  253. CalculateEyeAccoTarget();
  254. bool reachedTarget = CalculateEyeAcco(timeSlice);
  255. ApplyEyeAcco();
  256. if(reachedTarget && !m_Player.m_UndergroundPresence)
  257. {
  258. GetRequester().Stop();
  259. UpdateNVGRequester(1);
  260. //m_NVRequester.SetUndergroundExposureCoef(1.0);
  261. m_Player.KillUndergroundHandler();
  262. }
  263. }
  264. protected void ProcessLighting(float timeSlice)
  265. {
  266. #ifdef DEVELOPER
  267. if (!DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_DISABLE_DARKENING) )
  268. {
  269. GetGame().GetWorld().SetUserLightingLerp(m_LightingLerp);
  270. }
  271. else
  272. {
  273. GetGame().GetWorld().SetUserLightingLerp(0);
  274. }
  275. #else
  276. GetGame().GetWorld().SetUserLightingLerp(m_LightingLerp);
  277. #endif
  278. }
  279. protected void ProcessSound(float timeSlice)
  280. {
  281. GetGame().GetWorld().SetExplicitVolumeFactor_EnvSounds2D(m_EyeAcco, 0);
  282. if (m_AmbientSound)
  283. {
  284. if (m_TransitionalTrigger && m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
  285. m_AmbientSound.SetSoundVolume(1-m_EyeAcco);
  286. }
  287. }
  288. void Tick(float timeSlice)
  289. {
  290. if (!m_Player.IsAlive())
  291. return;
  292. ProcessEyeAcco(timeSlice);
  293. ProcessLighting(timeSlice);
  294. ProcessSound(timeSlice);
  295. #ifdef DIAG_DEVELOPER
  296. if ( DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
  297. {
  298. DisplayDebugInfo(GetGame().GetWorld().GetEyeAccom(), m_LightingLerp);
  299. }
  300. #endif
  301. }
  302. protected void ApplyEyeAcco()
  303. {
  304. #ifdef DIAG_DEVELOPER
  305. if (!DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_DISABLE_DARKENING) )
  306. {
  307. GetRequester().SetEyeAccommodation(m_EyeAcco);
  308. }
  309. else
  310. {
  311. GetRequester().SetEyeAccommodation(1);
  312. }
  313. #else
  314. GetRequester().SetEyeAccommodation(m_EyeAcco);
  315. #endif
  316. float undergrounNVExposureCoef = m_EyeAcco;
  317. if (m_LightingLerp >= 1.0 || GetDayZGame().GetWorld().IsNight())
  318. {
  319. undergrounNVExposureCoef = 1.0;
  320. }
  321. //m_NVRequester.SetUndergroundExposureCoef(undergrounNVExposureCoef);
  322. UpdateNVGRequester(undergrounNVExposureCoef);
  323. }
  324. protected void UpdateNVGRequester(float value)
  325. {
  326. m_NVRequester.SetUndergroundExposureCoef(value);
  327. }
  328. protected bool CalculateEyeAcco(float timeSlice)
  329. {
  330. if (m_TransitionalTrigger || !m_Player.m_UndergroundPresence || (m_EyeAccoTarget == 1))
  331. {
  332. float accoDiff = m_EyeAccoTarget - m_EyeAcco;
  333. float increase = accoDiff * m_AccoInterpolationSpeed * timeSlice;
  334. m_EyeAcco += increase;
  335. if (Math.AbsFloat(accoDiff) < 0.01)
  336. {
  337. m_EyeAcco = m_EyeAccoTarget;
  338. return true;
  339. }
  340. }
  341. else
  342. {
  343. m_EyeAcco = m_EyeAccoTarget;
  344. }
  345. return false;
  346. }
  347. protected void OnTriggerInsiderUpdate()
  348. {
  349. EUndergroundTriggerType bestType = EUndergroundTriggerType.UNDEFINED;
  350. m_TransitionalTrigger = null;
  351. UndergroundTrigger bestTrigger;
  352. m_EyeAccoTarget = 1;
  353. m_AccoInterpolationSpeed = DEFAULT_INTERPOLATION_SPEED;
  354. foreach (auto t:m_InsideTriggers)
  355. {
  356. if (t.m_Type > bestType)
  357. {
  358. bestTrigger = t;
  359. bestType = t.m_Type;
  360. }
  361. }
  362. //Print(m_InsideTriggers.Count());
  363. //Print(bestType);
  364. if (bestTrigger)
  365. {
  366. if (bestTrigger.m_Type == EUndergroundTriggerType.TRANSITIONING)
  367. {
  368. m_TransitionalTrigger = bestTrigger;
  369. }
  370. m_EyeAccoTarget = bestTrigger.m_Accommodation;
  371. if (bestTrigger.m_InterpolationSpeed != -1 && bestTrigger.m_InterpolationSpeed != 0)
  372. m_AccoInterpolationSpeed = bestTrigger.m_InterpolationSpeed;
  373. }
  374. SetUndergroundPresence(bestTrigger);
  375. }
  376. protected void SetUndergroundPresence(UndergroundTrigger trigger)
  377. {
  378. EUndergroundPresence newPresence = EUndergroundPresence.NONE;
  379. EUndergroundPresence oldPresence = m_Player.m_UndergroundPresence;
  380. if (trigger)
  381. {
  382. if (trigger.m_Type == EUndergroundTriggerType.OUTER)
  383. {
  384. newPresence = EUndergroundPresence.OUTER;
  385. }
  386. else if (trigger.m_Type == EUndergroundTriggerType.TRANSITIONING)
  387. {
  388. newPresence = EUndergroundPresence.TRANSITIONING;
  389. }
  390. else if (trigger.m_Type == EUndergroundTriggerType.INNER)
  391. {
  392. newPresence = EUndergroundPresence.FULL;
  393. }
  394. }
  395. if (newPresence != oldPresence)//was there a change ?
  396. {
  397. OnUndergroundPresenceUpdate(newPresence,oldPresence);
  398. m_Player.SetUnderground(newPresence);
  399. }
  400. }
  401. protected void EnableLights(bool enable)
  402. {
  403. foreach (ScriptedLightBase light:ScriptedLightBase.m_NightTimeOnlyLights)
  404. {
  405. light.SetVisibleDuringDaylight(enable);
  406. }
  407. }
  408. void OnUpdateTimerEnd();
  409. void OnUpdateTimerIn()
  410. {
  411. if (!m_AnimTimerLightBlend)
  412. return;
  413. float value01 = m_AnimTimerLightBlend.GetValue();
  414. float result = Easing.EaseInQuint(value01);
  415. m_LightingLerp = result;
  416. }
  417. void OnUpdateTimerOut()
  418. {
  419. if (!m_AnimTimerLightBlend)
  420. return;
  421. float value01 = m_AnimTimerLightBlend.GetValue();
  422. float result = Easing.EaseOutCubic(value01);
  423. m_LightingLerp = result;
  424. }
  425. protected void PlayAmbientSound()
  426. {
  427. if (m_TransitionalTrigger && m_TransitionalTrigger.m_Data.AmbientSoundType != string.Empty)
  428. {
  429. m_AmbientController = m_TransitionalTrigger.m_Data.AmbientSoundType;
  430. SetSoundControllerOverride(m_AmbientController, 1.0, SoundControllerAction.Overwrite);
  431. }
  432. else
  433. m_Player.PlaySoundSetLoop(m_AmbientSound, "Underground_SoundSet",3,3);
  434. }
  435. protected void StopAmbientSound()
  436. {
  437. if (m_AmbientController != string.Empty)
  438. {
  439. SetSoundControllerOverride(m_AmbientController, 0, SoundControllerAction.None);
  440. m_AmbientController = string.Empty;
  441. }
  442. else if (m_AmbientSound)
  443. m_Player.StopSoundSet(m_AmbientSound);
  444. }
  445. protected void OnUndergroundPresenceUpdate(EUndergroundPresence newPresence, EUndergroundPresence oldPresence)
  446. {
  447. //Print("-----> On Undeground Presence update " + EnumTools.EnumToString(EUndergroundPresence, newPresence) + " " + EnumTools.EnumToString(EUndergroundPresence, oldPresence));
  448. if (newPresence > EUndergroundPresence.NONE)
  449. {
  450. if (oldPresence == EUndergroundPresence.NONE)
  451. {
  452. EnableLights(true);
  453. }
  454. if (newPresence > EUndergroundPresence.OUTER && oldPresence <= EUndergroundPresence.OUTER)
  455. {
  456. GetGame().GetWeather().SuppressLightningSimulation(true);
  457. PlayAmbientSound();
  458. }
  459. if (newPresence == EUndergroundPresence.FULL)
  460. {
  461. m_AnimTimerLightBlend = new AnimationTimer();
  462. m_AnimTimerLightBlend.Run(1, this, "OnUpdateTimerIn", "OnUpdateTimerEnd",0, false, LIGHT_BLEND_SPEED_IN);
  463. }
  464. }
  465. if (newPresence < EUndergroundPresence.FULL && oldPresence == EUndergroundPresence.FULL)
  466. {
  467. m_AnimTimerLightBlend = new AnimationTimer();
  468. m_AnimTimerLightBlend.Run(0, this, "OnUpdateTimerOut", "OnUpdateTimerEnd",m_LightingLerp, false, LIGHT_BLEND_SPEED_OUT);
  469. }
  470. if (newPresence <= EUndergroundPresence.OUTER && oldPresence > EUndergroundPresence.OUTER)
  471. {
  472. GetGame().GetWeather().SuppressLightningSimulation(false);
  473. }
  474. if (newPresence == EUndergroundPresence.NONE)
  475. {
  476. StopAmbientSound();
  477. if (oldPresence >= EUndergroundPresence.OUTER)
  478. {
  479. GetGame().GetWorld().SetUserLightingLerp(0);
  480. EnableLights(false);
  481. }
  482. }
  483. }
  484. #ifdef DIAG_DEVELOPER
  485. protected void DisplayDebugInfo(float acco, float lighting)
  486. {
  487. if (acco < 0.0001)
  488. acco = 0;
  489. DbgUI.Begin(String("Underground Areas"), 20, 20);
  490. DbgUI.Text(String("Eye Accomodation: " + acco.ToString()));
  491. DbgUI.Text(String("Lighting lerp: " + lighting.ToString()));
  492. DbgUI.End();
  493. }
  494. #endif
  495. }