Dayz Explorer 1.29.162510
Loading...
Searching...
No Matches
dynamicmusicplayer.c
Go to the documentation of this file.
1//#define DMP_DEBUG_PRINT
2//#define DMP_DEBUG_SETTINGS
3
5{
6 const int NONE = -1;
7 const int CONTAMINATED_ZONE = 0;
8 const int UNDERGROUND = 1;
9}
10
11class DynamicMusicLocationShape
12{
13 const int BOX = 0;
14 const int POLYGON = 1;
15}
16
18{
19 int m_Type = DynamicMusicLocationTypes.NONE;
20
22 vector m_Min = vector.Zero;
23 vector m_Max = vector.Zero;
24
25 static array<vector> GetRectangularCoordsFromSize(vector origin, float size)
26 {
27 vector min = Vector(origin[0] - size, origin[1], origin[2] - size);
28 vector max = Vector(origin[0] + size, origin[1], origin[2] + size);
29
30 return {min, max};
31 }
32}
33
34class DynamicMusicPlayerSettings
35{
38
40}
41
43{
44 bool m_HasPriority = false;
45 int m_TimeOfDay = -1;
46 int m_LocationType = DynamicMusicLocationTypes.NONE;
47 int m_Shape = DynamicMusicLocationShape.BOX;
48 string m_SoundSet;
49
51
52 ref array<ref array<vector>> locationBoundaries = new array<ref array<vector>>();
53 ref array<vector> vertices = new array<vector>();
54
55 void InsertLocation(vector min, vector max)
56 {
57 locationBoundaries.Insert({min, max});
58 }
59}
60
61class DynamicMusicPlayerTrackHistoryLookupType
62{
63 const int ANY = 0;
64 const int BUFFER = 1;
65}
66
67/*
68 * \brief Structure for setting of Category playback
69 * @param m_Forced Force play of category (DEPRECATED)
70 * @param m_FadeOut If true, previously playing track will be faded out and stopped. Otherwise stopped only.
71 * @param m_Category Selected category that is going to be played
72 */
74{
75 bool m_Forced = false;
76 bool m_FadeOut = false;
77
79}
80
81class DynamicMusicPlayer
82{
83 #ifdef DMP_DEBUG_SETTINGS
84 protected const float TICK_TIME_OF_DATE_UPDATE_SECONDS = 10.0;
85 protected const float TICK_LOCATION_CACHE_UPDATE_SECONDS = 10.0;
86 protected const float TICK_LOCATION_UPDATE_SECONDS = 5.0;
87 protected const float TICK_PRIORITY_LOCATION_UPDATE_SECONDS = 2.0;
88 #else
89 protected const float TICK_TIME_OF_DATE_UPDATE_SECONDS = 300.0;
90 protected const float TICK_LOCATION_CACHE_UPDATE_SECONDS = 120.0;
91 protected const float TICK_LOCATION_UPDATE_SECONDS = 120.0;
92 protected const float TICK_PRIORITY_LOCATION_UPDATE_SECONDS = 30.0;
93 #endif
94
95 protected const float TICK_FADEOUT_PROCESSOR_SECONDS = 0.2;
96
97 protected const int TRACKS_BUFFER_HISTORY_SIZE = 2;
98 protected const float LOCATION_DISTANCE_MAX = 500;
99
100 protected float m_TickTimeOfDateElapsed;
105
106 protected int m_ActualTimeOfDay
110
111 protected ref map<int, ref DynamicMusicLocationDynamicData> m_LocationsDynamic
112
113 private ref array<ref DynamicMusicTrackData> m_TracksLocationStaticCached;
114 private ref array<ref DynamicMusicTrackData> m_TracksLocationStaticPrioritizedCached;
115
117
119 private bool m_WaitingForPlayback;
120 private int m_RequestedPlaybackMode
121
122 private ref map<EDynamicMusicPlayerCategory, ref SimpleCircularBuffer<int>> m_LastPlayedTrackBufferPerCategory;
123
124 private vector m_PlayerPosition;
125
126 private float m_FadeoutTimeElapsed;
127 private float m_FadeoutTimeRequested;
128 private bool m_FadeoutInProgress;
129
130 private bool m_Created;
131
132 void DynamicMusicPlayer(DynamicMusicPlayerRegistry configuration)
133 {
134 m_DynamicMusicPlayerRegistry = configuration;
135 m_RequestedPlaybackMode = g_Game.GetProfileOptionInt(EDayZProfilesOptions.AMBIENT_MUSIC_MODE);
136
137 m_ActualTimeOfDay = DynamicMusicPlayerTimeOfDay.ANY;
139
140 m_LastPlayedTrackBufferPerCategory = new map<EDynamicMusicPlayerCategory, ref SimpleCircularBuffer<int>>;
141
142 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.MENU] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
143 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.CREDITS] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
144 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.TIME] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
145
146 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.LOCATION_STATIC] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
147 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.LOCATION_STATIC_PRIORITY] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
148 m_LastPlayedTrackBufferPerCategory[EDynamicMusicPlayerCategory.LOCATION_DYNAMIC] = new SimpleCircularBuffer<int>(TRACKS_BUFFER_HISTORY_SIZE, -1);
149
150 m_LocationsDynamic = new map<int, ref DynamicMusicLocationDynamicData>();
151 m_TracksLocationStaticCached = new array<ref DynamicMusicTrackData>();
152 m_TracksLocationStaticPrioritizedCached = new array<ref DynamicMusicTrackData>();
153
155
156 SetTimeOfDate();
157
159 m_FadeoutTimeElapsed = 0.0;
160 m_FadeoutTimeRequested = 0.0;
161
162 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(RefreshTracksCache, 5000);
163
164 DayZProfilesOptions.m_OnIntOptionChanged.Insert(OnProfileOptionChanged);
165
166 m_Created = true;
167 }
168
169 void OnUpdate(float timeslice)
170 {
172 return;
173
179
182 {
183 m_FadeoutTimeElapsed += TICK_FADEOUT_PROCESSOR_SECONDS;
185 if (m_FadeoutTimeElapsed >= m_FadeoutTimeRequested)
186 {
187 m_FadeoutTimeElapsed = 0.0;
188 m_FadeoutTimeRequested = 0.0;
189 m_FadeoutInProgress = false;
191 }
192 else
193 ProcessFadeOut();
194 }
195 else
196 {
198 {
201 {
203 RefreshTracksCache();
204 }
205
207 {
208 if (g_Game.GetPlayer())
209 {
210 m_PlayerPosition = g_Game.GetPlayer().GetPosition();
211 m_PlayerPosition[1] = 0.0;
212 }
213
215
218 {
219 if (PlayerInsideOfLocationFilter(m_LocationsDynamic))
220 OnLocationMatched(EDynamicMusicPlayerCategory.LOCATION_DYNAMIC, true);
221 else if (PlayerInsideOfLocationFilter(m_TracksLocationStaticPrioritizedCached))
222 OnLocationMatched(EDynamicMusicPlayerCategory.LOCATION_STATIC_PRIORITY, true);
223 }
224 }
225
227 {
229
230 if (!IsPlaybackActive())
231 {
232 if (PlayerInsideOfLocationFilter(m_TracksLocationStaticCached))
233 OnLocationMatched(EDynamicMusicPlayerCategory.LOCATION_STATIC, false);
234 }
235 }
236
238 {
240 SetTimeOfDate();
241
244 {
245 DynamicMusicPlayerCategoryPlaybackData playbackData = new DynamicMusicPlayerCategoryPlaybackData();
246 playbackData.m_Category = EDynamicMusicPlayerCategory.TIME;
247 SetCategory(playbackData);
248 }
249 }
250 }
251 else
252 {
253 if (!IsPlaybackActive())
255 }
256
257 }
258
259 #ifdef DIAG_DEVELOPER
260 if (DiagMenu.GetBool(DiagMenuIDs.SOUNDS_DYNAMIC_MUSIC_PLAYER_STATS))
261 {
262 DisplayDebugStats(true);
263 DisplayStaticLocations(true);
264 }
265 #endif
266 }
267
268 /*
269 * \brief Set playback category
270 * @param playbackData Structure holding information about category playback settings
271 */
272 void SetCategory(DynamicMusicPlayerCategoryPlaybackData playbackData)
273 {
275 return;
276
277 m_CategorySelected = playbackData.m_Category;
278
279 if (!playbackData.m_FadeOut)
280 {
281 OnCategorySet(playbackData.m_Category, playbackData.m_Forced);
282 return;
283 }
284
286 FadeoutTrack(GetPreviousTrackFadeoutSeconds(playbackData.m_Category));
287 }
288
289 void RegisterDynamicLocation(notnull Entity caller, int locationType, float locationSize)
290 {
291 int id = caller.GetID();
292 if (!m_LocationsDynamic.Contains(id))
293 {
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);
300 }
301 }
302
303 void UnregisterDynamicLocation(notnull Entity caller)
304 {
305 m_LocationsDynamic.Remove(caller.GetID());
306 }
307
308 void OnGameEvent(EventType eventTypeId, Param params)
309 {
310 if (eventTypeId == MPSessionPlayerReadyEventTypeID)
311 {
312 SetTimeOfDate();
313
314 DynamicMusicPlayerCategoryPlaybackData playbackData = new DynamicMusicPlayerCategoryPlaybackData();
315 playbackData.m_Category = EDynamicMusicPlayerCategory.TIME;
316 SetCategory(playbackData);
317 }
318 }
319
321 {
322 return m_CategorySelected == EDynamicMusicPlayerCategory.LOCATION_STATIC_PRIORITY || m_CategorySelected == EDynamicMusicPlayerCategory.LOCATION_DYNAMIC;
323 }
324
326 {
327 if (m_CategorySelected != EDynamicMusicPlayerCategory.MENU && m_RequestedPlaybackMode == 1)
328 return;
329
330 if (IsPlaybackActive())
331 return;
332
333 switch (category)
334 {
336 if (SetSelectedTrackFromCategory(category, m_DynamicMusicPlayerRegistry.m_TracksMenu, DynamicMusicPlayerTrackHistoryLookupType.BUFFER))
337 break;
338
339 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
340 break;
341
342 case EDynamicMusicPlayerCategory.CREDITS:
343 if (SetSelectedTrackFromCategory(category, m_DynamicMusicPlayerRegistry.m_TracksCredits, DynamicMusicPlayerTrackHistoryLookupType.BUFFER))
344 break;
345
346 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
347 break;
348
350 if (SetSelectedTrackFromCategory(category, m_DynamicMusicPlayerRegistry.m_TracksTime, DynamicMusicPlayerTrackHistoryLookupType.BUFFER))
351 break;
352
353 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
354 break;
355 case EDynamicMusicPlayerCategory.LOCATION_STATIC:
356 if (SetSelectedTrackFromCategory(category, m_TracksLocationMatchedPlayerInside))
357 break;
358
359 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
360 break;
361 case EDynamicMusicPlayerCategory.LOCATION_STATIC_PRIORITY:
362 if (SetSelectedTrackFromCategory(category, m_TracksLocationMatchedPlayerInside))
363 break;
364
365 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
366 break;
367 case EDynamicMusicPlayerCategory.LOCATION_DYNAMIC:
368 if (SetSelectedTrackFromCategory(category, m_DynamicMusicPlayerRegistry.m_TracksLocationDynamic))
369 break;
370
371 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(DetermineTrackByCategory, 5000, false, category);
372
373 break;
374 }
375 }
376
377 protected bool IsPlaybackActive()
378 {
379 return m_SoundPlaying || m_WaitingForPlayback;
380 }
381
384
385 protected void OnProfileOptionChanged(EDayZProfilesOptions option, int value)
386 {
387 if (option == EDayZProfilesOptions.AMBIENT_MUSIC_MODE)
388 {
389 m_RequestedPlaybackMode = value;
390
391 if (value == 1 && m_CategorySelected != EDynamicMusicPlayerCategory.MENU)
392 {
393 StopTrack();
394 ResetWaitingQueue();
395 }
396 }
397 }
398
399 protected void OnCategorySet(EDynamicMusicPlayerCategory category, bool forced)
400 {
401 #ifdef ENABLE_LOGGING
402 DMPDebugPrint(string.Format(
403 "OnCategorySet() - category: %1, forced: %2",
404 EnumTools.EnumToString(EDynamicMusicPlayerCategory, category),
405 forced),
406 );
407 #endif
408
409 DetermineTrackByCategory(category);
410 }
411
412 protected void OnTrackEnded()
413 {
414 #ifdef ENABLE_LOGGING
415 if (m_CurrentTrack)
416 DMPDebugPrint(string.Format("Track END - %1", m_CurrentTrack.m_SoundSet));
417 #endif
418
419 m_SoundPlaying = null;
420 m_CurrentTrack = null;
421 m_WaitingForPlayback = false;
422 }
423
424 protected void OnTrackStopped()
425 {
427 #ifdef ENABLE_LOGGING
428 if (m_CurrentTrack)
429 DMPDebugPrint(string.Format("Track STOP - %1", m_CurrentTrack.m_SoundSet));
430 #endif
431
432 m_SoundPlaying = null;
433 m_CurrentTrack = null;
434 m_WaitingForPlayback = false;
435 }
436
437 protected void OnNextTrackSelected(DynamicMusicTrackData track, float waitTime)
438 {
439 m_WaitingForPlayback = true;
440 m_CurrentTrack = track;
441
442 if (m_Created)
443 m_Created = false;
444
445 #ifdef ENABLE_LOGGING
446 DMPDebugPrint(string.Format(
447 "WaitTime set to %1s, deferring playback of \"%2\"",
448 (int)waitTime,
449 track.m_SoundSet),
450 );
451 #endif
452
453 #ifdef DIAG_DEVELOPER
454 m_DebugWaitTime = waitTime;
455 #endif
456
457 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(PlayTrack, (int)waitTime * 1000, false, track);
458 }
459
460 protected void OnLocationMatched(EDynamicMusicPlayerCategory category, bool isPriorityLocation)
461 {
462 #ifdef ENABLE_LOGGING
463 string messagePriority;
464 if (isPriorityLocation)
465 messagePriority = "(with priority)";
466 DMPDebugPrint(string.Format("Location matched %1", messagePriority));
467 #endif
468
470 playbackData.m_Category = category;
471
472 if (isPriorityLocation)
473 {
474 playbackData.m_Forced = isPriorityLocation;
476 {
477 m_CategorySelected = category;
478 if (m_WaitingForPlayback)
479 ResetWaitingQueue();
480
481 if (m_SoundPlaying)
482 {
483 playbackData.m_FadeOut = true;
484 SetCategory(playbackData);
485 return;
486 }
487
488 SetCategory(playbackData);
489 }
490 else
491 SetCategory(playbackData);
492 }
493 else
494 SetCategory(playbackData);
495 }
496
498 {
499 if (m_SoundPlaying)
500 m_SoundPlaying.GetEvents().Event_OnSoundWaveEnded.Remove(OnTrackEnded);
501
502 StopTrack();
503
505 playbackData.m_Category = category;
506 playbackData.m_Forced = IsPriotitizedCategorySelected();
507 SetCategory(playbackData);
508 }
509
510
511 private void PlayTrack(DynamicMusicTrackData track)
512 {
513 SoundParams soundParams = new SoundParams(track.m_SoundSet);
514 if (soundParams.IsValid())
515 {
516 SoundObjectBuilder soundBuilder = new SoundObjectBuilder(soundParams);
517 SoundObject soundObject = soundBuilder.BuildSoundObject();
518 soundObject.SetKind(WaveKind.WAVEMUSIC);
519
520 m_SoundPlaying = g_Game.GetSoundScene().Play2D(soundObject, soundBuilder);
521 if (m_SoundPlaying)
522 {
523 m_SoundPlaying.Loop(false);
524 m_SoundPlaying.Play();
525
527 m_SoundPlaying.GetEvents().Event_OnSoundWaveEnded.Insert(OnTrackEnded);
528 m_SoundPlaying.GetEvents().Event_OnSoundWaveStopped.Insert(OnTrackStopped);
529
530 m_WaitingForPlayback = false;
531 }
532 }
533 else
534 {
535 m_WaitingForPlayback = false;
536 m_CurrentTrack = null;
537 }
538 }
539
540 private void StopTrack()
541 {
542 if (m_SoundPlaying)
543 m_SoundPlaying.Stop();
544 }
545
546 private void ResetWaitingQueue()
547 {
548 if (m_WaitingForPlayback)
549 {
550 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).Remove(PlayTrack);
551 m_WaitingForPlayback = false;
552 m_CurrentTrack = null;
553 }
554 }
555
556 private void FadeoutTrack(float fadeoutSeconds)
557 {
558 if (m_FadeoutInProgress)
559 return;
560
561 ResetWaitingQueue();
562
564 {
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));
568 #endif
569 m_FadeoutInProgress = true;
570 m_FadeoutTimeRequested = fadeoutSeconds;
571 }
572 }
573
574 private void ProcessFadeOut()
575 {
576 if (m_SoundPlaying)
577 {
578 float volume = 1 - (m_FadeoutTimeElapsed / m_FadeoutTimeRequested);
579 m_SoundPlaying.SetFadeOutFactor(volume);
580 }
581 }
582
583 private bool PlayerInsideOfLocationFilter(array<ref DynamicMusicTrackData> locations)
584 {
586
587 if (locations.Count() > 0)
588 {
589 foreach (DynamicMusicTrackData track : locations)
590 {
591 switch (track.m_Shape)
592 {
593 case DynamicMusicLocationShape.BOX:
594 foreach (int locationId, array<vector> bounds : track.locationBoundaries)
595 {
596 if (Math.IsPointInRectangle(bounds[0], bounds[1], m_PlayerPosition))
597 {
600
601 #ifdef ENABLE_LOGGING
602 DMPDebugPrint(string.Format("Player inside location <%1, %2>", bounds[0], bounds[1]));
603 #endif
604 }
605 }
606 break;
607 case DynamicMusicLocationShape.POLYGON:
608 if (Math2D.IsPointInPolygonXZ(track.vertices, m_PlayerPosition))
609 {
612
613 #ifdef ENABLE_LOGGING
614 DMPDebugPrint(string.Format("Player inside polygon location at <%1>", m_PlayerPosition));
615 #endif
616 }
617 break;
618 }
619 }
620 }
621
622 return m_TracksLocationMatchedPlayerInside.Count() > 0;
623 }
624
625 private bool PlayerInsideOfLocationFilter(map<int, ref DynamicMusicLocationDynamicData> locations)
626 {
627 if (locations.Count() > 0)
628 {
629 foreach (int locationId, DynamicMusicLocationDynamicData location : locations)
630 {
631 if (Math.IsPointInRectangle(location.m_Min, location.m_Max, m_PlayerPosition))
632 {
633 #ifdef ENABLE_LOGGING
634 DMPDebugPrint(string.Format("Player inside location <%1, %2>", location.m_Min, location.m_Max));
635 #endif
636 return true;
637 }
638 }
639 }
640
641 return false;
642 }
643
644 private bool SetSelectedTrackFromCategory(EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracklist, int historyLookupType = DynamicMusicPlayerTrackHistoryLookupType.ANY)
645 {
646 if (tracklist.Count() == 0)
647 return true;
648
649 array<ref DynamicMusicTrackData> filteredTracks = new array<ref DynamicMusicTrackData>();
650 foreach (DynamicMusicTrackData filteredTrack : tracklist)
651 {
652 if (filteredTrack.m_TimeOfDay == m_ActualTimeOfDay || filteredTrack.m_TimeOfDay == DynamicMusicPlayerTimeOfDay.ANY)
653 filteredTracks.Insert(filteredTrack);
654 }
655
656 float trackIndex;
658 if (m_Created && category == EDynamicMusicPlayerCategory.MENU)
659 trackIndex = SelectRandomTrackIndexFromCategoryPriorityFlagFirst(category, filteredTracks);
660 else
661 trackIndex = SelectRandomTrackIndexFromCategory(category, historyLookupType, filteredTracks);
662
663 if (trackIndex > INDEX_NOT_FOUND)
664 {
665 m_LastPlayedTrackBufferPerCategory[category].Add(trackIndex);
666 OnNextTrackSelected(filteredTracks[trackIndex], GetWaitTimeForCategory(category));
667
668 return true;
669 }
670
671 return false;
672 }
673
674 private int SelectRandomTrackIndexFromCategoryPriorityFlagFirst(EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracks)
675 {
677 if (category == EDynamicMusicPlayerCategory.MENU)
678 {
679 array<int> priorityFlagIndices = new array<int>();
680
681 foreach (int i, DynamicMusicTrackData track : tracks)
682 {
683
684 if (!track.m_HasPriority)
685 continue;
686
687 priorityFlagIndices.Insert(i);
688 }
689
690 if (priorityFlagIndices.Count() > 0)
691 return priorityFlagIndices[priorityFlagIndices.GetRandomIndex()];
692
694 return tracks.GetRandomIndex();
695 }
696
697 return INDEX_NOT_FOUND;
698 }
699
700 private int SelectRandomTrackIndexFromCategory(EDynamicMusicPlayerCategory category, int lookupType, notnull array<ref DynamicMusicTrackData> tracks)
701 {
702 int count = tracks.Count();
703 if (count > 0)
704 {
705 int index = Math.RandomInt(0, count);
706
707 switch (lookupType)
708 {
709 case DynamicMusicPlayerTrackHistoryLookupType.ANY:
710 return index;
711
712 case DynamicMusicPlayerTrackHistoryLookupType.BUFFER:
713 // fallback - num of track is smaller than actual history size;
714 if (count <= TRACKS_BUFFER_HISTORY_SIZE)
715 return index;
716
717 if (m_LastPlayedTrackBufferPerCategory[category].GetValues().Find(index) == INDEX_NOT_FOUND)
718 return index;
719
720 return INDEX_NOT_FOUND;
721 }
722 }
723
724 return INDEX_NOT_FOUND;
725 }
726
727 private void SetTimeOfDate()
728 {
729 Mission mission = g_Game.GetMission();
730 if (mission)
731 {
732 m_ActualTimeOfDay = mission.GetWorldData().GetDaytime();
733 return;
734 }
735
736 m_ActualTimeOfDay = DynamicMusicPlayerTimeOfDay.DAY;
737 }
738
740 {
741 return Math.RandomFloatInclusive(GetMinWaitTimePerCategory(category), GetMaxWaitTimePerCategory(category));
742 }
743
744 private float GetMinWaitTimePerCategory(EDynamicMusicPlayerCategory category)
745 {
746 float waitTime = m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_MinWaitTimeSeconds;
747 #ifdef DIAG_DEVELOPER
748 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
749 {
750 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
751 if (timeAccel > 0)
752 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
753 }
754 #endif
755 return waitTime;
756 }
757
758 private float GetMaxWaitTimePerCategory(EDynamicMusicPlayerCategory category)
759 {
760 float waitTime = m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_MaxWaitTimeSeconds;
761 #ifdef DIAG_DEVELOPER
762 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
763 {
764 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
765 if (timeAccel > 0)
766 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
767 }
768 #endif
769 return waitTime;
770 }
771
772 private float GetPreviousTrackFadeoutSeconds(EDynamicMusicPlayerCategory category)
773 {
774 return m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_PreviousTrackFadeoutSeconds;
775 }
776
777 private void RefreshTracksCache()
778 {
780 {
781 m_TracksLocationStaticCached.Clear();
782 foreach (DynamicMusicTrackData track : m_DynamicMusicPlayerRegistry.m_TracksLocationStatic)
783 {
784 if (track.m_Shape == DynamicMusicLocationShape.BOX)
785 {
786 foreach (array<vector> bounds : track.locationBoundaries)
787 {
788 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(bounds[0], bounds[1])) > LOCATION_DISTANCE_MAX)
789 continue;
790 }
791 }
792
793 m_TracksLocationStaticCached.Insert(track);
794 }
795
796 m_TracksLocationStaticPrioritizedCached.Clear();
797 foreach (DynamicMusicTrackData trackPrio : m_DynamicMusicPlayerRegistry.m_TracksLocationStaticPrioritized)
798 {
799 if (trackPrio.m_Shape == DynamicMusicLocationShape.BOX)
800 {
801 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
802 {
803 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(boundsPrio[0], boundsPrio[1])) > LOCATION_DISTANCE_MAX)
804 continue;
805 }
806 }
807
808 m_TracksLocationStaticPrioritizedCached.Insert(trackPrio);
809 }
810 }
811 }
812
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;
817
818 private void DisplayDebugStats(bool enabled)
819 {
820 int windowPosX = 10;
821 int windowPosY = 200;
822
823 DbgUI.Begin("DMP - Overall stats", windowPosX, windowPosY);
824 if (enabled)
825 {
826 bool isPlaybackActive = m_SoundPlaying != null;
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()));
831 DbgUI.Text(string.Format("Selected Category: %1", EnumTools.EnumToString(EDynamicMusicPlayerCategory, m_CategorySelected)));
832
834 {
835 DbgUI.Text("Update timers:");
836 DbgUI.Text(string.Format(" TimeOfDay: %1(%2)", TICK_TIME_OF_DATE_UPDATE_SECONDS, TICK_TIME_OF_DATE_UPDATE_SECONDS - (int)m_TickTimeOfDateElapsed));
837 DbgUI.Text(string.Format(" Location: %1(%2)", TICK_LOCATION_UPDATE_SECONDS, TICK_LOCATION_UPDATE_SECONDS - (int)m_TickLocationUpdateElapsed));
839 DbgUI.Text(string.Format(" Location Cache: %1(%2)", TICK_LOCATION_CACHE_UPDATE_SECONDS, TICK_LOCATION_CACHE_UPDATE_SECONDS - (int)m_TickLocationCacheUpdateElapsed));
840 }
841
843 {
844 DbgUI.Text("Player:");
845 DbgUI.Text(string.Format(" position: %1", m_PlayerPosition.ToString()));
846 DbgUI.Text(string.Format(" matched num tracks(location): %1", m_TracksLocationMatchedPlayerInside.Count()));
847 }
848
849 DbgUI.Text("Tracks counts:");
851 {
852 DbgUI.Text(string.Format(" Menu: %1", m_DynamicMusicPlayerRegistry.m_TracksMenu.Count()));
853 DbgUI.Text(string.Format(" Credits: %1", m_DynamicMusicPlayerRegistry.m_TracksCredits.Count()));
854 }
855 else
856 {
857 DbgUI.Text(string.Format(" Time: %1", m_DynamicMusicPlayerRegistry.m_TracksTime.Count()));
858 DbgUI.Text(string.Format(" Static[cache]: %1", m_TracksLocationStaticCached.Count()));
859 DbgUI.Text(string.Format(" Static(prio)[cache]: %1", m_TracksLocationStaticPrioritizedCached.Count()));
860 DbgUI.Text(string.Format(" Dynamic(prio): %1", m_DynamicMusicPlayerRegistry.m_TracksLocationDynamic.Count()));
861 }
862 }
863 DbgUI.End();
864
865 DbgUI.Begin("DMP - Current track", windowPosX, windowPosY+380);
866 if (enabled && m_CurrentTrack)
867 {
868 string isPlaying = "waiting";
869 if (m_SoundPlaying != null)
870 isPlaying = "playing";
871
872 DbgUI.Text(string.Format("State: %1", isPlaying));
873 if (m_WaitingForPlayback)
874 {
875 DbgUI.Text(string.Format("Wait time: %1s (%2s)", (int)m_DebugWaitTime, (int)(g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).GetRemainingTime(PlayTrack) * 0.001)));
876 }
877 DbgUI.Text(string.Format("Sound set: %1", m_CurrentTrack.m_SoundSet));
878 DbgUI.Text(string.Format("Category: %1", EnumTools.EnumToString(EDynamicMusicPlayerCategory, m_CurrentTrack.m_Category)));
879 DbgUI.Text(string.Format("Time of day: %1", DynamicMusicPlayerTimeOfDay.ToString(m_CurrentTrack.m_TimeOfDay)));
880 }
881 DbgUI.End();
882
883 DbgUI.Begin("DMP - Controls", windowPosX + 500, windowPosY);
884 if (enabled)
885 {
886 if (DbgUI.Button("Stop"))
887 StopTrack();
888
889 if (DbgUI.Button("Reset Waiting"))
890 ResetWaitingQueue();
891
892 DynamicMusicPlayerCategoryPlaybackData playbackData = new DynamicMusicPlayerCategoryPlaybackData();
893 playbackData.m_Category = EDynamicMusicPlayerCategory.TIME;
894
895 DbgUI.Text("Set Category:\n");
896 if (DbgUI.Button("Time"))
897 SetCategory(playbackData);
898 if (DbgUI.Button("Location"))
899 {
900 playbackData.m_Category = EDynamicMusicPlayerCategory.LOCATION_STATIC;
901 SetCategory(playbackData);
902 }
903 if (DbgUI.Button("Menu"))
904 {
905 playbackData.m_Category = EDynamicMusicPlayerCategory.MENU;
906 SetCategory(playbackData);
907 }
908 if (DbgUI.Button("Credits"))
909 {
910 playbackData.m_Category = EDynamicMusicPlayerCategory.CREDITS;
911 SetCategory(playbackData);
912 }
913
914 DbgUI.Text("Reset Timers\n");
915 if (DbgUI.Button("Timer ALL"))
916 {
920 }
921
922 if (DbgUI.Button("Timer Daytime"))
924 if (DbgUI.Button("Timer Location"))
926 if (DbgUI.Button("Timer Location(prio)"))
928
929 }
930 DbgUI.End();
931 }
932
933 private void DisplayStaticLocations(bool enabled)
934 {
935 if (enabled)
936 {
937 vector locationMin;
938 vector locationMax;
939 vector position = g_Game.GetCurrentCameraPosition();
940
941 foreach (DynamicMusicTrackData track : m_TracksLocationStaticCached)
942 {
943 foreach (array<vector> bounds : track.locationBoundaries)
944 {
945 locationMin = bounds[0];
946 locationMax = bounds[1];
947
948 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
949 continue;
950
951 Debug.CleanupDrawShapes(m_DebugShapesLocations);
952
953 locationMax[1] = locationMin[1] + 200.0;
954 locationMin[1] = locationMin[1] - 50.0;
955 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.PURPLE, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
956 }
957
958 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
959 DrawPolygonLocation(track);
960 }
961
962 foreach (DynamicMusicTrackData trackPrio : m_TracksLocationStaticPrioritizedCached)
963 {
964 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
965 {
966 locationMin = boundsPrio[0];
967 locationMax = boundsPrio[1];
968
969 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
970 continue;
971
972 Debug.CleanupDrawShapes(m_DebugShapesLocations);
973
974 locationMax[1] = locationMin[1] + 200.0;
975 locationMin[1] = locationMin[1] - 50.0;
976 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.RED, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
977 }
978
979 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
980 DrawPolygonLocation(trackPrio);
981 }
982
983 foreach (DynamicMusicLocationDynamicData locationDynamic : m_LocationsDynamic)
984 {
985 locationMin = locationDynamic.m_Min;
986 locationMax = locationDynamic.m_Max;
987
988 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
989 continue;
990
991 Debug.CleanupDrawShapes(m_DebugShapesLocations);
992
993 locationMax[1] = locationMin[1] + 200.0;
994 locationMin[1] = locationMin[1] - 50.0;
995 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.YELLOW, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
996 }
997 }
998 else
999 {
1000 Debug.CleanupDrawShapes(m_DebugShapesLocations);
1001 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
1002 }
1003 }
1004
1005 private void DrawPolygonLocation(notnull DynamicMusicTrackData track)
1006 {
1007 vector first, current, last;
1008
1009 int count = track.vertices.Count();
1010 foreach (int i, vector vertexPos : track.vertices)
1011 {
1012 vertexPos[1] = vertexPos[1] + 0.5;
1013 current = vertexPos;
1014
1015 if (i == 0)
1016 first = vertexPos;
1017 else
1018 m_DebugShapesLocationsVertices.Insert(Debug.DrawLine(last, current, COLOR_WHITE, ShapeFlags.TRANSP|ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
1019
1020 last = current;
1021 }
1022
1023 m_DebugShapesLocationsVertices.Insert(Debug.DrawLine(current, first, COLOR_WHITE, ShapeFlags.TRANSP|ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
1024 }
1025 #endif
1026
1027 #ifdef ENABLE_LOGGING
1028 private void DMPDebugPrint(string message)
1029 {
1030 #ifdef DMP_DEBUG_PRINT
1031 Debug.Log(message);
1032 #endif
1033 }
1034 #endif
1035
1037 private void CleanupDebugShapes(array<Shape> shapesArr)
1038 {
1039 Debug.CleanupDrawShapes(shapesArr);
1040 }
1041
1042 void SetCategory(EDynamicMusicPlayerCategory category, bool forced)
1043 {
1044 DynamicMusicPlayerCategoryPlaybackData playbackData = new DynamicMusicPlayerCategoryPlaybackData();
1045 playbackData.m_Category = category;
1046 playbackData.m_Forced = forced;
1047
1048 SetCategory(playbackData);
1049 }
1050}
1051
1052
1054class DynamicMusicPlayerTimeOfDay : WorldDataDaytime {}
string Debug()
Definition enmath.c:7
int GetDaytime()
Definition worlddata.c:104
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
DayZGame g_Game
Definition dayzgame.c:3942
Mission mission
const int TRACKS_BUFFER_HISTORY_SIZE
class DynamicMusicLocationDynamicData m_MinWaitTimeSeconds
const int POLYGON
EDynamicMusicPlayerCategory m_CategorySelected
const float TICK_PRIORITY_LOCATION_UPDATE_SECONDS
const int BUFFER
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)
void OnTrackStopped()
const float TICK_LOCATION_CACHE_UPDATE_SECONDS
const float TICK_LOCATION_UPDATE_SECONDS
class DynamicMusicPlayerCategoryPlaybackData TICK_TIME_OF_DATE_UPDATE_SECONDS
DynamicMusicTrackData m_CurrentTrack
bool IsPlaybackActive()
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)
void OnTrackEnded()
float m_TickLocationUpdateElapsed
float m_MaxWaitTimeSeconds
EDayZProfilesOptions
DiagMenuIDs
Definition ediagmenuids.c:2
const int INDEX_NOT_FOUND
Definition gameplay.c:13
const EventType MPSessionPlayerReadyEventTypeID
no params
Definition gameplay.c:481
@ Colors
Definition enworld.c:88
const int COLOR_WHITE
Definition constants.c:63
ShapeFlags
Definition endebug.c:126
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)
void AbstractWave()
Definition sound.c:167
class SoundObject SoundParams(string name)
void OnUpdate()
Definition tools.c:349
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
TypeID EventType
Definition enwidgets.c:55
@ BOX
Definition enworld.c:190
class PresenceNotifierNoiseEvents windowPosX
dbgUI settings
const int windowPosY
WaveKind
Definition sound.c:2