123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- enum EUndergroundPresence
- {
- NONE,//player is not interacting with underground at any level
- OUTER,//player is on the outskirts of the underdound, some effects are already in effect, while others might not be
- TRANSITIONING,//player has entered underground and is in the process of screen darkening transition
- FULL//the player is now fully entered underground
- }
- class UndergroundHandlerClient
- {
- const float LIGHT_BLEND_SPEED_IN = 5;
- const float LIGHT_BLEND_SPEED_OUT = 1.75;
- const float MAX_RATIO = 0.9;//how much max ratio between 0..1 can a single breadcrumb occupy
- const float RATIO_CUTOFF = 0;//what's the minimum ratio a breadcrumb needs to have to be considered when calculatiing accommodation
- const float DISTANCE_CUTOFF = 5;//we ignore breadcrumbs further than this distance
- 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
- const float DEFAULT_INTERPOLATION_SPEED = 7;
- const string UNDERGROUND_LIGHTING = "dz\\data\\lighting\\lighting_underground.txt";
- protected ref AnimationTimer m_AnimTimerLightBlend;
-
- protected PlayerBase m_Player;
- protected PPERUndergroundAcco m_Requester;
- protected PPERequester_CameraNV m_NVRequester;
- protected ref set<UndergroundTrigger> m_InsideTriggers = new set<UndergroundTrigger>();
-
- protected float m_EyeAccoTarget = 1;
- protected float m_AccoInterpolationSpeed;
- protected float m_EyeAcco = 1;
- protected float m_LightingLerpTarget;
- protected float m_LightingLerp;
- protected string m_AmbientController; // active sound controlelr for ambient
- protected EffectSound m_AmbientSound;
-
- protected UndergroundTrigger m_TransitionalTrigger;
-
- void UndergroundHandlerClient(PlayerBase player)
- {
- GetGame().GetWorld().LoadUserLightingCfg(UNDERGROUND_LIGHTING, "Underground");
- m_Player = player;
- m_NVRequester = PPERequester_CameraNV.Cast(PPERequesterBank.GetRequester( PPERequesterBank.REQ_CAMERANV));
- }
-
- void ~UndergroundHandlerClient()
- {
- if (GetGame())
- {
- GetGame().GetWorld().SetExplicitVolumeFactor_EnvSounds2D(1, 0.5);
- GetGame().GetWeather().SuppressLightningSimulation(false);
- GetGame().GetWorld().SetUserLightingLerp(0);
- if (m_AmbientSound)
- m_AmbientSound.Stop();
- }
- }
-
- protected PPERUndergroundAcco GetRequester()
- {
- if (!m_Requester)
- {
- m_Requester = PPERUndergroundAcco.Cast(PPERequesterBank.GetRequester( PPERequesterBank.REQ_UNDERGROUND));
- m_Requester.Start();
- }
- return m_Requester;
- }
-
- void OnTriggerEnter(UndergroundTrigger trigger)
- {
- m_InsideTriggers.Insert(trigger);
- OnTriggerInsiderUpdate();
-
- }
-
- void OnTriggerLeave(UndergroundTrigger trigger)
- {
- int index = m_InsideTriggers.Find(trigger);
- if (index != -1)
- {
- m_InsideTriggers.Remove(index);
- }
- OnTriggerInsiderUpdate();
- }
-
- protected void CalculateEyeAccoTarget()
- {
- if (!m_TransitionalTrigger)
- return;
-
- if (m_TransitionalTrigger.m_Data.UseLinePointFade && m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
- {
- CalculateLinePointFade();
- }
- else if (m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
- {
- CalculateBreadCrumbs();
- }
- }
-
- protected void CalculateBreadCrumbs()
- {
- float closestDist = float.MAX;
- array<float> distances = new array<float>();
- array<float> distancesInverted = new array<float>();
- int excludeMask = 0;
- foreach (int indx, auto crumb:m_TransitionalTrigger.m_Data.Breadcrumbs)
- {
- if (indx > 32)//error handling for exceeding this limit is handled elsewhere
- break;
-
- float dist = vector.Distance(m_Player.GetPosition(), crumb.GetPosition());
- float crumbRadius = m_TransitionalTrigger.m_Data.Breadcrumbs[indx].Radius;
- float maxRadiusAllowed = DISTANCE_CUTOFF;
-
- if (crumbRadius != -1)
- maxRadiusAllowed = crumbRadius;
- if (dist > maxRadiusAllowed)
- excludeMask = (excludeMask | (1 << indx));
- else if (m_TransitionalTrigger.m_Data.Breadcrumbs[indx].UseRaycast)
- {
- int idx = m_Player.GetBoneIndexByName("Head");
- vector rayStart = m_Player.GetBonePositionWS(idx);
- vector rayEnd = crumb.GetPosition();
- vector hitPos, hitNormal;
- float hitFraction;
- Object hitObj;
- if (DayZPhysics.RayCastBullet(rayStart, rayEnd,PhxInteractionLayers.TERRAIN | PhxInteractionLayers.ROADWAY| PhxInteractionLayers.BUILDING, null, hitObj, hitPos, hitNormal, hitFraction))
- {
- excludeMask = (excludeMask | (1 << indx));
- }
- }
-
- distances.Insert(dist);
-
- #ifdef DIAG_DEVELOPER
- if ( DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
- Debug.DrawSphere(crumb.GetPosition(),0.1, COLOR_RED, ShapeFlags.ONCE);
- #endif
- }
-
- float baseDst = distances[0];
- float sum = 0;
- foreach (float dst:distances)
- {
- if (dst == 0)
- dst = 0.1;
- float dstInv = (baseDst / dst) * baseDst;
- sum += dstInv;
- distancesInverted.Insert(dstInv);
- }
-
- float sumCheck = 0;
- float eyeAcco = 0;
- foreach (int i, float dstInvert:distancesInverted)
- {
- if ((1 << i) & excludeMask)
- continue;
-
- float ratio = dstInvert / sum;
- if (ratio > MAX_RATIO)
- ratio = MAX_RATIO;
-
- if (ratio > RATIO_CUTOFF)
- {
- #ifdef DIAG_DEVELOPER
- if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
- {
- float intensity = (1-ratio) * 255;
- Debug.DrawLine(GetGame().GetPlayer().GetPosition() + "0 1 0", m_TransitionalTrigger.m_Data.Breadcrumbs[i].GetPosition(),ARGB(0,255,intensity,intensity),ShapeFlags.ONCE);
- }
- #endif
-
- eyeAcco += ratio * m_TransitionalTrigger.m_Data.Breadcrumbs[i].EyeAccommodation;
- }
- }
-
- m_EyeAccoTarget = eyeAcco * ACCO_MODIFIER;
- }
-
- protected void CalculateLinePointFade()
- {
- array<ref JsonUndergroundAreaBreadcrumb> points = m_TransitionalTrigger.m_Data.Breadcrumbs;
- JsonUndergroundAreaBreadcrumb startPoint = points[0];
- JsonUndergroundAreaBreadcrumb endPoint = points[points.Count() - 1];
- vector playerPos = m_Player.GetPosition();
-
- bool forceAcco;
- float acco;
- float accoMax = m_TransitionalTrigger.m_Data.Breadcrumbs[0].EyeAccommodation;
- float accoMin = endPoint.EyeAccommodation;
- JsonUndergroundAreaBreadcrumb closestPoint;
- JsonUndergroundAreaBreadcrumb secondaryPoint;
- float distanceToClosest;
- float distanceToSecondary;
- float distanceBetweenPoints;
-
- foreach (JsonUndergroundAreaBreadcrumb point : points) //identify closest segment
- {
- float dist = vector.DistanceSq(playerPos, point.GetPosition());
- if (!closestPoint || dist < distanceToClosest)
- {
- if (closestPoint)
- {
- secondaryPoint = closestPoint;
- distanceToSecondary = distanceToClosest;
- }
- closestPoint = point;
- distanceToClosest = dist;
- }
- else if (!secondaryPoint || dist < secondaryPoint)
- {
- secondaryPoint = point;
- distanceToSecondary = dist;
- }
-
- #ifdef DIAG_DEVELOPER
- if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB))
- Debug.DrawSphere(point.GetPosition(),0.1, COLOR_RED, ShapeFlags.ONCE);
- #endif
- }
-
- distanceBetweenPoints = vector.DistanceSq(closestPoint.GetPosition(), secondaryPoint.GetPosition());
- if (closestPoint == startPoint && secondaryPoint == points[1] && distanceToSecondary > distanceBetweenPoints) // before first point, do nothing
- acco = accoMax;
- else if (closestPoint == endPoint && secondaryPoint == points[points.Count() - 2] && distanceToSecondary > distanceBetweenPoints) // past second point, do nothing
- acco = accoMin;
- else // between the two points, lerp
- {
- if (closestPoint == endPoint)
- secondaryPoint = points[points.Count() - 2];
- else if (closestPoint == startPoint)
- secondaryPoint = points[1];
- else if (distanceBetweenPoints < distanceToClosest || distanceBetweenPoints < distanceToSecondary)
- {
- JsonUndergroundAreaBreadcrumb nexPoint = points[points.Find(closestPoint) + 1];
- if (vector.DistanceSq(playerPos, nexPoint.GetPosition()) < vector.DistanceSq(closestPoint.GetPosition(), nexPoint.GetPosition()))
- secondaryPoint = nexPoint;
- else
- {
- acco = closestPoint.EyeAccommodation;
- forceAcco = true;
- }
- }
-
- if (!forceAcco)
- {
- distanceToSecondary = vector.DistanceSq(playerPos, secondaryPoint.GetPosition());
-
- acco = distanceToSecondary / (distanceToClosest + distanceToSecondary); // progress
- acco = Math.Lerp(secondaryPoint.EyeAccommodation, closestPoint.EyeAccommodation, acco);
-
- if (points.Find(closestPoint) > points.Find(secondaryPoint))
- m_LightingLerpTarget = closestPoint.LightLerp;
- else
- m_LightingLerpTarget = secondaryPoint.LightLerp;
-
- }
- }
-
- m_EyeAccoTarget = acco * ACCO_MODIFIER;
-
- if (m_LightingLerpTarget != m_LightingLerp && (!m_AnimTimerLightBlend || !m_AnimTimerLightBlend.IsRunning()))
- {
- if (m_LightingLerpTarget == 1)
- {
- m_AnimTimerLightBlend = new AnimationTimer();
- m_AnimTimerLightBlend.Run(1, this, "OnUpdateTimerIn", "OnUpdateTimerEnd",0, false, LIGHT_BLEND_SPEED_IN);
- }
- else
- {
- m_AnimTimerLightBlend = new AnimationTimer();
- m_AnimTimerLightBlend.Run(0, this, "OnUpdateTimerOut", "OnUpdateTimerEnd",m_LightingLerp, false, LIGHT_BLEND_SPEED_OUT);
- }
- }
-
- #ifdef DIAG_DEVELOPER
- if (DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB))
- {
- Debug.DrawLine(m_Player.GetPosition() + "0 1 0", closestPoint.GetPosition(), COLOR_YELLOW, ShapeFlags.ONCE);
- if (acco != accoMin && acco != accoMax)
- Debug.DrawLine(closestPoint.GetPosition(), secondaryPoint.GetPosition(), COLOR_RED, ShapeFlags.ONCE);
-
- DbgUI.Begin(String("Underground Areas"), 20, 20);
- DbgUI.Text(String("Closest point id: " + points.Find(closestPoint)));
- DbgUI.Text(String("Second closest id: " + points.Find(secondaryPoint)));
- DbgUI.End();
- }
- #endif
- }
-
- protected void ProcessEyeAcco(float timeSlice)
- {
- CalculateEyeAccoTarget();
- bool reachedTarget = CalculateEyeAcco(timeSlice);
- ApplyEyeAcco();
- if(reachedTarget && !m_Player.m_UndergroundPresence)
- {
- GetRequester().Stop();
- UpdateNVGRequester(1);
- //m_NVRequester.SetUndergroundExposureCoef(1.0);
- m_Player.KillUndergroundHandler();
- }
- }
-
- protected void ProcessLighting(float timeSlice)
- {
- #ifdef DEVELOPER
- if (!DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_DISABLE_DARKENING) )
- {
- GetGame().GetWorld().SetUserLightingLerp(m_LightingLerp);
- }
- else
- {
- GetGame().GetWorld().SetUserLightingLerp(0);
- }
- #else
- GetGame().GetWorld().SetUserLightingLerp(m_LightingLerp);
- #endif
- }
-
- protected void ProcessSound(float timeSlice)
- {
- GetGame().GetWorld().SetExplicitVolumeFactor_EnvSounds2D(m_EyeAcco, 0);
- if (m_AmbientSound)
- {
- if (m_TransitionalTrigger && m_TransitionalTrigger.m_Data.Breadcrumbs.Count() >= 2)
- m_AmbientSound.SetSoundVolume(1-m_EyeAcco);
- }
- }
-
- void Tick(float timeSlice)
- {
- if (!m_Player.IsAlive())
- return;
-
- ProcessEyeAcco(timeSlice);
- ProcessLighting(timeSlice);
- ProcessSound(timeSlice);
-
- #ifdef DIAG_DEVELOPER
- if ( DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_SHOW_BREADCRUMB) )
- {
- DisplayDebugInfo(GetGame().GetWorld().GetEyeAccom(), m_LightingLerp);
- }
- #endif
-
- }
-
- protected void ApplyEyeAcco()
- {
- #ifdef DIAG_DEVELOPER
- if (!DiagMenu.GetBool(DiagMenuIDs.UNDERGROUND_DISABLE_DARKENING) )
- {
- GetRequester().SetEyeAccommodation(m_EyeAcco);
- }
- else
- {
- GetRequester().SetEyeAccommodation(1);
- }
- #else
- GetRequester().SetEyeAccommodation(m_EyeAcco);
- #endif
-
- float undergrounNVExposureCoef = m_EyeAcco;
- if (m_LightingLerp >= 1.0 || GetDayZGame().GetWorld().IsNight())
- {
- undergrounNVExposureCoef = 1.0;
- }
- //m_NVRequester.SetUndergroundExposureCoef(undergrounNVExposureCoef);
- UpdateNVGRequester(undergrounNVExposureCoef);
- }
-
- protected void UpdateNVGRequester(float value)
- {
- m_NVRequester.SetUndergroundExposureCoef(value);
- }
-
- protected bool CalculateEyeAcco(float timeSlice)
- {
- if (m_TransitionalTrigger || !m_Player.m_UndergroundPresence || (m_EyeAccoTarget == 1))
- {
- float accoDiff = m_EyeAccoTarget - m_EyeAcco;
- float increase = accoDiff * m_AccoInterpolationSpeed * timeSlice;
- m_EyeAcco += increase;
- if (Math.AbsFloat(accoDiff) < 0.01)
- {
- m_EyeAcco = m_EyeAccoTarget;
- return true;
- }
- }
- else
- {
- m_EyeAcco = m_EyeAccoTarget;
- }
- return false;
- }
-
-
-
- protected void OnTriggerInsiderUpdate()
- {
- EUndergroundTriggerType bestType = EUndergroundTriggerType.UNDEFINED;
- m_TransitionalTrigger = null;
- UndergroundTrigger bestTrigger;
- m_EyeAccoTarget = 1;
- m_AccoInterpolationSpeed = DEFAULT_INTERPOLATION_SPEED;
- foreach (auto t:m_InsideTriggers)
- {
- if (t.m_Type > bestType)
- {
- bestTrigger = t;
- bestType = t.m_Type;
- }
- }
- //Print(m_InsideTriggers.Count());
- //Print(bestType);
- if (bestTrigger)
- {
- if (bestTrigger.m_Type == EUndergroundTriggerType.TRANSITIONING)
- {
- m_TransitionalTrigger = bestTrigger;
- }
- m_EyeAccoTarget = bestTrigger.m_Accommodation;
- if (bestTrigger.m_InterpolationSpeed != -1 && bestTrigger.m_InterpolationSpeed != 0)
- m_AccoInterpolationSpeed = bestTrigger.m_InterpolationSpeed;
- }
-
- SetUndergroundPresence(bestTrigger);
- }
-
-
- protected void SetUndergroundPresence(UndergroundTrigger trigger)
- {
- EUndergroundPresence newPresence = EUndergroundPresence.NONE;
- EUndergroundPresence oldPresence = m_Player.m_UndergroundPresence;
-
- if (trigger)
- {
- if (trigger.m_Type == EUndergroundTriggerType.OUTER)
- {
- newPresence = EUndergroundPresence.OUTER;
- }
- else if (trigger.m_Type == EUndergroundTriggerType.TRANSITIONING)
- {
- newPresence = EUndergroundPresence.TRANSITIONING;
- }
- else if (trigger.m_Type == EUndergroundTriggerType.INNER)
- {
- newPresence = EUndergroundPresence.FULL;
- }
- }
-
- if (newPresence != oldPresence)//was there a change ?
- {
- OnUndergroundPresenceUpdate(newPresence,oldPresence);
- m_Player.SetUnderground(newPresence);
- }
-
-
- }
-
- protected void EnableLights(bool enable)
- {
- foreach (ScriptedLightBase light:ScriptedLightBase.m_NightTimeOnlyLights)
- {
- light.SetVisibleDuringDaylight(enable);
- }
- }
-
- void OnUpdateTimerEnd();
-
- void OnUpdateTimerIn()
- {
- if (!m_AnimTimerLightBlend)
- return;
- float value01 = m_AnimTimerLightBlend.GetValue();
- float result = Easing.EaseInQuint(value01);
- m_LightingLerp = result;
-
- }
-
- void OnUpdateTimerOut()
- {
- if (!m_AnimTimerLightBlend)
- return;
- float value01 = m_AnimTimerLightBlend.GetValue();
- float result = Easing.EaseOutCubic(value01);
- m_LightingLerp = result;
- }
-
- protected void PlayAmbientSound()
- {
- if (m_TransitionalTrigger && m_TransitionalTrigger.m_Data.AmbientSoundType != string.Empty)
- {
- m_AmbientController = m_TransitionalTrigger.m_Data.AmbientSoundType;
- SetSoundControllerOverride(m_AmbientController, 1.0, SoundControllerAction.Overwrite);
- }
- else
- m_Player.PlaySoundSetLoop(m_AmbientSound, "Underground_SoundSet",3,3);
- }
-
- protected void StopAmbientSound()
- {
- if (m_AmbientController != string.Empty)
- {
- SetSoundControllerOverride(m_AmbientController, 0, SoundControllerAction.None);
- m_AmbientController = string.Empty;
- }
- else if (m_AmbientSound)
- m_Player.StopSoundSet(m_AmbientSound);
- }
-
- protected void OnUndergroundPresenceUpdate(EUndergroundPresence newPresence, EUndergroundPresence oldPresence)
- {
- //Print("-----> On Undeground Presence update " + EnumTools.EnumToString(EUndergroundPresence, newPresence) + " " + EnumTools.EnumToString(EUndergroundPresence, oldPresence));
- if (newPresence > EUndergroundPresence.NONE)
- {
- if (oldPresence == EUndergroundPresence.NONE)
- {
- EnableLights(true);
- }
- if (newPresence > EUndergroundPresence.OUTER && oldPresence <= EUndergroundPresence.OUTER)
- {
- GetGame().GetWeather().SuppressLightningSimulation(true);
- PlayAmbientSound();
- }
- if (newPresence == EUndergroundPresence.FULL)
- {
- m_AnimTimerLightBlend = new AnimationTimer();
- m_AnimTimerLightBlend.Run(1, this, "OnUpdateTimerIn", "OnUpdateTimerEnd",0, false, LIGHT_BLEND_SPEED_IN);
- }
- }
- if (newPresence < EUndergroundPresence.FULL && oldPresence == EUndergroundPresence.FULL)
- {
- m_AnimTimerLightBlend = new AnimationTimer();
- m_AnimTimerLightBlend.Run(0, this, "OnUpdateTimerOut", "OnUpdateTimerEnd",m_LightingLerp, false, LIGHT_BLEND_SPEED_OUT);
- }
- if (newPresence <= EUndergroundPresence.OUTER && oldPresence > EUndergroundPresence.OUTER)
- {
- GetGame().GetWeather().SuppressLightningSimulation(false);
- }
- if (newPresence == EUndergroundPresence.NONE)
- {
- StopAmbientSound();
-
- if (oldPresence >= EUndergroundPresence.OUTER)
- {
- GetGame().GetWorld().SetUserLightingLerp(0);
- EnableLights(false);
- }
- }
- }
-
- #ifdef DIAG_DEVELOPER
- protected void DisplayDebugInfo(float acco, float lighting)
- {
- if (acco < 0.0001)
- acco = 0;
- DbgUI.Begin(String("Underground Areas"), 20, 20);
- DbgUI.Text(String("Eye Accomodation: " + acco.ToString()));
- DbgUI.Text(String("Lighting lerp: " + lighting.ToString()));
- DbgUI.End();
- }
- #endif
- }
|