mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
161 lines
4.9 KiB
Lua
Executable File
161 lines
4.9 KiB
Lua
Executable File
local ambient = require('openmw.ambient')
|
|
local core = require('openmw.core')
|
|
local self = require('openmw.self')
|
|
local storage = require('openmw.storage')
|
|
local types = require('openmw.types')
|
|
|
|
local musicSettings = storage.playerSection('SettingsOMWMusic')
|
|
|
|
local helpers = require('scripts.omw.music.helpers')
|
|
|
|
local registeredPlaylists = {}
|
|
local playlistsTracksOrder = helpers.getStoredTracksOrder()
|
|
local fightingActors = {}
|
|
local registrationOrder = 0
|
|
|
|
local currentPlaylist = nil
|
|
local skippedOneFrame = false
|
|
|
|
local battlePriority = 10
|
|
local explorePriority = 100
|
|
|
|
local function registerPlaylist(playlist)
|
|
helpers.initMissingPlaylistFields(playlist)
|
|
|
|
local existingOrder = playlistsTracksOrder[playlist.id]
|
|
if not existingOrder or next(existingOrder) == nil or math.max(unpack(existingOrder)) > #playlist.tracks then
|
|
local newPlaylistOrder = helpers.initTracksOrder(playlist.tracks, playlist.randomize)
|
|
playlistsTracksOrder[playlist.id] = newPlaylistOrder
|
|
helpers.setStoredTracksOrder(playlist.id, newPlaylistOrder)
|
|
else
|
|
playlistsTracksOrder[playlist.id] = existingOrder
|
|
end
|
|
|
|
if registeredPlaylists[playlist.id] == nil then
|
|
playlist.registrationOrder = registrationOrder
|
|
registrationOrder = registrationOrder + 1
|
|
end
|
|
|
|
registeredPlaylists[playlist.id] = playlist
|
|
end
|
|
|
|
local function setPlaylistActive(id, state)
|
|
if id == nil then
|
|
error("Playlist ID is nil")
|
|
end
|
|
|
|
local playlist = registeredPlaylists[id]
|
|
if playlist then
|
|
playlist.active = state
|
|
else
|
|
error(string.format("Playlist '%s' is not registered.", id))
|
|
end
|
|
end
|
|
|
|
local function onCombatTargetsChanged(eventData)
|
|
if eventData.actor == nil then return end
|
|
|
|
if next(eventData.targets) ~= nil then
|
|
fightingActors[eventData.actor.id] = true
|
|
else
|
|
fightingActors[eventData.actor.id] = nil
|
|
end
|
|
end
|
|
|
|
local function playerDied()
|
|
ambient.streamMusic("music/special/mw_death.mp3")
|
|
end
|
|
|
|
local function switchPlaylist(newPlaylist)
|
|
local newPlaylistOrder = playlistsTracksOrder[newPlaylist.id]
|
|
local nextTrackIndex = table.remove(newPlaylistOrder)
|
|
|
|
if nextTrackIndex == nil then
|
|
error("Can not fetch track: nextTrackIndex is nil")
|
|
end
|
|
|
|
-- If there are no tracks left, fill playlist again.
|
|
if next(newPlaylistOrder) == nil then
|
|
newPlaylistOrder = helpers.initTracksOrder(newPlaylist.tracks, newPlaylist.randomize)
|
|
|
|
if not newPlaylist.cycleTracks then
|
|
newPlaylist.deactivateAfterEnd = true
|
|
end
|
|
|
|
-- If next track for randomized playist will be the same as one we want to play, swap it with random track.
|
|
if newPlaylist.randomize and #newPlaylistOrder > 1 and newPlaylistOrder[1] == nextTrackIndex then
|
|
local index = math.random(2, #newPlaylistOrder)
|
|
newPlaylistOrder[1], newPlaylistOrder[index] = newPlaylistOrder[index], newPlaylistOrder[1]
|
|
end
|
|
|
|
playlistsTracksOrder[newPlaylist.id] = newPlaylistOrder
|
|
end
|
|
|
|
helpers.setStoredTracksOrder(newPlaylist.id, newPlaylistOrder)
|
|
|
|
local trackPath = newPlaylist.tracks[nextTrackIndex]
|
|
if trackPath == nil then
|
|
error(string.format("Can not fetch track with index %s from playlist '%s'.", nextTrackIndex, newPlaylist.id))
|
|
else
|
|
ambient.streamMusic(trackPath, newPlaylist.fadeOut)
|
|
if newPlaylist.playOneTrack then
|
|
newPlaylist.deactivateAfterEnd = true
|
|
end
|
|
end
|
|
|
|
currentPlaylist = newPlaylist
|
|
end
|
|
|
|
local function onFrame(dt)
|
|
-- Skip a first frame to allow other scripts to update playlists state.
|
|
if not skippedOneFrame then
|
|
skippedOneFrame = true
|
|
return
|
|
end
|
|
|
|
if not core.sound.isEnabled() then return end
|
|
|
|
-- Do not allow to switch playlists when player is dead
|
|
local musicPlaying = ambient.isMusicPlaying()
|
|
if types.Actor.isDead(self) and musicPlaying then return end
|
|
|
|
local combatMusicEnabled = musicSettings:get("CombatMusicEnabled") and helpers.isInCombat(fightingActors)
|
|
setPlaylistActive("battle", combatMusicEnabled)
|
|
|
|
local newPlaylist = helpers.getActivePlaylistByPriority(registeredPlaylists)
|
|
|
|
if not newPlaylist then
|
|
ambient.stopMusic()
|
|
|
|
if currentPlaylist ~= nil then
|
|
currentPlaylist.deactivateAfterEnd = nil
|
|
end
|
|
|
|
currentPlaylist = nil
|
|
return
|
|
end
|
|
|
|
if newPlaylist == currentPlaylist and musicPlaying then return end
|
|
|
|
if newPlaylist and newPlaylist.deactivateAfterEnd then
|
|
newPlaylist.deactivateAfterEnd = nil
|
|
newPlaylist.active = false
|
|
return
|
|
end
|
|
|
|
switchPlaylist(newPlaylist)
|
|
end
|
|
|
|
registerPlaylist({ id = "battle", priority = battlePriority, randomize = true })
|
|
registerPlaylist({ id = "explore", priority = explorePriority, randomize = true, active = true })
|
|
|
|
return {
|
|
engineHandlers = {
|
|
onFrame = onFrame
|
|
},
|
|
eventHandlers = {
|
|
Died = playerDied,
|
|
OMWMusicCombatTargetsChanged = onCombatTargetsChanged
|
|
}
|
|
}
|