A port of an early version of Baystation's new instruments (#37447)

* first commit instruments

first commit for instruments, should have everything ready

* open dream linter fix 1

* fix linter warnings 1

* subsystem + other small fixes

* alternative sprites

* more alternative sprites

* style fixes + src. removal
This commit is contained in:
mentgah
2025-03-04 15:52:27 +01:00
committed by GitHub
parent 8107706f06
commit 12d884d312
458 changed files with 1867 additions and 4 deletions

View File

@@ -60,6 +60,7 @@
#define SS_PRIORITY_THERM_DISS 19
#define SS_PRIORITY_AMBIENCE 18
#define SS_PRIORITY_DBCORE 17
#define SS_PRIORITY_MUSIC 16
#define SS_PRIORITY_SUN 3
#define SS_PRIORITY_GARBAGE 2
#define SS_PRIORITY_INACTIVITY 1

View File

@@ -0,0 +1,32 @@
var/datum/subsystem/music/SSmusic
/datum/subsystem/music
name = "Music"
wait = 1
priority = SS_PRIORITY_MUSIC
flags = SS_NO_INIT | SS_KEEP_TIMING
var/list/datum/musical_event/events = list()
/datum/subsystem/music/New()
NEW_SS_GLOBAL(SSmusic)
/datum/subsystem/music/fire(resumed = FALSE)
if (isemptylist(events))
return
var/list/datum/musical_event/left_events = list()
for (var/datum/musical_event/event in events)
event.time -= wait
if (event.time <= 0)
event.tick()
else
left_events += event
events = left_events
/datum/subsystem/music/proc/push_event(datum/sound_player/source, mob/subject, sound/object, time, volume)
if (istype(source) && istype(subject) && istype(object) && volume >= 0 && volume <= 100)
events += new /datum/musical_event(source, subject, object, time, volume)
/datum/subsystem/music/proc/is_overloaded()
return events.len > global.musical_config.max_events

View File

@@ -292,3 +292,13 @@
containername = "big band musical instruments crate"
group = "Hospitality"
containsdesc = "One way around the strange space law is to just order the whole band. Contains one of every instrument."
/datum/supply_packs/synthesizer
contains = list(/obj/structure/synthesized_instrument/synthesizer)
name = "Synthesizer crate"
cost = 50
containertype = /obj/structure/closet/crate/basic
containername = "new age synthesizer crate"
containsdesc = "A new synthesizer has hit the market! Get it while it's still hot!"
group = "Hospitality"

View File

@@ -120,8 +120,13 @@
//to_chat(world, "beat: [beat] / beat length: [length(beat)]")
if(!length(beat)) //This occurs when a comma is at the end of a line
beat = " " //It's intended to be a space so here we make it a space
var/list/notes = splittext(beat, "/")
for(var/note in splittext(notes[1], "-"))
var/delta = length(notes)==2 && text2num(notes[2]) ? text2num(notes[2]) : 1
var/note_str = splittext(notes[1], "-")
var/duration = sanitize_tempo(src.tempo/delta)
for(var/note in note_str)
//to_chat(world, "note: [note]")
if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case
playing = 0
@@ -146,10 +151,11 @@
if (ui)
ui.send_message("activeChord", list2params(list(lineCount, chordCount)))
//nanomanager.send_message(src, instrumentObj.name, "activeChord", list(lineCount, chordCount))
if(notes.len >= 2 && text2num(notes[2]))
/*if(notes.len >= 2 && text2num(notes[2]))
sleep(sanitize_tempo(tempo / text2num(notes[2])))
else
sleep(tempo)
sleep(tempo)*/
sleep(duration)
chordCount++
lineCount++

View File

@@ -0,0 +1,17 @@
This module uses 4 components:
Real instruments -- the physical manifestation of the instrument, the one that is placed in the world
Virtual instruments -- the definition of an instrument, that is, what samples it uses, name and category
Sound player -- used to apply modification to all sounds emitted. Represents the actual source of sound
Synthesized Song - just like /datum/song it's what parses and plays a melody
---
Real instruments inherit from either /obj/structure/synthesized_instrument (static musical instrument) or /obj/item/device/synthesized_instrument (handheld musical instrument)
---
Virtual instruments all inherit from /datum/instrument.
Virtual instruments should follow this structure: /datum/instrument/category_name/instrument_name.
Refer to any file in ./instrument_data to see how it's done.
---
Sound player inherits from /datum/sound_player
---
For synthesized song only use /datum/synthesized_song
---

View File

@@ -0,0 +1,42 @@
/datum/musical_event
var/sound/object
var/mob/subject
var/datum/sound_player/source
var/time = 0
var/new_volume = 100
/datum/musical_event/New(datum/sound_player/source_, mob/subject_, sound/object_, time_, volume_)
source = source_
subject = subject_
object = object_
time = time_
new_volume = volume_
/datum/musical_event/proc/tick()
if (!(istype(object) && istype(subject) && istype(source)))
return
if (new_volume > 0)
update_sound()
else
destroy_sound()
/datum/musical_event/proc/update_sound()
object.volume = new_volume
object.status |= SOUND_UPDATE
if (subject)
subject << object
/datum/musical_event/proc/destroy_sound()
if (subject)
var/sound/null_sound = sound(channel=object.channel, wait=0)
if (global.musical_config.env_settings_available)
null_sound.environment = -1
subject << null_sound
if (source || source.song)
source.song.free_channel(object.channel)

View File

@@ -0,0 +1,244 @@
var/global/datum/musical_config/musical_config = new
/datum/musical_config
var/highest_octave = 9
var/lowest_octave = 0
var/highest_transposition = 4
var/lowest_transposition = -4
var/longest_sustain_timer = 50
var/gentlest_drop = 1.07
var/steepest_drop = 10.0
var/channels_per_instrument = 128
var/max_lines = 1000
var/max_line_length = 100
var/max_events = 2400
var/song_editor_lines_per_page = 20
var/usage_info_channel_resolution = 1
var/usage_info_event_resolution = 8
var/env_settings_available = 0
// Keep disabled until I figure out how to preserve environment settings
var/list/env_default = list(7.5, 1.0, -1000, -100, 0, 1.49, 0.83, 1.0, -2602, 0.0007, 200, 0.011, 0.25, 0.0, 0.25, 0.0, -5.0, 5000, 250.0, 0.0, 100, 100, 63)
var/list/list/env_params_bounds = list(
list(1, 100, 1),
list(0, 1, 1),
list(-10000, 0, 1),
list(-10000, 0, 1),
list(-10000, 0, 1),
list(0.1, 20, 1),
list(0.1, 2.0, 1),
list(0.1, 2.0, 1),
list(-10000, 1000, 0),
list(0, 0.3, 1),
list(-10000, 2000, 0),
list(0, 0.1, 1),
list(0.075, 0.25, 1),
list(0, 1, 1),
list(0.04, 4.0, 1),
list(0, 1, 1),
list(-100, 0.0, 1),
list(1000, 20000, 0),
list(20, 1000, 1),
list(0, 10, 1),
list(0, 100, 1),
list(0, 100, 1),
list(0, 256, 0))
var/list/all_environments = list(
"None",
"Generic",
"Padded cell",
"Room",
"Bathroom",
"Living Room",
"Stone Room",
"Auditorium",
"Concert Hall",
"Cave",
"Arena",
"Hangar",
"Carpetted Hallway",
"Hallway",
"Stone Coridor",
"Alley",
"Forest",
"City",
"Mountains",
"Quarry",
"Plain",
"Parking Lot",
"Sewer Pipe",
"Underwater",
"Drugged",
"Dizzy",
"Psychotic",
"Custom")
var/list/env_param_names = list(
"Env. Size",
"Env. Diff.",
"Room",
"Room (High Frequency)",
"Room (Low Frequency)",
"Decay Time",
"Decay (High Frequency Ratio)",
"Decay (Low Frequency Ratio)",
"Reflections",
"Reflections Delay",
"Reverb",
"Reverb Delay",
"Echo Time",
"Echo Depth",
"Modulation Time",
"Modulation Depth",
"Air Absorption (High Frequency)",
"High Frequency Reference",
"Low Frequency Reference",
"Room Rolloff Factor",
"Diffusion",
"Density",
"Flags")
var/list/env_param_desc = list(
"environment size in meters",
"environment diffusion",
"room effect level (at mid frequencies)",
"relative room effect level at high frequencies",
"relative room effect level at low frequencies",
"reverberation decay time at mid frequencies",
"high-frequency to mid-frequency decay time ratio",
"low-frequency to mid-frequency decay time ratio",
"early reflections level relative to room effect",
"initial reflection delay time",
"late reverberation level relative to room effect",
"late reverberation delay time relative to initial reflection",
"echo time",
"echo depth",
"modulation time",
"modulation depth",
"change in level per meter at high frequencies",
"reference high frequency (hz)",
"reference low frequency (hz)",
"like rolloffscale in System::set3DSettings but for reverb room size effect",
"Value that controls the echo density in the late reverberation decay.",
"Value that controls the modal density in the late reverberation decay",
{"
Bit flags that modify the behavior of above properties
•1 - 'EnvSize' affects reverberation decay time
•2 - 'EnvSize' affects reflection level
•4 - 'EnvSize' affects initial reflection delay time
•8 - 'EnvSize' affects reflections level
•16 - 'EnvSize' affects late reverberation delay time
•32 - AirAbsorptionHF affects DecayHFRatio
•64 - 'EnvSize' affects echo time
•128 - 'EnvSize' affects modulation time"})
var/list/echo_default = list(0, 0, 0, 0, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 7)
var/list/list/echo_params_bounds = list(
list(-10000, 1000, 0),
list(-10000, 0, 0),
list(-10000, 1000, 0),
list(-10000, 0, 0),
list(-10000, 0, 0),
list(0, 1, 1),
list(-10000, 0, 0),
list(0, 1, 1),
list(0, 10, 1),
list(0, 10, 1),
list(-10000, 0, 0),
list(0, 1, 1),
list(-10000, 0, 0),
list(0, 10, 1),
list(0, 10, 1),
list(0, 10, 1),
list(0, 10, 1),
list(0, 16, 0))
var/list/echo_param_names = list(
"Direct",
"Direct (High Frequency)",
"Room",
"Room (High Frequency)",
"Obstruction",
"Obstruction (Low Frequency Ratio)",
"Occlusion",
"Occlusion (Low Frequency Ratio)",
"Occlusion (Room Ratio)",
"Occlusion (Direct Ratio)",
"Exclusion",
"Exclusion (Low Frequency Ratio)",
"Outside Volume (High Frequency)",
"Doppler Factor",
"Rolloff Factor",
"Room Rolloff Factor",
"Air Absorption Factor",
"Flags")
var/list/echo_param_desc = list(
"direct path level (at low and mid frequencies)",
"relative direct path level at high frequencies ",
"room effect level (at low and mid frequencies)",
"relative room effect level at high frequencies",
"main obstruction control (attenuation at high frequencies)",
"obstruction low-frequency level re. main control",
"main occlusion control (attenuation at high frequencies)",
"occlusion low-frequency level re. main control",
"relative occlusion control for room effect",
"relative occlusion control for direct path",
"main exlusion control (attenuation at high frequencies)",
"exclusion low-frequency level re. main control",
"outside sound cone level at high frequencies",
"like DS3D flDopplerFactor but per source",
"like DS3D flRolloffFactor but per source",
"like DS3D flRolloffFactor but for room effect",
"multiplies AirAbsorptionHF member of environment reverb properties.",
{"
Bit flags that modify the behavior of properties•1 - Automatic setting of 'Direct' due to distance from listener
•2 - Automatic setting of 'Room' due to distance from listener
•4 - Automatic setting of 'RoomHF' due to distance from listener"})
var/list/n2t_int = list() // Instead of num2text it is used for faster access in n2t
var/list/free_channels = list() // Used to take up some channels and avoid istruments cancelling each other
var/free_channels_populated = 0
var/list/nn2no = list(0,2,4,5,7,9,11) // Maps note num onto note offset
/datum/musical_config/proc/n2t(key) // Used instead of num2text for faster access in sample_map
if (!n2t_int.len)
for (var/i=1, i<=127, i++)
n2t_int += num2text(i)
if (key==0)
return "0" // Fuck you BYOND
if (!isnum(key) || key < 0 || key>127 || round(key) != key)
CRASH("n2t argument must be an integer from 0 to 127")
return n2t_int[key]
/datum/musical_config/proc/environment_to_id(environment)
if (environment in all_environments)
return all_environments.Find(environment) - 2
return -1
/datum/musical_config/proc/id_to_environment(id)
if (id >= -1 && id <= 26)
return all_environments[id+2]
return "None"
/datum/musical_config/proc/index_to_id(index)
return max(min(index-2, 26), -1)
/datum/musical_config/proc/is_custom_env(id)
return id_to_environment(id) == all_environments[28]
/datum/sample_pair
var/sample
var/deviation = 0
/datum/sample_pair/New(sample_file, deviation_)
sample = sample_file
deviation = deviation_

View File

@@ -0,0 +1,39 @@
/datum/instrument
var/name = "Generic instrument" // Name of the instrument
var/id = null // Used everywhere to distinguish between categories and actual data and to identify instruments
var/category = null // Used to categorize instruments
var/list/samples = list() // Write here however many samples, follow this syntax: "%note num%"='%sample file%' eg. "27"='synthesizer/e2.ogg'. Key must never be lower than 0 and higher than 127
var/list/datum/sample_pair/sample_map = list() // Used to modulate sounds, don't fill yourself
/datum/instrument/proc/create_full_sample_deviation_map()
// Obtain samples
if (!samples.len)
CRASH("No samples were defined in [type]")
var/list/delta_1 = list()
for (var/key in samples)
delta_1 += text2num(key)
sortTim(delta_1, associative=0)
for (var/indx1=1 to delta_1.len-1)
var/from_key = delta_1[indx1]
var/to_key = delta_1[indx1+1]
var/sample1 = samples[global.musical_config.n2t(from_key)]
var/sample2 = samples[global.musical_config.n2t(to_key)]
var/pivot = round((from_key+to_key)/2)
for (var/key = from_key to pivot)
sample_map[global.musical_config.n2t(key)] = new /datum/sample_pair(sample1, key-from_key) // [55+56] / 2 -> 55.5 -> 55 so no changes will occur
for (var/key = pivot+1 to to_key)
sample_map[global.musical_config.n2t(key)] = new /datum/sample_pair(sample2, key-to_key)
// Fill in 0 -- first key and last key -- 127
var/first_key = delta_1[1]
var/last_key = delta_1[delta_1.len]
var/first_sample = samples[global.musical_config.n2t(first_key)]
var/last_sample = samples[global.musical_config.n2t(last_key)]
for (var/key=0 to first_key-1)
sample_map[global.musical_config.n2t(key)] = new /datum/sample_pair(first_sample, key-first_key)
for (var/key=last_key to 127)
sample_map[global.musical_config.n2t(key)] = new /datum/sample_pair(last_sample, key-last_key)
return samples

View File

@@ -0,0 +1,28 @@
/datum/instrument/brass
name = "Generic brass instrument"
category = "Brass"
/datum/instrument/brass/crisis_section
name = "Crisis Brass Section"
id = "crbrass"
samples = list("36"='code/modules/bayinstruments/samples/brass/crisis_brass/c2.ogg',
"48"='code/modules/bayinstruments/samples/brass/crisis_brass/c3.ogg',
"60"='code/modules/bayinstruments/samples/brass/crisis_brass/c4.ogg',
"72"='code/modules/bayinstruments/samples/brass/crisis_brass/c5.ogg')
/datum/instrument/brass/crisis_trombone
name = "Crisis Trombone"
id = "crtrombone"
samples = list("36"='code/modules/bayinstruments/samples/brass/crisis_trombone/c2.ogg',
"48"='code/modules/bayinstruments/samples/brass/crisis_trombone/c3.ogg',
"60"='code/modules/bayinstruments/samples/brass/crisis_trombone/c4.ogg',
"72"='code/modules/bayinstruments/samples/brass/crisis_trombone/c5.ogg')
/datum/instrument/brass/crisis_trumpet
name = "Crisis Trumpet"
id = "crtrumpet"
samples = list("60"='code/modules/bayinstruments/samples/brass/crisis_trumpet/c4.ogg',
"72"='code/modules/bayinstruments/samples/brass/crisis_trumpet/c5.ogg')

View File

@@ -0,0 +1,33 @@
/datum/instrument/chromatic
name = "Generic chromatic percussion instrument"
category = "Chromatic percussion"
/datum/instrument/chromatic/vibraphone1
name = "Crisis Vibraphone"
id = "crvibr"
samples = list("36"='code/modules/bayinstruments/samples/chromatic/vibraphone1/c2.ogg',
"48"='code/modules/bayinstruments/samples/chromatic/vibraphone1/c3.ogg',
"60"='code/modules/bayinstruments/samples/chromatic/vibraphone1/c4.ogg',
"72"='code/modules/bayinstruments/samples/chromatic/vibraphone1/c5.ogg')
/datum/instrument/chromatic/musicbox1
name = "SGM Music Box"
id = "sgmmbox"
samples = list("36"='code/modules/bayinstruments/samples/chromatic/sgmbox/c2.ogg',
"48"='code/modules/bayinstruments/samples/chromatic/sgmbox/c3.ogg',
"60"='code/modules/bayinstruments/samples/chromatic/sgmbox/c4.ogg',
"72"='code/modules/bayinstruments/samples/chromatic/sgmbox/c5.ogg')
/datum/instrument/chromatic/fluid_celeste
name = "FluidR3 Celeste"
id = "r3celeste"
samples = list("36"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c2.ogg',
"48"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c3.ogg',
"60"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c4.ogg',
"72"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c5.ogg',
"84"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c6.ogg',
"96"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c7.ogg',
"108"='code/modules/bayinstruments/samples/chromatic/fluid_celeste/c8.ogg')

View File

@@ -0,0 +1,21 @@
/datum/instrument/fun
name = "Generic Fun Instrument"
category = "Fun"
/datum/instrument/fun/honk
name = "!!HONK!!"
id = "honk"
samples = list("74"='sound/items/bikehorn.ogg') // Cluwne Heaven
/datum/instrument/fun/signal
name = "Ping"
id = "ping"
samples = list("79"='sound/machines/ping.ogg')
/datum/instrument/fun/chime
name = "Chime"
id = "chime"
samples = list("79"='sound/machines/chime.ogg')

View File

@@ -0,0 +1,39 @@
/datum/instrument/guitar
name = "Generic guitar-like instrument"
category = "Guitar"
/datum/instrument/guitar/steel_crisis
name = "Crisis Steel String Guitar"
id = "csteelgt"
samples = list("36"='code/modules/bayinstruments/samples/guitar/crisis_steel/c2.ogg',
"48"='code/modules/bayinstruments/samples/guitar/crisis_steel/c3.ogg',
"60"='code/modules/bayinstruments/samples/guitar/crisis_steel/c4.ogg',
"72"='code/modules/bayinstruments/samples/guitar/crisis_steel/c5.ogg')
/datum/instrument/guitar/nylon_crisis
name = "Crisis Nylon String Guitar"
id = "cnylongt"
samples = list("36"='code/modules/bayinstruments/samples/guitar/crisis_nylon/c2.ogg',
"48"='code/modules/bayinstruments/samples/guitar/crisis_nylon/c3.ogg',
"60"='code/modules/bayinstruments/samples/guitar/crisis_nylon/c4.ogg',
"72"='code/modules/bayinstruments/samples/guitar/crisis_nylon/c5.ogg')
/datum/instrument/guitar/clean_crisis
name = "Crisis Clean Guitar"
id = "ccleangt"
samples = list("36"='code/modules/bayinstruments/samples/guitar/crisis_clean/c2.ogg',
"48"='code/modules/bayinstruments/samples/guitar/crisis_clean/c3.ogg',
"60"='code/modules/bayinstruments/samples/guitar/crisis_clean/c4.ogg',
"72"='code/modules/bayinstruments/samples/guitar/crisis_clean/c5.ogg')
/datum/instrument/guitar/muted_crisis
name = "Crisis Muted Guitar"
id = "cmutedgt"
samples = list("36"='code/modules/bayinstruments/samples/guitar/crisis_muted/c2.ogg',
"48"='code/modules/bayinstruments/samples/guitar/crisis_muted/c3.ogg',
"60"='code/modules/bayinstruments/samples/guitar/crisis_muted/c4.ogg',
"72"='code/modules/bayinstruments/samples/guitar/crisis_muted/c5.ogg')

View File

@@ -0,0 +1,21 @@
/datum/instrument/tones
name = "Ideal tone"
category = "Tones"
/datum/instrument/tones/square_wave
name = "Ideal square wave"
id = "square"
samples = list("81"='code/modules/bayinstruments/samples/tones/Square.ogg')
/datum/instrument/tones/sine_wave
name = "Ideal sine wave"
id = "sine"
samples = list("81"='code/modules/bayinstruments/samples/tones/Sine.ogg')
/datum/instrument/tones/saw_wave
name = "Ideal sawtooth wave"
id = "saw"
samples = list("81"='code/modules/bayinstruments/samples/tones/Sawtooth.ogg')

View File

@@ -0,0 +1,207 @@
/datum/instrument/obsolete
name="Non-synthesized sounds"
category="Prerecorded"
/datum/instrument/obsolete/piano
name="Piano"
id="ss13piano"
samples=list(\
"12"='code/modules/bayinstruments/samples/obsolete/piano/Cn1.ogg',\
"13"='code/modules/bayinstruments/samples/obsolete/piano/C#1.ogg',\
"14"='code/modules/bayinstruments/samples/obsolete/piano/Dn1.ogg',\
"15"='code/modules/bayinstruments/samples/obsolete/piano/D#1.ogg',\
"16"='code/modules/bayinstruments/samples/obsolete/piano/En1.ogg',\
"17"='code/modules/bayinstruments/samples/obsolete/piano/Fn1.ogg',\
"18"='code/modules/bayinstruments/samples/obsolete/piano/F#1.ogg',\
"19"='code/modules/bayinstruments/samples/obsolete/piano/Gn1.ogg',\
"20"='code/modules/bayinstruments/samples/obsolete/piano/G#1.ogg',\
"21"='code/modules/bayinstruments/samples/obsolete/piano/An1.ogg',\
"22"='code/modules/bayinstruments/samples/obsolete/piano/A#1.ogg',\
"23"='code/modules/bayinstruments/samples/obsolete/piano/Bn1.ogg',\
"24"='code/modules/bayinstruments/samples/obsolete/piano/Cn2.ogg',\
"25"='code/modules/bayinstruments/samples/obsolete/piano/C#2.ogg',\
"26"='code/modules/bayinstruments/samples/obsolete/piano/Dn2.ogg',\
"27"='code/modules/bayinstruments/samples/obsolete/piano/D#2.ogg',\
"28"='code/modules/bayinstruments/samples/obsolete/piano/En2.ogg',\
"29"='code/modules/bayinstruments/samples/obsolete/piano/Fn2.ogg',\
"30"='code/modules/bayinstruments/samples/obsolete/piano/F#2.ogg',\
"31"='code/modules/bayinstruments/samples/obsolete/piano/Gn2.ogg',\
"32"='code/modules/bayinstruments/samples/obsolete/piano/G#2.ogg',\
"33"='code/modules/bayinstruments/samples/obsolete/piano/An2.ogg',\
"34"='code/modules/bayinstruments/samples/obsolete/piano/A#2.ogg',\
"35"='code/modules/bayinstruments/samples/obsolete/piano/Bn2.ogg',\
"36"='code/modules/bayinstruments/samples/obsolete/piano/Cn3.ogg',\
"37"='code/modules/bayinstruments/samples/obsolete/piano/C#3.ogg',\
"38"='code/modules/bayinstruments/samples/obsolete/piano/Dn3.ogg',\
"39"='code/modules/bayinstruments/samples/obsolete/piano/D#3.ogg',\
"40"='code/modules/bayinstruments/samples/obsolete/piano/En3.ogg',\
"41"='code/modules/bayinstruments/samples/obsolete/piano/Fn3.ogg',\
"42"='code/modules/bayinstruments/samples/obsolete/piano/F#3.ogg',\
"43"='code/modules/bayinstruments/samples/obsolete/piano/Gn3.ogg',\
"44"='code/modules/bayinstruments/samples/obsolete/piano/G#3.ogg',\
"45"='code/modules/bayinstruments/samples/obsolete/piano/An3.ogg',\
"46"='code/modules/bayinstruments/samples/obsolete/piano/A#3.ogg',\
"47"='code/modules/bayinstruments/samples/obsolete/piano/Bn3.ogg',\
"48"='code/modules/bayinstruments/samples/obsolete/piano/Cn4.ogg',\
"49"='code/modules/bayinstruments/samples/obsolete/piano/C#4.ogg',\
"50"='code/modules/bayinstruments/samples/obsolete/piano/Dn4.ogg',\
"51"='code/modules/bayinstruments/samples/obsolete/piano/D#4.ogg',\
"52"='code/modules/bayinstruments/samples/obsolete/piano/En4.ogg',\
"53"='code/modules/bayinstruments/samples/obsolete/piano/Fn4.ogg',\
"54"='code/modules/bayinstruments/samples/obsolete/piano/F#4.ogg',\
"55"='code/modules/bayinstruments/samples/obsolete/piano/Gn4.ogg',\
"56"='code/modules/bayinstruments/samples/obsolete/piano/G#4.ogg',\
"57"='code/modules/bayinstruments/samples/obsolete/piano/An4.ogg',\
"58"='code/modules/bayinstruments/samples/obsolete/piano/A#4.ogg',\
"59"='code/modules/bayinstruments/samples/obsolete/piano/Bn4.ogg',\
"60"='code/modules/bayinstruments/samples/obsolete/piano/Cn5.ogg',\
"61"='code/modules/bayinstruments/samples/obsolete/piano/C#5.ogg',\
"62"='code/modules/bayinstruments/samples/obsolete/piano/Dn5.ogg',\
"63"='code/modules/bayinstruments/samples/obsolete/piano/D#5.ogg',\
"64"='code/modules/bayinstruments/samples/obsolete/piano/En5.ogg',\
"65"='code/modules/bayinstruments/samples/obsolete/piano/Fn5.ogg',\
"66"='code/modules/bayinstruments/samples/obsolete/piano/F#5.ogg',\
"67"='code/modules/bayinstruments/samples/obsolete/piano/Gn5.ogg',\
"68"='code/modules/bayinstruments/samples/obsolete/piano/G#5.ogg',\
"69"='code/modules/bayinstruments/samples/obsolete/piano/An5.ogg',\
"70"='code/modules/bayinstruments/samples/obsolete/piano/A#5.ogg',\
"71"='code/modules/bayinstruments/samples/obsolete/piano/Bn5.ogg',\
"72"='code/modules/bayinstruments/samples/obsolete/piano/Cn6.ogg',\
"73"='code/modules/bayinstruments/samples/obsolete/piano/C#6.ogg',\
"74"='code/modules/bayinstruments/samples/obsolete/piano/Dn6.ogg',\
"75"='code/modules/bayinstruments/samples/obsolete/piano/D#6.ogg',\
"76"='code/modules/bayinstruments/samples/obsolete/piano/En6.ogg',\
"77"='code/modules/bayinstruments/samples/obsolete/piano/Fn6.ogg',\
"78"='code/modules/bayinstruments/samples/obsolete/piano/F#6.ogg',\
"79"='code/modules/bayinstruments/samples/obsolete/piano/Gn6.ogg',\
"80"='code/modules/bayinstruments/samples/obsolete/piano/G#6.ogg',\
"81"='code/modules/bayinstruments/samples/obsolete/piano/An6.ogg',\
"82"='code/modules/bayinstruments/samples/obsolete/piano/A#6.ogg',\
"83"='code/modules/bayinstruments/samples/obsolete/piano/Bn6.ogg',\
"84"='code/modules/bayinstruments/samples/obsolete/piano/Cn7.ogg',\
"85"='code/modules/bayinstruments/samples/obsolete/piano/C#7.ogg',\
"86"='code/modules/bayinstruments/samples/obsolete/piano/Dn7.ogg',\
"87"='code/modules/bayinstruments/samples/obsolete/piano/D#7.ogg',\
"88"='code/modules/bayinstruments/samples/obsolete/piano/En7.ogg',\
"89"='code/modules/bayinstruments/samples/obsolete/piano/Fn7.ogg',\
"90"='code/modules/bayinstruments/samples/obsolete/piano/F#7.ogg',\
"91"='code/modules/bayinstruments/samples/obsolete/piano/Gn7.ogg',\
"92"='code/modules/bayinstruments/samples/obsolete/piano/G#7.ogg',\
"93"='code/modules/bayinstruments/samples/obsolete/piano/An7.ogg',\
"94"='code/modules/bayinstruments/samples/obsolete/piano/A#7.ogg',\
"95"='code/modules/bayinstruments/samples/obsolete/piano/Bn7.ogg',\
"96"='code/modules/bayinstruments/samples/obsolete/piano/Cn8.ogg',\
"97"='code/modules/bayinstruments/samples/obsolete/piano/C#8.ogg',\
"98"='code/modules/bayinstruments/samples/obsolete/piano/Dn8.ogg',\
"99"='code/modules/bayinstruments/samples/obsolete/piano/D#8.ogg',\
"100"='code/modules/bayinstruments/samples/obsolete/piano/En8.ogg',\
"101"='code/modules/bayinstruments/samples/obsolete/piano/Fn8.ogg',\
"102"='code/modules/bayinstruments/samples/obsolete/piano/F#8.ogg',\
"103"='code/modules/bayinstruments/samples/obsolete/piano/Gn8.ogg',\
"104"='code/modules/bayinstruments/samples/obsolete/piano/G#8.ogg',\
"105"='code/modules/bayinstruments/samples/obsolete/piano/An8.ogg',\
"106"='code/modules/bayinstruments/samples/obsolete/piano/A#8.ogg',\
"107"='code/modules/bayinstruments/samples/obsolete/piano/Bn8.ogg')
/datum/instrument/obsolete/violin
name = "Violin"
id = "ss13violin"
samples=list(\
"12"='code/modules/bayinstruments/samples/obsolete/violin/Cn1.mid',\
"13"='code/modules/bayinstruments/samples/obsolete/violin/C#1.mid',\
"14"='code/modules/bayinstruments/samples/obsolete/violin/Dn1.mid',\
"15"='code/modules/bayinstruments/samples/obsolete/violin/D#1.mid',\
"16"='code/modules/bayinstruments/samples/obsolete/violin/En1.mid',\
"17"='code/modules/bayinstruments/samples/obsolete/violin/Fn1.mid',\
"18"='code/modules/bayinstruments/samples/obsolete/violin/F#1.mid',\
"19"='code/modules/bayinstruments/samples/obsolete/violin/Gn1.mid',\
"20"='code/modules/bayinstruments/samples/obsolete/violin/G#1.mid',\
"21"='code/modules/bayinstruments/samples/obsolete/violin/An1.mid',\
"22"='code/modules/bayinstruments/samples/obsolete/violin/A#1.mid',\
"23"='code/modules/bayinstruments/samples/obsolete/violin/Bn1.mid',\
"24"='code/modules/bayinstruments/samples/obsolete/violin/Cn2.mid',\
"25"='code/modules/bayinstruments/samples/obsolete/violin/C#2.mid',\
"26"='code/modules/bayinstruments/samples/obsolete/violin/Dn2.mid',\
"27"='code/modules/bayinstruments/samples/obsolete/violin/D#2.mid',\
"28"='code/modules/bayinstruments/samples/obsolete/violin/En2.mid',\
"29"='code/modules/bayinstruments/samples/obsolete/violin/Fn2.mid',\
"30"='code/modules/bayinstruments/samples/obsolete/violin/F#2.mid',\
"31"='code/modules/bayinstruments/samples/obsolete/violin/Gn2.mid',\
"32"='code/modules/bayinstruments/samples/obsolete/violin/G#2.mid',\
"33"='code/modules/bayinstruments/samples/obsolete/violin/An2.mid',\
"34"='code/modules/bayinstruments/samples/obsolete/violin/A#2.mid',\
"35"='code/modules/bayinstruments/samples/obsolete/violin/Bn2.mid',\
"36"='code/modules/bayinstruments/samples/obsolete/violin/Cn3.mid',\
"37"='code/modules/bayinstruments/samples/obsolete/violin/C#3.mid',\
"38"='code/modules/bayinstruments/samples/obsolete/violin/Dn3.mid',\
"39"='code/modules/bayinstruments/samples/obsolete/violin/D#3.mid',\
"40"='code/modules/bayinstruments/samples/obsolete/violin/En3.mid',\
"41"='code/modules/bayinstruments/samples/obsolete/violin/Fn3.mid',\
"42"='code/modules/bayinstruments/samples/obsolete/violin/F#3.mid',\
"43"='code/modules/bayinstruments/samples/obsolete/violin/Gn3.mid',\
"44"='code/modules/bayinstruments/samples/obsolete/violin/G#3.mid',\
"45"='code/modules/bayinstruments/samples/obsolete/violin/An3.mid',\
"46"='code/modules/bayinstruments/samples/obsolete/violin/A#3.mid',\
"47"='code/modules/bayinstruments/samples/obsolete/violin/Bn3.mid',\
"48"='code/modules/bayinstruments/samples/obsolete/violin/Cn4.mid',\
"49"='code/modules/bayinstruments/samples/obsolete/violin/C#4.mid',\
"50"='code/modules/bayinstruments/samples/obsolete/violin/Dn4.mid',\
"51"='code/modules/bayinstruments/samples/obsolete/violin/D#4.mid',\
"52"='code/modules/bayinstruments/samples/obsolete/violin/En4.mid',\
"53"='code/modules/bayinstruments/samples/obsolete/violin/Fn4.mid',\
"54"='code/modules/bayinstruments/samples/obsolete/violin/F#4.mid',\
"55"='code/modules/bayinstruments/samples/obsolete/violin/Gn4.mid',\
"56"='code/modules/bayinstruments/samples/obsolete/violin/G#4.mid',\
"57"='code/modules/bayinstruments/samples/obsolete/violin/An4.mid',\
"58"='code/modules/bayinstruments/samples/obsolete/violin/A#4.mid',\
"59"='code/modules/bayinstruments/samples/obsolete/violin/Bn4.mid',\
"60"='code/modules/bayinstruments/samples/obsolete/violin/Cn5.mid',\
"61"='code/modules/bayinstruments/samples/obsolete/violin/C#5.mid',\
"62"='code/modules/bayinstruments/samples/obsolete/violin/Dn5.mid',\
"63"='code/modules/bayinstruments/samples/obsolete/violin/D#5.mid',\
"64"='code/modules/bayinstruments/samples/obsolete/violin/En5.mid',\
"65"='code/modules/bayinstruments/samples/obsolete/violin/Fn5.mid',\
"66"='code/modules/bayinstruments/samples/obsolete/violin/F#5.mid',\
"67"='code/modules/bayinstruments/samples/obsolete/violin/Gn5.mid',\
"68"='code/modules/bayinstruments/samples/obsolete/violin/G#5.mid',\
"69"='code/modules/bayinstruments/samples/obsolete/violin/An5.mid',\
"70"='code/modules/bayinstruments/samples/obsolete/violin/A#5.mid',\
"71"='code/modules/bayinstruments/samples/obsolete/violin/Bn5.mid',\
"72"='code/modules/bayinstruments/samples/obsolete/violin/Cn6.mid',\
"73"='code/modules/bayinstruments/samples/obsolete/violin/C#6.mid',\
"74"='code/modules/bayinstruments/samples/obsolete/violin/Dn6.mid',\
"75"='code/modules/bayinstruments/samples/obsolete/violin/D#6.mid',\
"76"='code/modules/bayinstruments/samples/obsolete/violin/En6.mid',\
"77"='code/modules/bayinstruments/samples/obsolete/violin/Fn6.mid',\
"78"='code/modules/bayinstruments/samples/obsolete/violin/F#6.mid',\
"79"='code/modules/bayinstruments/samples/obsolete/violin/Gn6.mid',\
"80"='code/modules/bayinstruments/samples/obsolete/violin/G#6.mid',\
"81"='code/modules/bayinstruments/samples/obsolete/violin/An6.mid',\
"82"='code/modules/bayinstruments/samples/obsolete/violin/A#6.mid',\
"83"='code/modules/bayinstruments/samples/obsolete/violin/Bn6.mid',\
"84"='code/modules/bayinstruments/samples/obsolete/violin/Cn7.mid',\
"85"='code/modules/bayinstruments/samples/obsolete/violin/C#7.mid',\
"86"='code/modules/bayinstruments/samples/obsolete/violin/Dn7.mid',\
"87"='code/modules/bayinstruments/samples/obsolete/violin/D#7.mid',\
"88"='code/modules/bayinstruments/samples/obsolete/violin/En7.mid',\
"89"='code/modules/bayinstruments/samples/obsolete/violin/Fn7.mid',\
"90"='code/modules/bayinstruments/samples/obsolete/violin/F#7.mid',\
"91"='code/modules/bayinstruments/samples/obsolete/violin/Gn7.mid',\
"92"='code/modules/bayinstruments/samples/obsolete/violin/G#7.mid',\
"93"='code/modules/bayinstruments/samples/obsolete/violin/An7.mid',\
"94"='code/modules/bayinstruments/samples/obsolete/violin/A#7.mid',\
"95"='code/modules/bayinstruments/samples/obsolete/violin/Bn7.mid',\
"96"='code/modules/bayinstruments/samples/obsolete/violin/Cn8.mid',\
"97"='code/modules/bayinstruments/samples/obsolete/violin/C#8.mid',\
"98"='code/modules/bayinstruments/samples/obsolete/violin/Dn8.mid',\
"99"='code/modules/bayinstruments/samples/obsolete/violin/D#8.mid',\
"100"='code/modules/bayinstruments/samples/obsolete/violin/En8.mid',\
"101"='code/modules/bayinstruments/samples/obsolete/violin/Fn8.mid',\
"102"='code/modules/bayinstruments/samples/obsolete/violin/F#8.mid',\
"103"='code/modules/bayinstruments/samples/obsolete/violin/Gn8.mid',\
"104"='code/modules/bayinstruments/samples/obsolete/violin/G#8.mid',\
"105"='code/modules/bayinstruments/samples/obsolete/violin/An8.mid',\
"106"='code/modules/bayinstruments/samples/obsolete/violin/A#8.mid',\
"107"='code/modules/bayinstruments/samples/obsolete/violin/Bn8.mid')

View File

@@ -0,0 +1,47 @@
/datum/instrument/organ
name = "Generic organ"
category = "Organ"
/datum/instrument/organ/crisis_church
name = "Crisis Church Organ"
id = "crichugan"
samples = list("36"='code/modules/bayinstruments/samples/organ/crisis_church/c2.ogg',
"48"='code/modules/bayinstruments/samples/organ/crisis_church/c3.ogg',
"60"='code/modules/bayinstruments/samples/organ/crisis_church/c4.ogg',
"72"='code/modules/bayinstruments/samples/organ/crisis_church/c5.ogg')
/datum/instrument/organ/crisis_hammond
name = "Crisis Hammond Organ"
id = "crihamgan"
samples = list("36"='code/modules/bayinstruments/samples/organ/crisis_hammond/c2.ogg',
"48"='code/modules/bayinstruments/samples/organ/crisis_hammond/c3.ogg',
"60"='code/modules/bayinstruments/samples/organ/crisis_hammond/c4.ogg',
"72"='code/modules/bayinstruments/samples/organ/crisis_hammond/c5.ogg')
/datum/instrument/organ/crisis_accordian
name = "Crisis Accordian"
id = "crack"
samples = list("36"='code/modules/bayinstruments/samples/organ/crisis_accordian/c2.ogg',
"48"='code/modules/bayinstruments/samples/organ/crisis_accordian/c3.ogg',
"60"='code/modules/bayinstruments/samples/organ/crisis_accordian/c4.ogg',
"72"='code/modules/bayinstruments/samples/organ/crisis_accordian/c5.ogg')
/datum/instrument/organ/crisis_harmonica
name = "Crisis Harmonica"
id = "crharmony"
samples = list("48"='code/modules/bayinstruments/samples/organ/crisis_harmonica/c3.ogg',
"60"='code/modules/bayinstruments/samples/organ/crisis_harmonica/c4.ogg',
"72"='code/modules/bayinstruments/samples/organ/crisis_harmonica/c5.ogg')
/datum/instrument/organ/crisis_tango_accordian
name = "Crisis Tango Accordian"
id = "crtango"
samples = list("36"='code/modules/bayinstruments/samples/organ/crisis_tangaccordian/c2.ogg',
"48"='code/modules/bayinstruments/samples/organ/crisis_tangaccordian/c3.ogg',
"60"='code/modules/bayinstruments/samples/organ/crisis_tangaccordian/c4.ogg',
"72"='code/modules/bayinstruments/samples/organ/crisis_tangaccordian/c5.ogg')

View File

@@ -0,0 +1,60 @@
/datum/instrument/piano
name = "Generic piano"
category = "Piano"
/datum/instrument/piano/fluid_piano
name = "FluidR3 Grand Piano"
id = "r3grand"
samples = list("36"='code/modules/bayinstruments/samples/piano/fluid_piano/c2.ogg',
"48"='code/modules/bayinstruments/samples/piano/fluid_piano/c3.ogg',
"60"='code/modules/bayinstruments/samples/piano/fluid_piano/c4.ogg',
"72"='code/modules/bayinstruments/samples/piano/fluid_piano/c5.ogg',
"84"='code/modules/bayinstruments/samples/piano/fluid_piano/c6.ogg',
"96"='code/modules/bayinstruments/samples/piano/fluid_piano/c7.ogg',
"108"='code/modules/bayinstruments/samples/piano/fluid_piano/c8.ogg')
/datum/instrument/piano/fluid_harpsichord
name = "FluidR3 Harpsichord"
id = "r3harpsi"
samples = list("36"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c2.ogg',
"48"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c3.ogg',
"60"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c4.ogg',
"72"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c5.ogg',
"84"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c6.ogg',
"96"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c7.ogg',
"108"='code/modules/bayinstruments/samples/piano/fluid_harpsi/c8.ogg')
/datum/instrument/piano/crisis_harpsichord
name = "Crisis Harpsichord"
id = "crharpsi"
samples = list("36"='code/modules/bayinstruments/samples/piano/crisis_harpsichord/c2.ogg',
"48"='code/modules/bayinstruments/samples/piano/crisis_harpsichord/c3.ogg',
"60"='code/modules/bayinstruments/samples/piano/crisis_harpsichord/c4.ogg',
"72"='code/modules/bayinstruments/samples/piano/crisis_harpsichord/c5.ogg')
/datum/instrument/piano/crisis_grandpiano_uni
name = "Crisis Grand Piano One"
id = "crgrand1"
samples = list("36"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c2.ogg',
"48"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c3.ogg',
"60"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c4.ogg',
"72"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c5.ogg',
"84"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c6.ogg',
"96"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c7.ogg',
"108"='code/modules/bayinstruments/samples/piano/crisis_grand_piano/c8.ogg')
/datum/instrument/piano/crisis_brightpiano_uni
name = "Crisis Bright Piano One"
id = "crbright1"
samples = list("36"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c2.ogg',
"48"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c3.ogg',
"60"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c4.ogg',
"72"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c5.ogg',
"84"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c6.ogg',
"96"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c7.ogg',
"108"='code/modules/bayinstruments/samples/piano/crisis_bright_piano/c8.ogg')

View File

@@ -0,0 +1,186 @@
/obj/structure/synthesized_instrument
var/datum/sound_player/player
var/datum/nano_module/song_editor/song_editor
var/datum/nano_module/usage_info/usage_info
var/maximum_lines
var/maximum_line_length
/obj/structure/synthesized_instrument/New()
..()
maximum_lines = global.musical_config.max_lines
maximum_line_length = global.musical_config.max_line_length
/obj/structure/synthesized_instrument/Destroy()
qdel(player)
..()
/obj/structure/synthesized_instrument/attack_hand(mob/user)
interact(user)
/obj/structure/synthesized_instrument/interact(mob/user) // CONDITIONS ..(user) that shit in subclasses
ui_interact(user)
/obj/structure/synthesized_instrument/ui_interact(mob/user)
return 0
/obj/structure/synthesized_instrument/proc/shouldStopPlaying(mob/user)
return 0
/obj/structure/synthesized_instrument/Topic(href, href_list)
if (..())
return 1
var/target = href_list["target"]
var/value = text2num(href_list["value"])
if (href_list["value"] && !isnum(value))
to_chat(usr, "Non-numeric value was given")
return 0
add_fingerprint(usr)
switch (target)
if ("tempo") player.song.tempo = player.song.sanitize_tempo(player.song.tempo + value*world.tick_lag)
if ("play")
player.song.playing = value
if (player.song.playing)
player.song.play_song(usr)
if ("newsong")
player.song.lines.Cut()
player.song.tempo = player.song.sanitize_tempo(5) // default 120 BPM
if ("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(length(t) >= 2*maximum_lines*maximum_line_length)
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(length(t) > 2*maximum_lines*maximum_line_length)
if (length(t))
player.song.lines = splittext(t, "\n")
if(copytext(player.song.lines[1],1,6) == "BPM: ")
if(text2num(copytext(player.song.lines[1],6)) != 0)
player.song.tempo = player.song.sanitize_tempo(600 / text2num(copytext(player.song.lines[1],6)))
player.song.lines.Cut(1,2)
else
player.song.tempo = player.song.sanitize_tempo(5)
else
player.song.tempo = player.song.sanitize_tempo(5) // default 120 BPM
if(player.song.lines.len > maximum_lines)
to_chat(usr,"Too many lines!")
player.song.lines.Cut(maximum_lines+1)
var/linenum = 1
for(var/l in player.song.lines)
if(length(l) > maximum_line_length)
to_chat(usr, "Line [linenum] too long!")
player.song.lines.Remove(l)
else
linenum++
else
return 0
return 1
/obj/item/device/synthesized_instrument
var/datum/sound_player/player
var/datum/nano_module/song_editor/song_editor
var/datum/nano_module/usage_info/usage_info
var/maximum_lines
var/maximum_line_length
/obj/item/device/synthesized_instrument/New()
..()
maximum_lines = global.musical_config.max_lines
maximum_line_length = global.musical_config.max_line_length
/obj/item/device/synthesized_instrument/Destroy()
qdel(player)
..()
/obj/item/device/synthesized_instrument/attack_hand(mob/user)
interact(user)
/obj/item/device/synthesized_instrument/interact(mob/user) // CONDITIONS ..(user) that shit in subclasses
ui_interact(user)
/obj/item/device/synthesized_instrument/ui_interact(mob/user)
return 0
/obj/item/device/synthesized_instrument/proc/shouldStopPlaying(mob/user)
return 0
/obj/item/device/synthesized_instrument/Topic(href, href_list)
if (..())
return 1
var/target = href_list["target"]
var/value = text2num(href_list["value"])
if (href_list["value"] && !isnum(value))
to_chat(usr, "Non-numeric value was given")
return 0
add_fingerprint(usr)
switch (target)
if ("tempo") player.song.tempo = player.song.sanitize_tempo(player.song.tempo + value*world.tick_lag)
if ("play")
player.song.playing = value
if (player.song.playing)
player.song.play_song(usr)
if ("newsong")
player.song.lines.Cut()
player.song.tempo = player.song.sanitize_tempo(5) // default 120 BPM
if ("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(length(t) >= 2*maximum_lines*maximum_line_length)
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(length(t) > 2*maximum_lines*maximum_line_length)
if (length(t))
player.song.lines = splittext(t, "\n")
if(copytext(player.song.lines[1],1,6) == "BPM: ")
if(text2num(copytext(player.song.lines[1],6)) != 0)
player.song.tempo = player.song.sanitize_tempo(600 / text2num(copytext(player.song.lines[1],6)))
player.song.lines.Cut(1,2)
else
player.song.tempo = player.song.sanitize_tempo(5)
else
player.song.tempo = player.song.sanitize_tempo(5) // default 120 BPM
if(player.song.lines.len > maximum_lines)
to_chat(usr, "Too many lines!")
player.song.lines.Cut(maximum_lines+1)
var/linenum = 1
for(var/l in player.song.lines)
if(length(l) > maximum_line_length)
to_chat(usr, "Line [linenum] too long!")
player.song.lines.Remove(l)
else
linenum++
else
return 0
return 1

View File

@@ -0,0 +1,365 @@
/datum/sound_player/synthesizer
forced_sound_in = 0
var/list/datum/music_code/code = list()
/datum/sound_player/synthesizer/apply_modifications_for(mob/who, sound/what, which, where, which_one)
..(who, what, which)
for (var/datum/music_code/cond in code)
if (cond.test(which, where, which_one))
var/datum/sample_pair/pair = cond.instrument.sample_map[global.musical_config.n2t(which)]
what.file = pair.sample
#define LESSER 1
#define EQUAL 2
#define GREATER_MUSIC 3
#define COMPARE(alpha, beta) ((alpha)<(beta) ? LESSER : (alpha)==(beta) ? EQUAL : GREATER_MUSIC)
/datum/music_code
var/octave = null
var/octave_condition = null
var/line_num = null
var/line_condition = null
var/line_note_num = null
var/line_note_condition = null
var/datum/instrument/instrument = null
/datum/music_code/proc/test(note_num, line_num, line_note_num)
var/result = 1
if (octave!=null && octave_condition)
var/cur_octave = round(note_num * 0.083)
if (COMPARE(cur_octave, octave) != octave_condition)
result = 0
if (line_num && line_condition)
if (COMPARE(line_num, line_num) != line_condition)
result = 0
if (line_note_num && line_note_condition)
if (COMPARE(line_num, line_note_num) != line_note_condition)
result = 0
return result
/datum/music_code/proc/octave_code()
if (octave!=null)
var/sym = ""
switch(octave_condition)
if(LESSER)
sym = "<"
if(EQUAL)
sym = "="
if(GREATER_MUSIC)
sym = ">"
else
sym = null
return "O[sym][octave]"
return ""
/datum/music_code/proc/line_num_code()
if (line_num)
var/sym = ""
switch(line_condition)
if(LESSER)
sym = "<"
if(EQUAL)
sym = "="
if(GREATER_MUSIC)
sym = ">"
else
sym = null
return "L[sym][line_num]"
return ""
/datum/music_code/proc/line_note_num_code()
if (line_note_num)
var/sym = ""
switch(line_note_condition)
if(LESSER)
sym = "<"
if(EQUAL)
sym = "="
if(GREATER_MUSIC)
sym = ">"
else
sym = null
return "N[sym][line_note_num]"
return ""
#undef LESSER
#undef EQUAL
#undef GREATER_MUSIC
#undef COMPARE
/obj/structure/synthesized_instrument/synthesizer
name = "The Synthesizer 3.0"
desc = "This is the hottest new synth around! With new sounds!"
icon = 'icons/obj/musician.dmi'
icon_state = "nusynth"
anchored = 1
density = 1
var/list/instruments = list()
/obj/structure/synthesized_instrument/synthesizer/New()
..()
for (var/type in typesof(/datum/instrument))
var/datum/instrument/new_instrument = new type
if (!new_instrument.id) continue
new_instrument.create_full_sample_deviation_map()
instruments[new_instrument.name] = new_instrument
player = new /datum/sound_player/synthesizer(src, instruments[pick(instruments)])
icon_state = pick("nusynth","nusynth2","nusynth3")
/obj/structure/synthesized_instrument/synthesizer/attackby(obj/item/O, mob/user, params)
if (iswrench(O))
if (!anchored )//&& !isinspace())
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
to_chat(usr, "<span class='notice'> You begin to tighten \the [src] to the floor...</span>")
if (do_after(user,src , 20))
user.visible_message( \
"[user] tightens \the [src]'s casters.", \
"<span class='notice'> You tighten \the [src]'s casters. Now it can be played again.</span>", \
"<span class='italics'>You hear ratchet.</span>")
anchored = 1
else if(anchored)
playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
to_chat(usr, "<span class='notice'> You begin to loosen \the [src]'s casters...</span>")
if (do_after(user, src, 40))
user.visible_message( \
"[user] loosens \the [src]'s casters.", \
"<span class='notice'> You loosen \the [src]. Now it can be pulled somewhere else.</span>", \
"<span class='italics'>You hear ratchet.</span>")
anchored = 0
else
..()
/obj/structure/synthesized_instrument/synthesizer/proc/compose_code(var/html=0)
var/code = ""
var/line_number = 1
if (player:code:len)
// Find instruments involved and create a list of statements
var/list/list/datum/music_code/statements = list() // Instruments involved
for (var/datum/music_code/this_code in player:code)
if (statements[this_code.instrument.id])
statements[this_code.instrument.id] += this_code
else
statements[this_code.instrument.id] = list(this_code)
// Each instrument statement is split by ;\n or ;<br> in this case
// Each statement is in parenthesises and separated by |
// Statements have up to 3 conditions separated by &
for (var/instrument_id in statements)
var/conditions = ""
for (var/datum/music_code/cond in statements[instrument_id])
var/sub_code = "("
var/octave_code = cond.octave_code()
var/line_code = cond.line_num_code()
var/line_note_code = cond.line_note_num_code()
sub_code += octave_code ? octave_code+"|" : ""
sub_code += line_code ? line_code + "|" : ""
sub_code += line_note_code
sub_code = copytext(sub_code, 1, -1)
sub_code += ")"
conditions = sub_code + " & "
conditions = copytext(conditions, 1, -3)
code = code + (html ? "[line_number]: " : "") + conditions + " -> " + (instrument_id + (html ? "<br>" : "\n"))
line_number++
return code
/obj/structure/synthesized_instrument/synthesizer/proc/decompose_code(code, mob/blame)
if (length(code) > 10000)
to_chat(blame, "This code is WAAAAY too long.")
return
code = replacetext(code, " ", "")
code = replacetext(code, "(", "")
code = replacetext(code, ")", "")
var/list/instruments_ids = list()
var/list/datum/instrument/instruments_by_id = list()
for (var/ins in instruments)
var/datum/instrument/instr = instruments[ins]
instruments_by_id[instr.id] = instr
instruments_ids += instr.id
var/line = 1
var/list/datum/music_code/conditions = list()
for (var/super_statement in splittext(code, "\n"))
var/list/delta = splittext(super_statement, "->")
if (delta.len==0)
to_chat(blame, "Line [line]: Empty super statement")
return
if (delta.len==1)
to_chat(blame, "Line [line]: Not enough parameters in super statement")
return
if (delta.len>2)
to_chat(blame, "Line [line]: Too many parameters in super statement")
return
var/id = delta[2]
if (!(id in instruments_ids))
to_chat(blame, "Line [line]: Unknown ID. [id]")
return
for (var/statements in splittext(delta[1], "|"))
var/datum/music_code/new_condition = new
for (var/property in splittext(statements, "&"))
if (length(property) < 3)
to_chat(blame, "Line [line]: Invalid property [property]")
return
var/variable = copytext(property, 1, 2)
if (variable != "O" && variable != "N" && variable != "L")
to_chat(blame, "Line [line]: Unknown variable [variable] in [property]")
return
var/operator = copytext(property, 2, 3)
if (operator != "<" && operator != ">" && operator != "=")
to_chat(blame, "Line [line]: Unknown operator [operator] in [property]")
return
var/list/que = splittext(property, operator)
var/value = que[2]
operator = operator=="<" ? 1 : operator=="=" ? 2 : 3
if (num2text(text2num(value)) != value)
to_chat(blame, "Line [line]: Invalid value [value] in [property]")
return
value = text2num(value)
switch(variable)
if ("O")
new_condition.octave = value
new_condition.octave_condition = operator
if ("N")
new_condition.line_note_num = value
new_condition.line_note_condition = operator
if ("L")
new_condition.line_num = value
new_condition.line_condition = operator
new_condition.instrument = instruments_by_id[id]
conditions += new_condition
line++
player:code = conditions
/obj/structure/synthesized_instrument/synthesizer/ui_interact(mob/user, ui_key = "instrument", var/datum/nanoui/ui = null, var/force_open = 0)
var/list/data
data = list(
"playback" = list(
"playing" = player.song.playing,
"autorepeat" = player.song.autorepeat,
"three_dimensional_sound" = player.three_dimensional_sound
),
"basic_options" = list(
"cur_instrument" = player.song.instrument_data.name,
"volume" = player.volume,
"BPM" = round(600 / player.song.tempo),
"transposition" = player.song.transposition,
"octave_range" = list(
"min" = player.song.octave_range_min,
"max" = player.song.octave_range_max
)
),
/*"advanced_options" = list(
"all_environments" = global.musical_config.all_environments,
"selected_environment" = global.musical_config.id_to_environment(player.virtual_environment_selected),
"apply_echo" = player.apply_echo
),*/
"sustain" = list(
"linear_decay_active" = player.song.linear_decay,
"sustain_timer" = player.song.sustain_timer,
"soft_coeff" = player.song.soft_coeff
),
/*
"code" = list(
"code" = compose_code(html=1),
),*/
"show" = list(
"playback" = player.song.lines.len > 0
)
/* "custom_env_options" = global.musical_config.is_custom_env(player.virtual_environment_selected) && player.three_dimensional_sound,
"debug_button" = global.musical_config.debug_active,
"env_settings" = global.musical_config.env_settings_available
),
"status" = list(
"channels" = player.song.free_channels.len,
"events" = player.event_manager.events.len,
"max_channels" = global.musical_config.channels_per_instrument,
"max_events" = global.musical_config.max_events,
)*/
)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "synthesizer.tmpl", name, 600, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/structure/synthesized_instrument/synthesizer/Topic(href, href_list)
if (..())
return 1
var/target = href_list["target"]
var/value = text2num(href_list["value"])
if (href_list["value"] && !isnum(value))
to_chat(usr, "Non-numeric value was supplied")
return 0
switch (target)
if ("volume")
player.volume = max(min(player.volume+text2num(value), 100), 0)
if ("transposition")
player.song.transposition = max(min(player.song.transposition+value, global.musical_config.highest_transposition), global.musical_config.lowest_transposition)
if ("min_octave")
player.song.octave_range_min = max(min(player.song.octave_range_min+value, global.musical_config.highest_octave), global.musical_config.lowest_octave)
player.song.octave_range_max = max(player.song.octave_range_max, player.song.octave_range_min)
if ("max_octave")
player.song.octave_range_max = max(min(player.song.octave_range_max+value, global.musical_config.highest_octave), global.musical_config.lowest_octave)
player.song.octave_range_min = min(player.song.octave_range_max, player.song.octave_range_min)
if ("sustain_timer")
player.song.sustain_timer = max(min(player.song.sustain_timer+value, global.musical_config.longest_sustain_timer), 1)
if ("soft_coeff")
var/new_coeff = input(usr, "from [global.musical_config.gentlest_drop] to [global.musical_config.steepest_drop]") as num
new_coeff = round(min(max(new_coeff, global.musical_config.gentlest_drop), global.musical_config.steepest_drop), 0.001)
player.song.soft_coeff = new_coeff
if ("instrument")
var/list/categories = list()
for (var/key in instruments)
var/datum/instrument/instrument = instruments[key]
categories |= instrument.category
var/category = input(usr, "Choose a category") in categories
var/list/instruments_available = list()
for (var/key in instruments)
var/datum/instrument/instrument = instruments[key]
if (instrument.category == category)
instruments_available += key
var/new_instrument = input(usr, "Choose an instrument") in instruments_available
if (new_instrument)
player.song.instrument_data = instruments[new_instrument]
if ("3d_sound") player.three_dimensional_sound = value
if ("autorepeat") player.song.autorepeat = value
if ("decay") player.song.linear_decay = value
if ("echo") player.apply_echo = value
if ("select_env")
if (value in -1 to 26)
player.virtual_environment_selected = round(value)
/*
if ("show_code_editor") coding = value
if ("show_ids") showing_ids = value
if ("show_code_help") coding_help = value
if ("edit_code")
var/new_code = input(usr, "Program code", "Coding", compose_code()) as message
decompose_code(new_code, usr)
*/
return 1
/obj/structure/synthesized_instrument/synthesizer/shouldStopPlaying(mob/user)
return !((src && in_range(src, user) && anchored) || player.song.autorepeat)

Some files were not shown because too many files have changed in this diff Show More