mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2026-08-25 04:15:18 -06:00
music plugin
This commit is contained in:
parent
ab2a28db8c
commit
413f3c30cd
6 changed files with 769 additions and 2 deletions
|
|
@ -394,6 +394,43 @@ public class API {
|
|||
MidiPlayer.playFadeOut(trackId, client.js5Archive6, volume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Music hook used by the SmartAudio plugin.
|
||||
*/
|
||||
public interface AudioHandler {
|
||||
boolean onMusicRequest(int trackId);
|
||||
|
||||
boolean onMusicEnd(int trackId);
|
||||
|
||||
default void onMusicSelect(int slot) {}
|
||||
}
|
||||
|
||||
private static AudioHandler audioHandler = null;
|
||||
|
||||
public static void SetAudioHandler(AudioHandler handler) {
|
||||
audioHandler = handler;
|
||||
}
|
||||
|
||||
public static void ClearAudioHandler(AudioHandler handler) {
|
||||
if (audioHandler == handler) {
|
||||
audioHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean MusicRequest(int trackId) {
|
||||
return audioHandler == null || audioHandler.onMusicRequest(trackId);
|
||||
}
|
||||
|
||||
public static boolean MusicEnd(int trackId) {
|
||||
return audioHandler == null || audioHandler.onMusicEnd(trackId);
|
||||
}
|
||||
|
||||
public static void MusicSelect(int slot) {
|
||||
if (audioHandler != null) {
|
||||
audioHandler.onMusicSelect(slot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLoginScreenMusicOnLoad(String song) {
|
||||
client.TITLE_SONG = JagString.parse(song);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package rt4;
|
|||
import org.openrs2.deob.annotation.OriginalArg;
|
||||
import org.openrs2.deob.annotation.OriginalMember;
|
||||
import org.openrs2.deob.annotation.Pc;
|
||||
import plugin.api.API;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
|
@ -55,6 +56,9 @@ public class ClientProt {
|
|||
return;
|
||||
}
|
||||
if (arg2 == 1) {
|
||||
if (arg3 == ((187 << 16) + 1)) {
|
||||
API.MusicSelect(arg1);
|
||||
}
|
||||
Protocol.outboundBuffer.p1isaac(155);
|
||||
Protocol.outboundBuffer.p4(arg3);
|
||||
Protocol.outboundBuffer.p2(arg1);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.openrs2.deob.annotation.OriginalArg;
|
|||
import org.openrs2.deob.annotation.OriginalMember;
|
||||
import org.openrs2.deob.annotation.Pc;
|
||||
import plugin.PluginRepository;
|
||||
import plugin.api.API;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
|
@ -2320,7 +2321,9 @@ public class Protocol {
|
|||
if (id == 65535) {
|
||||
id = -1;
|
||||
}
|
||||
MusicPlayer.playSong(id);
|
||||
if (API.MusicRequest(id)) {
|
||||
MusicPlayer.playSong(id);
|
||||
}
|
||||
opcode = -1;
|
||||
return true;
|
||||
} else if (opcode == ServerProt.MIDI_JINGLE) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package rt4;
|
|||
import org.openrs2.deob.annotation.OriginalArg;
|
||||
import org.openrs2.deob.annotation.OriginalMember;
|
||||
import org.openrs2.deob.annotation.Pc;
|
||||
import plugin.api.API;
|
||||
|
||||
public class SoundPlayer {
|
||||
@OriginalMember(owner = "client!qe", name = "t", descriptor = "[I")
|
||||
|
|
@ -128,7 +129,11 @@ public class SoundPlayer {
|
|||
}
|
||||
MidiPlayer.jingle = false;
|
||||
} else if (Preferences.musicVolume != 0 && MusicPlayer.groupId != -1 && !MidiPlayer.isPlaying()) {
|
||||
sendTrackEndPacket();
|
||||
if (API.MusicEnd(MusicPlayer.groupId)) {
|
||||
sendTrackEndPacket();
|
||||
} else {
|
||||
MusicPlayer.groupId = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
715
plugin-playground/src/main/kotlin/SmartAudio/plugin.kt
Normal file
715
plugin-playground/src/main/kotlin/SmartAudio/plugin.kt
Normal file
|
|
@ -0,0 +1,715 @@
|
|||
package SmartAudio
|
||||
|
||||
import plugin.Plugin
|
||||
import plugin.api.API
|
||||
import rt4.Camera
|
||||
import rt4.Component
|
||||
import rt4.IntNode
|
||||
import rt4.InterfaceList
|
||||
import rt4.JagString
|
||||
import rt4.MidiPlayer
|
||||
import rt4.MusicPlayer
|
||||
import rt4.PlayerList
|
||||
import kotlin.random.Random
|
||||
|
||||
class plugin : Plugin() {
|
||||
|
||||
private var enabled = true
|
||||
private var jinglesOnly = false
|
||||
private var debug = true
|
||||
|
||||
private var latestTrack = -1
|
||||
private var lastPlayedTrack = -1
|
||||
private var playingMusicLocation: MusicLocation? = null
|
||||
private var currentMusicLocation: MusicLocation? = null
|
||||
private var manualMusicSelect = false
|
||||
private var manualMusicPlaying = false
|
||||
private var intervalMillis = 20 * 1000L
|
||||
private var nextMusicAt = 0L
|
||||
|
||||
private var musicTextComponent: Component? = null
|
||||
private var musicLabelsLoaded = false
|
||||
private val MUSIC_PLAYER_TRACK_COMPONENT_ID = (187 shl 16) + 14
|
||||
private val MUSIC_BUTTON_TO_SONG_ENUM = 1351
|
||||
private val MUSIC_BUTTON_TO_NAME_ENUM = 1345
|
||||
private val musicLabels = HashMap<Int, String>()
|
||||
|
||||
private val random = Random.Default
|
||||
|
||||
private val NEWBIE_MELODY = 62
|
||||
|
||||
private val handler = object : API.AudioHandler {
|
||||
override fun onMusicRequest(trackId: Int): Boolean {
|
||||
if (!enabled) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (trackId == -1) {
|
||||
latestTrack = -1
|
||||
manualMusicSelect = false
|
||||
manualMusicPlaying = false
|
||||
return true
|
||||
}
|
||||
|
||||
if (manualMusicSelect) {
|
||||
manualMusicSelect = false
|
||||
latestTrack = trackId
|
||||
lastPlayedTrack = trackId
|
||||
playingMusicLocation = null
|
||||
manualMusicPlaying = true
|
||||
nextMusicAt = System.currentTimeMillis() + intervalMillis
|
||||
debugMessage("Allowed manual music selection $trackId.")
|
||||
return true
|
||||
}
|
||||
|
||||
if (playImmediately(trackId)) {
|
||||
latestTrack = trackId
|
||||
lastPlayedTrack = trackId
|
||||
playingMusicLocation = null
|
||||
currentMusicLocation = getCurrentMusicLocation()
|
||||
manualMusicPlaying = false
|
||||
nextMusicAt = System.currentTimeMillis() + intervalMillis
|
||||
debugMessage("Playing ${getMusicName(trackId)} ($trackId) immediately.")
|
||||
return true
|
||||
}
|
||||
|
||||
latestTrack = trackId
|
||||
|
||||
if (checkMusicLocationChange()) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (playingMusicLocation != null) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (jinglesOnly) {
|
||||
MusicPlayer.playSong(-1)
|
||||
debugMessage("Blocked music $trackId because jingles-only mode is enabled.")
|
||||
return false
|
||||
}
|
||||
|
||||
requestPlayMusic(
|
||||
reason = "request",
|
||||
replacePlaying = currentMusicLocation == null && !manualMusicPlaying,
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMusicEnd(trackId: Int): Boolean {
|
||||
if (trackId <= 0) {
|
||||
debugMessage("Ignoring invalid music end: $trackId.")
|
||||
return false
|
||||
}
|
||||
|
||||
playingMusicLocation = null
|
||||
manualMusicPlaying = false
|
||||
nextMusicAt = System.currentTimeMillis() + intervalMillis
|
||||
debugMessage("Music ended: $trackId. Next music in ${formatRemaining()}.")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMusicSelect(slot: Int) {
|
||||
manualMusicSelect = true
|
||||
debugMessage("Manual music selection from slot $slot.")
|
||||
}
|
||||
}
|
||||
|
||||
override fun Init() {
|
||||
API.SetAudioHandler(handler)
|
||||
log("loaded")
|
||||
}
|
||||
|
||||
override fun OnLogout() {
|
||||
latestTrack = -1
|
||||
lastPlayedTrack = -1
|
||||
playingMusicLocation = null
|
||||
currentMusicLocation = null
|
||||
manualMusicSelect = false
|
||||
manualMusicPlaying = false
|
||||
}
|
||||
|
||||
override fun OnLogin() {
|
||||
if (System.currentTimeMillis() < nextMusicAt) {
|
||||
MidiPlayer.playFadeOut()
|
||||
MusicPlayer.groupId = -1
|
||||
debugMessage("Quiet time continues after login: ${formatRemaining()}.")
|
||||
}
|
||||
}
|
||||
|
||||
override fun OnPluginsReloaded(): Boolean {
|
||||
API.ClearAudioHandler(handler)
|
||||
return false
|
||||
}
|
||||
|
||||
private fun requestPlayMusic(reason: String, replacePlaying: Boolean = false) {
|
||||
if (!enabled || jinglesOnly) {
|
||||
return
|
||||
}
|
||||
|
||||
if (latestTrack == -1 || API.GetMusicVolume() <= 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!replacePlaying && API.IsMusicPlaying() && lastPlayedTrack != -1) {
|
||||
return
|
||||
}
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
if (now < nextMusicAt) {
|
||||
return
|
||||
}
|
||||
|
||||
val location = getCurrentMusicLocation()
|
||||
if (location != null) {
|
||||
playMusicForLocation(location, reason)
|
||||
return
|
||||
}
|
||||
|
||||
MusicPlayer.playSong(latestTrack)
|
||||
lastPlayedTrack = latestTrack
|
||||
playingMusicLocation = null
|
||||
manualMusicPlaying = false
|
||||
debugMessage("Playing music ${getMusicName(latestTrack)} ($latestTrack) from $reason.")
|
||||
}
|
||||
|
||||
private fun playMusicForLocation(location: MusicLocation, reason: String) {
|
||||
val trackToPlay = selectTrackFromLocation(location)
|
||||
|
||||
MusicPlayer.playSong(trackToPlay)
|
||||
lastPlayedTrack = trackToPlay
|
||||
playingMusicLocation = location
|
||||
manualMusicPlaying = false
|
||||
debugMessage("Playing music ${getMusicName(trackToPlay)} ($trackToPlay) from $reason.")
|
||||
}
|
||||
|
||||
private fun selectTrackToPlay(): Int {
|
||||
val location = getCurrentMusicLocation() ?: return latestTrack
|
||||
if (location.tracks.isEmpty()) {
|
||||
return latestTrack
|
||||
}
|
||||
|
||||
val choices = location.tracks.filter { it != lastPlayedTrack }
|
||||
val track = if (choices.isNotEmpty()) {
|
||||
choices[random.nextInt(choices.size)]
|
||||
} else {
|
||||
location.tracks[random.nextInt(location.tracks.size)]
|
||||
}
|
||||
|
||||
debugMessage("Using ${location.name} dynamic music: ${getMusicName(track)} ($track) instead of ${getMusicName(latestTrack)} ($latestTrack).")
|
||||
return track
|
||||
}
|
||||
|
||||
private fun selectTrackFromLocation(location: MusicLocation): Int {
|
||||
if (location.tracks.isEmpty()) {
|
||||
return latestTrack
|
||||
}
|
||||
|
||||
val choices = location.tracks.filter { it != lastPlayedTrack }
|
||||
return if (choices.isNotEmpty()) {
|
||||
choices[random.nextInt(choices.size)]
|
||||
} else {
|
||||
location.tracks[random.nextInt(location.tracks.size)]
|
||||
}
|
||||
}
|
||||
|
||||
private fun printStatus() {
|
||||
val regionId = getCurrentRegionId()
|
||||
val locationName = getCurrentMusicLocation()?.name ?: "none"
|
||||
|
||||
log(
|
||||
"enabled=$enabled jinglesOnly=$jinglesOnly playing=${API.IsMusicPlaying()} latest=$latestTrack last=$lastPlayedTrack next=${formatRemaining()} region=$regionId location=$locationName"
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatRemaining(): String {
|
||||
val remaining = nextMusicAt - System.currentTimeMillis()
|
||||
if (remaining <= 0L) {
|
||||
return "now"
|
||||
}
|
||||
|
||||
return "${remaining / 1000L}s"
|
||||
}
|
||||
|
||||
private fun getCurrentRegionId(): Int {
|
||||
val self = PlayerList.self ?: return -1
|
||||
val worldX = self.movementQueueX[0] + Camera.originX
|
||||
val worldZ = self.movementQueueZ[0] + Camera.originZ
|
||||
return ((worldX shr 6) shl 8) + (worldZ shr 6)
|
||||
}
|
||||
|
||||
private fun getCurrentMusicLocation(): MusicLocation? {
|
||||
val regionId = getCurrentRegionId()
|
||||
return musicLocations.firstOrNull { regionId in it.regions }
|
||||
}
|
||||
|
||||
private fun checkMusicLocationChange(): Boolean {
|
||||
val newLocation = getCurrentMusicLocation()
|
||||
|
||||
if (newLocation == currentMusicLocation) {
|
||||
return false
|
||||
}
|
||||
|
||||
val oldLocation = currentMusicLocation
|
||||
currentMusicLocation = newLocation
|
||||
|
||||
if (!enabled || manualMusicPlaying || lastPlayedTrack == -1) {
|
||||
return false
|
||||
}
|
||||
|
||||
debugMessage(
|
||||
"Music location changed from ${oldLocation?.name ?: "none"} " +
|
||||
"to ${newLocation?.name ?: "none"}."
|
||||
)
|
||||
|
||||
if (System.currentTimeMillis() >= nextMusicAt) {
|
||||
requestPlayMusic("region change", true)
|
||||
} else {
|
||||
MidiPlayer.playFadeOut()
|
||||
MusicPlayer.groupId = -1
|
||||
playingMusicLocation = null
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun playImmediately(trackId: Int): Boolean {
|
||||
return trackId == NEWBIE_MELODY &&
|
||||
lastPlayedTrack != NEWBIE_MELODY
|
||||
}
|
||||
|
||||
override fun Draw(timeDelta: Long) {
|
||||
checkMusicLocationChange()
|
||||
}
|
||||
|
||||
override fun Update() {
|
||||
requestPlayMusic("timer")
|
||||
updateMusicTabText()
|
||||
}
|
||||
|
||||
private fun updateMusicTabText() {
|
||||
val component = musicTextComponent ?: return
|
||||
|
||||
if (lastPlayedTrack == -1 || !API.IsMusicPlaying()) {
|
||||
return
|
||||
}
|
||||
|
||||
val label = getMusicName(lastPlayedTrack)
|
||||
if (component.text.toString() == label) {
|
||||
return
|
||||
}
|
||||
|
||||
component.text = JagString.parse(label)
|
||||
InterfaceList.redraw(component)
|
||||
}
|
||||
|
||||
private fun loadMusicLabels() {
|
||||
if (musicLabelsLoaded) {
|
||||
return
|
||||
}
|
||||
|
||||
val songs = API.GetDataMap(MUSIC_BUTTON_TO_SONG_ENUM)
|
||||
val names = API.GetDataMap(MUSIC_BUTTON_TO_NAME_ENUM)
|
||||
|
||||
var node = songs.table.head()
|
||||
while (node != null) {
|
||||
val buttonId = node.key.toInt()
|
||||
val songId = (node as IntNode).value
|
||||
val name = names.getString(buttonId).toString()
|
||||
|
||||
if (name.isNotBlank()) {
|
||||
musicLabels[songId] = name
|
||||
}
|
||||
|
||||
node = songs.table.next()
|
||||
}
|
||||
|
||||
musicLabelsLoaded = true
|
||||
debugMessage("Loaded ${musicLabels.size} music labels.")
|
||||
}
|
||||
|
||||
private fun getMusicName(trackId: Int): String {
|
||||
if (trackId == -1) {
|
||||
return ""
|
||||
}
|
||||
|
||||
loadMusicLabels()
|
||||
return musicLabels[trackId] ?: "Track $trackId"
|
||||
}
|
||||
|
||||
override fun ComponentDraw(componentIndex: Int, component: Component?, screenX: Int, screenY: Int) {
|
||||
if (component?.id != MUSIC_PLAYER_TRACK_COMPONENT_ID) {
|
||||
return
|
||||
}
|
||||
|
||||
musicTextComponent = component
|
||||
updateMusicTabText()
|
||||
}
|
||||
|
||||
override fun ProcessCommand(commandStr: String?, args: Array<out String>?) {
|
||||
if (!"::sm".equals(commandStr, ignoreCase = true) &&
|
||||
!"::smartaudio".equals(commandStr, ignoreCase = true)) {
|
||||
return
|
||||
}
|
||||
|
||||
when (args?.getOrNull(0)?.toLowerCase()) {
|
||||
null, "status" -> printStatus()
|
||||
|
||||
"on" -> {
|
||||
enabled = true
|
||||
log("SmartAudio enabled")
|
||||
}
|
||||
|
||||
"off" -> {
|
||||
enabled = false
|
||||
log("SmartAudio disabled")
|
||||
}
|
||||
|
||||
"debug" -> {
|
||||
debug = !debug
|
||||
log("SmartAudio debug ${if (debug) "on" else "off"}")
|
||||
}
|
||||
|
||||
"jingles" -> {
|
||||
jinglesOnly = !jinglesOnly
|
||||
if (jinglesOnly) {
|
||||
MusicPlayer.playSong(-1)
|
||||
}
|
||||
log("SmartAudio jingles-only ${if (jinglesOnly) "on" else "off"}")
|
||||
}
|
||||
|
||||
"interval" -> {
|
||||
val seconds = args?.getOrNull(1)?.toLongOrNull()
|
||||
if (seconds == null || seconds < 0) {
|
||||
log("Usage: ::sm interval <seconds>")
|
||||
return
|
||||
}
|
||||
|
||||
intervalMillis = seconds * 1000L
|
||||
log("SmartAudio track-end interval set to ${seconds}s")
|
||||
}
|
||||
|
||||
"play" -> {
|
||||
nextMusicAt = 0L
|
||||
requestPlayMusic("command")
|
||||
}
|
||||
|
||||
"stop" -> {
|
||||
manualMusicSelect = false
|
||||
manualMusicPlaying = false
|
||||
MusicPlayer.playSong(-1)
|
||||
lastPlayedTrack = -1
|
||||
nextMusicAt = System.currentTimeMillis() + intervalMillis
|
||||
log("music stopped; next=${formatRemaining()}")
|
||||
}
|
||||
|
||||
"next" -> {
|
||||
manualMusicSelect = false
|
||||
manualMusicPlaying = false
|
||||
MusicPlayer.playSong(-1)
|
||||
lastPlayedTrack = -1
|
||||
nextMusicAt = 0L
|
||||
requestPlayMusic("command")
|
||||
}
|
||||
|
||||
"dynamic" -> {
|
||||
val location = getCurrentMusicLocation()
|
||||
if (location == null) {
|
||||
log("No dynamic music location for region ${getCurrentRegionId()}")
|
||||
return
|
||||
}
|
||||
|
||||
log("${location.name}: ${location.tracks.joinToString { "${getMusicName(it)} ($it)" }}")
|
||||
}
|
||||
|
||||
else -> log("SmartAudio commands: status, on, off, debug, jingles, interval, play, next, stop, dynamic")
|
||||
}
|
||||
}
|
||||
|
||||
private fun log(message: String) {
|
||||
println("[SmartAudio] $message")
|
||||
}
|
||||
|
||||
private fun debugMessage(message: String) {
|
||||
if (debug) {
|
||||
log(message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamic music regions.
|
||||
*/
|
||||
private class MusicLocation(
|
||||
val name: String,
|
||||
val regions: Set<Int>,
|
||||
val tracks: IntArray
|
||||
)
|
||||
|
||||
//MusicLocation(
|
||||
//name = "name",
|
||||
//regions = setOf(),
|
||||
//tracks = intArrayOf()
|
||||
//),
|
||||
private val musicLocations = listOf(
|
||||
/**
|
||||
* Misthalin (add barb village to asgarnia)
|
||||
*/
|
||||
MusicLocation(
|
||||
name = "Lumbridge",
|
||||
regions = setOf(
|
||||
12595, 12594, 12593,
|
||||
12851, 12850, 12849,
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
76, // Harmony
|
||||
2, // Autumn Voyage
|
||||
64, // Book of Spells
|
||||
145, // Yesteryear
|
||||
163, // Flute Salad
|
||||
327, // Dream
|
||||
62 // Newbie Melody
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Draynor Village & Wizards' Tower",
|
||||
regions = setOf(
|
||||
12339, 12338, 12337
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
3, // Unknown Land
|
||||
85, // Vision
|
||||
151 // Start
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Al-Kharid & Kharidian Desert",
|
||||
regions = setOf(
|
||||
12591, 12590, 12589,
|
||||
12848, 12847, 12846, 12845, 12844, 12843,
|
||||
13107, 13106, 13105, 13104, 13103, 13102, 13101, 13100, 13099,
|
||||
13363, 13362, 13361, 13360, 13359, 13358, 13357, 13356, 13355,
|
||||
13617, 13616, 13615, 13614, 13613, 13612, 13611,
|
||||
13872
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
122, // Shine
|
||||
123, // Arabian 2
|
||||
47, // Duel Arena
|
||||
50, // Al Kharid
|
||||
352, // Scarab
|
||||
69, // Egypt
|
||||
79, // The Desert
|
||||
36, // Arabian
|
||||
124, // Arabian 3
|
||||
174, // Desert Voyage
|
||||
267, // Sunburn
|
||||
465, // Desert Heat
|
||||
387, // Sphinx
|
||||
351, // Dynasty
|
||||
263, // Bandit Camp
|
||||
377, // The Golem
|
||||
383, // City of the Dead
|
||||
447, // Over to Nardah
|
||||
451, // Tune from the Dune
|
||||
505, // Pharaoh's Tomb
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Varrock & Edgeville",
|
||||
regions = setOf(
|
||||
12342,
|
||||
12598, 12597, 12596,
|
||||
12854, 12853, 12852,
|
||||
13110, 13109, 13108,
|
||||
13366
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
125, // Garden
|
||||
157, // Medieval
|
||||
175, // Spirit
|
||||
177, // Adventure
|
||||
56, // Doorways
|
||||
93, // Parade
|
||||
98, // Forever
|
||||
106, // Expanse
|
||||
111, // Still Night
|
||||
116, // Greatness
|
||||
496 // The Trade Parade
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Digsite",
|
||||
regions = setOf(
|
||||
13365, 13364
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
20, // Lullaby
|
||||
75 // Venture
|
||||
)
|
||||
),
|
||||
|
||||
/**
|
||||
* Morytania
|
||||
*/
|
||||
MusicLocation(
|
||||
name = "Morytania",
|
||||
regions = setOf(
|
||||
13623, 13622, 13621,
|
||||
13620, 13619, 13618,
|
||||
13879, 13878, 13877,
|
||||
13876, 13875, 13874,
|
||||
13873, 14135, 14134,
|
||||
14133, 14132, 14131,
|
||||
14130, 14129, 14391,
|
||||
14390, 14388, 14387,
|
||||
14386, 14385, 14647,
|
||||
14646
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
48, // Morytania
|
||||
61, // Village
|
||||
84, // Dead Quiet
|
||||
154, // Bone Dance
|
||||
241, // Stagnant
|
||||
244, // Waterlogged
|
||||
245, // Natural
|
||||
286, // Shadowland
|
||||
288, // Deadlands
|
||||
339, // The Terrible Tower
|
||||
344, // Fenkenstrain's Refrain
|
||||
353, // Shipwrecked
|
||||
355, // The Other Side
|
||||
380, // Dance of the Undead
|
||||
501, // Distant Land
|
||||
)
|
||||
),
|
||||
|
||||
/**
|
||||
* Wilderness
|
||||
*/
|
||||
MusicLocation(
|
||||
name = "Wilderness",
|
||||
regions = setOf(
|
||||
11837, 11836, 11835, 11834, 11833, 11832, 11831,
|
||||
12093, 12092, 12091, 12090, 12089, 12088, 12087,
|
||||
12349, 12348, 12347, 12346, 12345, 12344, 12343,
|
||||
12605, 12604, 12603, 12602, 12601, 12600, 12599,
|
||||
12861, 12860, 12859, 12858, 12857, 12856, 12855,
|
||||
13117, 13116, 13115, 13114, 13113, 13112, 13111,
|
||||
13373, 13372, 13371, 13370, 13369, 13368, 13367
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
8, // Wildwood
|
||||
10, // Moody
|
||||
13, // Mage Arena
|
||||
14, // Witching
|
||||
34, // Wonder
|
||||
37, // Deep Wildy
|
||||
42, // Wilderness2
|
||||
43, // Wilderness3
|
||||
52, // Serene
|
||||
56, // Doorways
|
||||
66, // Legion
|
||||
67, // Close Quarters
|
||||
96, // Inspiration
|
||||
120, // Shining
|
||||
121, // Forbidden
|
||||
159, // Gaol
|
||||
160, // Army of Darkness
|
||||
169, // Crystal Sword
|
||||
176, // Undercurrent
|
||||
179, // Underground
|
||||
182, // Dangerous
|
||||
183, // Troubled
|
||||
326, // Dark
|
||||
329, // Regal
|
||||
331, // Scape Sad
|
||||
332, // Scape Wild
|
||||
334, // Pirates of Peril
|
||||
337, // Faithless
|
||||
435, // Wilderness
|
||||
449, // Wild Isle
|
||||
475, // Wild Side
|
||||
476, // Dead Can Dance
|
||||
586, // Everlasting Fire
|
||||
)
|
||||
),
|
||||
|
||||
/**
|
||||
* Asgarnia
|
||||
*/
|
||||
MusicLocation(
|
||||
name = "Rimmington & Mudskipper Point",
|
||||
regions = setOf(
|
||||
11570,
|
||||
11826, 11825, 11824,
|
||||
12081
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
12, // Long Way Home
|
||||
105, // Tomorrow
|
||||
138, // Emperor
|
||||
180, // Attention
|
||||
515 // Mudskipper Melody
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Falador",
|
||||
regions = setOf(
|
||||
11572, 11571,
|
||||
11828, 11827,
|
||||
12084, 12083
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
15, // Workshop
|
||||
49, // Wander
|
||||
72, // Fanfare
|
||||
107, // Miles Away
|
||||
127, // Nightfall
|
||||
186 // Arrival
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Barbarian/Goblin Village & Ice Mountain",
|
||||
regions = setOf(
|
||||
11830, 11829,
|
||||
12086, 12085,
|
||||
12341
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
54, // Scape Soft
|
||||
102, // Alone
|
||||
113, // Lightness
|
||||
141, // Barbarianism
|
||||
310, // Dwarf Theme
|
||||
313, // Goblin Village
|
||||
)
|
||||
),
|
||||
|
||||
/**
|
||||
* Islands/other
|
||||
*/
|
||||
MusicLocation(
|
||||
name = "Mos Le'Harmless",
|
||||
regions = setOf(
|
||||
14639, 14638, 14637,
|
||||
14895, 14894,
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
530, // In the Brine
|
||||
631 // Life's a Beach!
|
||||
)
|
||||
),
|
||||
MusicLocation(
|
||||
name = "Mos Le'Harmless (Trouble Brewing)",
|
||||
regions = setOf(
|
||||
15151, 15150
|
||||
),
|
||||
tracks = intArrayOf(
|
||||
610, // Distillery Hilarity
|
||||
611, // Trouble Brewing
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
AUTHOR='Edith'
|
||||
DESCRIPTION='Smart audio player'
|
||||
VERSION=1.0
|
||||
Loading…
Add table
Add a link
Reference in a new issue