7 const int CONTAMINATED_ZONE = 0;
8 const int UNDERGROUND = 1;
11class DynamicMusicLocationShape
27 vector min =
Vector(origin[0] - size, origin[1], origin[2] - size);
28 vector max =
Vector(origin[0] + size, origin[1], origin[2] + size);
34class DynamicMusicPlayerSettings
44 bool m_HasPriority =
false;
47 int m_Shape = DynamicMusicLocationShape.BOX;
57 locationBoundaries.Insert({min, max});
61class DynamicMusicPlayerTrackHistoryLookupType
75 bool m_Forced =
false;
76 bool m_FadeOut =
false;
81class DynamicMusicPlayer
83 #ifdef DMP_DEBUG_SETTINGS
106 protected int m_ActualTimeOfDay
119 private bool m_WaitingForPlayback;
120 private int m_RequestedPlaybackMode
124 private vector m_PlayerPosition;
126 private float m_FadeoutTimeElapsed;
127 private float m_FadeoutTimeRequested;
128 private bool m_FadeoutInProgress;
130 private bool m_Created;
137 m_ActualTimeOfDay = DynamicMusicPlayerTimeOfDay.ANY;
159 m_FadeoutTimeElapsed = 0.0;
160 m_FadeoutTimeRequested = 0.0;
185 if (m_FadeoutTimeElapsed >= m_FadeoutTimeRequested)
187 m_FadeoutTimeElapsed = 0.0;
188 m_FadeoutTimeRequested = 0.0;
189 m_FadeoutInProgress =
false;
203 RefreshTracksCache();
210 m_PlayerPosition =
g_Game.GetPlayer().GetPosition();
211 m_PlayerPosition[1] = 0.0;
219 if (PlayerInsideOfLocationFilter(m_LocationsDynamic))
221 else if (PlayerInsideOfLocationFilter(m_TracksLocationStaticPrioritizedCached))
232 if (PlayerInsideOfLocationFilter(m_TracksLocationStaticCached))
245 DynamicMusicPlayerCategoryPlaybackData playbackData =
new DynamicMusicPlayerCategoryPlaybackData();
247 SetCategory(playbackData);
259 #ifdef DIAG_DEVELOPER
260 if (DiagMenu.GetBool(
DiagMenuIDs.SOUNDS_DYNAMIC_MUSIC_PLAYER_STATS))
262 DisplayDebugStats(
true);
263 DisplayStaticLocations(
true);
272 void SetCategory(DynamicMusicPlayerCategoryPlaybackData playbackData)
279 if (!playbackData.m_FadeOut)
281 OnCategorySet(playbackData.m_Category, playbackData.m_Forced);
286 FadeoutTrack(GetPreviousTrackFadeoutSeconds(playbackData.m_Category));
289 void RegisterDynamicLocation(notnull Entity caller,
int locationType,
float locationSize)
291 int id = caller.GetID();
292 if (!m_LocationsDynamic.Contains(
id))
294 array<vector> minMax = DynamicMusicLocationDynamicData.GetRectangularCoordsFromSize(caller.GetPosition(), locationSize);
295 DynamicMusicLocationDynamicData location =
new DynamicMusicLocationDynamicData();
296 location.m_Type = locationType;
297 location.m_Min = minMax[0];
298 location.m_Max = minMax[1];
299 m_LocationsDynamic.Insert(
id, location);
303 void UnregisterDynamicLocation(notnull Entity caller)
305 m_LocationsDynamic.Remove(caller.GetID());
308 void OnGameEvent(
EventType eventTypeId, Param params)
314 DynamicMusicPlayerCategoryPlaybackData playbackData =
new DynamicMusicPlayerCategoryPlaybackData();
316 SetCategory(playbackData);
343 if (SetSelectedTrackFromCategory(category,
m_DynamicMusicPlayerRegistry.m_TracksCredits, DynamicMusicPlayerTrackHistoryLookupType.BUFFER))
389 m_RequestedPlaybackMode = value;
401 #ifdef ENABLE_LOGGING
402 DMPDebugPrint(
string.Format(
403 "OnCategorySet() - category: %1, forced: %2",
414 #ifdef ENABLE_LOGGING
416 DMPDebugPrint(
string.Format(
"Track END - %1",
m_CurrentTrack.m_SoundSet));
421 m_WaitingForPlayback =
false;
427 #ifdef ENABLE_LOGGING
429 DMPDebugPrint(
string.Format(
"Track STOP - %1",
m_CurrentTrack.m_SoundSet));
434 m_WaitingForPlayback =
false;
439 m_WaitingForPlayback =
true;
445 #ifdef ENABLE_LOGGING
446 DMPDebugPrint(
string.Format(
447 "WaitTime set to %1s, deferring playback of \"%2\"",
453 #ifdef DIAG_DEVELOPER
454 m_DebugWaitTime = waitTime;
462 #ifdef ENABLE_LOGGING
463 string messagePriority;
464 if (isPriorityLocation)
465 messagePriority =
"(with priority)";
466 DMPDebugPrint(
string.Format(
"Location matched %1", messagePriority));
470 playbackData.m_Category = category;
472 if (isPriorityLocation)
474 playbackData.m_Forced = isPriorityLocation;
478 if (m_WaitingForPlayback)
483 playbackData.m_FadeOut =
true;
484 SetCategory(playbackData);
488 SetCategory(playbackData);
491 SetCategory(playbackData);
494 SetCategory(playbackData);
505 playbackData.m_Category = category;
507 SetCategory(playbackData);
511 private void PlayTrack(DynamicMusicTrackData track)
514 if (soundParams.IsValid())
517 SoundObject soundObject = soundBuilder.BuildSoundObject();
518 soundObject.SetKind(
WaveKind.WAVEMUSIC);
530 m_WaitingForPlayback =
false;
535 m_WaitingForPlayback =
false;
540 private void StopTrack()
546 private void ResetWaitingQueue()
548 if (m_WaitingForPlayback)
551 m_WaitingForPlayback =
false;
556 private void FadeoutTrack(
float fadeoutSeconds)
558 if (m_FadeoutInProgress)
565 #ifdef ENABLE_LOGGING
566 DMPDebugPrint(
string.Format(
"Stopping currently played track %1",
m_CurrentTrack.m_SoundSet));
567 DMPDebugPrint(
string.Format(
"-- Setting fadeout to %1", fadeoutSeconds));
569 m_FadeoutInProgress =
true;
570 m_FadeoutTimeRequested = fadeoutSeconds;
574 private void ProcessFadeOut()
578 float volume = 1 - (m_FadeoutTimeElapsed / m_FadeoutTimeRequested);
583 private bool PlayerInsideOfLocationFilter(array<ref DynamicMusicTrackData> locations)
587 if (locations.Count() > 0)
589 foreach (DynamicMusicTrackData track : locations)
591 switch (track.m_Shape)
593 case DynamicMusicLocationShape.BOX:
594 foreach (
int locationId, array<vector> bounds : track.locationBoundaries)
596 if (Math.IsPointInRectangle(bounds[0], bounds[1], m_PlayerPosition))
601 #ifdef ENABLE_LOGGING
602 DMPDebugPrint(
string.Format(
"Player inside location <%1, %2>", bounds[0], bounds[1]));
607 case DynamicMusicLocationShape.POLYGON:
608 if (
Math2D.IsPointInPolygonXZ(track.vertices, m_PlayerPosition))
613 #ifdef ENABLE_LOGGING
614 DMPDebugPrint(
string.Format(
"Player inside polygon location at <%1>", m_PlayerPosition));
627 if (locations.Count() > 0)
629 foreach (
int locationId, DynamicMusicLocationDynamicData location : locations)
631 if (Math.IsPointInRectangle(location.m_Min, location.m_Max, m_PlayerPosition))
633 #ifdef ENABLE_LOGGING
634 DMPDebugPrint(
string.Format(
"Player inside location <%1, %2>", location.m_Min, location.m_Max));
644 private bool SetSelectedTrackFromCategory(
EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracklist,
int historyLookupType = DynamicMusicPlayerTrackHistoryLookupType.ANY)
646 if (tracklist.Count() == 0)
649 array<ref DynamicMusicTrackData> filteredTracks =
new array<ref DynamicMusicTrackData>();
650 foreach (DynamicMusicTrackData filteredTrack : tracklist)
652 if (filteredTrack.m_TimeOfDay == m_ActualTimeOfDay || filteredTrack.m_TimeOfDay == DynamicMusicPlayerTimeOfDay.ANY)
653 filteredTracks.Insert(filteredTrack);
659 trackIndex = SelectRandomTrackIndexFromCategoryPriorityFlagFirst(category, filteredTracks);
661 trackIndex = SelectRandomTrackIndexFromCategory(category, historyLookupType, filteredTracks);
665 m_LastPlayedTrackBufferPerCategory[category].Add(trackIndex);
674 private int SelectRandomTrackIndexFromCategoryPriorityFlagFirst(
EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracks)
679 array<int> priorityFlagIndices =
new array<int>();
681 foreach (
int i, DynamicMusicTrackData track : tracks)
684 if (!track.m_HasPriority)
687 priorityFlagIndices.Insert(i);
690 if (priorityFlagIndices.Count() > 0)
691 return priorityFlagIndices[priorityFlagIndices.GetRandomIndex()];
694 return tracks.GetRandomIndex();
700 private int SelectRandomTrackIndexFromCategory(
EDynamicMusicPlayerCategory category,
int lookupType, notnull array<ref DynamicMusicTrackData> tracks)
702 int count = tracks.Count();
705 int index = Math.RandomInt(0, count);
709 case DynamicMusicPlayerTrackHistoryLookupType.ANY:
712 case DynamicMusicPlayerTrackHistoryLookupType.BUFFER:
717 if (m_LastPlayedTrackBufferPerCategory[category].GetValues().Find(index) ==
INDEX_NOT_FOUND)
727 private void SetTimeOfDate()
736 m_ActualTimeOfDay = DynamicMusicPlayerTimeOfDay.DAY;
741 return Math.RandomFloatInclusive(GetMinWaitTimePerCategory(category), GetMaxWaitTimePerCategory(category));
747 #ifdef DIAG_DEVELOPER
748 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
750 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
752 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
761 #ifdef DIAG_DEVELOPER
762 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
764 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
766 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
777 private void RefreshTracksCache()
781 m_TracksLocationStaticCached.Clear();
784 if (track.m_Shape == DynamicMusicLocationShape.BOX)
786 foreach (array<vector> bounds : track.locationBoundaries)
788 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(bounds[0], bounds[1])) >
LOCATION_DISTANCE_MAX)
793 m_TracksLocationStaticCached.Insert(track);
796 m_TracksLocationStaticPrioritizedCached.Clear();
799 if (trackPrio.m_Shape == DynamicMusicLocationShape.BOX)
801 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
803 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(boundsPrio[0], boundsPrio[1])) >
LOCATION_DISTANCE_MAX)
808 m_TracksLocationStaticPrioritizedCached.Insert(trackPrio);
813 #ifdef DIAG_DEVELOPER
814 private ref array<Shape> m_DebugShapesLocations =
new array<Shape>();
815 private ref array<Shape> m_DebugShapesLocationsVertices =
new array<Shape>();
816 private float m_DebugWaitTime = 0;
818 private void DisplayDebugStats(
bool enabled)
827 DbgUI.Text(
string.Format(
"Day/Night: %1", DynamicMusicPlayerTimeOfDay.ToString(m_ActualTimeOfDay)));
828 DbgUI.Text(
"Playback:");
829 DbgUI.Text(
string.Format(
" active: %1", isPlaybackActive.ToString()));
830 DbgUI.Text(
string.Format(
" waiting: %1", m_WaitingForPlayback.ToString()));
835 DbgUI.Text(
"Update timers:");
844 DbgUI.Text(
"Player:");
845 DbgUI.Text(
string.Format(
" position: %1", m_PlayerPosition.ToString()));
849 DbgUI.Text(
"Tracks counts:");
858 DbgUI.Text(
string.Format(
" Static[cache]: %1", m_TracksLocationStaticCached.Count()));
859 DbgUI.Text(
string.Format(
" Static(prio)[cache]: %1", m_TracksLocationStaticPrioritizedCached.Count()));
868 string isPlaying =
"waiting";
870 isPlaying =
"playing";
872 DbgUI.Text(
string.Format(
"State: %1", isPlaying));
873 if (m_WaitingForPlayback)
875 DbgUI.Text(
string.Format(
"Wait time: %1s (%2s)", (
int)m_DebugWaitTime, (
int)(
g_Game.GetCallQueue(
CALL_CATEGORY_SYSTEM).GetRemainingTime(PlayTrack) * 0.001)));
877 DbgUI.Text(
string.Format(
"Sound set: %1",
m_CurrentTrack.m_SoundSet));
879 DbgUI.Text(
string.Format(
"Time of day: %1", DynamicMusicPlayerTimeOfDay.ToString(
m_CurrentTrack.m_TimeOfDay)));
886 if (DbgUI.Button(
"Stop"))
889 if (DbgUI.Button(
"Reset Waiting"))
892 DynamicMusicPlayerCategoryPlaybackData playbackData =
new DynamicMusicPlayerCategoryPlaybackData();
895 DbgUI.Text(
"Set Category:\n");
896 if (DbgUI.Button(
"Time"))
897 SetCategory(playbackData);
898 if (DbgUI.Button(
"Location"))
901 SetCategory(playbackData);
903 if (DbgUI.Button(
"Menu"))
906 SetCategory(playbackData);
908 if (DbgUI.Button(
"Credits"))
911 SetCategory(playbackData);
914 DbgUI.Text(
"Reset Timers\n");
915 if (DbgUI.Button(
"Timer ALL"))
922 if (DbgUI.Button(
"Timer Daytime"))
924 if (DbgUI.Button(
"Timer Location"))
926 if (DbgUI.Button(
"Timer Location(prio)"))
933 private void DisplayStaticLocations(
bool enabled)
939 vector position =
g_Game.GetCurrentCameraPosition();
941 foreach (DynamicMusicTrackData track : m_TracksLocationStaticCached)
943 foreach (array<vector> bounds : track.locationBoundaries)
945 locationMin = bounds[0];
946 locationMax = bounds[1];
948 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
951 Debug.CleanupDrawShapes(m_DebugShapesLocations);
953 locationMax[1] = locationMin[1] + 200.0;
954 locationMin[1] = locationMin[1] - 50.0;
958 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
959 DrawPolygonLocation(track);
962 foreach (DynamicMusicTrackData trackPrio : m_TracksLocationStaticPrioritizedCached)
964 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
966 locationMin = boundsPrio[0];
967 locationMax = boundsPrio[1];
969 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
972 Debug.CleanupDrawShapes(m_DebugShapesLocations);
974 locationMax[1] = locationMin[1] + 200.0;
975 locationMin[1] = locationMin[1] - 50.0;
979 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
980 DrawPolygonLocation(trackPrio);
983 foreach (DynamicMusicLocationDynamicData locationDynamic : m_LocationsDynamic)
985 locationMin = locationDynamic.m_Min;
986 locationMax = locationDynamic.m_Max;
988 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
991 Debug.CleanupDrawShapes(m_DebugShapesLocations);
993 locationMax[1] = locationMin[1] + 200.0;
994 locationMin[1] = locationMin[1] - 50.0;
1000 Debug.CleanupDrawShapes(m_DebugShapesLocations);
1001 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
1005 private void DrawPolygonLocation(notnull DynamicMusicTrackData track)
1007 vector first, current, last;
1009 int count = track.vertices.Count();
1010 foreach (
int i, vector vertexPos : track.vertices)
1012 vertexPos[1] = vertexPos[1] + 0.5;
1013 current = vertexPos;
1027 #ifdef ENABLE_LOGGING
1028 private void DMPDebugPrint(
string message)
1030 #ifdef DMP_DEBUG_PRINT
1037 private void CleanupDebugShapes(array<Shape> shapesArr)
1039 Debug.CleanupDrawShapes(shapesArr);
1044 DynamicMusicPlayerCategoryPlaybackData playbackData =
new DynamicMusicPlayerCategoryPlaybackData();
1045 playbackData.m_Category = category;
1046 playbackData.m_Forced = forced;
1048 SetCategory(playbackData);
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
const int TRACKS_BUFFER_HISTORY_SIZE
class DynamicMusicLocationDynamicData m_MinWaitTimeSeconds
EDynamicMusicPlayerCategory m_CategorySelected
const float TICK_PRIORITY_LOCATION_UPDATE_SECONDS
float m_TickLocationCacheUpdateElapsed
const float LOCATION_DISTANCE_MAX
float GetWaitTimeForCategory(EDynamicMusicPlayerCategory category)
void OnCategorySet(EDynamicMusicPlayerCategory category, bool forced)
const float TICK_FADEOUT_PROCESSOR_SECONDS
AbstractWave m_SoundPlaying
float m_PreviousTrackFadeoutSeconds
float m_TickTimeOfDateElapsed
ref DynamicMusicPlayerRegistry m_DynamicMusicPlayerRegistry
bool IsPriotitizedCategorySelected()
float m_TickFadeOutProcessingElapsed
void OnProfileOptionChanged(EDayZProfilesOptions option, int value)
void OnNextTrackSelected(DynamicMusicTrackData track, float waitTime)
void DetermineTrackByCategory(EDynamicMusicPlayerCategory category)
void OnLocationMatched(EDynamicMusicPlayerCategory category, bool isPriorityLocation)
const float TICK_LOCATION_CACHE_UPDATE_SECONDS
const float TICK_LOCATION_UPDATE_SECONDS
class DynamicMusicPlayerCategoryPlaybackData TICK_TIME_OF_DATE_UPDATE_SECONDS
DynamicMusicTrackData m_CurrentTrack
float m_TickPriorityLocationUpdateElapsed
ref array< ref DynamicMusicTrackData > m_TracksLocationMatchedPlayerInside
static prio + filtered by the distance between player and center of zone
void OnFadeoutFinished(EDynamicMusicPlayerCategory category)
float m_TickLocationUpdateElapsed
float m_MaxWaitTimeSeconds
EDynamicMusicPlayerCategory
const int INDEX_NOT_FOUND
const EventType MPSessionPlayerReadyEventTypeID
no params
enum WindingOrder Math2D()
proto native vector Vector(float x, float y, float z)
Vector constructor from components.
class AbstractSoundScene SoundObjectBuilder(SoundParams soundParams)
void SoundObject(SoundParams soundParams)
class SoundObject SoundParams(string name)
class PresenceNotifierNoiseEvents windowPosX
dbgUI settings