diff --git a/code/game/objects/items/devices/violin.dm b/code/game/objects/items/devices/violin.dm index 1da8e13afda..d37dee969c1 100644 --- a/code/game/objects/items/devices/violin.dm +++ b/code/game/objects/items/devices/violin.dm @@ -7,411 +7,21 @@ icon_state = "violin" item_state = "violin" force = 10 - var/datum/song/song - var/playing = 0 // if we're playing - var/help = 0 // if help is open - var/edit = 1 // if we're in editing mode - var/repeat = 0 // number of times remaining to repeat - var/max_repeats = 10 // maximum times we can repeat + var/datum/song/handheld/song -/obj/item/device/violin/proc/playnote(var/note as text) - //world << "Note: [note]" - var/soundfile - /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. - Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ - switch(note) - if("Cn1") soundfile = 'sound/violin/Cn1.mid' - if("C#1") soundfile = 'sound/violin/C#1.mid' - if("Db1") soundfile = 'sound/violin/Db1.mid' - if("Dn1") soundfile = 'sound/violin/Dn1.mid' - if("D#1") soundfile = 'sound/violin/D#1.mid' - if("Eb1") soundfile = 'sound/violin/Eb1.mid' - if("En1") soundfile = 'sound/violin/En1.mid' - if("E#1") soundfile = 'sound/violin/E#1.mid' - if("Fb1") soundfile = 'sound/violin/Fb1.mid' - if("Fn1") soundfile = 'sound/violin/Fn1.mid' - if("F#1") soundfile = 'sound/violin/F#1.mid' - if("Gb1") soundfile = 'sound/violin/Gb1.mid' - if("Gn1") soundfile = 'sound/violin/Gn1.mid' - if("G#1") soundfile = 'sound/violin/G#1.mid' - if("Ab1") soundfile = 'sound/violin/Ab1.mid' - if("An1") soundfile = 'sound/violin/An1.mid' - if("A#1") soundfile = 'sound/violin/A#1.mid' - if("Bb1") soundfile = 'sound/violin/Bb1.mid' - if("Bn1") soundfile = 'sound/violin/Bn1.mid' - if("B#1") soundfile = 'sound/violin/B#1.mid' - if("Cb2") soundfile = 'sound/violin/Cb2.mid' - if("Cn2") soundfile = 'sound/violin/Cn2.mid' - if("C#2") soundfile = 'sound/violin/C#2.mid' - if("Db2") soundfile = 'sound/violin/Db2.mid' - if("Dn2") soundfile = 'sound/violin/Dn2.mid' - if("D#2") soundfile = 'sound/violin/D#2.mid' - if("Eb2") soundfile = 'sound/violin/Eb2.mid' - if("En2") soundfile = 'sound/violin/En2.mid' - if("E#2") soundfile = 'sound/violin/E#2.mid' - if("Fb2") soundfile = 'sound/violin/Fb2.mid' - if("Fn2") soundfile = 'sound/violin/Fn2.mid' - if("F#2") soundfile = 'sound/violin/F#2.mid' - if("Gb2") soundfile = 'sound/violin/Gb2.mid' - if("Gn2") soundfile = 'sound/violin/Gn2.mid' - if("G#2") soundfile = 'sound/violin/G#2.mid' - if("Ab2") soundfile = 'sound/violin/Ab2.mid' - if("An2") soundfile = 'sound/violin/An2.mid' - if("A#2") soundfile = 'sound/violin/A#2.mid' - if("Bb2") soundfile = 'sound/violin/Bb2.mid' - if("Bn2") soundfile = 'sound/violin/Bn2.mid' - if("B#2") soundfile = 'sound/violin/B#2.mid' - if("Cb3") soundfile = 'sound/violin/Cb3.mid' - if("Cn3") soundfile = 'sound/violin/Cn3.mid' - if("C#3") soundfile = 'sound/violin/C#3.mid' - if("Db3") soundfile = 'sound/violin/Db3.mid' - if("Dn3") soundfile = 'sound/violin/Dn3.mid' - if("D#3") soundfile = 'sound/violin/D#3.mid' - if("Eb3") soundfile = 'sound/violin/Eb3.mid' - if("En3") soundfile = 'sound/violin/En3.mid' - if("E#3") soundfile = 'sound/violin/E#3.mid' - if("Fb3") soundfile = 'sound/violin/Fb3.mid' - if("Fn3") soundfile = 'sound/violin/Fn3.mid' - if("F#3") soundfile = 'sound/violin/F#3.mid' - if("Gb3") soundfile = 'sound/violin/Gb3.mid' - if("Gn3") soundfile = 'sound/violin/Gn3.mid' - if("G#3") soundfile = 'sound/violin/G#3.mid' - if("Ab3") soundfile = 'sound/violin/Ab3.mid' - if("An3") soundfile = 'sound/violin/An3.mid' - if("A#3") soundfile = 'sound/violin/A#3.mid' - if("Bb3") soundfile = 'sound/violin/Bb3.mid' - if("Bn3") soundfile = 'sound/violin/Bn3.mid' - if("B#3") soundfile = 'sound/violin/B#3.mid' - if("Cb4") soundfile = 'sound/violin/Cb4.mid' - if("Cn4") soundfile = 'sound/violin/Cn4.mid' - if("C#4") soundfile = 'sound/violin/C#4.mid' - if("Db4") soundfile = 'sound/violin/Db4.mid' - if("Dn4") soundfile = 'sound/violin/Dn4.mid' - if("D#4") soundfile = 'sound/violin/D#4.mid' - if("Eb4") soundfile = 'sound/violin/Eb4.mid' - if("En4") soundfile = 'sound/violin/En4.mid' - if("E#4") soundfile = 'sound/violin/E#4.mid' - if("Fb4") soundfile = 'sound/violin/Fb4.mid' - if("Fn4") soundfile = 'sound/violin/Fn4.mid' - if("F#4") soundfile = 'sound/violin/F#4.mid' - if("Gb4") soundfile = 'sound/violin/Gb4.mid' - if("Gn4") soundfile = 'sound/violin/Gn4.mid' - if("G#4") soundfile = 'sound/violin/G#4.mid' - if("Ab4") soundfile = 'sound/violin/Ab4.mid' - if("An4") soundfile = 'sound/violin/An4.mid' - if("A#4") soundfile = 'sound/violin/A#4.mid' - if("Bb4") soundfile = 'sound/violin/Bb4.mid' - if("Bn4") soundfile = 'sound/violin/Bn4.mid' - if("B#4") soundfile = 'sound/violin/B#4.mid' - if("Cb5") soundfile = 'sound/violin/Cb5.mid' - if("Cn5") soundfile = 'sound/violin/Cn5.mid' - if("C#5") soundfile = 'sound/violin/C#5.mid' - if("Db5") soundfile = 'sound/violin/Db5.mid' - if("Dn5") soundfile = 'sound/violin/Dn5.mid' - if("D#5") soundfile = 'sound/violin/D#5.mid' - if("Eb5") soundfile = 'sound/violin/Eb5.mid' - if("En5") soundfile = 'sound/violin/En5.mid' - if("E#5") soundfile = 'sound/violin/E#5.mid' - if("Fb5") soundfile = 'sound/violin/Fb5.mid' - if("Fn5") soundfile = 'sound/violin/Fn5.mid' - if("F#5") soundfile = 'sound/violin/F#5.mid' - if("Gb5") soundfile = 'sound/violin/Gb5.mid' - if("Gn5") soundfile = 'sound/violin/Gn5.mid' - if("G#5") soundfile = 'sound/violin/G#5.mid' - if("Ab5") soundfile = 'sound/violin/Ab5.mid' - if("An5") soundfile = 'sound/violin/An5.mid' - if("A#5") soundfile = 'sound/violin/A#5.mid' - if("Bb5") soundfile = 'sound/violin/Bb5.mid' - if("Bn5") soundfile = 'sound/violin/Bn5.mid' - if("B#5") soundfile = 'sound/violin/B#5.mid' - if("Cb6") soundfile = 'sound/violin/Cb6.mid' - if("Cn6") soundfile = 'sound/violin/Cn6.mid' - if("C#6") soundfile = 'sound/violin/C#6.mid' - if("Db6") soundfile = 'sound/violin/Db6.mid' - if("Dn6") soundfile = 'sound/violin/Dn6.mid' - if("D#6") soundfile = 'sound/violin/D#6.mid' - if("Eb6") soundfile = 'sound/violin/Eb6.mid' - if("En6") soundfile = 'sound/violin/En6.mid' - if("E#6") soundfile = 'sound/violin/E#6.mid' - if("Fb6") soundfile = 'sound/violin/Fb6.mid' - if("Fn6") soundfile = 'sound/violin/Fn6.mid' - if("F#6") soundfile = 'sound/violin/F#6.mid' - if("Gb6") soundfile = 'sound/violin/Gb6.mid' - if("Gn6") soundfile = 'sound/violin/Gn6.mid' - if("G#6") soundfile = 'sound/violin/G#6.mid' - if("Ab6") soundfile = 'sound/violin/Ab6.mid' - if("An6") soundfile = 'sound/violin/An6.mid' - if("A#6") soundfile = 'sound/violin/A#6.mid' - if("Bb6") soundfile = 'sound/violin/Bb6.mid' - if("Bn6") soundfile = 'sound/violin/Bn6.mid' - if("B#6") soundfile = 'sound/violin/B#6.mid' - if("Cb7") soundfile = 'sound/violin/Cb7.mid' - if("Cn7") soundfile = 'sound/violin/Cn7.mid' - if("C#7") soundfile = 'sound/violin/C#7.mid' - if("Db7") soundfile = 'sound/violin/Db7.mid' - if("Dn7") soundfile = 'sound/violin/Dn7.mid' - if("D#7") soundfile = 'sound/violin/D#7.mid' - if("Eb7") soundfile = 'sound/violin/Eb7.mid' - if("En7") soundfile = 'sound/violin/En7.mid' - if("E#7") soundfile = 'sound/violin/E#7.mid' - if("Fb7") soundfile = 'sound/violin/Fb7.mid' - if("Fn7") soundfile = 'sound/violin/Fn7.mid' - if("F#7") soundfile = 'sound/violin/F#7.mid' - if("Gb7") soundfile = 'sound/violin/Gb7.mid' - if("Gn7") soundfile = 'sound/violin/Gn7.mid' - if("G#7") soundfile = 'sound/violin/G#7.mid' - if("Ab7") soundfile = 'sound/violin/Ab7.mid' - if("An7") soundfile = 'sound/violin/An7.mid' - if("A#7") soundfile = 'sound/violin/A#7.mid' - if("Bb7") soundfile = 'sound/violin/Bb7.mid' - if("Bn7") soundfile = 'sound/violin/Bn7.mid' - if("B#7") soundfile = 'sound/violin/B#7.mid' - if("Cb8") soundfile = 'sound/violin/Cb8.mid' - if("Cn8") soundfile = 'sound/violin/Cn8.mid' - if("C#8") soundfile = 'sound/violin/C#8.mid' - if("Db8") soundfile = 'sound/violin/Db8.mid' - if("Dn8") soundfile = 'sound/violin/Dn8.mid' - if("D#8") soundfile = 'sound/violin/D#8.mid' - if("Eb8") soundfile = 'sound/violin/Eb8.mid' - if("En8") soundfile = 'sound/violin/En8.mid' - if("E#8") soundfile = 'sound/violin/E#8.mid' - if("Fb8") soundfile = 'sound/violin/Fb8.mid' - if("Fn8") soundfile = 'sound/violin/Fn8.mid' - if("F#8") soundfile = 'sound/violin/F#8.mid' - if("Gb8") soundfile = 'sound/violin/Gb8.mid' - if("Gn8") soundfile = 'sound/violin/Gn8.mid' - if("G#8") soundfile = 'sound/violin/G#8.mid' - if("Ab8") soundfile = 'sound/violin/Ab8.mid' - if("An8") soundfile = 'sound/violin/An8.mid' - if("A#8") soundfile = 'sound/violin/A#8.mid' - if("Bb8") soundfile = 'sound/violin/Bb8.mid' - if("Bn8") soundfile = 'sound/violin/Bn8.mid' - if("B#8") soundfile = 'sound/violin/B#8.mid' - if("Cb9") soundfile = 'sound/violin/Cb9.mid' - if("Cn9") soundfile = 'sound/violin/Cn9.mid' - else return - - hearers(15, get_turf(src)) << sound(soundfile) - -/obj/item/device/violin/proc/playsong(mob/user as mob) - while(repeat >= 0) - var/cur_oct[7] - var/cur_acc[7] - for(var/i = 1 to 7) - cur_oct[i] = "3" - cur_acc[i] = "n" - - for(var/line in song.lines) - //world << line - for(var/beat in text2list(lowertext(line), ",")) - //world << "beat: [beat]" - var/list/notes = text2list(beat, "/") - for(var/note in text2list(notes[1], "-")) - //world << "note: [note]" - if(!playing || !isliving(loc))//If the violin is playing, or isn't held by a person - playing = 0 - return - if(lentext(note) == 0) - continue - //world << "Parse: [copytext(note,1,2)]" - var/cur_note = text2ascii(note) - 96 - if(cur_note < 1 || cur_note > 7) - continue - for(var/i=2 to lentext(note)) - var/ni = copytext(note,i,i+1) - if(!text2num(ni)) - if(ni == "#" || ni == "b" || ni == "n") - cur_acc[cur_note] = ni - else if(ni == "s") - cur_acc[cur_note] = "#" // so shift is never required - else - cur_oct[cur_note] = ni - playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) - if(notes.len >= 2 && text2num(notes[2])) - sleep(song.tempo / text2num(notes[2])) - else - sleep(song.tempo) - repeat-- - if(repeat >= 0) // don't show the last -1 repeat - interact(user) - playing = 0 - repeat = 0 - interact(user) +/obj/item/device/violin/New() + song = new("violin", src) + song.instrumentExt = "mid" /obj/item/device/violin/attack_self(mob/user as mob) - if(!isliving(user) || user.stat || user.restrained() || user.lying) return - user.set_machine(src) interact(user) /obj/item/device/violin/interact(mob/user as mob) if(!user) return - if(!isliving(user) || user.stat || user.restrained() || user.lying) return - - var/dat = "" - - if(song && song.lines.len > 0) - dat += "

Playback

" - if(!playing) - dat += "Play Stop

" - dat += "Repeat Song: " - dat += repeat > 0 ? "--" : "--" - dat += " [repeat] times " - dat += repeat < max_repeats ? "++" : "++" - dat += "
" - else - dat += "Play Stop
" - dat += "Repeats left: [repeat]
" - if(!edit) - dat += "
Show Editor
" - else - dat += "

Editing

" - dat += "Hide Editor" - dat += " Start a New Song" - dat += " Import a Song

" - if(song) - var/calctempo = round(600 / song.tempo) - var/calcstep = song.tempo - 600 / (calctempo+1) - var/calcstep_b = song.tempo - 600 / (calctempo+10) - dat += "Tempo: -- [calctempo] BPM ++

" - var/linecount = 0 - for(var/line in song.lines) - linecount += 1 - dat += "Line [linecount]: Edit X [line]
" - dat += "Add Line

" - if(help) - dat += "Hide Help
" - dat += {" - Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
- Every note in a chord will play together, with chord timed by the tempo.
-
- Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.
- By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.
- Example: C,D,E,F,G,A,B will play a C major scale.
- After a note has an accidental placed, it will be remembered: C,C4,C,C3 is C3,C4,C4,C3
- Chords can be played simply by seperating each note with a hyphon: A-C#,Cn-E,E-G#,Gn-B
- A pause may be denoted by an empty chord: C,E,,C,G
- To make a chord be a different time, end it with /x, where the chord length will be length
- defined by tempo / x: C,G/2,E/4
- Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4 -
- Lines may be up to 50 characters.
- A song may only contain up to 50 lines.
- "} - else - dat += "Show Help
" - - var/datum/browser/popup = new(user, "apc", name) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/item/device/violin/Topic(href, href_list) - if(!in_range(src, usr) || issilicon(usr) || !isliving(usr) || !usr.canmove || usr.restrained()) - usr << browse(null, "window=violin") - usr.unset_machine() + if(!isliving(user) || user.stat || user.restrained() || user.lying) return - add_fingerprint(usr) - - if(href_list["newsong"]) - song = new() - - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) - if(!in_range(src, usr)) - return - - if(lentext(t) >= 3072) - var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") - if(cont == "no") - break - while(lentext(t) > 3072) - - //split into lines - spawn() - var/list/lines = text2list(t, "\n") - var/tempo = 5 - if(copytext(lines[1],1,6) == "BPM: ") - tempo = 600 / text2num(copytext(lines[1],6)) - lines.Cut(1,2) - if(lines.len > 50) - usr << "Too many lines!" - lines.Cut(51) - var/linenum = 1 - for(var/l in lines) - if(lentext(l) > 50) - usr << "Line [linenum] too long!" - lines.Remove(l) - else - linenum++ - song = new() - song.lines = lines - song.tempo = tempo - interact(usr) // make sure updates when complete - - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 - - else if(href_list["edit"]) - edit = text2num(href_list["edit"]) - 1 - - else if(song) - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - if(playing) - return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. - repeat += round(text2num(href_list["repeat"])) - if(repeat < 0) - repeat = 0 - if(repeat > max_repeats) - repeat = max_repeats - - else if(href_list["tempo"]) - song.tempo += text2num(href_list["tempo"]) - if(song.tempo < 1) - song.tempo = 1 - if(song.tempo > 600) - song.tempo = 600 - - else if(href_list["play"]) - if(song) - playing = 1 - spawn() - playsong(usr) - - else if(href_list["newline"]) - var/newline = html_encode(input("Enter your line: ", "violin") as text|null) - if(!newline) - return - if(song.lines.len > 50) - return - if(lentext(newline) > 50) - newline = copytext(newline, 1, 50) - song.lines.Add(newline) - - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > song.lines.len || num < 1) - return - song.lines.Cut(num, num+1) - - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = html_encode(input("Enter your line: ", "violin", song.lines[num]) as text|null) - if(!content) - return - if(lentext(content) > 50) - content = copytext(content, 1, 50) - if(num > song.lines.len || num < 1) - return - song.lines[num] = content - - else if(href_list["stop"]) - playing = 0 - - interact(usr) - return + user.set_machine(src) + song.interact(user) diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index c9bcbda3e5f..cd8cd627579 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -5,223 +5,221 @@ var/list/lines = new() var/tempo = 5 -/obj/structure/device/piano - name = "space minimoog" - icon = 'icons/obj/musician.dmi' - icon_state = "minimoog" - anchored = 1 - density = 1 - var/datum/song/song - var/playing = 0 - var/help = 0 - var/edit = 1 - var/repeat = 0 + var/playing = 0 // if we're playing + var/help = 0 // if help is open + var/edit = 1 // if we're in editing mode + var/repeat = 0 // number of times remaining to repeat + var/max_repeats = 10 // maximum times we can repeat -/obj/structure/device/piano/New() - if(prob(50)) - name = "space minimoog" - desc = "This is a minimoog, like a space piano, but more spacey!" - icon_state = "minimoog" - else - name = "space piano" - desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." - icon_state = "piano" + var/instrumentDir = "piano" // the folder with the sounds + var/instrumentExt = "ogg" // the file extension + var/obj/instrumentObj = null // the associated obj playing the sound -/obj/structure/device/piano/proc/playnote(var/note as text) +/datum/song/New(dir, obj) + instrumentDir = dir + instrumentObj = obj + +/datum/song/proc/playnote(var/note as text) //world << "Note: [note]" var/soundfile /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically. Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/ switch(note) - if("Cn1") soundfile = 'sound/piano/Cn1.ogg' - if("C#1") soundfile = 'sound/piano/C#1.ogg' - if("Db1") soundfile = 'sound/piano/Db1.ogg' - if("Dn1") soundfile = 'sound/piano/Dn1.ogg' - if("D#1") soundfile = 'sound/piano/D#1.ogg' - if("Eb1") soundfile = 'sound/piano/Eb1.ogg' - if("En1") soundfile = 'sound/piano/En1.ogg' - if("E#1") soundfile = 'sound/piano/E#1.ogg' - if("Fb1") soundfile = 'sound/piano/Fb1.ogg' - if("Fn1") soundfile = 'sound/piano/Fn1.ogg' - if("F#1") soundfile = 'sound/piano/F#1.ogg' - if("Gb1") soundfile = 'sound/piano/Gb1.ogg' - if("Gn1") soundfile = 'sound/piano/Gn1.ogg' - if("G#1") soundfile = 'sound/piano/G#1.ogg' - if("Ab1") soundfile = 'sound/piano/Ab1.ogg' - if("An1") soundfile = 'sound/piano/An1.ogg' - if("A#1") soundfile = 'sound/piano/A#1.ogg' - if("Bb1") soundfile = 'sound/piano/Bb1.ogg' - if("Bn1") soundfile = 'sound/piano/Bn1.ogg' - if("B#1") soundfile = 'sound/piano/B#1.ogg' - if("Cb2") soundfile = 'sound/piano/Cb2.ogg' - if("Cn2") soundfile = 'sound/piano/Cn2.ogg' - if("C#2") soundfile = 'sound/piano/C#2.ogg' - if("Db2") soundfile = 'sound/piano/Db2.ogg' - if("Dn2") soundfile = 'sound/piano/Dn2.ogg' - if("D#2") soundfile = 'sound/piano/D#2.ogg' - if("Eb2") soundfile = 'sound/piano/Eb2.ogg' - if("En2") soundfile = 'sound/piano/En2.ogg' - if("E#2") soundfile = 'sound/piano/E#2.ogg' - if("Fb2") soundfile = 'sound/piano/Fb2.ogg' - if("Fn2") soundfile = 'sound/piano/Fn2.ogg' - if("F#2") soundfile = 'sound/piano/F#2.ogg' - if("Gb2") soundfile = 'sound/piano/Gb2.ogg' - if("Gn2") soundfile = 'sound/piano/Gn2.ogg' - if("G#2") soundfile = 'sound/piano/G#2.ogg' - if("Ab2") soundfile = 'sound/piano/Ab2.ogg' - if("An2") soundfile = 'sound/piano/An2.ogg' - if("A#2") soundfile = 'sound/piano/A#2.ogg' - if("Bb2") soundfile = 'sound/piano/Bb2.ogg' - if("Bn2") soundfile = 'sound/piano/Bn2.ogg' - if("B#2") soundfile = 'sound/piano/B#2.ogg' - if("Cb3") soundfile = 'sound/piano/Cb3.ogg' - if("Cn3") soundfile = 'sound/piano/Cn3.ogg' - if("C#3") soundfile = 'sound/piano/C#3.ogg' - if("Db3") soundfile = 'sound/piano/Db3.ogg' - if("Dn3") soundfile = 'sound/piano/Dn3.ogg' - if("D#3") soundfile = 'sound/piano/D#3.ogg' - if("Eb3") soundfile = 'sound/piano/Eb3.ogg' - if("En3") soundfile = 'sound/piano/En3.ogg' - if("E#3") soundfile = 'sound/piano/E#3.ogg' - if("Fb3") soundfile = 'sound/piano/Fb3.ogg' - if("Fn3") soundfile = 'sound/piano/Fn3.ogg' - if("F#3") soundfile = 'sound/piano/F#3.ogg' - if("Gb3") soundfile = 'sound/piano/Gb3.ogg' - if("Gn3") soundfile = 'sound/piano/Gn3.ogg' - if("G#3") soundfile = 'sound/piano/G#3.ogg' - if("Ab3") soundfile = 'sound/piano/Ab3.ogg' - if("An3") soundfile = 'sound/piano/An3.ogg' - if("A#3") soundfile = 'sound/piano/A#3.ogg' - if("Bb3") soundfile = 'sound/piano/Bb3.ogg' - if("Bn3") soundfile = 'sound/piano/Bn3.ogg' - if("B#3") soundfile = 'sound/piano/B#3.ogg' - if("Cb4") soundfile = 'sound/piano/Cb4.ogg' - if("Cn4") soundfile = 'sound/piano/Cn4.ogg' - if("C#4") soundfile = 'sound/piano/C#4.ogg' - if("Db4") soundfile = 'sound/piano/Db4.ogg' - if("Dn4") soundfile = 'sound/piano/Dn4.ogg' - if("D#4") soundfile = 'sound/piano/D#4.ogg' - if("Eb4") soundfile = 'sound/piano/Eb4.ogg' - if("En4") soundfile = 'sound/piano/En4.ogg' - if("E#4") soundfile = 'sound/piano/E#4.ogg' - if("Fb4") soundfile = 'sound/piano/Fb4.ogg' - if("Fn4") soundfile = 'sound/piano/Fn4.ogg' - if("F#4") soundfile = 'sound/piano/F#4.ogg' - if("Gb4") soundfile = 'sound/piano/Gb4.ogg' - if("Gn4") soundfile = 'sound/piano/Gn4.ogg' - if("G#4") soundfile = 'sound/piano/G#4.ogg' - if("Ab4") soundfile = 'sound/piano/Ab4.ogg' - if("An4") soundfile = 'sound/piano/An4.ogg' - if("A#4") soundfile = 'sound/piano/A#4.ogg' - if("Bb4") soundfile = 'sound/piano/Bb4.ogg' - if("Bn4") soundfile = 'sound/piano/Bn4.ogg' - if("B#4") soundfile = 'sound/piano/B#4.ogg' - if("Cb5") soundfile = 'sound/piano/Cb5.ogg' - if("Cn5") soundfile = 'sound/piano/Cn5.ogg' - if("C#5") soundfile = 'sound/piano/C#5.ogg' - if("Db5") soundfile = 'sound/piano/Db5.ogg' - if("Dn5") soundfile = 'sound/piano/Dn5.ogg' - if("D#5") soundfile = 'sound/piano/D#5.ogg' - if("Eb5") soundfile = 'sound/piano/Eb5.ogg' - if("En5") soundfile = 'sound/piano/En5.ogg' - if("E#5") soundfile = 'sound/piano/E#5.ogg' - if("Fb5") soundfile = 'sound/piano/Fb5.ogg' - if("Fn5") soundfile = 'sound/piano/Fn5.ogg' - if("F#5") soundfile = 'sound/piano/F#5.ogg' - if("Gb5") soundfile = 'sound/piano/Gb5.ogg' - if("Gn5") soundfile = 'sound/piano/Gn5.ogg' - if("G#5") soundfile = 'sound/piano/G#5.ogg' - if("Ab5") soundfile = 'sound/piano/Ab5.ogg' - if("An5") soundfile = 'sound/piano/An5.ogg' - if("A#5") soundfile = 'sound/piano/A#5.ogg' - if("Bb5") soundfile = 'sound/piano/Bb5.ogg' - if("Bn5") soundfile = 'sound/piano/Bn5.ogg' - if("B#5") soundfile = 'sound/piano/B#5.ogg' - if("Cb6") soundfile = 'sound/piano/Cb6.ogg' - if("Cn6") soundfile = 'sound/piano/Cn6.ogg' - if("C#6") soundfile = 'sound/piano/C#6.ogg' - if("Db6") soundfile = 'sound/piano/Db6.ogg' - if("Dn6") soundfile = 'sound/piano/Dn6.ogg' - if("D#6") soundfile = 'sound/piano/D#6.ogg' - if("Eb6") soundfile = 'sound/piano/Eb6.ogg' - if("En6") soundfile = 'sound/piano/En6.ogg' - if("E#6") soundfile = 'sound/piano/E#6.ogg' - if("Fb6") soundfile = 'sound/piano/Fb6.ogg' - if("Fn6") soundfile = 'sound/piano/Fn6.ogg' - if("F#6") soundfile = 'sound/piano/F#6.ogg' - if("Gb6") soundfile = 'sound/piano/Gb6.ogg' - if("Gn6") soundfile = 'sound/piano/Gn6.ogg' - if("G#6") soundfile = 'sound/piano/G#6.ogg' - if("Ab6") soundfile = 'sound/piano/Ab6.ogg' - if("An6") soundfile = 'sound/piano/An6.ogg' - if("A#6") soundfile = 'sound/piano/A#6.ogg' - if("Bb6") soundfile = 'sound/piano/Bb6.ogg' - if("Bn6") soundfile = 'sound/piano/Bn6.ogg' - if("B#6") soundfile = 'sound/piano/B#6.ogg' - if("Cb7") soundfile = 'sound/piano/Cb7.ogg' - if("Cn7") soundfile = 'sound/piano/Cn7.ogg' - if("C#7") soundfile = 'sound/piano/C#7.ogg' - if("Db7") soundfile = 'sound/piano/Db7.ogg' - if("Dn7") soundfile = 'sound/piano/Dn7.ogg' - if("D#7") soundfile = 'sound/piano/D#7.ogg' - if("Eb7") soundfile = 'sound/piano/Eb7.ogg' - if("En7") soundfile = 'sound/piano/En7.ogg' - if("E#7") soundfile = 'sound/piano/E#7.ogg' - if("Fb7") soundfile = 'sound/piano/Fb7.ogg' - if("Fn7") soundfile = 'sound/piano/Fn7.ogg' - if("F#7") soundfile = 'sound/piano/F#7.ogg' - if("Gb7") soundfile = 'sound/piano/Gb7.ogg' - if("Gn7") soundfile = 'sound/piano/Gn7.ogg' - if("G#7") soundfile = 'sound/piano/G#7.ogg' - if("Ab7") soundfile = 'sound/piano/Ab7.ogg' - if("An7") soundfile = 'sound/piano/An7.ogg' - if("A#7") soundfile = 'sound/piano/A#7.ogg' - if("Bb7") soundfile = 'sound/piano/Bb7.ogg' - if("Bn7") soundfile = 'sound/piano/Bn7.ogg' - if("B#7") soundfile = 'sound/piano/B#7.ogg' - if("Cb8") soundfile = 'sound/piano/Cb8.ogg' - if("Cn8") soundfile = 'sound/piano/Cn8.ogg' - if("C#8") soundfile = 'sound/piano/C#8.ogg' - if("Db8") soundfile = 'sound/piano/Db8.ogg' - if("Dn8") soundfile = 'sound/piano/Dn8.ogg' - if("D#8") soundfile = 'sound/piano/D#8.ogg' - if("Eb8") soundfile = 'sound/piano/Eb8.ogg' - if("En8") soundfile = 'sound/piano/En8.ogg' - if("E#8") soundfile = 'sound/piano/E#8.ogg' - if("Fb8") soundfile = 'sound/piano/Fb8.ogg' - if("Fn8") soundfile = 'sound/piano/Fn8.ogg' - if("F#8") soundfile = 'sound/piano/F#8.ogg' - if("Gb8") soundfile = 'sound/piano/Gb8.ogg' - if("Gn8") soundfile = 'sound/piano/Gn8.ogg' - if("G#8") soundfile = 'sound/piano/G#8.ogg' - if("Ab8") soundfile = 'sound/piano/Ab8.ogg' - if("An8") soundfile = 'sound/piano/An8.ogg' - if("A#8") soundfile = 'sound/piano/A#8.ogg' - if("Bb8") soundfile = 'sound/piano/Bb8.ogg' - if("Bn8") soundfile = 'sound/piano/Bn8.ogg' - if("B#8") soundfile = 'sound/piano/B#8.ogg' - if("Cb9") soundfile = 'sound/piano/Cb9.ogg' - if("Cn9") soundfile = 'sound/piano/Cn9.ogg' + if("Cn1") soundfile = "sound/[instrumentDir]/Cn1.[instrumentExt]" + if("C#1") soundfile = "sound/[instrumentDir]/C#1.[instrumentExt]" + if("Db1") soundfile = "sound/[instrumentDir]/Db1.[instrumentExt]" + if("Dn1") soundfile = "sound/[instrumentDir]/Dn1.[instrumentExt]" + if("D#1") soundfile = "sound/[instrumentDir]/D#1.[instrumentExt]" + if("Eb1") soundfile = "sound/[instrumentDir]/Eb1.[instrumentExt]" + if("En1") soundfile = "sound/[instrumentDir]/En1.[instrumentExt]" + if("E#1") soundfile = "sound/[instrumentDir]/E#1.[instrumentExt]" + if("Fb1") soundfile = "sound/[instrumentDir]/Fb1.[instrumentExt]" + if("Fn1") soundfile = "sound/[instrumentDir]/Fn1.[instrumentExt]" + if("F#1") soundfile = "sound/[instrumentDir]/F#1.[instrumentExt]" + if("Gb1") soundfile = "sound/[instrumentDir]/Gb1.[instrumentExt]" + if("Gn1") soundfile = "sound/[instrumentDir]/Gn1.[instrumentExt]" + if("G#1") soundfile = "sound/[instrumentDir]/G#1.[instrumentExt]" + if("Ab1") soundfile = "sound/[instrumentDir]/Ab1.[instrumentExt]" + if("An1") soundfile = "sound/[instrumentDir]/An1.[instrumentExt]" + if("A#1") soundfile = "sound/[instrumentDir]/A#1.[instrumentExt]" + if("Bb1") soundfile = "sound/[instrumentDir]/Bb1.[instrumentExt]" + if("Bn1") soundfile = "sound/[instrumentDir]/Bn1.[instrumentExt]" + if("B#1") soundfile = "sound/[instrumentDir]/B#1.[instrumentExt]" + if("Cb2") soundfile = "sound/[instrumentDir]/Cb2.[instrumentExt]" + if("Cn2") soundfile = "sound/[instrumentDir]/Cn2.[instrumentExt]" + if("C#2") soundfile = "sound/[instrumentDir]/C#2.[instrumentExt]" + if("Db2") soundfile = "sound/[instrumentDir]/Db2.[instrumentExt]" + if("Dn2") soundfile = "sound/[instrumentDir]/Dn2.[instrumentExt]" + if("D#2") soundfile = "sound/[instrumentDir]/D#2.[instrumentExt]" + if("Eb2") soundfile = "sound/[instrumentDir]/Eb2.[instrumentExt]" + if("En2") soundfile = "sound/[instrumentDir]/En2.[instrumentExt]" + if("E#2") soundfile = "sound/[instrumentDir]/E#2.[instrumentExt]" + if("Fb2") soundfile = "sound/[instrumentDir]/Fb2.[instrumentExt]" + if("Fn2") soundfile = "sound/[instrumentDir]/Fn2.[instrumentExt]" + if("F#2") soundfile = "sound/[instrumentDir]/F#2.[instrumentExt]" + if("Gb2") soundfile = "sound/[instrumentDir]/Gb2.[instrumentExt]" + if("Gn2") soundfile = "sound/[instrumentDir]/Gn2.[instrumentExt]" + if("G#2") soundfile = "sound/[instrumentDir]/G#2.[instrumentExt]" + if("Ab2") soundfile = "sound/[instrumentDir]/Ab2.[instrumentExt]" + if("An2") soundfile = "sound/[instrumentDir]/An2.[instrumentExt]" + if("A#2") soundfile = "sound/[instrumentDir]/A#2.[instrumentExt]" + if("Bb2") soundfile = "sound/[instrumentDir]/Bb2.[instrumentExt]" + if("Bn2") soundfile = "sound/[instrumentDir]/Bn2.[instrumentExt]" + if("B#2") soundfile = "sound/[instrumentDir]/B#2.[instrumentExt]" + if("Cb3") soundfile = "sound/[instrumentDir]/Cb3.[instrumentExt]" + if("Cn3") soundfile = "sound/[instrumentDir]/Cn3.[instrumentExt]" + if("C#3") soundfile = "sound/[instrumentDir]/C#3.[instrumentExt]" + if("Db3") soundfile = "sound/[instrumentDir]/Db3.[instrumentExt]" + if("Dn3") soundfile = "sound/[instrumentDir]/Dn3.[instrumentExt]" + if("D#3") soundfile = "sound/[instrumentDir]/D#3.[instrumentExt]" + if("Eb3") soundfile = "sound/[instrumentDir]/Eb3.[instrumentExt]" + if("En3") soundfile = "sound/[instrumentDir]/En3.[instrumentExt]" + if("E#3") soundfile = "sound/[instrumentDir]/E#3.[instrumentExt]" + if("Fb3") soundfile = "sound/[instrumentDir]/Fb3.[instrumentExt]" + if("Fn3") soundfile = "sound/[instrumentDir]/Fn3.[instrumentExt]" + if("F#3") soundfile = "sound/[instrumentDir]/F#3.[instrumentExt]" + if("Gb3") soundfile = "sound/[instrumentDir]/Gb3.[instrumentExt]" + if("Gn3") soundfile = "sound/[instrumentDir]/Gn3.[instrumentExt]" + if("G#3") soundfile = "sound/[instrumentDir]/G#3.[instrumentExt]" + if("Ab3") soundfile = "sound/[instrumentDir]/Ab3.[instrumentExt]" + if("An3") soundfile = "sound/[instrumentDir]/An3.[instrumentExt]" + if("A#3") soundfile = "sound/[instrumentDir]/A#3.[instrumentExt]" + if("Bb3") soundfile = "sound/[instrumentDir]/Bb3.[instrumentExt]" + if("Bn3") soundfile = "sound/[instrumentDir]/Bn3.[instrumentExt]" + if("B#3") soundfile = "sound/[instrumentDir]/B#3.[instrumentExt]" + if("Cb4") soundfile = "sound/[instrumentDir]/Cb4.[instrumentExt]" + if("Cn4") soundfile = "sound/[instrumentDir]/Cn4.[instrumentExt]" + if("C#4") soundfile = "sound/[instrumentDir]/C#4.[instrumentExt]" + if("Db4") soundfile = "sound/[instrumentDir]/Db4.[instrumentExt]" + if("Dn4") soundfile = "sound/[instrumentDir]/Dn4.[instrumentExt]" + if("D#4") soundfile = "sound/[instrumentDir]/D#4.[instrumentExt]" + if("Eb4") soundfile = "sound/[instrumentDir]/Eb4.[instrumentExt]" + if("En4") soundfile = "sound/[instrumentDir]/En4.[instrumentExt]" + if("E#4") soundfile = "sound/[instrumentDir]/E#4.[instrumentExt]" + if("Fb4") soundfile = "sound/[instrumentDir]/Fb4.[instrumentExt]" + if("Fn4") soundfile = "sound/[instrumentDir]/Fn4.[instrumentExt]" + if("F#4") soundfile = "sound/[instrumentDir]/F#4.[instrumentExt]" + if("Gb4") soundfile = "sound/[instrumentDir]/Gb4.[instrumentExt]" + if("Gn4") soundfile = "sound/[instrumentDir]/Gn4.[instrumentExt]" + if("G#4") soundfile = "sound/[instrumentDir]/G#4.[instrumentExt]" + if("Ab4") soundfile = "sound/[instrumentDir]/Ab4.[instrumentExt]" + if("An4") soundfile = "sound/[instrumentDir]/An4.[instrumentExt]" + if("A#4") soundfile = "sound/[instrumentDir]/A#4.[instrumentExt]" + if("Bb4") soundfile = "sound/[instrumentDir]/Bb4.[instrumentExt]" + if("Bn4") soundfile = "sound/[instrumentDir]/Bn4.[instrumentExt]" + if("B#4") soundfile = "sound/[instrumentDir]/B#4.[instrumentExt]" + if("Cb5") soundfile = "sound/[instrumentDir]/Cb5.[instrumentExt]" + if("Cn5") soundfile = "sound/[instrumentDir]/Cn5.[instrumentExt]" + if("C#5") soundfile = "sound/[instrumentDir]/C#5.[instrumentExt]" + if("Db5") soundfile = "sound/[instrumentDir]/Db5.[instrumentExt]" + if("Dn5") soundfile = "sound/[instrumentDir]/Dn5.[instrumentExt]" + if("D#5") soundfile = "sound/[instrumentDir]/D#5.[instrumentExt]" + if("Eb5") soundfile = "sound/[instrumentDir]/Eb5.[instrumentExt]" + if("En5") soundfile = "sound/[instrumentDir]/En5.[instrumentExt]" + if("E#5") soundfile = "sound/[instrumentDir]/E#5.[instrumentExt]" + if("Fb5") soundfile = "sound/[instrumentDir]/Fb5.[instrumentExt]" + if("Fn5") soundfile = "sound/[instrumentDir]/Fn5.[instrumentExt]" + if("F#5") soundfile = "sound/[instrumentDir]/F#5.[instrumentExt]" + if("Gb5") soundfile = "sound/[instrumentDir]/Gb5.[instrumentExt]" + if("Gn5") soundfile = "sound/[instrumentDir]/Gn5.[instrumentExt]" + if("G#5") soundfile = "sound/[instrumentDir]/G#5.[instrumentExt]" + if("Ab5") soundfile = "sound/[instrumentDir]/Ab5.[instrumentExt]" + if("An5") soundfile = "sound/[instrumentDir]/An5.[instrumentExt]" + if("A#5") soundfile = "sound/[instrumentDir]/A#5.[instrumentExt]" + if("Bb5") soundfile = "sound/[instrumentDir]/Bb5.[instrumentExt]" + if("Bn5") soundfile = "sound/[instrumentDir]/Bn5.[instrumentExt]" + if("B#5") soundfile = "sound/[instrumentDir]/B#5.[instrumentExt]" + if("Cb6") soundfile = "sound/[instrumentDir]/Cb6.[instrumentExt]" + if("Cn6") soundfile = "sound/[instrumentDir]/Cn6.[instrumentExt]" + if("C#6") soundfile = "sound/[instrumentDir]/C#6.[instrumentExt]" + if("Db6") soundfile = "sound/[instrumentDir]/Db6.[instrumentExt]" + if("Dn6") soundfile = "sound/[instrumentDir]/Dn6.[instrumentExt]" + if("D#6") soundfile = "sound/[instrumentDir]/D#6.[instrumentExt]" + if("Eb6") soundfile = "sound/[instrumentDir]/Eb6.[instrumentExt]" + if("En6") soundfile = "sound/[instrumentDir]/En6.[instrumentExt]" + if("E#6") soundfile = "sound/[instrumentDir]/E#6.[instrumentExt]" + if("Fb6") soundfile = "sound/[instrumentDir]/Fb6.[instrumentExt]" + if("Fn6") soundfile = "sound/[instrumentDir]/Fn6.[instrumentExt]" + if("F#6") soundfile = "sound/[instrumentDir]/F#6.[instrumentExt]" + if("Gb6") soundfile = "sound/[instrumentDir]/Gb6.[instrumentExt]" + if("Gn6") soundfile = "sound/[instrumentDir]/Gn6.[instrumentExt]" + if("G#6") soundfile = "sound/[instrumentDir]/G#6.[instrumentExt]" + if("Ab6") soundfile = "sound/[instrumentDir]/Ab6.[instrumentExt]" + if("An6") soundfile = "sound/[instrumentDir]/An6.[instrumentExt]" + if("A#6") soundfile = "sound/[instrumentDir]/A#6.[instrumentExt]" + if("Bb6") soundfile = "sound/[instrumentDir]/Bb6.[instrumentExt]" + if("Bn6") soundfile = "sound/[instrumentDir]/Bn6.[instrumentExt]" + if("B#6") soundfile = "sound/[instrumentDir]/B#6.[instrumentExt]" + if("Cb7") soundfile = "sound/[instrumentDir]/Cb7.[instrumentExt]" + if("Cn7") soundfile = "sound/[instrumentDir]/Cn7.[instrumentExt]" + if("C#7") soundfile = "sound/[instrumentDir]/C#7.[instrumentExt]" + if("Db7") soundfile = "sound/[instrumentDir]/Db7.[instrumentExt]" + if("Dn7") soundfile = "sound/[instrumentDir]/Dn7.[instrumentExt]" + if("D#7") soundfile = "sound/[instrumentDir]/D#7.[instrumentExt]" + if("Eb7") soundfile = "sound/[instrumentDir]/Eb7.[instrumentExt]" + if("En7") soundfile = "sound/[instrumentDir]/En7.[instrumentExt]" + if("E#7") soundfile = "sound/[instrumentDir]/E#7.[instrumentExt]" + if("Fb7") soundfile = "sound/[instrumentDir]/Fb7.[instrumentExt]" + if("Fn7") soundfile = "sound/[instrumentDir]/Fn7.[instrumentExt]" + if("F#7") soundfile = "sound/[instrumentDir]/F#7.[instrumentExt]" + if("Gb7") soundfile = "sound/[instrumentDir]/Gb7.[instrumentExt]" + if("Gn7") soundfile = "sound/[instrumentDir]/Gn7.[instrumentExt]" + if("G#7") soundfile = "sound/[instrumentDir]/G#7.[instrumentExt]" + if("Ab7") soundfile = "sound/[instrumentDir]/Ab7.[instrumentExt]" + if("An7") soundfile = "sound/[instrumentDir]/An7.[instrumentExt]" + if("A#7") soundfile = "sound/[instrumentDir]/A#7.[instrumentExt]" + if("Bb7") soundfile = "sound/[instrumentDir]/Bb7.[instrumentExt]" + if("Bn7") soundfile = "sound/[instrumentDir]/Bn7.[instrumentExt]" + if("B#7") soundfile = "sound/[instrumentDir]/B#7.[instrumentExt]" + if("Cb8") soundfile = "sound/[instrumentDir]/Cb8.[instrumentExt]" + if("Cn8") soundfile = "sound/[instrumentDir]/Cn8.[instrumentExt]" + if("C#8") soundfile = "sound/[instrumentDir]/C#8.[instrumentExt]" + if("Db8") soundfile = "sound/[instrumentDir]/Db8.[instrumentExt]" + if("Dn8") soundfile = "sound/[instrumentDir]/Dn8.[instrumentExt]" + if("D#8") soundfile = "sound/[instrumentDir]/D#8.[instrumentExt]" + if("Eb8") soundfile = "sound/[instrumentDir]/Eb8.[instrumentExt]" + if("En8") soundfile = "sound/[instrumentDir]/En8.[instrumentExt]" + if("E#8") soundfile = "sound/[instrumentDir]/E#8.[instrumentExt]" + if("Fb8") soundfile = "sound/[instrumentDir]/Fb8.[instrumentExt]" + if("Fn8") soundfile = "sound/[instrumentDir]/Fn8.[instrumentExt]" + if("F#8") soundfile = "sound/[instrumentDir]/F#8.[instrumentExt]" + if("Gb8") soundfile = "sound/[instrumentDir]/Gb8.[instrumentExt]" + if("Gn8") soundfile = "sound/[instrumentDir]/Gn8.[instrumentExt]" + if("G#8") soundfile = "sound/[instrumentDir]/G#8.[instrumentExt]" + if("Ab8") soundfile = "sound/[instrumentDir]/Ab8.[instrumentExt]" + if("An8") soundfile = "sound/[instrumentDir]/An8.[instrumentExt]" + if("A#8") soundfile = "sound/[instrumentDir]/A#8.[instrumentExt]" + if("Bb8") soundfile = "sound/[instrumentDir]/Bb8.[instrumentExt]" + if("Bn8") soundfile = "sound/[instrumentDir]/Bn8.[instrumentExt]" + if("B#8") soundfile = "sound/[instrumentDir]/B#8.[instrumentExt]" + if("Cb9") soundfile = "sound/[instrumentDir]/Cb9.[instrumentExt]" + if("Cn9") soundfile = "sound/[instrumentDir]/Cn9.[instrumentExt]" else return - hearers(15, src) << sound(soundfile) + hearers(15, get_turf(instrumentObj)) << sound(soundfile) -/obj/structure/device/piano/proc/playsong() - do +/datum/song/proc/updateDialog(mob/user as mob) + instrumentObj.updateDialog() // assumes it's an object in world, override if otherwise + +/datum/song/proc/shouldStopPlaying() + return !instrumentObj.anchored // add special cases to stop in subclasses + +/datum/song/proc/playsong(mob/user as mob) + while(repeat >= 0) var/cur_oct[7] var/cur_acc[7] for(var/i = 1 to 7) cur_oct[i] = "3" cur_acc[i] = "n" - for(var/line in song.lines) + for(var/line in lines) //world << line for(var/beat in text2list(lowertext(line), ",")) //world << "beat: [beat]" var/list/notes = text2list(beat, "/") for(var/note in text2list(notes[1], "-")) //world << "note: [note]" - if(!playing || !anchored)//If the piano is playing, or is loose + if(!playing || shouldStopPlaying())//If the instrument is playing, or special case playing = 0 return if(lentext(note) == 0) @@ -241,45 +239,49 @@ cur_oct[cur_note] = ni playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note]) if(notes.len >= 2 && text2num(notes[2])) - sleep(song.tempo / text2num(notes[2])) + sleep(tempo / text2num(notes[2])) else - sleep(song.tempo) - if(repeat > 0) - repeat-- //Infinite loops are baaaad. - while(repeat > 0) + sleep(tempo) + repeat-- + if(repeat >= 0) // don't show the last -1 repeat + updateDialog(user) playing = 0 - updateUsrDialog() + repeat = 0 + updateDialog(user) -/obj/structure/device/piano/attack_hand(var/mob/user as mob) - if(!anchored) - return +/datum/song/proc/interact(mob/user as mob) + var/dat = "" - usr.machine = src - var/dat = "Piano" - - if(song) - if(song.lines.len > 0 && !(playing)) - dat += "Play Song

" - dat += "Repeat Song: [repeat] times.

" - if(playing) - dat += "Stop Playing
" - dat += "Repeats left: [repeat].

" + if(lines.len > 0) + dat += "

Playback

" + if(!playing) + dat += "Play Stop

" + dat += "Repeat Song: " + dat += repeat > 0 ? "--" : "--" + dat += " [repeat] times " + dat += repeat < max_repeats ? "++" : "++" + dat += "
" + else + dat += "Play Stop
" + dat += "Repeats left: [repeat]
" if(!edit) - dat += "Show Editor

" + dat += "
Show Editor
" else - dat += "Hide Editor
" - dat += "Start a New Song
" - dat += "Import a Song

" - if(song) - var/calctempo = (10/song.tempo)*60 - dat += "Tempo : -- [calctempo] BPM ++

" - var/linecount = 0 - for(var/line in song.lines) - linecount += 1 - dat += "Line [linecount]: [line] Delete Line Modify Line
" - dat += "Add Line

" + dat += "

Editing

" + dat += "Hide Editor" + dat += " Start a New Song" + dat += " Import a Song

" + var/calctempo = round(600 / tempo) + var/calcstep = tempo - 600 / (calctempo+1) + var/calcstep_b = tempo - 600 / (calctempo+10) + dat += "Tempo: -- [calctempo] BPM ++

" + var/linecount = 0 + for(var/line in lines) + linecount += 1 + dat += "Line [linecount]: Edit X [line]
" + dat += "Add Line

" if(help) - dat += "Hide Help
" + dat += "Hide Help
" dat += {" Lines are a series of chords, separated by commas (,), each with notes seperated by hyphens (-).
Every note in a chord will play together, with chord timed by the tempo.
@@ -292,121 +294,171 @@ A pause may be denoted by an empty chord: C,E,,C,G
To make a chord be a different time, end it with /x, where the chord length will be length
defined by tempo / x: C,G/2,E/4
- Combined, an example is: E-E4/4,/2,G#/8,B/8,E3-E4/4 + Combined, an example is: E-E4/4,F#/2,G#/8,B/8,E3-E4/4
Lines may be up to 50 characters.
A song may only contain up to 50 lines.
"} else - dat += "Show Help
" - dat += "" - user << browse(dat, "window=piano;size=700x300") - onclose(user, "piano") + dat += "Show Help
" -/obj/structure/device/piano/Topic(href, href_list) + var/datum/browser/popup = new(user, "instrument", instrumentObj.name, 700, 500) + popup.set_content(dat) + popup.set_title_image(user.browse_rsc_icon(instrumentObj.icon, instrumentObj.icon_state)) + popup.open() - if(!in_range(src, usr) || issilicon(usr) || !anchored || !usr.canmove || usr.restrained()) - usr << browse(null, "window=piano;size=700x300") - onclose(usr, "piano") + +/datum/song/Topic(href, href_list) + if(!in_range(instrumentObj, usr) || issilicon(usr) || !isliving(usr) || !usr.canmove || usr.restrained()) + usr << browse(null, "window=instrument") + usr.unset_machine() return + instrumentObj.add_fingerprint(usr) + if(href_list["newsong"]) - song = new() - else if(song) - if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. - if(playing) return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. - var/tempnum = input("How many times do you want to repeat this piece? (max:10)") as num|null - if(tempnum > 10) - tempnum = 10 - if(tempnum < 0) - tempnum = 0 - repeat = round(tempnum) + lines = new() + tempo = 5 // default 120 BPM + name = "" - else if(href_list["tempo"]) - song.tempo += round(text2num(href_list["tempo"])) - if(song.tempo < 1) - song.tempo = 1 - - else if(href_list["play"]) - if(song) - playing = 1 - spawn() playsong() - - else if(href_list["newline"]) - var/newline = html_encode(input("Enter your line: ", "Piano") as text|null) - if(!newline) + else if(href_list["import"]) + var/t = "" + do + t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", name), t) as message) + if(!in_range(instrumentObj, usr)) return - if(song.lines.len > 50) - return - if(lentext(newline) > 50) - newline = copytext(newline, 1, 50) - song.lines.Add(newline) - else if(href_list["deleteline"]) - var/num = round(text2num(href_list["deleteline"])) - if(num > song.lines.len || num < 1) - return - song.lines.Cut(num, num+1) + if(lentext(t) >= 3072) + var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") + if(cont == "no") + break + while(lentext(t) > 3072) - else if(href_list["modifyline"]) - var/num = round(text2num(href_list["modifyline"]),1) - var/content = html_encode(input("Enter your line: ", "Piano", song.lines[num]) as text|null) - if(!content) - return - if(lentext(content) > 50) - content = copytext(content, 1, 50) - if(num > song.lines.len || num < 1) - return - song.lines[num] = content + //split into lines + spawn() + lines = text2list(t, "\n") + if(copytext(lines[1],1,6) == "BPM: ") + tempo = 600 / text2num(copytext(lines[1],6)) + lines.Cut(1,2) + else + tempo = 5 // default 120 BPM + if(lines.len > 50) + usr << "Too many lines!" + lines.Cut(51) + var/linenum = 1 + for(var/l in lines) + if(lentext(l) > 50) + usr << "Line [linenum] too long!" + lines.Remove(l) + else + linenum++ + updateDialog(usr) // make sure updates when complete - else if(href_list["stop"]) - playing = 0 + else if(href_list["help"]) + help = text2num(href_list["help"]) - 1 - else if(href_list["help"]) - help = text2num(href_list["help"]) - 1 + else if(href_list["edit"]) + edit = text2num(href_list["edit"]) - 1 - else if(href_list["edit"]) - edit = text2num(href_list["edit"]) - 1 + if(href_list["repeat"]) //Changing this from a toggle to a number of repeats to avoid infinite loops. + if(playing) + return //So that people cant keep adding to repeat. If the do it intentionally, it could result in the server crashing. + repeat += round(text2num(href_list["repeat"])) + if(repeat < 0) + repeat = 0 + if(repeat > max_repeats) + repeat = max_repeats - else if(href_list["import"]) - var/t = "" - do - t = html_encode(input(usr, "Please paste the entire song, formatted:", text("[]", src.name), t) as message) - if (!in_range(src, usr)) - return + else if(href_list["tempo"]) + tempo += text2num(href_list["tempo"]) + if(tempo < 1) + tempo = 1 + if(tempo > 600) + tempo = 600 - if(lentext(t) >= 3072) - var/cont = input(usr, "Your message is too long! Would you like to continue editing it?", "", "yes") in list("yes", "no") - if(cont == "no") - break - while(lentext(t) > 3072) + else if(href_list["play"]) + playing = 1 + spawn() + playsong(usr) - //split into lines - spawn() - var/list/lines = text2list(t, "\n") - var/tempo = 5 - if(copytext(lines[1],1,6) == "BPM: ") - tempo = 600 / text2num(copytext(lines[1],6)) - lines.Cut(1,2) - if(lines.len > 50) - usr << "Too many lines!" - lines.Cut(51) - var/linenum = 1 - for(var/l in lines) - if(lentext(l) > 50) - usr << "Line [linenum] too long!" - lines.Remove(l) - else - linenum++ - song = new() - song.lines = lines - song.tempo = tempo - updateUsrDialog() + else if(href_list["newline"]) + var/newline = html_encode(input("Enter your line: ", instrumentObj.name) as text|null) + if(!newline || !in_range(instrumentObj, usr)) + return + if(lines.len > 50) + return + if(lentext(newline) > 50) + newline = copytext(newline, 1, 50) + lines.Add(newline) - add_fingerprint(usr) - updateUsrDialog() + else if(href_list["deleteline"]) + var/num = round(text2num(href_list["deleteline"])) + if(num > lines.len || num < 1) + return + lines.Cut(num, num+1) + + else if(href_list["modifyline"]) + var/num = round(text2num(href_list["modifyline"]),1) + var/content = html_encode(input("Enter your line: ", instrumentObj.name, lines[num]) as text|null) + if(!content || !in_range(instrumentObj, usr)) + return + if(lentext(content) > 50) + content = copytext(content, 1, 50) + if(num > lines.len || num < 1) + return + lines[num] = content + + else if(href_list["stop"]) + playing = 0 + + updateDialog(usr) return + +// subclass for handheld instruments, like violin +/datum/song/handheld + + updateDialog(mob/user as mob) + instrumentObj.interact(user) + + shouldStopPlaying() + return !isliving(instrumentObj.loc) + + +////////////////////////////////////////////////////////////////////////// + + +/obj/structure/device/piano + name = "space minimoog" + icon = 'icons/obj/musician.dmi' + icon_state = "minimoog" + anchored = 1 + density = 1 + var/datum/song/song + + +/obj/structure/device/piano/New() + song = new("piano", src) + + if(prob(50)) + name = "space minimoog" + desc = "This is a minimoog, like a space piano, but more spacey!" + icon_state = "minimoog" + else + name = "space piano" + desc = "This is a space piano, like a regular piano, but always in tune! Even if the musician isn't." + icon_state = "piano" + +/obj/structure/device/piano/attack_hand(mob/user as mob) + interact(user) + +/obj/structure/device/piano/interact(mob/user as mob) + if(!user || !anchored) + return + + user.set_machine(src) + song.interact(user) + /obj/structure/device/piano/attackby(obj/item/O as obj, mob/user as mob) if (istype(O, /obj/item/weapon/wrench)) if (anchored)