Dayz Explorer 1.28.160049
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 {
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);
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
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 m_DebugWaitTime = waitTime;
452 #endif
453
454 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(PlayTrack, (int)waitTime * 1000, false, track);
455 }
456
457 protected void OnLocationMatched(EDynamicMusicPlayerCategory category, bool isPriorityLocation)
458 {
459 #ifdef ENABLE_LOGGING
460 string messagePriority;
461 if (isPriorityLocation)
462 messagePriority = "(with priority)";
463 DMPDebugPrint(string.Format("Location matched %1", messagePriority));
464 #endif
465
467 playbackData.m_Category = category;
468
469 if (isPriorityLocation)
470 {
471 playbackData.m_Forced = isPriorityLocation;
473 {
474 m_CategorySelected = category;
475 if (m_WaitingForPlayback)
476 ResetWaitingQueue();
477
478 if (m_SoundPlaying)
479 {
480 playbackData.m_FadeOut = true;
481 SetCategory(playbackData);
482 return;
483 }
484
485 SetCategory(playbackData);
486 }
487 else
488 SetCategory(playbackData);
489 }
490 else
491 SetCategory(playbackData);
492 }
493
495 {
496 if (m_SoundPlaying)
497 m_SoundPlaying.GetEvents().Event_OnSoundWaveEnded.Remove(OnTrackEnded);
498
499 StopTrack();
500
502 playbackData.m_Category = category;
503 playbackData.m_Forced = IsPriotitizedCategorySelected();
504 SetCategory(playbackData);
505 }
507
508 private void PlayTrack(DynamicMusicTrackData track)
509 {
510 SoundParams soundParams = new SoundParams(track.m_SoundSet);
511 if (soundParams.IsValid())
512 {
513 SoundObjectBuilder soundBuilder = new SoundObjectBuilder(soundParams);
514 SoundObject soundObject = soundBuilder.BuildSoundObject();
515 soundObject.SetKind(WaveKind.WAVEMUSIC);
516
517 m_SoundPlaying = GetGame().GetSoundScene().Play2D(soundObject, soundBuilder);
518 if (m_SoundPlaying)
519 {
520 m_SoundPlaying.Loop(false);
521 m_SoundPlaying.Play();
522
524 m_SoundPlaying.GetEvents().Event_OnSoundWaveEnded.Insert(OnTrackEnded);
525 m_SoundPlaying.GetEvents().Event_OnSoundWaveStopped.Insert(OnTrackStopped);
526
527 m_WaitingForPlayback = false;
528 }
529 }
530 else
531 {
532 m_WaitingForPlayback = false;
533 m_CurrentTrack = null;
534 }
535 }
536
537 private void StopTrack()
538 {
539 if (m_SoundPlaying)
540 m_SoundPlaying.Stop();
541 }
542
543 private void ResetWaitingQueue()
544 {
545 if (m_WaitingForPlayback)
546 {
547 g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).Remove(PlayTrack);
548 m_WaitingForPlayback = false;
549 m_CurrentTrack = null;
550 }
551 }
552
553 private void FadeoutTrack(float fadeoutSeconds)
554 {
555 if (m_FadeoutInProgress)
556 return;
557
558 ResetWaitingQueue();
559
561 {
562 #ifdef ENABLE_LOGGING
563 DMPDebugPrint(string.Format("Stopping currently played track %1", m_CurrentTrack.m_SoundSet));
564 DMPDebugPrint(string.Format("-- Setting fadeout to %1", fadeoutSeconds));
565 #endif
566 m_FadeoutInProgress = true;
567 m_FadeoutTimeRequested = fadeoutSeconds;
568 }
569 }
570
571 private void ProcessFadeOut()
572 {
573 if (m_SoundPlaying)
574 {
575 float volume = 1 - (m_FadeoutTimeElapsed / m_FadeoutTimeRequested);
576 m_SoundPlaying.SetFadeOutFactor(volume);
577 }
578 }
579
580 private bool PlayerInsideOfLocationFilter(array<ref DynamicMusicTrackData> locations)
581 {
583
584 if (locations.Count() > 0)
585 {
586 foreach (DynamicMusicTrackData track : locations)
587 {
588 switch (track.m_Shape)
589 {
590 case DynamicMusicLocationShape.BOX:
591 foreach (int locationId, array<vector> bounds : track.locationBoundaries)
592 {
593 if (Math.IsPointInRectangle(bounds[0], bounds[1], m_PlayerPosition))
594 {
597
598 #ifdef ENABLE_LOGGING
599 DMPDebugPrint(string.Format("Player inside location <%1, %2>", bounds[0], bounds[1]));
600 #endif
601 }
602 }
603 break;
604 case DynamicMusicLocationShape.POLYGON:
605 if (Math2D.IsPointInPolygonXZ(track.vertices, m_PlayerPosition))
606 {
609
610 #ifdef ENABLE_LOGGING
611 DMPDebugPrint(string.Format("Player inside polygon location at <%1>", m_PlayerPosition));
612 #endif
613 }
614 break;
615 }
616 }
617 }
618
619 return m_TracksLocationMatchedPlayerInside.Count() > 0;
620 }
621
622 private bool PlayerInsideOfLocationFilter(map<int, ref DynamicMusicLocationDynamicData> locations)
623 {
624 if (locations.Count() > 0)
625 {
626 foreach (int locationId, DynamicMusicLocationDynamicData location : locations)
627 {
628 if (Math.IsPointInRectangle(location.m_Min, location.m_Max, m_PlayerPosition))
629 {
630 #ifdef ENABLE_LOGGING
631 DMPDebugPrint(string.Format("Player inside location <%1, %2>", location.m_Min, location.m_Max));
632 #endif
633 return true;
634 }
635 }
636 }
637
638 return false;
639 }
640
641 private bool SetSelectedTrackFromCategory(EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracklist, int historyLookupType = DynamicMusicPlayerTrackHistoryLookupType.ANY)
642 {
643 if (tracklist.Count() == 0)
644 return true;
645
647 foreach (DynamicMusicTrackData filteredTrack : tracklist)
648 {
649 if (filteredTrack.m_TimeOfDay == m_ActualTimeOfDay || filteredTrack.m_TimeOfDay == DynamicMusicPlayerTimeOfDay.ANY)
650 filteredTracks.Insert(filteredTrack);
651 }
652
653 float trackIndex;
655 if (m_Created && category == EDynamicMusicPlayerCategory.MENU)
656 trackIndex = SelectRandomTrackIndexFromCategoryPriorityFlagFirst(category, filteredTracks);
657 else
658 trackIndex = SelectRandomTrackIndexFromCategory(category, historyLookupType, filteredTracks);
659
660 if (trackIndex > INDEX_NOT_FOUND)
661 {
662 m_LastPlayedTrackBufferPerCategory[category].Add(trackIndex);
663 OnNextTrackSelected(filteredTracks[trackIndex], GetWaitTimeForCategory(category));
664
665 return true;
666 }
667
668 return false;
669 }
670
671 private int SelectRandomTrackIndexFromCategoryPriorityFlagFirst(EDynamicMusicPlayerCategory category, notnull array<ref DynamicMusicTrackData> tracks)
672 {
674 if (category == EDynamicMusicPlayerCategory.MENU)
675 {
676 array<int> priorityFlagIndices = new array<int>();
677
678 foreach (int i, DynamicMusicTrackData track : tracks)
679 {
680
681 if (!track.m_HasPriority)
682 continue;
683
684 priorityFlagIndices.Insert(i);
685 }
686
687 if (priorityFlagIndices.Count() > 0)
688 return priorityFlagIndices[priorityFlagIndices.GetRandomIndex()];
689
691 return tracks.GetRandomIndex();
692 }
693
694 return INDEX_NOT_FOUND;
695 }
696
697 private int SelectRandomTrackIndexFromCategory(EDynamicMusicPlayerCategory category, int lookupType, notnull array<ref DynamicMusicTrackData> tracks)
698 {
699 int count = tracks.Count();
700 if (count > 0)
701 {
702 int index = Math.RandomInt(0, count);
703
704 switch (lookupType)
705 {
706 case DynamicMusicPlayerTrackHistoryLookupType.ANY:
707 return index;
708
709 case DynamicMusicPlayerTrackHistoryLookupType.BUFFER:
710 // fallback - num of track is smaller than actual history size;
711 if (count <= TRACKS_BUFFER_HISTORY_SIZE)
712 return index;
713
714 if (m_LastPlayedTrackBufferPerCategory[category].GetValues().Find(index) == INDEX_NOT_FOUND)
715 return index;
716
717 return INDEX_NOT_FOUND;
718 }
719 }
720
721 return INDEX_NOT_FOUND;
722 }
723
724 private void SetTimeOfDate()
725 {
726 if (g_Game.GetMission())
727 {
728 m_ActualTimeOfDay = g_Game.GetMission().GetWorldData().GetDaytime();
729 return;
730 }
731
732 m_ActualTimeOfDay = DynamicMusicPlayerTimeOfDay.DAY;
733 }
734
736 {
737 return Math.RandomFloatInclusive(GetMinWaitTimePerCategory(category), GetMaxWaitTimePerCategory(category));
738 }
739
740 private float GetMinWaitTimePerCategory(EDynamicMusicPlayerCategory category)
741 {
742 float waitTime = m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_MinWaitTimeSeconds;
743 #ifdef DIAG_DEVELOPER
744 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
745 {
746 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
747 if (timeAccel > 0)
748 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
749 }
750 #endif
751 return waitTime;
752 }
753
754 private float GetMaxWaitTimePerCategory(EDynamicMusicPlayerCategory category)
755 {
756 float waitTime = m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_MaxWaitTimeSeconds;
757 #ifdef DIAG_DEVELOPER
758 if (FeatureTimeAccel.GetFeatureTimeAccelEnabled(ETimeAccelCategories.DYNAMIC_MUSIC_PLAYER))
759 {
760 float timeAccel = FeatureTimeAccel.GetFeatureTimeAccelValue();
761 if (timeAccel > 0)
762 return waitTime / FeatureTimeAccel.GetFeatureTimeAccelValue();
763 }
764 #endif
765 return waitTime;
766 }
767
768 private float GetPreviousTrackFadeoutSeconds(EDynamicMusicPlayerCategory category)
769 {
770 return m_DynamicMusicPlayerRegistry.m_SettingsByCategory[category].m_PreviousTrackFadeoutSeconds;
771 }
772
773 private void RefreshTracksCache()
774 {
776 {
777 m_TracksLocationStaticCached.Clear();
778 foreach (DynamicMusicTrackData track : m_DynamicMusicPlayerRegistry.m_TracksLocationStatic)
779 {
780 if (track.m_Shape == DynamicMusicLocationShape.BOX)
781 {
782 foreach (array<vector> bounds : track.locationBoundaries)
783 {
784 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(bounds[0], bounds[1])) > LOCATION_DISTANCE_MAX)
785 continue;
786 }
787 }
788
789 m_TracksLocationStaticCached.Insert(track);
790 }
791
792 m_TracksLocationStaticPrioritizedCached.Clear();
793 foreach (DynamicMusicTrackData trackPrio : m_DynamicMusicPlayerRegistry.m_TracksLocationStaticPrioritized)
794 {
795 if (trackPrio.m_Shape == DynamicMusicLocationShape.BOX)
796 {
797 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
798 {
799 if (vector.Distance(m_PlayerPosition, Math.CenterOfRectangle(boundsPrio[0], boundsPrio[1])) > LOCATION_DISTANCE_MAX)
800 continue;
801 }
802 }
803
804 m_TracksLocationStaticPrioritizedCached.Insert(trackPrio);
805 }
806 }
807 }
808
809 #ifdef DIAG_DEVELOPER
810 private ref array<Shape> m_DebugShapesLocations = new array<Shape>();
811 private ref array<Shape> m_DebugShapesLocationsVertices = new array<Shape>();
812 private float m_DebugWaitTime = 0;
813
814 private void DisplayDebugStats(bool enabled)
815 {
816 int windowPosX = 10;
817 int windowPosY = 200;
818
819 DbgUI.Begin("DMP - Overall stats", windowPosX, windowPosY);
820 if (enabled)
821 {
822 bool isPlaybackActive = m_SoundPlaying != null;
823 DbgUI.Text(string.Format("Day/Night: %1", DynamicMusicPlayerTimeOfDay.ToString(m_ActualTimeOfDay)));
824 DbgUI.Text("Playback:");
825 DbgUI.Text(string.Format(" active: %1", isPlaybackActive.ToString()));
826 DbgUI.Text(string.Format(" waiting: %1", m_WaitingForPlayback.ToString()));
827 DbgUI.Text(string.Format("Selected Category: %1", EnumTools.EnumToString(EDynamicMusicPlayerCategory, m_CategorySelected)));
828
830 {
831 DbgUI.Text("Update timers:");
833 DbgUI.Text(string.Format(" Location: %1(%2)", TICK_LOCATION_UPDATE_SECONDS, TICK_LOCATION_UPDATE_SECONDS - (int)m_TickLocationUpdateElapsed));
836 }
837
839 {
840 DbgUI.Text("Player:");
841 DbgUI.Text(string.Format(" position: %1", m_PlayerPosition.ToString()));
842 DbgUI.Text(string.Format(" matched num tracks(location): %1", m_TracksLocationMatchedPlayerInside.Count()));
843 }
844
845 DbgUI.Text("Tracks counts:");
847 {
848 DbgUI.Text(string.Format(" Menu: %1", m_DynamicMusicPlayerRegistry.m_TracksMenu.Count()));
849 DbgUI.Text(string.Format(" Credits: %1", m_DynamicMusicPlayerRegistry.m_TracksCredits.Count()));
850 }
851 else
852 {
853 DbgUI.Text(string.Format(" Time: %1", m_DynamicMusicPlayerRegistry.m_TracksTime.Count()));
854 DbgUI.Text(string.Format(" Static[cache]: %1", m_TracksLocationStaticCached.Count()));
855 DbgUI.Text(string.Format(" Static(prio)[cache]: %1", m_TracksLocationStaticPrioritizedCached.Count()));
856 DbgUI.Text(string.Format(" Dynamic(prio): %1", m_DynamicMusicPlayerRegistry.m_TracksLocationDynamic.Count()));
857 }
858 }
859 DbgUI.End();
860
861 DbgUI.Begin("DMP - Current track", windowPosX, windowPosY+380);
862 if (enabled && m_CurrentTrack)
863 {
864 string isPlaying = "waiting";
865 if (m_SoundPlaying != null)
866 isPlaying = "playing";
867
868 DbgUI.Text(string.Format("State: %1", isPlaying));
869 if (m_WaitingForPlayback)
870 {
871 DbgUI.Text(string.Format("Wait time: %1s (%2s)", (int)m_DebugWaitTime, (int)(g_Game.GetCallQueue(CALL_CATEGORY_SYSTEM).GetRemainingTime(PlayTrack) * 0.001)));
872 }
873 DbgUI.Text(string.Format("Sound set: %1", m_CurrentTrack.m_SoundSet));
874 DbgUI.Text(string.Format("Category: %1", EnumTools.EnumToString(EDynamicMusicPlayerCategory, m_CurrentTrack.m_Category)));
875 DbgUI.Text(string.Format("Time of day: %1", DynamicMusicPlayerTimeOfDay.ToString(m_CurrentTrack.m_TimeOfDay)));
876 }
877 DbgUI.End();
878
879 DbgUI.Begin("DMP - Controls", windowPosX + 500, windowPosY);
880 if (enabled)
881 {
882 if (DbgUI.Button("Stop"))
883 StopTrack();
884
885 if (DbgUI.Button("Reset Waiting"))
886 ResetWaitingQueue();
887
889 playbackData.m_Category = EDynamicMusicPlayerCategory.TIME;
890
891 DbgUI.Text("Set Category:\n");
892 if (DbgUI.Button("Time"))
893 SetCategory(playbackData);
894 if (DbgUI.Button("Location"))
895 {
896 playbackData.m_Category = EDynamicMusicPlayerCategory.LOCATION_STATIC;
897 SetCategory(playbackData);
898 }
899 if (DbgUI.Button("Menu"))
900 {
901 playbackData.m_Category = EDynamicMusicPlayerCategory.MENU;
902 SetCategory(playbackData);
903 }
904 if (DbgUI.Button("Credits"))
905 {
906 playbackData.m_Category = EDynamicMusicPlayerCategory.CREDITS;
907 SetCategory(playbackData);
908 }
909
910 DbgUI.Text("Reset Timers\n");
911 if (DbgUI.Button("Timer ALL"))
912 {
916 }
917
918 if (DbgUI.Button("Timer Daytime"))
920 if (DbgUI.Button("Timer Location"))
922 if (DbgUI.Button("Timer Location(prio)"))
924
925 }
926 DbgUI.End();
927 }
928
929 private void DisplayStaticLocations(bool enabled)
930 {
931 if (enabled)
932 {
933 vector locationMin;
934 vector locationMax;
935 vector position = g_Game.GetCurrentCameraPosition();
936
937 foreach (DynamicMusicTrackData track : m_TracksLocationStaticCached)
938 {
939 foreach (array<vector> bounds : track.locationBoundaries)
940 {
941 locationMin = bounds[0];
942 locationMax = bounds[1];
943
944 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
945 continue;
946
947 Debug.CleanupDrawShapes(m_DebugShapesLocations);
948
949 locationMax[1] = locationMin[1] + 200.0;
950 locationMin[1] = locationMin[1] - 50.0;
951 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.PURPLE, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
952 }
953
954 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
955 DrawPolygonLocation(track);
956 }
957
958 foreach (DynamicMusicTrackData trackPrio : m_TracksLocationStaticPrioritizedCached)
959 {
960 foreach (array<vector> boundsPrio : trackPrio.locationBoundaries)
961 {
962 locationMin = boundsPrio[0];
963 locationMax = boundsPrio[1];
964
965 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
966 continue;
967
968 Debug.CleanupDrawShapes(m_DebugShapesLocations);
969
970 locationMax[1] = locationMin[1] + 200.0;
971 locationMin[1] = locationMin[1] - 50.0;
972 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.RED, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
973 }
974
975 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
976 DrawPolygonLocation(trackPrio);
977 }
978
979 foreach (DynamicMusicLocationDynamicData locationDynamic : m_LocationsDynamic)
980 {
981 locationMin = locationDynamic.m_Min;
982 locationMax = locationDynamic.m_Max;
983
984 if (vector.Distance(position, Math.CenterOfRectangle(locationMin, locationMax)) > 2000)
985 continue;
986
987 Debug.CleanupDrawShapes(m_DebugShapesLocations);
988
989 locationMax[1] = locationMin[1] + 200.0;
990 locationMin[1] = locationMin[1] - 50.0;
991 m_DebugShapesLocations.Insert(Debug.DrawBoxEx(locationMin, locationMax, Colors.YELLOW, ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
992 }
993 }
994 else
995 {
996 Debug.CleanupDrawShapes(m_DebugShapesLocations);
997 Debug.CleanupDrawShapes(m_DebugShapesLocationsVertices);
998 }
999 }
1000
1001 private void DrawPolygonLocation(notnull DynamicMusicTrackData track)
1002 {
1003 vector first, current, last;
1004
1005 int count = track.vertices.Count();
1006 foreach (int i, vector vertexPos : track.vertices)
1007 {
1008 vertexPos[1] = vertexPos[1] + 0.5;
1009 current = vertexPos;
1010
1011 if (i == 0)
1012 first = vertexPos;
1013 else
1014 m_DebugShapesLocationsVertices.Insert(Debug.DrawLine(last, current, COLOR_WHITE, ShapeFlags.TRANSP|ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
1015
1016 last = current;
1017 }
1018
1019 m_DebugShapesLocationsVertices.Insert(Debug.DrawLine(current, first, COLOR_WHITE, ShapeFlags.TRANSP|ShapeFlags.NOZWRITE|ShapeFlags.ONCE));
1020 }
1021
1022 #ifdef ENABLE_LOGGING
1023 private void DMPDebugPrint(string message)
1024 {
1025 #ifdef DMP_DEBUG_PRINT
1026 Debug.Log(message);
1027 #endif
1028 }
1029 #endif
1030 #endif
1031
1033 private void CleanupDebugShapes(array<Shape> shapesArr)
1034 {
1035 Debug.CleanupDrawShapes(shapesArr);
1036 }
1037
1038 void SetCategory(EDynamicMusicPlayerCategory category, bool forced)
1039 {
1041 playbackData.m_Category = category;
1042 playbackData.m_Forced = forced;
1043
1044 SetCategory(playbackData);
1045 }
1046}
1047
1048
1050class DynamicMusicPlayerTimeOfDay : WorldDataDaytime {}
Definition colors.c:4
Definition dbgui.c:60
Definition debug.c:2
Definition camera.c:2
Definition enmath.c:7
Base Param Class with no parameters. Used as general purpose parameter overloaded with Param1 to Para...
Definition param.c:12
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
DayZGame g_Game
Definition dayzgame.c:3868
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
class DynamicMusicTrackData ANY
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
proto native CGame GetGame()
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 AbstractWave()
Definition sound.c:167
class SoundObject SoundParams(string name)
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