undergroundhandlerclient.c 17 KB

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