Instrument tweaks

The piano will stop playing once you walk away from it or get stunned.

The song BPM of the piano and violin will generally speaking be wrong because of discrepancies between the sleep between notes and world.tick_lag. I've solved this by locking BPM to points where the stated BPM will actually be the case because tempo == world.tick_lag.

Example
Current:
song @ 5 tempo - 120 BPM: c, c/2, c -> note -> sleep(5) -> 6 ticks (5.4 time passes) -> note -> sleep(2.5) -> 3 ticks (2.7 time passes) -> note.

With this PR:
song @ 5.4 tempo - 111 BPM: c, c/2, c -> note -> sleep(5.4) -> 6 ticks (5.4 time passes) -> note/2 -> sleep(2.7) -> 3 ticks (2.7 time passes) -> note.

I was hoping this would make the damn things sound better but then I realized it wasn't actually messing anything up. Oh well.
This commit is contained in:
MrPerson
2015-03-20 20:40:36 -07:00
parent 3db1919f67
commit fa7a89b25b
2 changed files with 24 additions and 16 deletions
+20 -16
View File
@@ -3,7 +3,7 @@
/datum/song
var/name = "Untitled"
var/list/lines = new()
var/tempo = 5
var/tempo = 5 // delay between notes
var/playing = 0 // if we're playing
var/help = 0 // if help is open
@@ -16,6 +16,7 @@
var/obj/instrumentObj = null // the associated obj playing the sound
/datum/song/New(dir, obj)
tempo = sanitize_tempo(tempo)
instrumentDir = dir
instrumentObj = obj
@@ -63,8 +64,10 @@
/datum/song/proc/updateDialog(mob/user as mob)
instrumentObj.updateDialog() // assumes it's an object in world, override if otherwise
/datum/song/proc/shouldStopPlaying()
/datum/song/proc/shouldStopPlaying(mob/user)
if(instrumentObj)
if(!user.canUseTopic(instrumentObj))
return 1
return !instrumentObj.anchored // add special cases to stop in subclasses
else
return 1
@@ -84,7 +87,7 @@
var/list/notes = text2list(beat, "/")
for(var/note in text2list(notes[1], "-"))
//world << "note: [note]"
if(!playing || shouldStopPlaying())//If the instrument is playing, or special case
if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case
playing = 0
return
if(lentext(note) == 0)
@@ -104,7 +107,7 @@
cur_oct[cur_note] = text2num(ni)
playnote(cur_note, cur_acc[cur_note], cur_oct[cur_note])
if(notes.len >= 2 && text2num(notes[2]))
sleep(tempo / text2num(notes[2]))
sleep(sanitize_tempo(tempo / text2num(notes[2])))
else
sleep(tempo)
repeat--
@@ -136,10 +139,8 @@
dat += "<B><A href='?src=\ref[src];edit=1'>Hide Editor</A></B>"
dat += " <A href='?src=\ref[src];newsong=1'>Start a New Song</A>"
dat += " <A href='?src=\ref[src];import=1'>Import a Song</A><BR><BR>"
var/calctempo = round(600 / tempo)
var/calcstep = tempo - 600 / (calctempo+1)
var/calcstep_b = tempo - 600 / (calctempo+10)
dat += "Tempo: <A href='?src=\ref[src];tempo=[calcstep_b]'>-</A><A href='?src=\ref[src];tempo=[calcstep]'>-</A> [calctempo] BPM <A href='?src=\ref[src];tempo=-[calcstep]'>+</A><A href='?src=\ref[src];tempo=-[calcstep_b]'>+</A><BR><BR>"
var/bpm = round(600 / tempo)
dat += "Tempo: <A href='?src=\ref[src];tempo=[world.tick_lag]'>-</A> [bpm] BPM <A href='?src=\ref[src];tempo=-[world.tick_lag]'>+</A><BR><BR>"
var/linecount = 0
for(var/line in lines)
linecount += 1
@@ -183,7 +184,7 @@
if(href_list["newsong"])
lines = new()
tempo = 5 // default 120 BPM
tempo = sanitize_tempo(5) // default 120 BPM
name = ""
else if(href_list["import"])
@@ -203,10 +204,10 @@
spawn()
lines = text2list(t, "\n")
if(copytext(lines[1],1,6) == "BPM: ")
tempo = 600 / max(1, text2num(copytext(lines[1],6)))
tempo = sanitize_tempo(600 / text2num(copytext(lines[1],6)))
lines.Cut(1,2)
else
tempo = 5 // default 120 BPM
tempo = sanitize_tempo(5) // default 120 BPM
if(lines.len > 50)
usr << "Too many lines!"
lines.Cut(51)
@@ -235,11 +236,7 @@
repeat = max_repeats
else if(href_list["tempo"])
tempo += text2num(href_list["tempo"])
if(tempo < 1)
tempo = 1
if(tempo > 600)
tempo = 600
tempo = sanitize_tempo(tempo + text2num(href_list["tempo"]))
else if(href_list["play"])
playing = 1
@@ -279,6 +276,9 @@
updateDialog(usr)
return
/datum/song/proc/sanitize_tempo(new_tempo)
new_tempo = abs(new_tempo)
return max(round(new_tempo, world.tick_lag), world.tick_lag)
// subclass for handheld instruments, like violin
/datum/song/handheld
@@ -322,6 +322,10 @@
song = null
..()
/obj/structure/piano/initialize()
song.tempo = song.sanitize_tempo(song.tempo) // tick_lag isn't set when the map is loaded
..()
/obj/structure/piano/attack_hand(mob/user as mob)
if(!user.IsAdvancedToolUser())
user << "<span class='danger'>You don't have the dexterity to do this!</span>"