mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Ports musical instruments from /tg/
This commit is contained in:
@@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )
|
#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) )
|
||||||
|
|
||||||
|
/// Signifies that this proc is used to handle signals.
|
||||||
|
/// Every proc you pass to RegisterSignal must have this.
|
||||||
|
#define SIGNAL_HANDLER SHOULD_NOT_SLEEP(TRUE)
|
||||||
|
|
||||||
/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments
|
/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments
|
||||||
#define AddElement(arguments...) _AddElement(list(##arguments))
|
#define AddElement(arguments...) _AddElement(list(##arguments))
|
||||||
/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments
|
/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments
|
||||||
|
|||||||
24
code/__defines/instruments.dm
Normal file
24
code/__defines/instruments.dm
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#define INSTRUMENT_MIN_OCTAVE 1
|
||||||
|
#define INSTRUMENT_MAX_OCTAVE 9
|
||||||
|
#define INSTRUMENT_MIN_KEY 0
|
||||||
|
#define INSTRUMENT_MAX_KEY 127
|
||||||
|
|
||||||
|
/// Max number of playing notes per instrument.
|
||||||
|
#define CHANNELS_PER_INSTRUMENT 128
|
||||||
|
|
||||||
|
/// Maximum length a note should ever go for
|
||||||
|
#define INSTRUMENT_MAX_TOTAL_SUSTAIN (5 SECONDS)
|
||||||
|
|
||||||
|
/// These are per decisecond.
|
||||||
|
#define INSTRUMENT_EXP_FALLOFF_MIN 1.025 //100/(1.025^50) calculated for [INSTRUMENT_MIN_SUSTAIN_DROPOFF] to be 30.
|
||||||
|
#define INSTRUMENT_EXP_FALLOFF_MAX 10
|
||||||
|
|
||||||
|
/// Minimum volume for when the sound is considered dead.
|
||||||
|
#define INSTRUMENT_MIN_SUSTAIN_DROPOFF 0
|
||||||
|
|
||||||
|
#define SUSTAIN_LINEAR 1
|
||||||
|
#define SUSTAIN_EXPONENTIAL 2
|
||||||
|
|
||||||
|
// /datum/instrument instrument_flags
|
||||||
|
#define INSTRUMENT_LEGACY (1<<0) //Legacy instrument. Implies INSTRUMENT_DO_NOT_AUTOSAMPLE
|
||||||
|
#define INSTRUMENT_DO_NOT_AUTOSAMPLE (1<<1) //Do not automatically sample
|
||||||
@@ -423,6 +423,7 @@ GLOBAL_LIST_EMPTY(##LIST_NAME);\
|
|||||||
#define VOLUME_CHANNEL_ALARMS "Alarms"
|
#define VOLUME_CHANNEL_ALARMS "Alarms"
|
||||||
#define VOLUME_CHANNEL_VORE "Vore"
|
#define VOLUME_CHANNEL_VORE "Vore"
|
||||||
#define VOLUME_CHANNEL_DOORS "Doors"
|
#define VOLUME_CHANNEL_DOORS "Doors"
|
||||||
|
#define VOLUME_CHANNEL_INSTRUMENTS "Instruments"
|
||||||
|
|
||||||
// Make sure you update this or clients won't be able to adjust the channel
|
// Make sure you update this or clients won't be able to adjust the channel
|
||||||
GLOBAL_LIST_INIT(all_volume_channels, list(
|
GLOBAL_LIST_INIT(all_volume_channels, list(
|
||||||
@@ -431,6 +432,7 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
|
|||||||
VOLUME_CHANNEL_ALARMS,
|
VOLUME_CHANNEL_ALARMS,
|
||||||
VOLUME_CHANNEL_VORE,
|
VOLUME_CHANNEL_VORE,
|
||||||
VOLUME_CHANNEL_DOORS,
|
VOLUME_CHANNEL_DOORS,
|
||||||
|
VOLUME_CHANNEL_INSTRUMENTS
|
||||||
))
|
))
|
||||||
|
|
||||||
#define APPEARANCECHANGER_CHANGED_RACE "Race"
|
#define APPEARANCECHANGER_CHANGED_RACE "Race"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<<<<<<< HEAD
|
||||||
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
|
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
|
||||||
#define CHANNEL_LOBBYMUSIC 1024
|
#define CHANNEL_LOBBYMUSIC 1024
|
||||||
#define CHANNEL_ADMIN 1023
|
#define CHANNEL_ADMIN 1023
|
||||||
@@ -233,3 +234,456 @@
|
|||||||
'sound/ambience/engineering/engineering3.ogg',\
|
'sound/ambience/engineering/engineering3.ogg',\
|
||||||
'sound/ambience/atmospherics/atmospherics1.ogg'\
|
'sound/ambience/atmospherics/atmospherics1.ogg'\
|
||||||
)
|
)
|
||||||
|
||||||| parent of db274375dc... Merge pull request #10518 from VOREStation/Arokha/instrumental
|
||||||
|
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
|
||||||
|
#define CHANNEL_LOBBYMUSIC 1024
|
||||||
|
#define CHANNEL_ADMIN 1023
|
||||||
|
#define CHANNEL_VOX 1022
|
||||||
|
#define CHANNEL_JUKEBOX 1021
|
||||||
|
#define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats
|
||||||
|
#define CHANNEL_AMBIENCE_FORCED 1019
|
||||||
|
#define CHANNEL_AMBIENCE 1018
|
||||||
|
#define CHANNEL_BUZZ 1017
|
||||||
|
#define CHANNEL_BICYCLE 1016
|
||||||
|
#define CHANNEL_PREYLOOP 1015 //VORESTATION ADD - Fancy Sound Loop channel
|
||||||
|
|
||||||
|
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
|
||||||
|
//KEEP IT UPDATED
|
||||||
|
|
||||||
|
#define CHANNEL_HIGHEST_AVAILABLE 1014 //VORESTATION EDIT - Fancy Sound Loop channel from 1015
|
||||||
|
|
||||||
|
#define SOUND_MINIMUM_PRESSURE 10
|
||||||
|
#define FALLOFF_SOUNDS 0.5
|
||||||
|
|
||||||
|
//Sound environment defines. Reverb preset for sounds played in an area, see sound datum reference for more.
|
||||||
|
#define GENERIC 0
|
||||||
|
#define PADDED_CELL 1
|
||||||
|
#define ROOM 2
|
||||||
|
#define BATHROOM 3
|
||||||
|
#define LIVINGROOM 4
|
||||||
|
#define STONEROOM 5
|
||||||
|
#define AUDITORIUM 6
|
||||||
|
#define CONCERT_HALL 7
|
||||||
|
#define CAVE 8
|
||||||
|
#define ARENA 9
|
||||||
|
#define HANGAR 10
|
||||||
|
#define CARPETED_HALLWAY 11
|
||||||
|
#define HALLWAY 12
|
||||||
|
#define STONE_CORRIDOR 13
|
||||||
|
#define ALLEY 14
|
||||||
|
#define FOREST 15
|
||||||
|
#define CITY 16
|
||||||
|
#define MOUNTAINS 17
|
||||||
|
#define QUARRY 18
|
||||||
|
#define PLAIN 19
|
||||||
|
#define PARKING_LOT 20
|
||||||
|
#define SEWER_PIPE 21
|
||||||
|
#define UNDERWATER 22
|
||||||
|
#define DRUGGED 23
|
||||||
|
#define DIZZY 24
|
||||||
|
#define PSYCHOTIC 25
|
||||||
|
|
||||||
|
#define STANDARD_STATION STONEROOM
|
||||||
|
#define LARGE_ENCLOSED HANGAR
|
||||||
|
#define SMALL_ENCLOSED BATHROOM
|
||||||
|
#define TUNNEL_ENCLOSED CAVE
|
||||||
|
#define LARGE_SOFTFLOOR CARPETED_HALLWAY
|
||||||
|
#define MEDIUM_SOFTFLOOR LIVINGROOM
|
||||||
|
#define SMALL_SOFTFLOOR ROOM
|
||||||
|
#define ASTEROID CAVE
|
||||||
|
#define SPACE UNDERWATER
|
||||||
|
|
||||||
|
// Ambience presets.
|
||||||
|
// All you need to do to make an area play one of these is set their ambience var to one of these lists.
|
||||||
|
// You can even combine them by adding them together, since they're just lists, however you'd have to do that in initialization.
|
||||||
|
|
||||||
|
// For weird alien places like the crashed UFO.
|
||||||
|
#define AMBIENCE_OTHERWORLDLY list(\
|
||||||
|
'sound/ambience/otherworldly/otherworldly1.ogg',\
|
||||||
|
'sound/ambience/otherworldly/otherworldly2.ogg',\
|
||||||
|
'sound/ambience/otherworldly/otherworldly3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Restricted, military, or mercenary aligned locations like the armory, the merc ship/base, BSD, etc.
|
||||||
|
#define AMBIENCE_HIGHSEC list(\
|
||||||
|
'sound/ambience/highsec/highsec1.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec2.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec3.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ruined structures found on the surface or in the caves.
|
||||||
|
#define AMBIENCE_RUINS list(\
|
||||||
|
'sound/ambience/ruins/ruins1.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins2.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins3.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins4.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins5.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Similar to the above, but for more technology/signaling based ruins.
|
||||||
|
#define AMBIENCE_TECH_RUINS list(\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins1.ogg',\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins2.ogg',\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// The actual chapel room, and maybe some other places of worship.
|
||||||
|
#define AMBIENCE_CHAPEL list(\
|
||||||
|
'sound/ambience/chapel/chapel1.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel2.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel3.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// For peaceful, serene areas, distinct from the Chapel.
|
||||||
|
#define AMBIENCE_HOLY list(\
|
||||||
|
'sound/ambience/holy/holy1.ogg',\
|
||||||
|
'sound/ambience/holy/holy2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generic sounds for less special rooms.
|
||||||
|
#define AMBIENCE_GENERIC list(\
|
||||||
|
'sound/ambience/generic/generic1.ogg',\
|
||||||
|
'sound/ambience/generic/generic2.ogg',\
|
||||||
|
'sound/ambience/generic/generic3.ogg'\
|
||||||
|
)
|
||||||
|
// 'sound/ambience/generic/generic4.ogg'
|
||||||
|
|
||||||
|
// Sounds of PA announcements, presumably involving shuttles?
|
||||||
|
#define AMBIENCE_ARRIVALS list(\
|
||||||
|
'sound/ambience/arrivals/arrivals1.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals2.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals3.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals4.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals5.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals6.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals7.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sounds suitable for being inside dark, tight corridors in the underbelly of the station.
|
||||||
|
#define AMBIENCE_MAINTENANCE list(\
|
||||||
|
'sound/ambience/maintenance/maintenance1.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance2.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance3.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance4.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance5.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance6.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance7.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance8.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance9.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Life support machinery at work, keeping everyone breathing.
|
||||||
|
#define AMBIENCE_ENGINEERING list(\
|
||||||
|
'sound/ambience/engineering/engineering1.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering2.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Creepy AI/borg stuff.
|
||||||
|
#define AMBIENCE_AI list(\
|
||||||
|
'sound/ambience/ai/ai1.ogg',\
|
||||||
|
'sound/ambience/ai/ai2.ogg',\
|
||||||
|
'sound/ambience/ai/ai3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Peaceful sounds when floating in the void.
|
||||||
|
#define AMBIENCE_SPACE list(\
|
||||||
|
'sound/ambience/space/space_serithi.ogg',\
|
||||||
|
'sound/ambience/space/space1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vaguely spooky sounds when around dead things.
|
||||||
|
#define AMBIENCE_GHOSTLY list(\
|
||||||
|
'sound/ambience/ghostly/ghostly1.ogg',\
|
||||||
|
'sound/ambience/ghostly/ghostly2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Concerning sounds, for when one discovers something horrible happened in a PoI.
|
||||||
|
#define AMBIENCE_FOREBODING list(\
|
||||||
|
'sound/ambience/foreboding/foreboding1.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding2.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding3.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding4.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding5.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ambience heard when aboveground on Sif and not in a Point of Interest.
|
||||||
|
#define AMBIENCE_SIF list(\
|
||||||
|
'sound/ambience/sif/sif1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// If we ever add geothermal PoIs or other places that are really hot, this will do.
|
||||||
|
#define AMBIENCE_LAVA list(\
|
||||||
|
'sound/ambience/lava/lava1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cult-y ambience, for some PoIs, and maybe when the cultists darken the world with the ritual.
|
||||||
|
#define AMBIENCE_UNHOLY list(\
|
||||||
|
'sound/ambience/unholy/unholy1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// For the memes.
|
||||||
|
#define AMBIENCE_AESTHETIC list(\
|
||||||
|
'sound/ambience/vaporwave.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_OUTPOST list(\
|
||||||
|
'sound/ambience/expoutpost/expoutpost1.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost2.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost3.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_SUBSTATION list(\
|
||||||
|
'sound/ambience/substation/substation1.ogg',\
|
||||||
|
'sound/ambience/substation/substation2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_HANGAR list(\
|
||||||
|
'sound/ambience/hangar/hangar1.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar2.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar3.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar4.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar5.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_ATMOS list(\
|
||||||
|
'sound/ambience/engineering/engineering1.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering2.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering3.ogg',\
|
||||||
|
'sound/ambience/atmospherics/atmospherics1.ogg'\
|
||||||
|
)
|
||||||
|
=======
|
||||||
|
//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on
|
||||||
|
#define CHANNEL_LOBBYMUSIC 1024
|
||||||
|
#define CHANNEL_ADMIN 1023
|
||||||
|
#define CHANNEL_VOX 1022
|
||||||
|
#define CHANNEL_JUKEBOX 1021
|
||||||
|
#define CHANNEL_HEARTBEAT 1020 //sound channel for heartbeats
|
||||||
|
#define CHANNEL_AMBIENCE_FORCED 1019
|
||||||
|
#define CHANNEL_AMBIENCE 1018
|
||||||
|
#define CHANNEL_BUZZ 1017
|
||||||
|
#define CHANNEL_BICYCLE 1016
|
||||||
|
#define CHANNEL_PREYLOOP 1015 //VORESTATION ADD - Fancy Sound Loop channel
|
||||||
|
|
||||||
|
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
|
||||||
|
//KEEP IT UPDATED
|
||||||
|
|
||||||
|
#define CHANNEL_HIGHEST_AVAILABLE 1014 //VORESTATION EDIT - Fancy Sound Loop channel from 1015
|
||||||
|
|
||||||
|
#define SOUND_MINIMUM_PRESSURE 10
|
||||||
|
#define FALLOFF_SOUNDS 0.5
|
||||||
|
|
||||||
|
#define MAX_INSTRUMENT_CHANNELS (128 * 6)
|
||||||
|
|
||||||
|
//default byond sound environments
|
||||||
|
#define SOUND_ENVIRONMENT_NONE -1
|
||||||
|
#define SOUND_ENVIRONMENT_GENERIC 0
|
||||||
|
#define SOUND_ENVIRONMENT_PADDED_CELL 1
|
||||||
|
#define SOUND_ENVIRONMENT_ROOM 2
|
||||||
|
#define SOUND_ENVIRONMENT_BATHROOM 3
|
||||||
|
#define SOUND_ENVIRONMENT_LIVINGROOM 4
|
||||||
|
#define SOUND_ENVIRONMENT_STONEROOM 5
|
||||||
|
#define SOUND_ENVIRONMENT_AUDITORIUM 6
|
||||||
|
#define SOUND_ENVIRONMENT_CONCERT_HALL 7
|
||||||
|
#define SOUND_ENVIRONMENT_CAVE 8
|
||||||
|
#define SOUND_ENVIRONMENT_ARENA 9
|
||||||
|
#define SOUND_ENVIRONMENT_HANGAR 10
|
||||||
|
#define SOUND_ENVIRONMENT_CARPETED_HALLWAY 11
|
||||||
|
#define SOUND_ENVIRONMENT_HALLWAY 12
|
||||||
|
#define SOUND_ENVIRONMENT_STONE_CORRIDOR 13
|
||||||
|
#define SOUND_ENVIRONMENT_ALLEY 14
|
||||||
|
#define SOUND_ENVIRONMENT_FOREST 15
|
||||||
|
#define SOUND_ENVIRONMENT_CITY 16
|
||||||
|
#define SOUND_ENVIRONMENT_MOUNTAINS 17
|
||||||
|
#define SOUND_ENVIRONMENT_QUARRY 18
|
||||||
|
#define SOUND_ENVIRONMENT_PLAIN 19
|
||||||
|
#define SOUND_ENVIRONMENT_PARKING_LOT 20
|
||||||
|
#define SOUND_ENVIRONMENT_SEWER_PIPE 21
|
||||||
|
#define SOUND_ENVIRONMENT_UNDERWATER 22
|
||||||
|
#define SOUND_ENVIRONMENT_DRUGGED 23
|
||||||
|
#define SOUND_ENVIRONMENT_DIZZY 24
|
||||||
|
#define SOUND_ENVIRONMENT_PSYCHOTIC 25
|
||||||
|
//If we ever make custom ones add them here
|
||||||
|
|
||||||
|
#define STANDARD_STATION SOUND_ENVIRONMENT_STONEROOM
|
||||||
|
#define LARGE_ENCLOSED SOUND_ENVIRONMENT_HANGAR
|
||||||
|
#define SMALL_ENCLOSED SOUND_ENVIRONMENT_BATHROOM
|
||||||
|
#define TUNNEL_ENCLOSED SOUND_ENVIRONMENT_CAVE
|
||||||
|
#define LARGE_SOFTFLOOR SOUND_ENVIRONMENT_CARPETED_HALLWAY
|
||||||
|
#define MEDIUM_SOFTFLOOR SOUND_ENVIRONMENT_LIVINGROOM
|
||||||
|
#define SMALL_SOFTFLOOR SOUND_ENVIRONMENT_ROOM
|
||||||
|
#define ASTEROID SOUND_ENVIRONMENT_CAVE
|
||||||
|
#define SPACE SOUND_ENVIRONMENT_UNDERWATER
|
||||||
|
|
||||||
|
// Ambience presets.
|
||||||
|
// All you need to do to make an area play one of these is set their ambience var to one of these lists.
|
||||||
|
// You can even combine them by adding them together, since they're just lists, however you'd have to do that in initialization.
|
||||||
|
|
||||||
|
// For weird alien places like the crashed UFO.
|
||||||
|
#define AMBIENCE_OTHERWORLDLY list(\
|
||||||
|
'sound/ambience/otherworldly/otherworldly1.ogg',\
|
||||||
|
'sound/ambience/otherworldly/otherworldly2.ogg',\
|
||||||
|
'sound/ambience/otherworldly/otherworldly3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Restricted, military, or mercenary aligned locations like the armory, the merc ship/base, BSD, etc.
|
||||||
|
#define AMBIENCE_HIGHSEC list(\
|
||||||
|
'sound/ambience/highsec/highsec1.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec2.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec3.ogg',\
|
||||||
|
'sound/ambience/highsec/highsec4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ruined structures found on the surface or in the caves.
|
||||||
|
#define AMBIENCE_RUINS list(\
|
||||||
|
'sound/ambience/ruins/ruins1.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins2.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins3.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins4.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins5.ogg',\
|
||||||
|
'sound/ambience/ruins/ruins6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Similar to the above, but for more technology/signaling based ruins.
|
||||||
|
#define AMBIENCE_TECH_RUINS list(\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins1.ogg',\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins2.ogg',\
|
||||||
|
'sound/ambience/tech_ruins/tech_ruins3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// The actual chapel room, and maybe some other places of worship.
|
||||||
|
#define AMBIENCE_CHAPEL list(\
|
||||||
|
'sound/ambience/chapel/chapel1.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel2.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel3.ogg',\
|
||||||
|
'sound/ambience/chapel/chapel4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// For peaceful, serene areas, distinct from the Chapel.
|
||||||
|
#define AMBIENCE_HOLY list(\
|
||||||
|
'sound/ambience/holy/holy1.ogg',\
|
||||||
|
'sound/ambience/holy/holy2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generic sounds for less special rooms.
|
||||||
|
#define AMBIENCE_GENERIC list(\
|
||||||
|
'sound/ambience/generic/generic1.ogg',\
|
||||||
|
'sound/ambience/generic/generic2.ogg',\
|
||||||
|
'sound/ambience/generic/generic3.ogg'\
|
||||||
|
)
|
||||||
|
// 'sound/ambience/generic/generic4.ogg'
|
||||||
|
|
||||||
|
// Sounds of PA announcements, presumably involving shuttles?
|
||||||
|
#define AMBIENCE_ARRIVALS list(\
|
||||||
|
'sound/ambience/arrivals/arrivals1.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals2.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals3.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals4.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals5.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals6.ogg',\
|
||||||
|
'sound/ambience/arrivals/arrivals7.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sounds suitable for being inside dark, tight corridors in the underbelly of the station.
|
||||||
|
#define AMBIENCE_MAINTENANCE list(\
|
||||||
|
'sound/ambience/maintenance/maintenance1.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance2.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance3.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance4.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance5.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance6.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance7.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance8.ogg',\
|
||||||
|
'sound/ambience/maintenance/maintenance9.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Life support machinery at work, keeping everyone breathing.
|
||||||
|
#define AMBIENCE_ENGINEERING list(\
|
||||||
|
'sound/ambience/engineering/engineering1.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering2.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Creepy AI/borg stuff.
|
||||||
|
#define AMBIENCE_AI list(\
|
||||||
|
'sound/ambience/ai/ai1.ogg',\
|
||||||
|
'sound/ambience/ai/ai2.ogg',\
|
||||||
|
'sound/ambience/ai/ai3.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Peaceful sounds when floating in the void.
|
||||||
|
#define AMBIENCE_SPACE list(\
|
||||||
|
'sound/ambience/space/space_serithi.ogg',\
|
||||||
|
'sound/ambience/space/space1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Vaguely spooky sounds when around dead things.
|
||||||
|
#define AMBIENCE_GHOSTLY list(\
|
||||||
|
'sound/ambience/ghostly/ghostly1.ogg',\
|
||||||
|
'sound/ambience/ghostly/ghostly2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Concerning sounds, for when one discovers something horrible happened in a PoI.
|
||||||
|
#define AMBIENCE_FOREBODING list(\
|
||||||
|
'sound/ambience/foreboding/foreboding1.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding2.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding3.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding4.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding5.ogg',\
|
||||||
|
'sound/ambience/foreboding/foreboding6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ambience heard when aboveground on Sif and not in a Point of Interest.
|
||||||
|
#define AMBIENCE_SIF list(\
|
||||||
|
'sound/ambience/sif/sif1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// If we ever add geothermal PoIs or other places that are really hot, this will do.
|
||||||
|
#define AMBIENCE_LAVA list(\
|
||||||
|
'sound/ambience/lava/lava1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cult-y ambience, for some PoIs, and maybe when the cultists darken the world with the ritual.
|
||||||
|
#define AMBIENCE_UNHOLY list(\
|
||||||
|
'sound/ambience/unholy/unholy1.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
// For the memes.
|
||||||
|
#define AMBIENCE_AESTHETIC list(\
|
||||||
|
'sound/ambience/vaporwave.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_OUTPOST list(\
|
||||||
|
'sound/ambience/expoutpost/expoutpost1.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost2.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost3.ogg',\
|
||||||
|
'sound/ambience/expoutpost/expoutpost4.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_SUBSTATION list(\
|
||||||
|
'sound/ambience/substation/substation1.ogg',\
|
||||||
|
'sound/ambience/substation/substation2.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_HANGAR list(\
|
||||||
|
'sound/ambience/hangar/hangar1.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar2.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar3.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar4.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar5.ogg',\
|
||||||
|
'sound/ambience/hangar/hangar6.ogg'\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define AMBIENCE_ATMOS list(\
|
||||||
|
'sound/ambience/engineering/engineering1.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering2.ogg',\
|
||||||
|
'sound/ambience/engineering/engineering3.ogg',\
|
||||||
|
'sound/ambience/atmospherics/atmospherics1.ogg'\
|
||||||
|
)
|
||||||
|
>>>>>>> db274375dc... Merge pull request #10518 from VOREStation/Arokha/instrumental
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
|||||||
#define INIT_ORDER_CHEMISTRY 35
|
#define INIT_ORDER_CHEMISTRY 35
|
||||||
#define INIT_ORDER_SKYBOX 30
|
#define INIT_ORDER_SKYBOX 30
|
||||||
#define INIT_ORDER_MAPPING 25
|
#define INIT_ORDER_MAPPING 25
|
||||||
|
#define INIT_ORDER_SOUNDS 23
|
||||||
|
#define INIT_ORDER_INSTRUMENTS 22
|
||||||
#define INIT_ORDER_DECALS 20
|
#define INIT_ORDER_DECALS 20
|
||||||
#define INIT_ORDER_PLANTS 19 // Must initialize before atoms.
|
#define INIT_ORDER_PLANTS 19 // Must initialize before atoms.
|
||||||
#define INIT_ORDER_PLANETS 18
|
#define INIT_ORDER_PLANETS 18
|
||||||
@@ -92,8 +94,9 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
|||||||
#define FIRE_PRIORITY_SUPPLY 5
|
#define FIRE_PRIORITY_SUPPLY 5
|
||||||
#define FIRE_PRIORITY_NIGHTSHIFT 5
|
#define FIRE_PRIORITY_NIGHTSHIFT 5
|
||||||
#define FIRE_PRIORITY_PLANTS 5
|
#define FIRE_PRIORITY_PLANTS 5
|
||||||
#define FIRE_PRIORITY_ORBIT 8
|
#define FIRE_PRIORITY_ORBIT 7
|
||||||
#define FIRE_PRIORITY_VOTE 9
|
#define FIRE_PRIORITY_VOTE 8
|
||||||
|
#define FIRE_PRIORITY_INSTRUMENTS 9
|
||||||
#define FIRE_PRIORITY_AI 10
|
#define FIRE_PRIORITY_AI 10
|
||||||
#define FIRE_PRIORITY_GARBAGE 15
|
#define FIRE_PRIORITY_GARBAGE 15
|
||||||
#define FIRE_PRIORITY_ALARM 20
|
#define FIRE_PRIORITY_ALARM 20
|
||||||
|
|||||||
56
code/controllers/subsystems/processing/instruments.dm
Normal file
56
code/controllers/subsystems/processing/instruments.dm
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
PROCESSING_SUBSYSTEM_DEF(instruments)
|
||||||
|
name = "Instruments"
|
||||||
|
wait = 0.5
|
||||||
|
init_order = INIT_ORDER_INSTRUMENTS
|
||||||
|
flags = SS_KEEP_TIMING
|
||||||
|
priority = FIRE_PRIORITY_INSTRUMENTS
|
||||||
|
/// List of all instrument data, associative id = datum
|
||||||
|
var/static/list/datum/instrument/instrument_data = list()
|
||||||
|
/// List of all song datums.
|
||||||
|
var/static/list/datum/song/songs = list()
|
||||||
|
/// Max lines in songs
|
||||||
|
var/static/musician_maxlines = 600
|
||||||
|
/// Max characters per line in songs
|
||||||
|
var/static/musician_maxlinechars = 300
|
||||||
|
/// Deciseconds between hearchecks. Too high and instruments seem to lag when people are moving around in terms of who can hear it. Too low and the server lags from this.
|
||||||
|
var/static/musician_hearcheck_mindelay = 5
|
||||||
|
/// Maximum instrument channels total instruments are allowed to use. This is so you don't have instruments deadlocking all sound channels.
|
||||||
|
var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS
|
||||||
|
/// Current number of channels allocated for instruments
|
||||||
|
var/static/current_instrument_channels = 0
|
||||||
|
/// Single cached list for synthesizer instrument ids, so you don't have to have a new list with every synthesizer.
|
||||||
|
var/static/list/synthesizer_instrument_ids
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/Initialize()
|
||||||
|
initialize_instrument_data()
|
||||||
|
synthesizer_instrument_ids = get_allowed_instrument_ids()
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S)
|
||||||
|
songs += S
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/proc/on_song_del(datum/song/S)
|
||||||
|
songs -= S
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/proc/initialize_instrument_data()
|
||||||
|
for(var/path in subtypesof(/datum/instrument))
|
||||||
|
var/datum/instrument/I = path
|
||||||
|
if(initial(I.abstract_type) == path)
|
||||||
|
continue
|
||||||
|
I = new path
|
||||||
|
I.Initialize()
|
||||||
|
if(!I.id)
|
||||||
|
qdel(I)
|
||||||
|
continue
|
||||||
|
instrument_data[I.id] = I
|
||||||
|
CHECK_TICK
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path)
|
||||||
|
return instrument_data["[id_or_path]"]
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/instruments/proc/reserve_instrument_channel(datum/instrument/I)
|
||||||
|
if(current_instrument_channels > max_instrument_channels)
|
||||||
|
return
|
||||||
|
. = SSsounds.reserve_sound_channel(I)
|
||||||
|
if(!isnull(.))
|
||||||
|
current_instrument_channels++
|
||||||
135
code/controllers/subsystems/sounds.dm
Normal file
135
code/controllers/subsystems/sounds.dm
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#define DATUMLESS "NO_DATUM"
|
||||||
|
|
||||||
|
SUBSYSTEM_DEF(sounds)
|
||||||
|
name = "Sounds"
|
||||||
|
flags = SS_NO_FIRE
|
||||||
|
init_order = INIT_ORDER_SOUNDS
|
||||||
|
var/static/using_channels_max = CHANNEL_HIGHEST_AVAILABLE //BYOND max channels
|
||||||
|
/// Amount of channels to reserve for random usage rather than reservations being allowed to reserve all channels. Also a nice safeguard for when someone screws up.
|
||||||
|
var/static/random_channels_min = 50
|
||||||
|
|
||||||
|
// Hey uh these two needs to be initialized fast because the whole "things get deleted before init" thing.
|
||||||
|
/// Assoc list, `"[channel]" =` either the datum using it or TRUE for an unsafe-reserved (datumless reservation) channel
|
||||||
|
var/list/using_channels
|
||||||
|
/// Assoc list datum = list(channel1, channel2, ...) for what channels something reserved.
|
||||||
|
var/list/using_channels_by_datum
|
||||||
|
// Special datastructure for fast channel management
|
||||||
|
/// List of all channels as numbers
|
||||||
|
var/list/channel_list
|
||||||
|
/// Associative list of all reserved channels associated to their position. `"[channel_number]" =` index as number
|
||||||
|
var/list/reserved_channels
|
||||||
|
/// lower iteration position - Incremented and looped to get "random" sound channels for normal sounds. The channel at this index is returned when asking for a random channel.
|
||||||
|
var/channel_random_low
|
||||||
|
/// higher reserve position - decremented and incremented to reserve sound channels, anything above this is reserved. The channel at this index is the highest unreserved channel.
|
||||||
|
var/channel_reserve_high
|
||||||
|
|
||||||
|
/datum/controller/subsystem/sounds/Initialize()
|
||||||
|
setup_available_channels()
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/sounds/proc/setup_available_channels()
|
||||||
|
channel_list = list()
|
||||||
|
reserved_channels = list()
|
||||||
|
using_channels = list()
|
||||||
|
using_channels_by_datum = list()
|
||||||
|
for(var/i in 1 to using_channels_max)
|
||||||
|
channel_list += i
|
||||||
|
channel_random_low = 1
|
||||||
|
channel_reserve_high = length(channel_list)
|
||||||
|
|
||||||
|
/// Removes a channel from using list.
|
||||||
|
/datum/controller/subsystem/sounds/proc/free_sound_channel(channel)
|
||||||
|
var/text_channel = num2text(channel)
|
||||||
|
var/using = using_channels[text_channel]
|
||||||
|
using_channels -= text_channel
|
||||||
|
if(using != TRUE) // datum channel
|
||||||
|
using_channels_by_datum[using] -= channel
|
||||||
|
if(!length(using_channels_by_datum[using]))
|
||||||
|
using_channels_by_datum -= using
|
||||||
|
free_channel(channel)
|
||||||
|
|
||||||
|
/// Frees all the channels a datum is using.
|
||||||
|
/datum/controller/subsystem/sounds/proc/free_datum_channels(datum/D)
|
||||||
|
var/list/L = using_channels_by_datum[D]
|
||||||
|
if(!L)
|
||||||
|
return
|
||||||
|
for(var/channel in L)
|
||||||
|
using_channels -= num2text(channel)
|
||||||
|
free_channel(channel)
|
||||||
|
using_channels_by_datum -= D
|
||||||
|
|
||||||
|
/// Frees all datumless channels
|
||||||
|
/datum/controller/subsystem/sounds/proc/free_datumless_channels()
|
||||||
|
free_datum_channels(DATUMLESS)
|
||||||
|
|
||||||
|
/// NO AUTOMATIC CLEANUP - If you use this, you better manually free it later! Returns an integer for channel.
|
||||||
|
/datum/controller/subsystem/sounds/proc/reserve_sound_channel_datumless()
|
||||||
|
. = reserve_channel()
|
||||||
|
if(!.) //oh no..
|
||||||
|
return FALSE
|
||||||
|
var/text_channel = num2text(.)
|
||||||
|
using_channels[text_channel] = DATUMLESS
|
||||||
|
LAZYINITLIST(using_channels_by_datum[DATUMLESS])
|
||||||
|
using_channels_by_datum[DATUMLESS] += .
|
||||||
|
|
||||||
|
/// Reserves a channel for a datum. Automatic cleanup only when the datum is deleted. Returns an integer for channel.
|
||||||
|
/datum/controller/subsystem/sounds/proc/reserve_sound_channel(datum/D)
|
||||||
|
if(!D) //i don't like typechecks but someone will fuck it up
|
||||||
|
CRASH("Attempted to reserve sound channel without datum using the managed proc.")
|
||||||
|
.= reserve_channel()
|
||||||
|
if(!.)
|
||||||
|
return FALSE
|
||||||
|
var/text_channel = num2text(.)
|
||||||
|
using_channels[text_channel] = D
|
||||||
|
LAZYINITLIST(using_channels_by_datum[D])
|
||||||
|
using_channels_by_datum[D] += .
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserves a channel and updates the datastructure. Private proc.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/sounds/proc/reserve_channel()
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
if(channel_reserve_high <= random_channels_min) // out of channels
|
||||||
|
return
|
||||||
|
var/channel = channel_list[channel_reserve_high]
|
||||||
|
reserved_channels[num2text(channel)] = channel_reserve_high--
|
||||||
|
return channel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a channel and updates the datastructure. Private proc.
|
||||||
|
*/
|
||||||
|
/datum/controller/subsystem/sounds/proc/free_channel(number)
|
||||||
|
PRIVATE_PROC(TRUE)
|
||||||
|
var/text_channel = num2text(number)
|
||||||
|
var/index = reserved_channels[text_channel]
|
||||||
|
if(!index)
|
||||||
|
CRASH("Attempted to (internally) free a channel that wasn't reserved.")
|
||||||
|
reserved_channels -= text_channel
|
||||||
|
// push reserve index up, which makes it now on a channel that is reserved
|
||||||
|
channel_reserve_high++
|
||||||
|
// swap the reserved channel wtih the unreserved channel so the reserve index is now on an unoccupied channel and the freed channel is next to be used.
|
||||||
|
channel_list.Swap(channel_reserve_high, index)
|
||||||
|
// now, an existing reserved channel will likely (exception: unreserving last reserved channel) be at index
|
||||||
|
// get it, and update position.
|
||||||
|
var/text_reserved = num2text(channel_list[index])
|
||||||
|
if(!reserved_channels[text_reserved]) //if it isn't already reserved make sure we don't accidently mistakenly put it on reserved list!
|
||||||
|
return
|
||||||
|
reserved_channels[text_reserved] = index
|
||||||
|
|
||||||
|
/// Random available channel, returns text.
|
||||||
|
/datum/controller/subsystem/sounds/proc/random_available_channel_text()
|
||||||
|
if(channel_random_low > channel_reserve_high)
|
||||||
|
channel_random_low = 1
|
||||||
|
. = "[channel_list[channel_random_low++]]"
|
||||||
|
|
||||||
|
/// Random available channel, returns number
|
||||||
|
/datum/controller/subsystem/sounds/proc/random_available_channel()
|
||||||
|
if(channel_random_low > channel_reserve_high)
|
||||||
|
channel_random_low = 1
|
||||||
|
. = channel_list[channel_random_low++]
|
||||||
|
|
||||||
|
/// How many channels we have left.
|
||||||
|
/datum/controller/subsystem/sounds/proc/available_channels_left()
|
||||||
|
return length(channel_list) - random_channels_min
|
||||||
|
|
||||||
|
#undef DATUMLESS
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
var/list/atoms_cache = output_atoms
|
var/list/atoms_cache = output_atoms
|
||||||
var/sound/S = sound(soundfile)
|
var/sound/S = sound(soundfile)
|
||||||
if(direct)
|
if(direct)
|
||||||
S.channel = open_sound_channel()
|
S.channel = SSsounds.random_available_channel()
|
||||||
S.volume = volume
|
S.volume = volume
|
||||||
for(var/i in 1 to atoms_cache.len)
|
for(var/i in 1 to atoms_cache.len)
|
||||||
var/atom/thing = atoms_cache[i]
|
var/atom/thing = atoms_cache[i]
|
||||||
|
|||||||
39
code/datums/supplypacks/musical.dm
Normal file
39
code/datums/supplypacks/musical.dm
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/datum/supply_pack/musical/strings
|
||||||
|
contains = list(
|
||||||
|
/obj/item/instrument/violin,
|
||||||
|
/obj/item/instrument/banjo,
|
||||||
|
/obj/item/instrument/guitar,
|
||||||
|
/obj/item/instrument/eguitar,
|
||||||
|
)
|
||||||
|
name = "string instruments"
|
||||||
|
cost = 50
|
||||||
|
containertype = /obj/structure/closet/crate
|
||||||
|
containername = "string instrument crate"
|
||||||
|
|
||||||
|
/datum/supply_pack/musical/wind
|
||||||
|
contains = list(
|
||||||
|
/obj/item/instrument/accordion,
|
||||||
|
/obj/item/instrument/trumpet,
|
||||||
|
/obj/item/instrument/saxophone,
|
||||||
|
/obj/item/instrument/trombone,
|
||||||
|
/obj/item/instrument/recorder,
|
||||||
|
/obj/item/instrument/harmonica,
|
||||||
|
/obj/item/instrument/bikehorn,
|
||||||
|
)
|
||||||
|
name = "wind instruments"
|
||||||
|
cost = 50
|
||||||
|
containertype = /obj/structure/closet/crate
|
||||||
|
containername = "wind instrument crate"
|
||||||
|
|
||||||
|
/datum/supply_pack/musical/keys
|
||||||
|
contains = list(
|
||||||
|
/obj/item/instrument/piano_synth,
|
||||||
|
/obj/item/instrument/glockenspiel, // cough
|
||||||
|
/obj/item/instrument/musicalmoth
|
||||||
|
)
|
||||||
|
name = "keyed instruments"
|
||||||
|
cost = 50
|
||||||
|
containertype = /obj/structure/closet/crate
|
||||||
|
containername = "keyed instruments crate"
|
||||||
|
|
||||||
|
// /obj/item/instrument/piano_synth/headphones
|
||||||
@@ -339,7 +339,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
|||||||
icon_state = "thunder"
|
icon_state = "thunder"
|
||||||
requires_power = 0
|
requires_power = 0
|
||||||
dynamic_lighting = 0
|
dynamic_lighting = 0
|
||||||
sound_env = ARENA
|
sound_env = SOUND_ENVIRONMENT_ARENA
|
||||||
flags = AREA_FLAG_IS_NOT_PERSISTENT
|
flags = AREA_FLAG_IS_NOT_PERSISTENT
|
||||||
|
|
||||||
/area/tdome/tdome1
|
/area/tdome/tdome1
|
||||||
@@ -1289,28 +1289,28 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
|||||||
|
|
||||||
/area/holodeck/source_emptycourt
|
/area/holodeck/source_emptycourt
|
||||||
name = "\improper Holodeck - Empty Court"
|
name = "\improper Holodeck - Empty Court"
|
||||||
sound_env = ARENA
|
sound_env = SOUND_ENVIRONMENT_ARENA
|
||||||
|
|
||||||
/area/holodeck/source_boxingcourt
|
/area/holodeck/source_boxingcourt
|
||||||
name = "\improper Holodeck - Boxing Court"
|
name = "\improper Holodeck - Boxing Court"
|
||||||
sound_env = ARENA
|
sound_env = SOUND_ENVIRONMENT_ARENA
|
||||||
|
|
||||||
/area/holodeck/source_basketball
|
/area/holodeck/source_basketball
|
||||||
name = "\improper Holodeck - Basketball Court"
|
name = "\improper Holodeck - Basketball Court"
|
||||||
sound_env = ARENA
|
sound_env = SOUND_ENVIRONMENT_ARENA
|
||||||
|
|
||||||
/area/holodeck/source_thunderdomecourt
|
/area/holodeck/source_thunderdomecourt
|
||||||
name = "\improper Holodeck - Thunderdome Court"
|
name = "\improper Holodeck - Thunderdome Court"
|
||||||
requires_power = 0
|
requires_power = 0
|
||||||
sound_env = ARENA
|
sound_env = SOUND_ENVIRONMENT_ARENA
|
||||||
|
|
||||||
/area/holodeck/source_courtroom
|
/area/holodeck/source_courtroom
|
||||||
name = "\improper Holodeck - Courtroom"
|
name = "\improper Holodeck - Courtroom"
|
||||||
sound_env = AUDITORIUM
|
sound_env = SOUND_ENVIRONMENT_AUDITORIUM
|
||||||
|
|
||||||
/area/holodeck/source_beach
|
/area/holodeck/source_beach
|
||||||
name = "\improper Holodeck - Beach"
|
name = "\improper Holodeck - Beach"
|
||||||
sound_env = PLAIN
|
sound_env = SOUND_ENVIRONMENT_PLAIN
|
||||||
|
|
||||||
/area/holodeck/source_burntest
|
/area/holodeck/source_burntest
|
||||||
name = "\improper Holodeck - Atmospheric Burn Test"
|
name = "\improper Holodeck - Atmospheric Burn Test"
|
||||||
@@ -1320,23 +1320,23 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
|||||||
|
|
||||||
/area/holodeck/source_meetinghall
|
/area/holodeck/source_meetinghall
|
||||||
name = "\improper Holodeck - Meeting Hall"
|
name = "\improper Holodeck - Meeting Hall"
|
||||||
sound_env = AUDITORIUM
|
sound_env = SOUND_ENVIRONMENT_AUDITORIUM
|
||||||
|
|
||||||
/area/holodeck/source_theatre
|
/area/holodeck/source_theatre
|
||||||
name = "\improper Holodeck - Theatre"
|
name = "\improper Holodeck - Theatre"
|
||||||
sound_env = CONCERT_HALL
|
sound_env = SOUND_ENVIRONMENT_CONCERT_HALL
|
||||||
|
|
||||||
/area/holodeck/source_picnicarea
|
/area/holodeck/source_picnicarea
|
||||||
name = "\improper Holodeck - Picnic Area"
|
name = "\improper Holodeck - Picnic Area"
|
||||||
sound_env = PLAIN
|
sound_env = SOUND_ENVIRONMENT_PLAIN
|
||||||
|
|
||||||
/area/holodeck/source_snowfield
|
/area/holodeck/source_snowfield
|
||||||
name = "\improper Holodeck - Snow Field"
|
name = "\improper Holodeck - Snow Field"
|
||||||
sound_env = FOREST
|
sound_env = SOUND_ENVIRONMENT_FOREST
|
||||||
|
|
||||||
/area/holodeck/source_desert
|
/area/holodeck/source_desert
|
||||||
name = "\improper Holodeck - Desert"
|
name = "\improper Holodeck - Desert"
|
||||||
sound_env = PLAIN
|
sound_env = SOUND_ENVIRONMENT_PLAIN
|
||||||
|
|
||||||
/area/holodeck/source_space
|
/area/holodeck/source_space
|
||||||
name = "\improper Holodeck - Space"
|
name = "\improper Holodeck - Space"
|
||||||
|
|||||||
@@ -669,3 +669,6 @@
|
|||||||
|
|
||||||
/atom/proc/get_visible_gender()
|
/atom/proc/get_visible_gender()
|
||||||
return gender
|
return gender
|
||||||
|
|
||||||
|
/atom/proc/interact(mob/user)
|
||||||
|
return
|
||||||
|
|||||||
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
clicksound = "keyboard"
|
clicksound = "keyboard"
|
||||||
|
|
||||||
/obj/machinery/computer/New()
|
|
||||||
..()
|
|
||||||
|
|
||||||
/obj/machinery/computer/Initialize()
|
/obj/machinery/computer/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
power_change()
|
power_change()
|
||||||
|
|||||||
@@ -1054,7 +1054,9 @@
|
|||||||
/obj/item/device/radio/headset = 10,
|
/obj/item/device/radio/headset = 10,
|
||||||
/obj/item/device/flashlight = 5,
|
/obj/item/device/flashlight = 5,
|
||||||
/obj/item/device/laser_pointer = 3,
|
/obj/item/device/laser_pointer = 3,
|
||||||
/obj/item/clothing/glasses/omnihud = 10)
|
/obj/item/clothing/glasses/omnihud = 10,
|
||||||
|
/obj/item/instrument/piano_synth/headphones = 2, // You're making a subsystem do work, I don't want it TOO busy
|
||||||
|
/obj/item/instrument/piano_synth/headphones/spacepods = 2)
|
||||||
prices = list(/obj/item/clothing/suit/circuitry = 100,
|
prices = list(/obj/item/clothing/suit/circuitry = 100,
|
||||||
/obj/item/clothing/head/circuitry = 100,
|
/obj/item/clothing/head/circuitry = 100,
|
||||||
/obj/item/clothing/shoes/circuitry = 100,
|
/obj/item/clothing/shoes/circuitry = 100,
|
||||||
@@ -1074,7 +1076,9 @@
|
|||||||
/obj/item/device/radio/headset = 50,
|
/obj/item/device/radio/headset = 50,
|
||||||
/obj/item/device/flashlight = 100,
|
/obj/item/device/flashlight = 100,
|
||||||
/obj/item/device/laser_pointer = 200,
|
/obj/item/device/laser_pointer = 200,
|
||||||
/obj/item/clothing/glasses/omnihud = 100)
|
/obj/item/clothing/glasses/omnihud = 100,
|
||||||
|
/obj/item/instrument/piano_synth/headphones = 200,
|
||||||
|
/obj/item/instrument/piano_synth/headphones/spacepods = 600)
|
||||||
premium = list(/obj/item/device/perfect_tele/one_beacon = 1)
|
premium = list(/obj/item/device/perfect_tele/one_beacon = 1)
|
||||||
contraband = list(/obj/item/weapon/disk/nifsoft/compliance = 1)
|
contraband = list(/obj/item/weapon/disk/nifsoft/compliance = 1)
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
icon = 'icons/effects/effects_vr.dmi'
|
icon = 'icons/effects/effects_vr.dmi'
|
||||||
icon_state = "confetti"
|
icon_state = "confetti"
|
||||||
|
|
||||||
/obj/effect/effect/sparks/New()
|
/obj/effect/effect/sparks/Initialize()
|
||||||
..()
|
. = ..()
|
||||||
playsound(src, "sounds/items/confetti.ogg ", 100, 1)
|
playsound(src, "sounds/items/confetti.ogg ", 100, 1)
|
||||||
|
|
||||||
/datum/effect/effect/system/confetti_spread
|
/datum/effect/effect/system/confetti_spread
|
||||||
|
|||||||
@@ -99,15 +99,12 @@ steam.start() -- spawns the effect
|
|||||||
anchored = 1.0
|
anchored = 1.0
|
||||||
mouse_opacity = 0
|
mouse_opacity = 0
|
||||||
|
|
||||||
/obj/effect/effect/sparks/New()
|
/obj/effect/effect/sparks/Initialize()
|
||||||
..()
|
. = ..()
|
||||||
playsound(src, "sparks", 100, 1)
|
playsound(src, "sparks", 100, 1)
|
||||||
var/turf/T = src.loc
|
var/turf/T = src.loc
|
||||||
if (istype(T, /turf))
|
if (istype(T, /turf))
|
||||||
T.hotspot_expose(1000,100)
|
T.hotspot_expose(1000,100)
|
||||||
|
|
||||||
/obj/effect/effect/sparks/Initialize()
|
|
||||||
. = ..()
|
|
||||||
QDEL_IN(src, 5 SECONDS)
|
QDEL_IN(src, 5 SECONDS)
|
||||||
|
|
||||||
/obj/effect/effect/sparks/Destroy()
|
/obj/effect/effect/sparks/Destroy()
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus,
|
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiadeus,
|
||||||
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris,
|
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris,
|
||||||
/obj/item/device/paicard,
|
/obj/item/device/paicard,
|
||||||
/obj/item/device/instrument/violin,
|
/obj/item/instrument/violin,
|
||||||
/obj/item/weapon/storage/belt/utility/full,
|
/obj/item/weapon/storage/belt/utility/full,
|
||||||
/obj/item/clothing/accessory/tie/horrible)
|
/obj/item/clothing/accessory/tie/horrible)
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,6 @@
|
|||||||
tgui_interact(user)
|
tgui_interact(user)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/proc/interact(mob/user)
|
|
||||||
return
|
|
||||||
|
|
||||||
/mob/proc/unset_machine()
|
/mob/proc/unset_machine()
|
||||||
machine?.remove_visual(src)
|
machine?.remove_visual(src)
|
||||||
src.machine = null
|
src.machine = null
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
var/area/area_source = turf_source.loc
|
var/area/area_source = turf_source.loc
|
||||||
|
|
||||||
//allocate a channel if necessary now so its the same for everyone
|
//allocate a channel if necessary now so its the same for everyone
|
||||||
channel = channel || open_sound_channel()
|
channel = channel || SSsounds.random_available_channel()
|
||||||
|
|
||||||
// Looping through the player list has the added bonus of working for mobs inside containers
|
// Looping through the player list has the added bonus of working for mobs inside containers
|
||||||
var/sound/S = sound(get_sfx(soundin))
|
var/sound/S = sound(get_sfx(soundin))
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
S = sound(get_sfx(soundin))
|
S = sound(get_sfx(soundin))
|
||||||
|
|
||||||
S.wait = 0 //No queue
|
S.wait = 0 //No queue
|
||||||
S.channel = channel || open_sound_channel()
|
S.channel = channel || SSsounds.random_available_channel()
|
||||||
|
|
||||||
// I'm not sure if you can modify S.volume, but I'd rather not try to find out what
|
// I'm not sure if you can modify S.volume, but I'd rather not try to find out what
|
||||||
// horrible things lurk in BYOND's internals, so we're just gonna do vol *=
|
// horrible things lurk in BYOND's internals, so we're just gonna do vol *=
|
||||||
@@ -109,15 +109,14 @@
|
|||||||
var/mob/MO = M
|
var/mob/MO = M
|
||||||
MO.playsound_local(get_turf(MO), sound, volume, vary, pressure_affected = FALSE)
|
MO.playsound_local(get_turf(MO), sound, volume, vary, pressure_affected = FALSE)
|
||||||
|
|
||||||
/proc/open_sound_channel()
|
|
||||||
var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used
|
|
||||||
. = ++next_channel
|
|
||||||
if(next_channel > CHANNEL_HIGHEST_AVAILABLE)
|
|
||||||
next_channel = 1
|
|
||||||
|
|
||||||
/mob/proc/stop_sound_channel(chan)
|
/mob/proc/stop_sound_channel(chan)
|
||||||
src << sound(null, repeat = 0, wait = 0, channel = chan)
|
src << sound(null, repeat = 0, wait = 0, channel = chan)
|
||||||
|
|
||||||
|
/mob/proc/set_sound_channel_volume(channel, volume)
|
||||||
|
var/sound/S = sound(null, FALSE, FALSE, channel, volume)
|
||||||
|
S.status = SOUND_UPDATE
|
||||||
|
src << S
|
||||||
|
|
||||||
/proc/get_rand_frequency()
|
/proc/get_rand_frequency()
|
||||||
return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
|
return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
|
||||||
|
|
||||||
|
|||||||
113
code/modules/instruments/instrument_data/_instrument_data.dm
Normal file
113
code/modules/instruments/instrument_data/_instrument_data.dm
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* Get all non admin_only instruments as a list of text ids.
|
||||||
|
*/
|
||||||
|
/proc/get_allowed_instrument_ids()
|
||||||
|
. = list()
|
||||||
|
for(var/id in SSinstruments.instrument_data)
|
||||||
|
var/datum/instrument/I = SSinstruments.instrument_data[id]
|
||||||
|
if(!I.admin_only)
|
||||||
|
. += I.id
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # Instrument Datums
|
||||||
|
*
|
||||||
|
* Instrument datums hold the data for any given instrument, as well as data on how to play it and what bounds there are to playing it.
|
||||||
|
*
|
||||||
|
* The datums themselves are kept in SSinstruments in a list by their unique ID. The reason it uses ID instead of typepath is to support the runtime creation of instruments.
|
||||||
|
* Since songs cache them while playing, there isn't realistic issues regarding performance from accessing.
|
||||||
|
*/
|
||||||
|
/datum/instrument
|
||||||
|
/// Name of the instrument
|
||||||
|
var/name = "Generic instrument"
|
||||||
|
/// Uniquely identifies this instrument so runtime changes are possible as opposed to paths. If this is unset, things will use path instead.
|
||||||
|
var/id
|
||||||
|
/// Category
|
||||||
|
var/category = "Unsorted"
|
||||||
|
/// Used for categorization subtypes
|
||||||
|
var/abstract_type = /datum/instrument
|
||||||
|
/// 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/real_samples
|
||||||
|
/// assoc list key = /datum/instrument_key. do not fill this yourself!
|
||||||
|
var/list/samples
|
||||||
|
/// See __DEFINES/flags/instruments.dm
|
||||||
|
var/instrument_flags = NONE
|
||||||
|
/// For legacy instruments, the path to our notes
|
||||||
|
var/legacy_instrument_path
|
||||||
|
/// For legacy instruments, our file extension
|
||||||
|
var/legacy_instrument_ext
|
||||||
|
/// What songs are using us
|
||||||
|
var/list/datum/song/songs_using = list()
|
||||||
|
/// Don't touch this
|
||||||
|
var/static/HIGHEST_KEY = 127
|
||||||
|
/// Don't touch this x2
|
||||||
|
var/static/LOWEST_KEY = 0
|
||||||
|
/// Oh no - For truly troll instruments.
|
||||||
|
var/admin_only = FALSE
|
||||||
|
/// Volume multiplier. Synthesized instruments are quite loud and I don't like to cut off potential detail via editing. (someone correct me if this isn't a thing)
|
||||||
|
var/volume_multiplier = 0.33
|
||||||
|
|
||||||
|
/datum/instrument/New()
|
||||||
|
if(isnull(id))
|
||||||
|
id = "[type]"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the instrument, calculating its samples if necessary.
|
||||||
|
*/
|
||||||
|
/datum/instrument/proc/Initialize()
|
||||||
|
if(instrument_flags & (INSTRUMENT_LEGACY | INSTRUMENT_DO_NOT_AUTOSAMPLE))
|
||||||
|
return
|
||||||
|
calculate_samples()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this instrument is ready to play.
|
||||||
|
*/
|
||||||
|
/datum/instrument/proc/ready()
|
||||||
|
if(instrument_flags & INSTRUMENT_LEGACY)
|
||||||
|
return legacy_instrument_path && legacy_instrument_ext
|
||||||
|
else if(instrument_flags & INSTRUMENT_DO_NOT_AUTOSAMPLE)
|
||||||
|
return length(samples)
|
||||||
|
return (length(samples) >= 128)
|
||||||
|
|
||||||
|
/datum/instrument/Destroy()
|
||||||
|
SSinstruments.instrument_data -= id
|
||||||
|
for(var/i in songs_using)
|
||||||
|
var/datum/song/S = i
|
||||||
|
S.set_instrument(null)
|
||||||
|
real_samples = null
|
||||||
|
samples = null
|
||||||
|
songs_using = null
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For synthesized instruments, this is how the instrument generates the "keys" that a [/datum/song] uses to play notes.
|
||||||
|
* Calculating them on the fly would be unperformant, so we do it during init and keep it all cached in a list.
|
||||||
|
*/
|
||||||
|
/datum/instrument/proc/calculate_samples()
|
||||||
|
if(!length(real_samples))
|
||||||
|
CRASH("No real samples defined for [id] [type] on calculate_samples() call.")
|
||||||
|
var/list/real_keys = list()
|
||||||
|
samples = list()
|
||||||
|
for(var/key in real_samples)
|
||||||
|
real_keys += text2num(key)
|
||||||
|
sortTim(real_keys, /proc/cmp_numeric_asc, associative = FALSE)
|
||||||
|
|
||||||
|
for(var/i in 1 to (length(real_keys) - 1))
|
||||||
|
var/from_key = real_keys[i]
|
||||||
|
var/to_key = real_keys[i+1]
|
||||||
|
var/sample1 = real_samples[num2text(from_key)]
|
||||||
|
var/sample2 = real_samples[num2text(to_key)]
|
||||||
|
var/pivot = FLOOR((from_key + to_key) / 2, 1) //original code was a round but I replaced it because that's effectively a floor, thanks Baystation! who knows what was intended.
|
||||||
|
for(var/key in from_key to pivot)
|
||||||
|
samples[num2text(key)] = new /datum/instrument_key(sample1, key, key - from_key)
|
||||||
|
for(var/key in (pivot + 1) to to_key)
|
||||||
|
samples[num2text(key)] = new /datum/instrument_key(sample2, key, key - to_key)
|
||||||
|
|
||||||
|
// Fill in 0 to first key and last key to 127
|
||||||
|
var/first_key = real_keys[1]
|
||||||
|
var/last_key = real_keys[length(real_keys)]
|
||||||
|
var/first_sample = real_samples[num2text(first_key)]
|
||||||
|
var/last_sample = real_samples[num2text(last_key)]
|
||||||
|
for(var/key in LOWEST_KEY to (first_key - 1))
|
||||||
|
samples[num2text(key)] = new /datum/instrument_key(first_sample, key, key - first_key)
|
||||||
|
for(var/key in last_key to HIGHEST_KEY)
|
||||||
|
samples[num2text(key)] = new /datum/instrument_key(last_sample, key, key - last_key)
|
||||||
31
code/modules/instruments/instrument_data/_instrument_key.dm
Normal file
31
code/modules/instruments/instrument_data/_instrument_key.dm
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Instrument key datums contain everything needed to know how to play a specific
|
||||||
|
* note of an instrument.*
|
||||||
|
*/
|
||||||
|
/datum/instrument_key
|
||||||
|
/// The numerical key of what this is, from 1 to 127 on a standard piano keyboard.
|
||||||
|
var/key
|
||||||
|
/// The actual sample file that will be loaded when playing.
|
||||||
|
var/sample
|
||||||
|
/// The frequency to play the sample to get our desired note.
|
||||||
|
var/frequency
|
||||||
|
/// Deviation up/down from the pivot point that uses its sample. Used to calculate frequency.
|
||||||
|
var/deviation
|
||||||
|
|
||||||
|
/datum/instrument_key/New(sample = src.sample, key = src.key, deviation = src.deviation, frequency = src.frequency)
|
||||||
|
src.sample = sample
|
||||||
|
src.key = key
|
||||||
|
src.deviation = deviation
|
||||||
|
src.frequency = frequency
|
||||||
|
if(!frequency && deviation)
|
||||||
|
calculate()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates and stores our deviation.
|
||||||
|
*/
|
||||||
|
/datum/instrument_key/proc/calculate()
|
||||||
|
if(!deviation)
|
||||||
|
CRASH("Invalid calculate call: No deviation or sample in instrument_key")
|
||||||
|
#define KEY_TWELTH (1/12)
|
||||||
|
frequency = 2 ** (KEY_TWELTH * deviation)
|
||||||
|
#undef KEY_TWELTH
|
||||||
26
code/modules/instruments/instrument_data/brass.dm
Normal file
26
code/modules/instruments/instrument_data/brass.dm
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/datum/instrument/brass
|
||||||
|
name = "Generic brass instrument"
|
||||||
|
category = "Brass"
|
||||||
|
abstract_type = /datum/instrument/brass
|
||||||
|
|
||||||
|
/datum/instrument/brass/crisis_section
|
||||||
|
name = "Crisis Brass Section"
|
||||||
|
id = "crbrass"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/brass/crisis_trombone
|
||||||
|
name = "Crisis Trombone"
|
||||||
|
id = "crtrombone"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/brass/crisis_trombone/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/brass/crisis_trombone/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/brass/crisis_trombone/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/brass/crisis_trombone/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/brass/crisis_trumpet
|
||||||
|
name = "Crisis Trumpet"
|
||||||
|
id = "crtrumpet"
|
||||||
|
real_samples = list("60"='sound/instruments/synthesis_samples/brass/crisis_trumpet/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/brass/crisis_trumpet/c5.ogg')
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/datum/instrument/chromatic
|
||||||
|
name = "Generic chromatic percussion instrument"
|
||||||
|
category = "Chromatic percussion"
|
||||||
|
abstract_type = /datum/instrument/chromatic
|
||||||
|
|
||||||
|
/datum/instrument/chromatic/vibraphone1
|
||||||
|
name = "Crisis Vibraphone"
|
||||||
|
id = "crvibr"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/chromatic/vibraphone1/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/chromatic/musicbox1
|
||||||
|
name = "SGM Music Box"
|
||||||
|
id = "sgmmbox"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/sgmbox/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/chromatic/sgmbox/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/chromatic/sgmbox/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/chromatic/sgmbox/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/chromatic/fluid_celeste
|
||||||
|
name = "FluidR3 Celeste"
|
||||||
|
id = "r3celeste"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c5.ogg',
|
||||||
|
"84"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c6.ogg',
|
||||||
|
"96"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c7.ogg',
|
||||||
|
"108"='sound/instruments/synthesis_samples/chromatic/fluid_celeste/c8.ogg')
|
||||||
25
code/modules/instruments/instrument_data/fun.dm
Normal file
25
code/modules/instruments/instrument_data/fun.dm
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/datum/instrument/fun
|
||||||
|
name = "Generic Fun Instrument"
|
||||||
|
category = "Fun"
|
||||||
|
abstract_type = /datum/instrument/fun
|
||||||
|
|
||||||
|
/datum/instrument/fun/honk
|
||||||
|
name = "!!HONK!!"
|
||||||
|
id = "honk"
|
||||||
|
real_samples = list("74"='sound/items/bikehorn.ogg') // Cluwne Heaven
|
||||||
|
|
||||||
|
/datum/instrument/fun/signal
|
||||||
|
name = "Ping"
|
||||||
|
id = "ping"
|
||||||
|
real_samples = list("79"='sound/machines/ping.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/fun/chime
|
||||||
|
name = "Chime"
|
||||||
|
id = "chime"
|
||||||
|
real_samples = list("79"='sound/machines/chime.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/fun/mothscream
|
||||||
|
name = "Moth Scream"
|
||||||
|
id = "mothscream"
|
||||||
|
real_samples = list("60"='sound/voice/moth/scream_moth.ogg')
|
||||||
|
admin_only = TRUE
|
||||||
36
code/modules/instruments/instrument_data/guitar.dm
Normal file
36
code/modules/instruments/instrument_data/guitar.dm
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/datum/instrument/guitar
|
||||||
|
name = "Generic guitar-like instrument"
|
||||||
|
category = "Guitar"
|
||||||
|
abstract_type = /datum/instrument/guitar
|
||||||
|
|
||||||
|
/datum/instrument/guitar/steel_crisis
|
||||||
|
name = "Crisis Steel String Guitar"
|
||||||
|
id = "csteelgt"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_steel/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/guitar/crisis_steel/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/guitar/crisis_steel/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/guitar/crisis_steel/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/guitar/nylon_crisis
|
||||||
|
name = "Crisis Nylon String Guitar"
|
||||||
|
id = "cnylongt"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/guitar/crisis_nylon/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/guitar/clean_crisis
|
||||||
|
name = "Crisis Clean Guitar"
|
||||||
|
id = "ccleangt"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_clean/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/guitar/crisis_clean/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/guitar/crisis_clean/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/guitar/crisis_clean/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/guitar/muted_crisis
|
||||||
|
name = "Crisis Muted Guitar"
|
||||||
|
id = "cmutedgt"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/guitar/crisis_muted/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/guitar/crisis_muted/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/guitar/crisis_muted/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/guitar/crisis_muted/c5.ogg')
|
||||||
86
code/modules/instruments/instrument_data/hardcoded.dm
Normal file
86
code/modules/instruments/instrument_data/hardcoded.dm
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
//THESE ARE HARDCODED INSTRUMENT SAMPLES.
|
||||||
|
//SONGS WILL BE AUTOMATICALLY SWITCHED TO LEGACY MODE IF THEY USE THIS KIND OF INSTRUMENT!
|
||||||
|
//I'd prefer these stayed. They sound different from the mechanical synthesis of synthed instruments, and I quite like them that way. It's not legacy, it's hardcoded, old style. - kevinz000
|
||||||
|
/datum/instrument/hardcoded
|
||||||
|
abstract_type = /datum/instrument/hardcoded
|
||||||
|
category = "Non-Synthesized"
|
||||||
|
instrument_flags = INSTRUMENT_LEGACY
|
||||||
|
volume_multiplier = 1 //not as loud as synth'd
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/accordion
|
||||||
|
name = "Accordion"
|
||||||
|
id = "accordion"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "accordion"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/bikehorn
|
||||||
|
name = "Bike Horn"
|
||||||
|
id = "bikehorn"
|
||||||
|
legacy_instrument_ext = "ogg"
|
||||||
|
legacy_instrument_path = "bikehorn"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/eguitar
|
||||||
|
name = "Electric Guitar"
|
||||||
|
id = "eguitar"
|
||||||
|
legacy_instrument_ext = "ogg"
|
||||||
|
legacy_instrument_path = "eguitar"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/glockenspiel
|
||||||
|
name = "Glockenspiel"
|
||||||
|
id = "glockenspiel"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "glockenspiel"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/guitar
|
||||||
|
name = "Guitar"
|
||||||
|
id = "guitar"
|
||||||
|
legacy_instrument_ext = "ogg"
|
||||||
|
legacy_instrument_path = "guitar"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/harmonica
|
||||||
|
name = "Harmonica"
|
||||||
|
id = "harmonica"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "harmonica"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/piano
|
||||||
|
name = "Piano"
|
||||||
|
id = "piano"
|
||||||
|
legacy_instrument_ext = "ogg"
|
||||||
|
legacy_instrument_path = "piano"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/recorder
|
||||||
|
name = "Recorder"
|
||||||
|
id = "recorder"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "recorder"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/saxophone
|
||||||
|
name = "Saxophone"
|
||||||
|
id = "saxophone"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "saxophone"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/trombone
|
||||||
|
name = "Trombone"
|
||||||
|
id = "trombone"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "trombone"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/violin
|
||||||
|
name = "Violin"
|
||||||
|
id = "violin"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "violin"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/xylophone
|
||||||
|
name = "Xylophone"
|
||||||
|
id = "xylophone"
|
||||||
|
legacy_instrument_ext = "mid"
|
||||||
|
legacy_instrument_path = "xylophone"
|
||||||
|
|
||||||
|
/datum/instrument/hardcoded/banjo
|
||||||
|
name = "Banjo"
|
||||||
|
id = "banjo"
|
||||||
|
legacy_instrument_ext = "ogg"
|
||||||
|
legacy_instrument_path = "banjo"
|
||||||
43
code/modules/instruments/instrument_data/organ.dm
Normal file
43
code/modules/instruments/instrument_data/organ.dm
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/datum/instrument/organ
|
||||||
|
name = "Generic organ"
|
||||||
|
category = "Organ"
|
||||||
|
abstract_type = /datum/instrument/organ
|
||||||
|
|
||||||
|
/datum/instrument/organ/crisis_church
|
||||||
|
name = "Crisis Church Organ"
|
||||||
|
id = "crichugan"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_church/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/organ/crisis_church/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/organ/crisis_church/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/organ/crisis_church/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/organ/crisis_hammond
|
||||||
|
name = "Crisis Hammond Organ"
|
||||||
|
id = "crihamgan"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_hammond/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/organ/crisis_hammond/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/organ/crisis_hammond/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/organ/crisis_hammond/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/organ/crisis_accordian
|
||||||
|
name = "Crisis Accordian"
|
||||||
|
id = "crack"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_accordian/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/organ/crisis_accordian/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/organ/crisis_accordian/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/organ/crisis_accordian/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/organ/crisis_harmonica
|
||||||
|
name = "Crisis Harmonica"
|
||||||
|
id = "crharmony"
|
||||||
|
real_samples = list("48"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/organ/crisis_harmonica/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/organ/crisis_tango_accordian
|
||||||
|
name = "Crisis Tango Accordian"
|
||||||
|
id = "crtango"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/organ/crisis_tangaccordian/c5.ogg')
|
||||||
56
code/modules/instruments/instrument_data/piano.dm
Normal file
56
code/modules/instruments/instrument_data/piano.dm
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/datum/instrument/piano
|
||||||
|
name = "Generic piano"
|
||||||
|
category = "Piano"
|
||||||
|
abstract_type = /datum/instrument/piano
|
||||||
|
|
||||||
|
/datum/instrument/piano/fluid_piano
|
||||||
|
name = "FluidR3 Grand Piano"
|
||||||
|
id = "r3grand"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/piano/fluid_piano/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/piano/fluid_piano/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/piano/fluid_piano/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/piano/fluid_piano/c5.ogg',
|
||||||
|
"84"='sound/instruments/synthesis_samples/piano/fluid_piano/c6.ogg',
|
||||||
|
"96"='sound/instruments/synthesis_samples/piano/fluid_piano/c7.ogg',
|
||||||
|
"108"='sound/instruments/synthesis_samples/piano/fluid_piano/c8.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/piano/fluid_harpsichord
|
||||||
|
name = "FluidR3 Harpsichord"
|
||||||
|
id = "r3harpsi"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c5.ogg',
|
||||||
|
"84"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c6.ogg',
|
||||||
|
"96"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c7.ogg',
|
||||||
|
"108"='sound/instruments/synthesis_samples/piano/fluid_harpsi/c8.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/piano/crisis_harpsichord
|
||||||
|
name = "Crisis Harpsichord"
|
||||||
|
id = "crharpsi"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/piano/crisis_harpsichord/c5.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/piano/crisis_grandpiano_uni
|
||||||
|
name = "Crisis Grand Piano One"
|
||||||
|
id = "crgrand1"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c5.ogg',
|
||||||
|
"84"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c6.ogg',
|
||||||
|
"96"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c7.ogg',
|
||||||
|
"108"='sound/instruments/synthesis_samples/piano/crisis_grand_piano/c8.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/piano/crisis_brightpiano_uni
|
||||||
|
name = "Crisis Bright Piano One"
|
||||||
|
id = "crbright1"
|
||||||
|
real_samples = list("36"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c2.ogg',
|
||||||
|
"48"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c3.ogg',
|
||||||
|
"60"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c4.ogg',
|
||||||
|
"72"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c5.ogg',
|
||||||
|
"84"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c6.ogg',
|
||||||
|
"96"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c7.ogg',
|
||||||
|
"108"='sound/instruments/synthesis_samples/piano/crisis_bright_piano/c8.ogg')
|
||||||
19
code/modules/instruments/instrument_data/synth_tones.dm
Normal file
19
code/modules/instruments/instrument_data/synth_tones.dm
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/datum/instrument/tones
|
||||||
|
name = "Ideal tone"
|
||||||
|
category = "Tones"
|
||||||
|
abstract_type = /datum/instrument/tones
|
||||||
|
|
||||||
|
/datum/instrument/tones/square_wave
|
||||||
|
name = "Ideal square wave"
|
||||||
|
id = "square"
|
||||||
|
real_samples = list("81"='sound/instruments/synthesis_samples/tones/Square.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/tones/sine_wave
|
||||||
|
name = "Ideal sine wave"
|
||||||
|
id = "sine"
|
||||||
|
real_samples = list("81"='sound/instruments/synthesis_samples/tones/Sine.ogg')
|
||||||
|
|
||||||
|
/datum/instrument/tones/saw_wave
|
||||||
|
name = "Ideal sawtooth wave"
|
||||||
|
id = "saw"
|
||||||
|
real_samples = list("81"='sound/instruments/synthesis_samples/tones/Sawtooth.ogg')
|
||||||
312
code/modules/instruments/items.dm
Normal file
312
code/modules/instruments/items.dm
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
//copy pasta of the space piano, don't hurt me -Pete
|
||||||
|
/obj/item/instrument
|
||||||
|
name = "generic instrument"
|
||||||
|
force = 10
|
||||||
|
health = 100
|
||||||
|
//resistance_flags = FLAMMABLE
|
||||||
|
icon = 'icons/obj/musician.dmi'
|
||||||
|
item_icons = list(
|
||||||
|
slot_l_hand_str = 'icons/mob/items/lefthand_instruments.dmi',
|
||||||
|
slot_r_hand_str = 'icons/mob/items/righthand_instruments.dmi',
|
||||||
|
)
|
||||||
|
|
||||||
|
/// Our song datum.
|
||||||
|
var/datum/song/handheld/song
|
||||||
|
/// Our allowed list of instrument ids. This is nulled on initialize.
|
||||||
|
var/list/allowed_instrument_ids
|
||||||
|
/// How far away our song datum can be heard.
|
||||||
|
var/instrument_range = 15
|
||||||
|
|
||||||
|
/obj/item/instrument/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
song = new(src, allowed_instrument_ids, instrument_range)
|
||||||
|
allowed_instrument_ids = null //We don't need this clogging memory after it's used.
|
||||||
|
|
||||||
|
/obj/item/instrument/Destroy()
|
||||||
|
QDEL_NULL(song)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/item/instrument/proc/should_stop_playing(mob/user)
|
||||||
|
return user.incapacitated() || !((loc == user) || (isturf(loc) && Adjacent(user))) // sorry, no more TK playing.
|
||||||
|
|
||||||
|
/obj/item/instrument/suicide_act(mob/user)
|
||||||
|
var/datum/gender/T = gender_datums[user.get_visible_gender()]
|
||||||
|
user.visible_message("<span class='suicide'>[user] begins to play 'Gloomy Sunday'! It looks like [T.hes] trying to commit suicide!</span>")
|
||||||
|
return (BRUTELOSS)
|
||||||
|
|
||||||
|
/obj/item/instrument/attack_self(mob/user)
|
||||||
|
if(!user.IsAdvancedToolUser())
|
||||||
|
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||||
|
return TRUE
|
||||||
|
interact(user)
|
||||||
|
|
||||||
|
/obj/item/instrument/interact(mob/living/user)
|
||||||
|
if(!isliving(user) || user.incapacitated())
|
||||||
|
return
|
||||||
|
|
||||||
|
user.set_machine(src)
|
||||||
|
song.interact(user)
|
||||||
|
|
||||||
|
/obj/item/instrument/violin
|
||||||
|
name = "space violin"
|
||||||
|
desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\""
|
||||||
|
icon_state = "violin"
|
||||||
|
hitsound = "swing_hit"
|
||||||
|
allowed_instrument_ids = "violin"
|
||||||
|
|
||||||
|
/obj/item/instrument/violin/golden
|
||||||
|
name = "golden violin"
|
||||||
|
desc = "A golden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\""
|
||||||
|
icon_state = "golden_violin"
|
||||||
|
|
||||||
|
/obj/item/instrument/piano_synth
|
||||||
|
name = "synthesizer"
|
||||||
|
desc = "An advanced electronic synthesizer that can be used as various instruments."
|
||||||
|
icon_state = "synth"
|
||||||
|
allowed_instrument_ids = "piano"
|
||||||
|
|
||||||
|
/obj/item/instrument/piano_synth/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
song.allowed_instrument_ids = SSinstruments.synthesizer_instrument_ids
|
||||||
|
|
||||||
|
/obj/item/instrument/piano_synth/headphones
|
||||||
|
name = "headphones"
|
||||||
|
desc = "Unce unce unce unce. Boop!"
|
||||||
|
icon_state = "headphones"
|
||||||
|
slot_flags = SLOT_EARS | SLOT_HEAD
|
||||||
|
force = 0
|
||||||
|
w_class = ITEMSIZE_SMALL
|
||||||
|
instrument_range = 1
|
||||||
|
|
||||||
|
/obj/item/instrument/piano_synth/headphones/Initialize()
|
||||||
|
. = ..()
|
||||||
|
RegisterSignal(src, COMSIG_SONG_START, .proc/start_playing)
|
||||||
|
RegisterSignal(src, COMSIG_SONG_END, .proc/stop_playing)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a component signal when our song starts playing.
|
||||||
|
*/
|
||||||
|
/obj/item/instrument/piano_synth/headphones/proc/start_playing()
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
|
||||||
|
icon_state = "[initial(icon_state)]_on"
|
||||||
|
if(ishuman(loc))
|
||||||
|
var/mob/living/carbon/human/H = loc
|
||||||
|
if(H.l_ear == src || H.r_ear == src)
|
||||||
|
H.update_inv_ears()
|
||||||
|
else if(H.head == src)
|
||||||
|
H.update_inv_head()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a component signal when our song stops playing.
|
||||||
|
*/
|
||||||
|
/obj/item/instrument/piano_synth/headphones/proc/stop_playing()
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
|
||||||
|
icon_state = "[initial(icon_state)]"
|
||||||
|
if(ishuman(loc))
|
||||||
|
var/mob/living/carbon/human/H = loc
|
||||||
|
if(H.l_ear == src || H.r_ear == src)
|
||||||
|
H.update_inv_ears()
|
||||||
|
else if(H.head == src)
|
||||||
|
H.update_inv_head()
|
||||||
|
|
||||||
|
|
||||||
|
/obj/item/instrument/piano_synth/headphones/spacepods
|
||||||
|
name = "\improper Nanotrasen space pods"
|
||||||
|
desc = "Flex your money, AND ignore what everyone else says, all at once!"
|
||||||
|
icon_state = "spacepods"
|
||||||
|
slot_flags = SLOT_EARS
|
||||||
|
//strip_delay = 100 //air pods don't fall out
|
||||||
|
instrument_range = 0 //you're paying for quality here
|
||||||
|
|
||||||
|
/obj/item/instrument/banjo
|
||||||
|
name = "banjo"
|
||||||
|
desc = "A 'Mura' brand banjo. It's pretty much just a drum with a neck and strings."
|
||||||
|
icon_state = "banjo"
|
||||||
|
attack_verb = list("scruggs-styled", "hum-diggitied", "shin-dug", "clawhammered")
|
||||||
|
hitsound = 'sound/weapons/banjoslap.ogg'
|
||||||
|
allowed_instrument_ids = "banjo"
|
||||||
|
|
||||||
|
/obj/item/instrument/guitar
|
||||||
|
name = "guitar"
|
||||||
|
desc = "It's made of wood and has bronze strings."
|
||||||
|
icon_state = "guitar"
|
||||||
|
attack_verb = list("played metal on", "serenaded", "crashed", "smashed")
|
||||||
|
hitsound = 'sound/weapons/stringsmash.ogg'
|
||||||
|
allowed_instrument_ids = list("guitar","csteelgt","cnylongt", "ccleangt", "cmutedgt")
|
||||||
|
|
||||||
|
/obj/item/instrument/eguitar
|
||||||
|
name = "electric guitar"
|
||||||
|
desc = "Makes all your shredding needs possible."
|
||||||
|
icon_state = "eguitar"
|
||||||
|
force = 12
|
||||||
|
attack_verb = list("played metal on", "shreded", "crashed", "smashed")
|
||||||
|
hitsound = 'sound/weapons/stringsmash.ogg'
|
||||||
|
allowed_instrument_ids = "eguitar"
|
||||||
|
|
||||||
|
/obj/item/instrument/glockenspiel
|
||||||
|
name = "glockenspiel"
|
||||||
|
desc = "Smooth metal bars perfect for any marching band."
|
||||||
|
icon_state = "glockenspiel"
|
||||||
|
allowed_instrument_ids = list("glockenspiel","crvibr", "sgmmbox", "r3celeste")
|
||||||
|
|
||||||
|
/obj/item/instrument/accordion
|
||||||
|
name = "accordion"
|
||||||
|
desc = "Pun-Pun not included."
|
||||||
|
icon_state = "accordion"
|
||||||
|
allowed_instrument_ids = list("crack", "crtango", "accordion")
|
||||||
|
|
||||||
|
/obj/item/instrument/trumpet
|
||||||
|
name = "trumpet"
|
||||||
|
desc = "To announce the arrival of the king!"
|
||||||
|
icon_state = "trumpet"
|
||||||
|
allowed_instrument_ids = "crtrumpet"
|
||||||
|
|
||||||
|
/obj/item/instrument/trumpet/spectral
|
||||||
|
name = "spectral trumpet"
|
||||||
|
desc = "Things are about to get spooky!"
|
||||||
|
icon_state = "spectral_trumpet"
|
||||||
|
force = 0
|
||||||
|
attack_verb = list("played", "jazzed", "trumpeted", "mourned", "dooted", "spooked")
|
||||||
|
|
||||||
|
/*
|
||||||
|
/obj/item/instrument/trumpet/spectral/Initialize()
|
||||||
|
. = ..()
|
||||||
|
AddComponent(/datum/component/spooky)
|
||||||
|
*/
|
||||||
|
/obj/item/instrument/trumpet/spectral/attack(mob/living/carbon/C, mob/user)
|
||||||
|
playsound (src, 'sound/instruments/trombone/En4.mid', 100,1,-1)
|
||||||
|
..()
|
||||||
|
|
||||||
|
/obj/item/instrument/saxophone
|
||||||
|
name = "saxophone"
|
||||||
|
desc = "This soothing sound will be sure to leave your audience in tears."
|
||||||
|
icon_state = "saxophone"
|
||||||
|
allowed_instrument_ids = "saxophone"
|
||||||
|
|
||||||
|
/obj/item/instrument/saxophone/spectral
|
||||||
|
name = "spectral saxophone"
|
||||||
|
desc = "This spooky sound will be sure to leave mortals in bones."
|
||||||
|
icon_state = "saxophone"
|
||||||
|
force = 0
|
||||||
|
attack_verb = list("played", "jazzed", "saxed", "mourned", "dooted", "spooked")
|
||||||
|
|
||||||
|
/*
|
||||||
|
/obj/item/instrument/saxophone/spectral/Initialize()
|
||||||
|
. = ..()
|
||||||
|
AddComponent(/datum/component/spooky)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/obj/item/instrument/saxophone/spectral/attack(mob/living/carbon/C, mob/user)
|
||||||
|
playsound (src, 'sound/instruments/saxophone/En4.mid', 100,1,-1)
|
||||||
|
..()
|
||||||
|
|
||||||
|
/obj/item/instrument/trombone
|
||||||
|
name = "trombone"
|
||||||
|
desc = "How can any pool table ever hope to compete?"
|
||||||
|
icon_state = "trombone"
|
||||||
|
allowed_instrument_ids = list("crtrombone", "crbrass", "trombone")
|
||||||
|
|
||||||
|
/obj/item/instrument/trombone/spectral
|
||||||
|
name = "spectral trombone"
|
||||||
|
desc = "A skeleton's favorite instrument. Apply directly on the mortals."
|
||||||
|
icon_state = "trombone"
|
||||||
|
force = 0
|
||||||
|
attack_verb = list("played", "jazzed", "tromboneed", "mourned", "dooted", "spooked")
|
||||||
|
|
||||||
|
/*
|
||||||
|
/obj/item/instrument/trombone/spectral/Initialize()
|
||||||
|
. = ..()
|
||||||
|
AddComponent(/datum/component/spooky)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/obj/item/instrument/trombone/spectral/attack(mob/living/carbon/C, mob/user)
|
||||||
|
playsound (src, 'sound/instruments/trombone/Cn4.mid', 100,1,-1)
|
||||||
|
..()
|
||||||
|
|
||||||
|
/obj/item/instrument/recorder
|
||||||
|
name = "recorder"
|
||||||
|
desc = "Just like in school, playing ability and all."
|
||||||
|
force = 5
|
||||||
|
icon_state = "recorder"
|
||||||
|
allowed_instrument_ids = "recorder"
|
||||||
|
|
||||||
|
/obj/item/instrument/harmonica
|
||||||
|
name = "harmonica"
|
||||||
|
desc = "For when you get a bad case of the space blues."
|
||||||
|
icon_state = "harmonica"
|
||||||
|
allowed_instrument_ids = list("crharmony", "harmonica")
|
||||||
|
slot_flags = SLOT_MASK
|
||||||
|
force = 5
|
||||||
|
w_class = ITEMSIZE_SMALL
|
||||||
|
/*
|
||||||
|
actions_types = list(/datum/action/item_action/instrument)
|
||||||
|
|
||||||
|
/obj/item/instrument/harmonica/proc/handle_speech(datum/source, list/speech_args)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
if(song.playing && ismob(loc))
|
||||||
|
to_chat(loc, "<span class='warning'>You stop playing the harmonica to talk...</span>")
|
||||||
|
song.playing = FALSE
|
||||||
|
|
||||||
|
/obj/item/instrument/harmonica/equipped(mob/M, slot)
|
||||||
|
. = ..()
|
||||||
|
RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||||
|
|
||||||
|
/obj/item/instrument/harmonica/dropped(mob/M)
|
||||||
|
. = ..()
|
||||||
|
UnregisterSignal(M, COMSIG_MOB_SAY)
|
||||||
|
*/
|
||||||
|
/obj/item/instrument/bikehorn
|
||||||
|
name = "gilded bike horn"
|
||||||
|
desc = "An exquisitely decorated bike horn, capable of honking in a variety of notes."
|
||||||
|
icon_state = "bike_horn"
|
||||||
|
item_icons = list(
|
||||||
|
slot_l_hand_str = 'icons/mob/items/lefthand_horns.dmi',
|
||||||
|
slot_r_hand_str = 'icons/mob/items/righthand_horns.dmi',
|
||||||
|
)
|
||||||
|
allowed_instrument_ids = list("bikehorn", "honk")
|
||||||
|
attack_verb = list("beautifully honked")
|
||||||
|
w_class = ITEMSIZE_SMALL
|
||||||
|
force = 0
|
||||||
|
throw_speed = 3
|
||||||
|
throw_range = 15
|
||||||
|
hitsound = 'sound/items/bikehorn.ogg'
|
||||||
|
/*
|
||||||
|
/obj/item/choice_beacon/music
|
||||||
|
name = "instrument delivery beacon"
|
||||||
|
desc = "Summon your tool of art."
|
||||||
|
icon_state = "gangtool-red"
|
||||||
|
|
||||||
|
/obj/item/choice_beacon/music/generate_display_names()
|
||||||
|
var/static/list/instruments
|
||||||
|
if(!instruments)
|
||||||
|
instruments = list()
|
||||||
|
var/list/templist = list(/obj/item/instrument/violin,
|
||||||
|
/obj/item/instrument/piano_synth,
|
||||||
|
/obj/item/instrument/banjo,
|
||||||
|
/obj/item/instrument/guitar,
|
||||||
|
/obj/item/instrument/eguitar,
|
||||||
|
/obj/item/instrument/glockenspiel,
|
||||||
|
/obj/item/instrument/accordion,
|
||||||
|
/obj/item/instrument/trumpet,
|
||||||
|
/obj/item/instrument/saxophone,
|
||||||
|
/obj/item/instrument/trombone,
|
||||||
|
/obj/item/instrument/recorder,
|
||||||
|
/obj/item/instrument/harmonica,
|
||||||
|
/obj/item/instrument/piano_synth/headphones
|
||||||
|
)
|
||||||
|
for(var/V in templist)
|
||||||
|
var/atom/A = V
|
||||||
|
instruments[initial(A.name)] = A
|
||||||
|
return instruments
|
||||||
|
*/
|
||||||
|
/obj/item/instrument/musicalmoth
|
||||||
|
name = "musical moth"
|
||||||
|
desc = "Despite its popularity, this controversial musical toy was eventually banned due to its unethically sampled sounds of moths screaming in agony."
|
||||||
|
icon_state = "mothsician"
|
||||||
|
allowed_instrument_ids = "mothscream"
|
||||||
|
attack_verb = list("fluttered", "flaped")
|
||||||
|
w_class = ITEMSIZE_SMALL
|
||||||
|
force = 0
|
||||||
|
hitsound = 'sound/voice/moth/scream_moth.ogg'
|
||||||
405
code/modules/instruments/songs/_song.dm
Normal file
405
code/modules/instruments/songs/_song.dm
Normal file
@@ -0,0 +1,405 @@
|
|||||||
|
#define MUSICIAN_HEARCHECK_MINDELAY 4
|
||||||
|
#define MUSIC_MAXLINES 1000
|
||||||
|
#define MUSIC_MAXLINECHARS 300
|
||||||
|
|
||||||
|
/**
|
||||||
|
* # Song datum
|
||||||
|
*
|
||||||
|
* These are the actual backend behind instruments.
|
||||||
|
* They attach to an atom and provide the editor + playback functionality.
|
||||||
|
*/
|
||||||
|
/datum/song
|
||||||
|
/// Name of the song
|
||||||
|
var/name = "Untitled"
|
||||||
|
|
||||||
|
/// The atom we're attached to/playing from
|
||||||
|
var/atom/parent
|
||||||
|
|
||||||
|
/// Our song lines
|
||||||
|
var/list/lines
|
||||||
|
|
||||||
|
/// delay between notes in deciseconds
|
||||||
|
var/tempo = 5
|
||||||
|
|
||||||
|
/// How far we can be heard
|
||||||
|
var/instrument_range = 15
|
||||||
|
|
||||||
|
/// Are we currently playing?
|
||||||
|
var/playing = FALSE
|
||||||
|
|
||||||
|
/// Are we currently editing?
|
||||||
|
var/editing = TRUE
|
||||||
|
/// Is the help screen open?
|
||||||
|
var/help = FALSE
|
||||||
|
|
||||||
|
/// Repeats left
|
||||||
|
var/repeat = 0
|
||||||
|
/// Maximum times we can repeat
|
||||||
|
var/max_repeats = 10
|
||||||
|
|
||||||
|
/// Our volume
|
||||||
|
var/volume = 35
|
||||||
|
/// Max volume
|
||||||
|
var/max_volume = 75
|
||||||
|
/// Min volume - This is so someone doesn't decide it's funny to set it to 0 and play invisible songs.
|
||||||
|
var/min_volume = 1
|
||||||
|
|
||||||
|
/// What instruments our built in picker can use. The picker won't show unless this is longer than one.
|
||||||
|
var/list/allowed_instrument_ids = list("r3grand")
|
||||||
|
|
||||||
|
//////////// Cached instrument variables /////////////
|
||||||
|
/// Instrument we are currently using
|
||||||
|
var/datum/instrument/using_instrument
|
||||||
|
/// Cached legacy ext for legacy instruments
|
||||||
|
var/cached_legacy_ext
|
||||||
|
/// Cached legacy dir for legacy instruments
|
||||||
|
var/cached_legacy_dir
|
||||||
|
/// Cached list of samples, referenced directly from the instrument for synthesized instruments
|
||||||
|
var/list/cached_samples
|
||||||
|
/// Are we operating in legacy mode (so if the instrument is a legacy instrument)
|
||||||
|
var/legacy = FALSE
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////// Playing variables ////////////////
|
||||||
|
/**
|
||||||
|
* Build by compile_chords()
|
||||||
|
* Must be rebuilt on instrument switch.
|
||||||
|
* Compilation happens when we start playing and is cleared after we finish playing.
|
||||||
|
* Format: list of chord lists, with chordlists having (key1, key2, key3, tempodiv)
|
||||||
|
*/
|
||||||
|
var/list/compiled_chords
|
||||||
|
/// Current section of a long chord we're on, so we don't need to make a billion chords, one for every unit ticklag.
|
||||||
|
var/elapsed_delay
|
||||||
|
/// Amount of delay to wait before playing the next chord
|
||||||
|
var/delay_by
|
||||||
|
/// Current chord we're on.
|
||||||
|
var/current_chord
|
||||||
|
/// Channel as text = current volume percentage but it's 0 to 100 instead of 0 to 1.
|
||||||
|
var/list/channels_playing = list()
|
||||||
|
/// List of channels that aren't being used, as text. This is to prevent unnecessary freeing and reallocations from SSsounds/SSinstruments.
|
||||||
|
var/list/channels_idle = list()
|
||||||
|
/// Person playing us
|
||||||
|
var/mob/user_playing
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Last world.time we checked for who can hear us
|
||||||
|
var/last_hearcheck = 0
|
||||||
|
/// The list of mobs that can hear us
|
||||||
|
var/list/hearing_mobs
|
||||||
|
/// If this is enabled, some things won't be strictly cleared when they usually are (liked compiled_chords on play stop)
|
||||||
|
var/debug_mode = FALSE
|
||||||
|
/// Max sound channels to occupy
|
||||||
|
var/max_sound_channels = CHANNELS_PER_INSTRUMENT
|
||||||
|
/// Current channels, so we can save a length() call.
|
||||||
|
var/using_sound_channels = 0
|
||||||
|
/// Last channel to play. text.
|
||||||
|
var/last_channel_played
|
||||||
|
/// Should we not decay our last played note?
|
||||||
|
var/full_sustain_held_note = TRUE
|
||||||
|
|
||||||
|
/////////////////////// DO NOT TOUCH THESE ///////////////////
|
||||||
|
var/octave_min = INSTRUMENT_MIN_OCTAVE
|
||||||
|
var/octave_max = INSTRUMENT_MAX_OCTAVE
|
||||||
|
var/key_min = INSTRUMENT_MIN_KEY
|
||||||
|
var/key_max = INSTRUMENT_MAX_KEY
|
||||||
|
var/static/list/note_offset_lookup = list(9, 11, 0, 2, 4, 5, 7)
|
||||||
|
var/static/list/accent_lookup = list("b" = -1, "s" = 1, "#" = 1, "n" = 0)
|
||||||
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///////////// !!FUN!! - Only works in synthesized mode! /////////////////
|
||||||
|
/// Note numbers to shift.
|
||||||
|
var/note_shift = 0
|
||||||
|
var/note_shift_min = -100
|
||||||
|
var/note_shift_max = 100
|
||||||
|
var/can_noteshift = TRUE
|
||||||
|
/// The kind of sustain we're using
|
||||||
|
var/sustain_mode = SUSTAIN_LINEAR
|
||||||
|
/// When a note is considered dead if it is below this in volume
|
||||||
|
var/sustain_dropoff_volume = 0
|
||||||
|
/// Total duration of linear sustain for 100 volume note to get to SUSTAIN_DROPOFF
|
||||||
|
var/sustain_linear_duration = 5
|
||||||
|
/// Exponential sustain dropoff rate per decisecond
|
||||||
|
var/sustain_exponential_dropoff = 1.4
|
||||||
|
////////// DO NOT DIRECTLY SET THESE!
|
||||||
|
/// Do not directly set, use update_sustain()
|
||||||
|
var/cached_linear_dropoff = 10
|
||||||
|
/// Do not directly set, use update_sustain()
|
||||||
|
var/cached_exponential_dropoff = 1.045
|
||||||
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/datum/song/New(atom/parent, list/instrument_ids, new_range)
|
||||||
|
SSinstruments.on_song_new(src)
|
||||||
|
lines = list()
|
||||||
|
tempo = sanitize_tempo(tempo)
|
||||||
|
src.parent = parent
|
||||||
|
if(instrument_ids)
|
||||||
|
allowed_instrument_ids = islist(instrument_ids)? instrument_ids : list(instrument_ids)
|
||||||
|
if(length(allowed_instrument_ids))
|
||||||
|
set_instrument(allowed_instrument_ids[1])
|
||||||
|
hearing_mobs = list()
|
||||||
|
volume = clamp(volume, min_volume, max_volume)
|
||||||
|
update_sustain()
|
||||||
|
if(new_range)
|
||||||
|
instrument_range = new_range
|
||||||
|
|
||||||
|
/datum/song/Destroy()
|
||||||
|
stop_playing()
|
||||||
|
SSinstruments.on_song_del(src)
|
||||||
|
lines = null
|
||||||
|
if(using_instrument)
|
||||||
|
using_instrument.songs_using -= src
|
||||||
|
using_instrument = null
|
||||||
|
allowed_instrument_ids = null
|
||||||
|
parent = null
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks and stores which mobs can hear us. Terminates sounds for mobs that leave our range.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/do_hearcheck()
|
||||||
|
last_hearcheck = world.time
|
||||||
|
var/list/old = hearing_mobs.Copy()
|
||||||
|
hearing_mobs.len = 0
|
||||||
|
var/turf/source = get_turf(parent)
|
||||||
|
var/list/in_range = get_mobs_and_objs_in_view_fast(source, instrument_range)
|
||||||
|
for(var/mob/M in in_range["mobs"])
|
||||||
|
hearing_mobs[M] = get_dist(M, source)
|
||||||
|
var/list/exited = old - hearing_mobs
|
||||||
|
for(var/i in exited)
|
||||||
|
terminate_sound_mob(i)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets our instrument, caching anything necessary for faster accessing. Accepts an ID, typepath, or instantiated instrument datum.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_instrument(datum/instrument/I)
|
||||||
|
terminate_all_sounds()
|
||||||
|
var/old_legacy
|
||||||
|
if(using_instrument)
|
||||||
|
using_instrument.songs_using -= src
|
||||||
|
old_legacy = (using_instrument.instrument_flags & INSTRUMENT_LEGACY)
|
||||||
|
using_instrument = null
|
||||||
|
cached_samples = null
|
||||||
|
cached_legacy_ext = null
|
||||||
|
cached_legacy_dir = null
|
||||||
|
legacy = null
|
||||||
|
if(istext(I) || ispath(I))
|
||||||
|
I = SSinstruments.instrument_data[I]
|
||||||
|
if(istype(I))
|
||||||
|
using_instrument = I
|
||||||
|
I.songs_using += src
|
||||||
|
var/instrument_legacy = (I.instrument_flags & INSTRUMENT_LEGACY)
|
||||||
|
if(instrument_legacy)
|
||||||
|
cached_legacy_ext = I.legacy_instrument_ext
|
||||||
|
cached_legacy_dir = I.legacy_instrument_path
|
||||||
|
legacy = TRUE
|
||||||
|
else
|
||||||
|
cached_samples = I.samples
|
||||||
|
legacy = FALSE
|
||||||
|
if(isnull(old_legacy) || (old_legacy != instrument_legacy))
|
||||||
|
if(playing)
|
||||||
|
compile_chords()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to start playing our song.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/start_playing(mob/user)
|
||||||
|
if(playing)
|
||||||
|
return
|
||||||
|
if(!using_instrument?.ready())
|
||||||
|
to_chat(user, "<span class='warning'>An error has occured with [src]. Please reset the instrument.</span>")
|
||||||
|
return
|
||||||
|
compile_chords()
|
||||||
|
if(!length(compiled_chords))
|
||||||
|
to_chat(user, "<span class='warning'>Song is empty.</span>")
|
||||||
|
return
|
||||||
|
playing = TRUE
|
||||||
|
updateDialog(user_playing)
|
||||||
|
//we can not afford to runtime, since we are going to be doing sound channel reservations and if we runtime it means we have a channel allocation leak.
|
||||||
|
//wrap the rest of the stuff to ensure stop_playing() is called.
|
||||||
|
do_hearcheck()
|
||||||
|
SEND_SIGNAL(parent, COMSIG_SONG_START)
|
||||||
|
elapsed_delay = 0
|
||||||
|
delay_by = 0
|
||||||
|
current_chord = 1
|
||||||
|
user_playing = user
|
||||||
|
START_PROCESSING(SSinstruments, src)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops playing, terminating all sounds if in synthesized mode. Clears hearing_mobs.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/stop_playing()
|
||||||
|
if(!playing)
|
||||||
|
return
|
||||||
|
playing = FALSE
|
||||||
|
if(!debug_mode)
|
||||||
|
compiled_chords = null
|
||||||
|
STOP_PROCESSING(SSinstruments, src)
|
||||||
|
SEND_SIGNAL(parent, COMSIG_SONG_END)
|
||||||
|
terminate_all_sounds(TRUE)
|
||||||
|
hearing_mobs.len = 0
|
||||||
|
user_playing = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes our song.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/process_song(wait)
|
||||||
|
if(!length(compiled_chords) || should_stop_playing(user_playing))
|
||||||
|
stop_playing()
|
||||||
|
return
|
||||||
|
var/list/chord = compiled_chords[current_chord]
|
||||||
|
if(++elapsed_delay >= delay_by)
|
||||||
|
play_chord(chord)
|
||||||
|
elapsed_delay = 0
|
||||||
|
delay_by = tempodiv_to_delay(chord[length(chord)])
|
||||||
|
current_chord++
|
||||||
|
if(current_chord > length(compiled_chords))
|
||||||
|
if(repeat)
|
||||||
|
repeat--
|
||||||
|
current_chord = 1
|
||||||
|
return
|
||||||
|
else
|
||||||
|
stop_playing()
|
||||||
|
return
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a tempodiv to ticks to elapse before playing the next chord, taking into account our tempo.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/tempodiv_to_delay(tempodiv)
|
||||||
|
if(!tempodiv)
|
||||||
|
tempodiv = 1 // no division by 0. some song converters tend to use 0 for when it wants to have no div, for whatever reason.
|
||||||
|
return max(1, round((tempo/tempodiv) / world.tick_lag, 1))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles chords.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/compile_chords()
|
||||||
|
legacy ? compile_legacy() : compile_synthesized()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays a chord.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/play_chord(list/chord)
|
||||||
|
// last value is timing information
|
||||||
|
for(var/i in 1 to (length(chord) - 1))
|
||||||
|
legacy? playkey_legacy(chord[i][1], chord[i][2], chord[i][3], user_playing) : playkey_synth(chord[i], user_playing)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if we should halt playback.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/should_stop_playing(mob/user)
|
||||||
|
return QDELETED(parent) || !using_instrument || !playing
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitizes tempo to a value that makes sense and fits the current world.tick_lag.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/sanitize_tempo(new_tempo)
|
||||||
|
new_tempo = abs(new_tempo)
|
||||||
|
return clamp(round(new_tempo, world.tick_lag), world.tick_lag, 5 SECONDS)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets our beats per minute based on our tempo.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/get_bpm()
|
||||||
|
return 600 / tempo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets our tempo from a beats-per-minute, sanitizing it to a valid number first.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_bpm(bpm)
|
||||||
|
tempo = sanitize_tempo(600 / bpm)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the window for our users. Override down the line.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/updateDialog(mob/user)
|
||||||
|
interact(user)
|
||||||
|
|
||||||
|
/datum/song/process(wait)
|
||||||
|
if(!playing)
|
||||||
|
return PROCESS_KILL
|
||||||
|
// it's expected this ticks at every world.tick_lag. if it lags, do not attempt to catch up.
|
||||||
|
process_song(world.tick_lag)
|
||||||
|
process_decay(world.tick_lag)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates our cached linear/exponential falloff stuff, saving calculations down the line.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/update_sustain()
|
||||||
|
// Exponential is easy
|
||||||
|
cached_exponential_dropoff = sustain_exponential_dropoff
|
||||||
|
// Linear, not so much, since it's a target duration from 100 volume rather than an exponential rate.
|
||||||
|
var/target_duration = sustain_linear_duration
|
||||||
|
var/volume_diff = max(0, 100 - sustain_dropoff_volume)
|
||||||
|
var/volume_decrease_per_decisecond = volume_diff / target_duration
|
||||||
|
cached_linear_dropoff = volume_decrease_per_decisecond
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for setting output volume.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_volume(volume)
|
||||||
|
src.volume = clamp(volume, max(0, min_volume), min(100, max_volume))
|
||||||
|
update_sustain()
|
||||||
|
updateDialog()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for setting how low the volume has to get before a note is considered "dead" and dropped
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_dropoff_volume(volume)
|
||||||
|
sustain_dropoff_volume = clamp(volume, INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100)
|
||||||
|
update_sustain()
|
||||||
|
updateDialog()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for setting exponential falloff factor.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_exponential_drop_rate(drop)
|
||||||
|
sustain_exponential_dropoff = clamp(drop, INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX)
|
||||||
|
update_sustain()
|
||||||
|
updateDialog()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for setting linear falloff duration.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/set_linear_falloff_duration(duration)
|
||||||
|
sustain_linear_duration = clamp(duration, 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN)
|
||||||
|
update_sustain()
|
||||||
|
updateDialog()
|
||||||
|
|
||||||
|
/datum/song/vv_edit_var(var_name, var_value)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
switch(var_name)
|
||||||
|
if(NAMEOF(src, volume))
|
||||||
|
set_volume(var_value)
|
||||||
|
if(NAMEOF(src, sustain_dropoff_volume))
|
||||||
|
set_dropoff_volume(var_value)
|
||||||
|
if(NAMEOF(src, sustain_exponential_dropoff))
|
||||||
|
set_exponential_drop_rate(var_value)
|
||||||
|
if(NAMEOF(src, sustain_linear_duration))
|
||||||
|
set_linear_falloff_duration(var_value)
|
||||||
|
|
||||||
|
// subtype for handheld instruments, like violin
|
||||||
|
/datum/song/handheld
|
||||||
|
|
||||||
|
/datum/song/handheld/updateDialog(mob/user)
|
||||||
|
parent.interact(user || usr)
|
||||||
|
|
||||||
|
/datum/song/handheld/should_stop_playing(mob/user)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
return TRUE
|
||||||
|
var/obj/item/instrument/I = parent
|
||||||
|
return I.should_stop_playing(user)
|
||||||
|
|
||||||
|
// subtype for stationary structures, like pianos
|
||||||
|
/datum/song/stationary
|
||||||
|
|
||||||
|
/datum/song/stationary/updateDialog(mob/user)
|
||||||
|
parent.interact(user || usr)
|
||||||
|
|
||||||
|
/datum/song/stationary/should_stop_playing(mob/user)
|
||||||
|
. = ..()
|
||||||
|
if(.)
|
||||||
|
return TRUE
|
||||||
|
var/obj/structure/musician/M = parent
|
||||||
|
return M.should_stop_playing(user)
|
||||||
251
code/modules/instruments/songs/editor.dm
Normal file
251
code/modules/instruments/songs/editor.dm
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
/**
|
||||||
|
* Returns the HTML for the status UI for this song datum.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/instrument_status_ui()
|
||||||
|
. = list()
|
||||||
|
. += "<div class='statusDisplay'>"
|
||||||
|
. += "<b><a href='?src=[REF(src)];switchinstrument=1'>Current instrument</a>:</b> "
|
||||||
|
if(!using_instrument)
|
||||||
|
. += "<span class='danger'>No instrument loaded!</span><br>"
|
||||||
|
else
|
||||||
|
. += "[using_instrument.name]<br>"
|
||||||
|
. += "Playback Settings:<br>"
|
||||||
|
if(can_noteshift)
|
||||||
|
. += "<a href='?src=[REF(src)];setnoteshift=1'>Note Shift/Note Transpose</a>: [note_shift] keys / [round(note_shift / 12, 0.01)] octaves<br>"
|
||||||
|
var/smt
|
||||||
|
var/modetext = ""
|
||||||
|
switch(sustain_mode)
|
||||||
|
if(SUSTAIN_LINEAR)
|
||||||
|
smt = "Linear"
|
||||||
|
modetext = "<a href='?src=[REF(src)];setlinearfalloff=1'>Linear Sustain Duration</a>: [sustain_linear_duration / 10] seconds<br>"
|
||||||
|
if(SUSTAIN_EXPONENTIAL)
|
||||||
|
smt = "Exponential"
|
||||||
|
modetext = "<a href='?src=[REF(src)];setexpfalloff=1'>Exponential Falloff Factor</a>: [sustain_exponential_dropoff]% per decisecond<br>"
|
||||||
|
. += "<a href='?src=[REF(src)];setsustainmode=1'>Sustain Mode</a>: [smt]<br>"
|
||||||
|
. += modetext
|
||||||
|
. += using_instrument?.ready()? "Status: <span class='good'>Ready</span><br>" : "Status: <span class='bad'>!Instrument Definition Error!</span><br>"
|
||||||
|
. += "Instrument Type: [legacy? "Legacy" : "Synthesized"]<br>"
|
||||||
|
. += "<a href='?src=[REF(src)];setvolume=1'>Volume</a>: [volume]<br>"
|
||||||
|
. += "<a href='?src=[REF(src)];setdropoffvolume=1'>Volume Dropoff Threshold</a>: [sustain_dropoff_volume]<br>"
|
||||||
|
. += "<a href='?src=[REF(src)];togglesustainhold=1'>Sustain indefinitely last held note</a>: [full_sustain_held_note? "Enabled" : "Disabled"].<br>"
|
||||||
|
. += "</div>"
|
||||||
|
|
||||||
|
/datum/song/proc/interact(mob/user)
|
||||||
|
var/list/dat = list()
|
||||||
|
|
||||||
|
dat += instrument_status_ui()
|
||||||
|
|
||||||
|
if(lines.len > 0)
|
||||||
|
dat += "<H3>Playback</H3>"
|
||||||
|
if(!playing)
|
||||||
|
dat += "<A href='?src=[REF(src)];play=1'>Play</A> <SPAN CLASS='linkOn'>Stop</SPAN><BR><BR>"
|
||||||
|
dat += "Repeat Song: "
|
||||||
|
dat += repeat > 0 ? "<A href='?src=[REF(src)];repeat=-10'>-</A><A href='?src=[REF(src)];repeat=-1'>-</A>" : "<SPAN CLASS='linkOff'>-</SPAN><SPAN CLASS='linkOff'>-</SPAN>"
|
||||||
|
dat += " [repeat] times "
|
||||||
|
dat += repeat < max_repeats ? "<A href='?src=[REF(src)];repeat=1'>+</A><A href='?src=[REF(src)];repeat=10'>+</A>" : "<SPAN CLASS='linkOff'>+</SPAN><SPAN CLASS='linkOff'>+</SPAN>"
|
||||||
|
dat += "<BR>"
|
||||||
|
else
|
||||||
|
dat += "<SPAN CLASS='linkOn'>Play</SPAN> <A href='?src=[REF(src)];stop=1'>Stop</A><BR>"
|
||||||
|
dat += "Repeats left: <B>[repeat]</B><BR>"
|
||||||
|
if(!editing)
|
||||||
|
dat += "<BR><B><A href='?src=[REF(src)];edit=2'>Show Editor</A></B><BR>"
|
||||||
|
else
|
||||||
|
dat += "<H3>Editing</H3>"
|
||||||
|
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/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
|
||||||
|
dat += "Line [linecount]: <A href='?src=[REF(src)];modifyline=[linecount]'>Edit</A> <A href='?src=[REF(src)];deleteline=[linecount]'>X</A> [line]<BR>"
|
||||||
|
dat += "<A href='?src=[REF(src)];newline=1'>Add Line</A><BR><BR>"
|
||||||
|
if(help)
|
||||||
|
dat += "<B><A href='?src=[REF(src)];help=1'>Hide Help</A></B><BR>"
|
||||||
|
dat += {"
|
||||||
|
Lines are a series of chords, separated by commas (,), each with notes separated by hyphens (-).<br>
|
||||||
|
Every note in a chord will play together, with chord timed by the tempo.<br>
|
||||||
|
<br>
|
||||||
|
Notes are played by the names of the note, and optionally, the accidental, and/or the octave number.<br>
|
||||||
|
By default, every note is natural and in octave 3. Defining otherwise is remembered for each note.<br>
|
||||||
|
Example: <i>C,D,E,F,G,A,B</i> will play a C major scale.<br>
|
||||||
|
After a note has an accidental placed, it will be remembered: <i>C,C4,C,C3</i> is <i>C3,C4,C4,C3</i><br>
|
||||||
|
Chords can be played simply by seperating each note with a hyphon: <i>A-C#,Cn-E,E-G#,Gn-B</i><br>
|
||||||
|
A pause may be denoted by an empty chord: <i>C,E,,C,G</i><br>
|
||||||
|
To make a chord be a different time, end it with /x, where the chord length will be length<br>
|
||||||
|
defined by tempo / x: <i>C,G/2,E/4</i><br>
|
||||||
|
Combined, an example is: <i>E-E4/4,F#/2,G#/8,B/8,E3-E4/4</i>
|
||||||
|
<br>
|
||||||
|
Lines may be up to [MUSIC_MAXLINECHARS] characters.<br>
|
||||||
|
A song may only contain up to [MUSIC_MAXLINES] lines.<br>
|
||||||
|
"}
|
||||||
|
else
|
||||||
|
dat += "<B><A href='?src=[REF(src)];help=2'>Show Help</A></B><BR>"
|
||||||
|
|
||||||
|
var/datum/browser/popup = new(user, "instrument", parent?.name || "instrument", 700, 500)
|
||||||
|
popup.set_content(dat.Join(""))
|
||||||
|
popup.open()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a song the user has input into lines and stores them.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/ParseSong(text)
|
||||||
|
set waitfor = FALSE
|
||||||
|
//split into lines
|
||||||
|
lines = splittext(text, "\n")
|
||||||
|
if(lines.len)
|
||||||
|
var/bpm_string = "BPM: "
|
||||||
|
if(findtext(lines[1], bpm_string, 1, length(bpm_string) + 1))
|
||||||
|
var/divisor = text2num(copytext(lines[1], length(bpm_string) + 1)) || 120 // default
|
||||||
|
tempo = sanitize_tempo(600 / round(divisor, 1))
|
||||||
|
lines.Cut(1, 2)
|
||||||
|
else
|
||||||
|
tempo = sanitize_tempo(5) // default 120 BPM
|
||||||
|
if(lines.len > MUSIC_MAXLINES)
|
||||||
|
to_chat(usr, "Too many lines!")
|
||||||
|
lines.Cut(MUSIC_MAXLINES + 1)
|
||||||
|
var/linenum = 1
|
||||||
|
for(var/l in lines)
|
||||||
|
if(length_char(l) > MUSIC_MAXLINECHARS)
|
||||||
|
to_chat(usr, "Line [linenum] too long!")
|
||||||
|
lines.Remove(l)
|
||||||
|
else
|
||||||
|
linenum++
|
||||||
|
updateDialog(usr) // make sure updates when complete
|
||||||
|
|
||||||
|
/datum/song/Topic(href, href_list)
|
||||||
|
if(!parent.CanUseTopic(usr))
|
||||||
|
usr << browse(null, "window=instrument")
|
||||||
|
usr.unset_machine()
|
||||||
|
return
|
||||||
|
|
||||||
|
parent.add_fingerprint(usr)
|
||||||
|
|
||||||
|
if(href_list["newsong"])
|
||||||
|
lines = new()
|
||||||
|
tempo = sanitize_tempo(5) // default 120 BPM
|
||||||
|
name = ""
|
||||||
|
|
||||||
|
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(parent, usr))
|
||||||
|
return
|
||||||
|
|
||||||
|
if(length_char(t) >= MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||||
|
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_char(t) > MUSIC_MAXLINES * MUSIC_MAXLINECHARS)
|
||||||
|
ParseSong(t)
|
||||||
|
|
||||||
|
else if(href_list["help"])
|
||||||
|
help = text2num(href_list["help"]) - 1
|
||||||
|
|
||||||
|
else if(href_list["edit"])
|
||||||
|
editing = 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["tempo"])
|
||||||
|
tempo = sanitize_tempo(tempo + text2num(href_list["tempo"]))
|
||||||
|
|
||||||
|
else if(href_list["play"])
|
||||||
|
INVOKE_ASYNC(src, .proc/start_playing, usr)
|
||||||
|
|
||||||
|
else if(href_list["newline"])
|
||||||
|
var/newline = html_encode(input("Enter your line: ", parent.name) as text|null)
|
||||||
|
if(!newline || !in_range(parent, usr))
|
||||||
|
return
|
||||||
|
if(lines.len > MUSIC_MAXLINES)
|
||||||
|
return
|
||||||
|
if(length(newline) > MUSIC_MAXLINECHARS)
|
||||||
|
newline = copytext(newline, 1, MUSIC_MAXLINECHARS)
|
||||||
|
lines.Add(newline)
|
||||||
|
|
||||||
|
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 = stripped_input(usr, "Enter your line: ", parent.name, lines[num], MUSIC_MAXLINECHARS)
|
||||||
|
if(!content || !in_range(parent, usr))
|
||||||
|
return
|
||||||
|
if(num > lines.len || num < 1)
|
||||||
|
return
|
||||||
|
lines[num] = content
|
||||||
|
|
||||||
|
else if(href_list["stop"])
|
||||||
|
stop_playing()
|
||||||
|
|
||||||
|
else if(href_list["setlinearfalloff"])
|
||||||
|
var/amount = input(usr, "Set linear sustain duration in seconds", "Linear Sustain Duration") as null|num
|
||||||
|
if(!isnull(amount))
|
||||||
|
set_linear_falloff_duration(round(amount * 10, world.tick_lag))
|
||||||
|
|
||||||
|
else if(href_list["setexpfalloff"])
|
||||||
|
var/amount = input(usr, "Set exponential sustain factor", "Exponential sustain factor") as null|num
|
||||||
|
if(!isnull(amount))
|
||||||
|
set_exponential_drop_rate(round(amount, 0.00001))
|
||||||
|
|
||||||
|
else if(href_list["setvolume"])
|
||||||
|
var/amount = input(usr, "Set volume", "Volume") as null|num
|
||||||
|
if(!isnull(amount))
|
||||||
|
set_volume(round(amount, 1))
|
||||||
|
|
||||||
|
else if(href_list["setdropoffvolume"])
|
||||||
|
var/amount = input(usr, "Set dropoff threshold", "Dropoff Threshold Volume") as null|num
|
||||||
|
if(!isnull(amount))
|
||||||
|
set_dropoff_volume(round(amount, 0.01))
|
||||||
|
|
||||||
|
else if(href_list["switchinstrument"])
|
||||||
|
if(!length(allowed_instrument_ids))
|
||||||
|
return
|
||||||
|
else if(length(allowed_instrument_ids) == 1)
|
||||||
|
set_instrument(allowed_instrument_ids[1])
|
||||||
|
return
|
||||||
|
var/list/categories = list()
|
||||||
|
for(var/i in allowed_instrument_ids)
|
||||||
|
var/datum/instrument/I = SSinstruments.get_instrument(i)
|
||||||
|
if(I)
|
||||||
|
LAZYSET(categories[I.category || "ERROR CATEGORY"], I.name, I.id)
|
||||||
|
var/cat = input(usr, "Select Category", "Instrument Category") as null|anything in categories
|
||||||
|
if(!cat)
|
||||||
|
return
|
||||||
|
var/list/instruments = categories[cat]
|
||||||
|
var/choice = input(usr, "Select Instrument", "Instrument Selection") as null|anything in instruments
|
||||||
|
if(!choice)
|
||||||
|
return
|
||||||
|
choice = instruments[choice] //get id
|
||||||
|
if(choice)
|
||||||
|
set_instrument(choice)
|
||||||
|
|
||||||
|
else if(href_list["setnoteshift"])
|
||||||
|
var/amount = input(usr, "Set note shift", "Note Shift") as null|num
|
||||||
|
if(!isnull(amount))
|
||||||
|
note_shift = clamp(amount, note_shift_min, note_shift_max)
|
||||||
|
|
||||||
|
else if(href_list["setsustainmode"])
|
||||||
|
var/choice = input(usr, "Choose a sustain mode", "Sustain Mode") as null|anything in list("Linear", "Exponential")
|
||||||
|
switch(choice)
|
||||||
|
if("Linear")
|
||||||
|
sustain_mode = SUSTAIN_LINEAR
|
||||||
|
if("Exponential")
|
||||||
|
sustain_mode = SUSTAIN_EXPONENTIAL
|
||||||
|
|
||||||
|
else if(href_list["togglesustainhold"])
|
||||||
|
full_sustain_held_note = !full_sustain_held_note
|
||||||
|
|
||||||
|
updateDialog()
|
||||||
91
code/modules/instruments/songs/play_legacy.dm
Normal file
91
code/modules/instruments/songs/play_legacy.dm
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Compiles our lines into "chords" with filenames for legacy playback. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/compile_legacy()
|
||||||
|
if(!length(src.lines))
|
||||||
|
return
|
||||||
|
var/list/lines = src.lines //cache for hyepr speed!
|
||||||
|
compiled_chords = list()
|
||||||
|
var/list/octaves = list(3, 3, 3, 3, 3, 3, 3)
|
||||||
|
var/list/accents = list("n", "n", "n", "n", "n", "n", "n")
|
||||||
|
for(var/line in lines)
|
||||||
|
var/list/chords = splittext(lowertext(line), ",")
|
||||||
|
for(var/chord in chords)
|
||||||
|
var/list/compiled_chord = list()
|
||||||
|
var/tempodiv = 1
|
||||||
|
var/list/notes_tempodiv = splittext(chord, "/")
|
||||||
|
var/len = length(notes_tempodiv)
|
||||||
|
if(len >= 2)
|
||||||
|
tempodiv = text2num(notes_tempodiv[2])
|
||||||
|
if(len) //some dunkass is going to do ,,,, to make 3 rests instead of ,/1 because there's no standardization so let's be prepared for that.
|
||||||
|
var/list/notes = splittext(notes_tempodiv[1], "-")
|
||||||
|
for(var/note in notes)
|
||||||
|
if(length(note) == 0)
|
||||||
|
continue
|
||||||
|
// 1-7, A-G
|
||||||
|
var/key = text2ascii(note) - 96
|
||||||
|
if((key < 1) || (key > 7))
|
||||||
|
continue
|
||||||
|
for(var/i in 2 to length(note))
|
||||||
|
var/oct_acc = copytext(note, i, i + 1)
|
||||||
|
var/num = text2num(oct_acc)
|
||||||
|
if(!num) //it's an accidental
|
||||||
|
accents[key] = oct_acc //if they misspelled it/fucked up that's on them lmao, no safety checks.
|
||||||
|
else //octave
|
||||||
|
octaves[key] = clamp(num, octave_min, octave_max)
|
||||||
|
compiled_chord[++compiled_chord.len] = list(key, accents[key], octaves[key])
|
||||||
|
compiled_chord += tempodiv //this goes last
|
||||||
|
if(length(compiled_chord))
|
||||||
|
compiled_chords[++compiled_chords.len] = compiled_chord
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proc to play a legacy note. Just plays the sound to hearing mobs (and does hearcheck if necessary), no fancy channel/sustain/management.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * note is a number from 1-7 for A-G
|
||||||
|
* * acc is either "b", "n", or "#"
|
||||||
|
* * oct is 1-8 (or 9 for C)
|
||||||
|
*/
|
||||||
|
/datum/song/proc/playkey_legacy(note, acc as text, oct, mob/user)
|
||||||
|
// handle accidental -> B<>C of E<>F
|
||||||
|
if(acc == "b" && (note == 3 || note == 6)) // C or F
|
||||||
|
if(note == 3)
|
||||||
|
oct--
|
||||||
|
note--
|
||||||
|
acc = "n"
|
||||||
|
else if(acc == "#" && (note == 2 || note == 5)) // B or E
|
||||||
|
if(note == 2)
|
||||||
|
oct++
|
||||||
|
note++
|
||||||
|
acc = "n"
|
||||||
|
else if(acc == "#" && (note == 7)) //G#
|
||||||
|
note = 1
|
||||||
|
acc = "b"
|
||||||
|
else if(acc == "#") // mass convert all sharps to flats, octave jump already handled
|
||||||
|
acc = "b"
|
||||||
|
note++
|
||||||
|
|
||||||
|
// check octave, C is allowed to go to 9
|
||||||
|
if(oct < 1 || (note == 3 ? oct > 9 : oct > 8))
|
||||||
|
return
|
||||||
|
|
||||||
|
// now generate name
|
||||||
|
var/soundfile = "sound/instruments/[cached_legacy_dir]/[ascii2text(note+64)][acc][oct].[cached_legacy_ext]"
|
||||||
|
soundfile = file(soundfile)
|
||||||
|
// make sure the note exists
|
||||||
|
if(!fexists(soundfile))
|
||||||
|
return
|
||||||
|
// and play
|
||||||
|
var/turf/source = get_turf(parent)
|
||||||
|
if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck)
|
||||||
|
do_hearcheck()
|
||||||
|
var/sound/music_played = sound(soundfile)
|
||||||
|
for(var/i in hearing_mobs)
|
||||||
|
var/mob/M = i
|
||||||
|
/* Would be nice
|
||||||
|
if(user && HAS_TRAIT(user, TRAIT_MUSICIAN) && isliving(M))
|
||||||
|
var/mob/living/L = M
|
||||||
|
L.apply_status_effect(STATUS_EFFECT_GOOD_MUSIC)
|
||||||
|
*/
|
||||||
|
M.playsound_local(source, null, volume * using_instrument.volume_multiplier, S = music_played, preference = /datum/client_preference/instrument_toggle, volume_channel = VOLUME_CHANNEL_INSTRUMENTS)
|
||||||
|
// Could do environment and echo later but not for now
|
||||||
150
code/modules/instruments/songs/play_synthesized.dm
Normal file
150
code/modules/instruments/songs/play_synthesized.dm
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
/**
|
||||||
|
* Compiles our lines into "chords" with numbers. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/compile_synthesized()
|
||||||
|
if(!length(src.lines))
|
||||||
|
return
|
||||||
|
var/list/lines = src.lines //cache for hyepr speed!
|
||||||
|
compiled_chords = list()
|
||||||
|
var/list/octaves = list(3, 3, 3, 3, 3, 3, 3)
|
||||||
|
var/list/accents = list("n", "n", "n", "n", "n", "n", "n")
|
||||||
|
for(var/line in lines)
|
||||||
|
var/list/chords = splittext(lowertext(line), ",")
|
||||||
|
for(var/chord in chords)
|
||||||
|
var/list/compiled_chord = list()
|
||||||
|
var/tempodiv = 1
|
||||||
|
var/list/notes_tempodiv = splittext(chord, "/")
|
||||||
|
var/len = length(notes_tempodiv)
|
||||||
|
if(len >= 2)
|
||||||
|
tempodiv = text2num(notes_tempodiv[2])
|
||||||
|
if(len) //some dunkass is going to do ,,,, to make 3 rests instead of ,/1 because there's no standardization so let's be prepared for that.
|
||||||
|
var/list/notes = splittext(notes_tempodiv[1], "-")
|
||||||
|
for(var/note in notes)
|
||||||
|
if(length(note) == 0)
|
||||||
|
continue
|
||||||
|
// 1-7, A-G
|
||||||
|
var/key = text2ascii(note) - 96
|
||||||
|
if((key < 1) || (key > 7))
|
||||||
|
continue
|
||||||
|
for(var/i in 2 to length(note))
|
||||||
|
var/oct_acc = copytext(note, i, i + 1)
|
||||||
|
var/num = text2num(oct_acc)
|
||||||
|
if(!num) //it's an accidental
|
||||||
|
accents[key] = oct_acc //if they misspelled it/fucked up that's on them lmao, no safety checks.
|
||||||
|
else //octave
|
||||||
|
octaves[key] = clamp(num, octave_min, octave_max)
|
||||||
|
compiled_chord += clamp((note_offset_lookup[key] + octaves[key] * 12 + accent_lookup[accents[key]]), key_min, key_max)
|
||||||
|
compiled_chord += tempodiv //this goes last
|
||||||
|
if(length(compiled_chord))
|
||||||
|
compiled_chords[++compiled_chords.len] = compiled_chord
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays a specific numerical key from our instrument to anyone who can hear us.
|
||||||
|
* Does a hearing check if enough time has passed.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/playkey_synth(key, mob/user)
|
||||||
|
if(can_noteshift)
|
||||||
|
key = clamp(key + note_shift, key_min, key_max)
|
||||||
|
if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck)
|
||||||
|
do_hearcheck()
|
||||||
|
var/datum/instrument_key/K = using_instrument.samples[num2text(key)] //See how fucking easy it is to make a number text? You don't need a complicated 9 line proc!
|
||||||
|
//Should probably add channel limiters here at some point but I don't care right now.
|
||||||
|
var/channel = pop_channel()
|
||||||
|
if(isnull(channel))
|
||||||
|
return FALSE
|
||||||
|
. = TRUE
|
||||||
|
var/sound/copy = sound(K.sample)
|
||||||
|
var/volume = src.volume * using_instrument.volume_multiplier
|
||||||
|
copy.frequency = K.frequency
|
||||||
|
copy.volume = volume
|
||||||
|
var/channel_text = num2text(channel)
|
||||||
|
channels_playing[channel_text] = 100
|
||||||
|
last_channel_played = channel_text
|
||||||
|
for(var/i in hearing_mobs)
|
||||||
|
var/mob/M = i
|
||||||
|
/* Maybe someday
|
||||||
|
if(user && HAS_TRAIT(user, TRAIT_MUSICIAN) && isliving(M))
|
||||||
|
var/mob/living/L = M
|
||||||
|
L.apply_status_effect(STATUS_EFFECT_GOOD_MUSIC)
|
||||||
|
*/
|
||||||
|
// Jeez
|
||||||
|
M.playsound_local(
|
||||||
|
turf_source = get_turf(parent),
|
||||||
|
soundin = null,
|
||||||
|
vol = volume,
|
||||||
|
vary = FALSE,
|
||||||
|
frequency = K.frequency,
|
||||||
|
falloff = null,
|
||||||
|
is_global = null,
|
||||||
|
channel = channel,
|
||||||
|
pressure_affected = null,
|
||||||
|
S = copy,
|
||||||
|
preference = /datum/client_preference/instrument_toggle,
|
||||||
|
volume_channel = VOLUME_CHANNEL_INSTRUMENTS)
|
||||||
|
// Could do environment and echo later but not for now
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops all sounds we are "responsible" for. Only works in synthesized mode.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/terminate_all_sounds(clear_channels = TRUE)
|
||||||
|
for(var/i in hearing_mobs)
|
||||||
|
terminate_sound_mob(i)
|
||||||
|
if(clear_channels)
|
||||||
|
channels_playing.len = 0
|
||||||
|
channels_idle.len = 0
|
||||||
|
SSinstruments.current_instrument_channels -= using_sound_channels
|
||||||
|
using_sound_channels = 0
|
||||||
|
SSsounds.free_datum_channels(src)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops all sounds we are responsible for in a given person. Only works in synthesized mode.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/terminate_sound_mob(mob/M)
|
||||||
|
for(var/channel in channels_playing)
|
||||||
|
M.stop_sound_channel(text2num(channel))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops a channel we have reserved so we don't have to release and re-request them from SSsounds every time we play a note. This is faster.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/pop_channel()
|
||||||
|
if(length(channels_idle)) //just pop one off of here if we have one available
|
||||||
|
. = text2num(channels_idle[1])
|
||||||
|
channels_idle.Cut(1,2)
|
||||||
|
return
|
||||||
|
if(using_sound_channels >= max_sound_channels)
|
||||||
|
return
|
||||||
|
. = SSinstruments.reserve_instrument_channel(src)
|
||||||
|
if(!isnull(.))
|
||||||
|
using_sound_channels++
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decays our channels and updates their volumes to mobs who can hear us.
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* * wait_ds - the deciseconds we should decay by. This is to compensate for any lag, as otherwise songs would get pretty nasty during high time dilation.
|
||||||
|
*/
|
||||||
|
/datum/song/proc/process_decay(wait_ds)
|
||||||
|
var/linear_dropoff = cached_linear_dropoff * wait_ds
|
||||||
|
var/exponential_dropoff = cached_exponential_dropoff ** wait_ds
|
||||||
|
for(var/channel in channels_playing)
|
||||||
|
if(full_sustain_held_note && (channel == last_channel_played))
|
||||||
|
continue
|
||||||
|
var/current_volume = channels_playing[channel]
|
||||||
|
switch(sustain_mode)
|
||||||
|
if(SUSTAIN_LINEAR)
|
||||||
|
current_volume -= linear_dropoff
|
||||||
|
if(SUSTAIN_EXPONENTIAL)
|
||||||
|
current_volume /= exponential_dropoff
|
||||||
|
channels_playing[channel] = current_volume
|
||||||
|
var/dead = current_volume <= sustain_dropoff_volume
|
||||||
|
var/channelnumber = text2num(channel)
|
||||||
|
if(dead)
|
||||||
|
channels_playing -= channel
|
||||||
|
channels_idle += channel
|
||||||
|
for(var/i in hearing_mobs)
|
||||||
|
var/mob/M = i
|
||||||
|
M.stop_sound_channel(channelnumber)
|
||||||
|
else
|
||||||
|
for(var/i in hearing_mobs)
|
||||||
|
var/mob/M = i
|
||||||
|
M.set_sound_channel_volume(channelnumber, (current_volume * 0.01) * volume * using_instrument.volume_multiplier)
|
||||||
59
code/modules/instruments/stationary.dm
Normal file
59
code/modules/instruments/stationary.dm
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/obj/structure/musician
|
||||||
|
name = "Not A Piano"
|
||||||
|
desc = "Something broke, contact coderbus."
|
||||||
|
var/can_play_unanchored = FALSE
|
||||||
|
var/list/allowed_instrument_ids = list("r3grand","r3harpsi","crharpsi","crgrand1","crbright1", "crichugan", "crihamgan","piano")
|
||||||
|
var/datum/song/song
|
||||||
|
|
||||||
|
/obj/structure/musician/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
song = new(src, allowed_instrument_ids)
|
||||||
|
allowed_instrument_ids = null
|
||||||
|
|
||||||
|
/obj/structure/musician/Destroy()
|
||||||
|
QDEL_NULL(song)
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/obj/structure/musician/attack_hand(mob/M)
|
||||||
|
if(!M.IsAdvancedToolUser())
|
||||||
|
return
|
||||||
|
|
||||||
|
interact(M)
|
||||||
|
|
||||||
|
/obj/structure/musician/proc/should_stop_playing(mob/user)
|
||||||
|
if(!(anchored || can_play_unanchored))
|
||||||
|
return TRUE
|
||||||
|
if(!user)
|
||||||
|
return FALSE
|
||||||
|
return !CanUseTopic(user)
|
||||||
|
|
||||||
|
/obj/structure/musician/interact(mob/user)
|
||||||
|
. = ..()
|
||||||
|
song.interact(user)
|
||||||
|
|
||||||
|
/*
|
||||||
|
/obj/structure/musician/wrench_act(mob/living/user, obj/item/I)
|
||||||
|
default_unfasten_wrench(user, I, 40)
|
||||||
|
return TRUE
|
||||||
|
*/
|
||||||
|
|
||||||
|
/obj/structure/musician/piano
|
||||||
|
name = "space minimoog"
|
||||||
|
icon = 'icons/obj/musician.dmi'
|
||||||
|
icon_state = "minimoog"
|
||||||
|
anchored = TRUE
|
||||||
|
density = TRUE
|
||||||
|
|
||||||
|
/obj/structure/musician/piano/unanchored
|
||||||
|
anchored = FALSE
|
||||||
|
|
||||||
|
/obj/structure/musician/piano/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
if(prob(50) && icon_state == initial(icon_state))
|
||||||
|
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"
|
||||||
@@ -1059,15 +1059,15 @@
|
|||||||
|
|
||||||
/mob/living/get_sound_env(var/pressure_factor)
|
/mob/living/get_sound_env(var/pressure_factor)
|
||||||
if (hallucination)
|
if (hallucination)
|
||||||
return PSYCHOTIC
|
return SOUND_ENVIRONMENT_PSYCHOTIC
|
||||||
else if (druggy)
|
else if (druggy)
|
||||||
return DRUGGED
|
return SOUND_ENVIRONMENT_DRUGGED
|
||||||
else if (drowsyness)
|
else if (drowsyness)
|
||||||
return DIZZY
|
return SOUND_ENVIRONMENT_DIZZY
|
||||||
else if (confused)
|
else if (confused)
|
||||||
return DIZZY
|
return SOUND_ENVIRONMENT_DIZZY
|
||||||
else if (sleeping)
|
else if (sleeping)
|
||||||
return UNDERWATER
|
return SOUND_ENVIRONMENT_UNDERWATER
|
||||||
else
|
else
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
|
|||||||
@@ -189,9 +189,7 @@ GLOBAL_LIST_EMPTY(apcs)
|
|||||||
|
|
||||||
pixel_x = (dir & 3)? 0 : (dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26
|
pixel_x = (dir & 3)? 0 : (dir == 4 ? 26 : -26) //VOREStation Edit -> 24 to 26
|
||||||
pixel_y = (dir & 3)? (dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26
|
pixel_y = (dir & 3)? (dir ==1 ? 26 : -26) : 0 //VOREStation Edit -> 24 to 26
|
||||||
if(building==0)
|
if(building)
|
||||||
init()
|
|
||||||
else
|
|
||||||
area = get_area(src)
|
area = get_area(src)
|
||||||
area.apc = src
|
area.apc = src
|
||||||
opened = 1
|
opened = 1
|
||||||
@@ -200,6 +198,16 @@ GLOBAL_LIST_EMPTY(apcs)
|
|||||||
stat |= MAINT
|
stat |= MAINT
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
/obj/machinery/power/apc/Initialize(mapload, ndir, building)
|
||||||
|
. = ..()
|
||||||
|
if(!building)
|
||||||
|
init()
|
||||||
|
return INITIALIZE_HINT_LATELOAD
|
||||||
|
|
||||||
|
/obj/machinery/power/apc/LateInitialize()
|
||||||
|
. = ..()
|
||||||
|
update()
|
||||||
|
|
||||||
/obj/machinery/power/apc/Destroy()
|
/obj/machinery/power/apc/Destroy()
|
||||||
GLOB.apcs -= src
|
GLOB.apcs -= src
|
||||||
update()
|
update()
|
||||||
@@ -268,9 +276,6 @@ GLOBAL_LIST_EMPTY(apcs)
|
|||||||
|
|
||||||
make_terminal()
|
make_terminal()
|
||||||
|
|
||||||
spawn(5)
|
|
||||||
update()
|
|
||||||
|
|
||||||
/obj/machinery/power/apc/examine(mob/user)
|
/obj/machinery/power/apc/examine(mob/user)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(Adjacent(user))
|
if(Adjacent(user))
|
||||||
|
|||||||
@@ -288,8 +288,8 @@ var/global/list/light_type_cache = list()
|
|||||||
shows_alerts = FALSE //VOREStation Edit
|
shows_alerts = FALSE //VOREStation Edit
|
||||||
var/lamp_shade = 1
|
var/lamp_shade = 1
|
||||||
|
|
||||||
/obj/machinery/light/flamp/New(atom/newloc, obj/machinery/light_construct/construct = null)
|
/obj/machinery/light/flamp/Initialize(mapload, obj/machinery/light_construct/construct = null)
|
||||||
..(newloc, construct)
|
. = ..()
|
||||||
if(construct)
|
if(construct)
|
||||||
start_with_cell = FALSE
|
start_with_cell = FALSE
|
||||||
lamp_shade = 0
|
lamp_shade = 0
|
||||||
@@ -322,15 +322,13 @@ var/global/list/light_type_cache = list()
|
|||||||
auto_flicker = TRUE
|
auto_flicker = TRUE
|
||||||
|
|
||||||
//VOREStation Add - Shadeless!
|
//VOREStation Add - Shadeless!
|
||||||
/obj/machinery/light/flamp/noshade/New()
|
/obj/machinery/light/flamp/noshade
|
||||||
lamp_shade = 0
|
lamp_shade = 0
|
||||||
update(0)
|
|
||||||
..()
|
|
||||||
//VOREStation Add End
|
//VOREStation Add End
|
||||||
|
|
||||||
// create a new lighting fixture
|
// create a new lighting fixture
|
||||||
/obj/machinery/light/New(atom/newloc, obj/machinery/light_construct/construct = null)
|
/obj/machinery/light/Initialize(mapload, obj/machinery/light_construct/construct = null)
|
||||||
..(newloc)
|
. =..()
|
||||||
|
|
||||||
if(start_with_cell && !no_emergency)
|
if(start_with_cell && !no_emergency)
|
||||||
cell = new/obj/item/weapon/cell/emergency_light(src)
|
cell = new/obj/item/weapon/cell/emergency_light(src)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 232 KiB After Width: | Height: | Size: 234 KiB |
BIN
icons/mob/items/lefthand_horns.dmi
Normal file
BIN
icons/mob/items/lefthand_horns.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 470 B |
BIN
icons/mob/items/righthand_horns.dmi
Normal file
BIN
icons/mob/items/righthand_horns.dmi
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 472 B |
Binary file not shown.
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 32 KiB |
@@ -63,8 +63,18 @@
|
|||||||
"Fe" = (/obj/random/outcrop,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
"Fe" = (/obj/random/outcrop,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
||||||
"HE" = (/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
"HE" = (/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
"HF" = (/obj/structure/cliff/automatic{dir = 5},/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
"HF" = (/obj/structure/cliff/automatic{dir = 5},/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
<<<<<<< HEAD
|
||||||
"Ji" = (/obj/item/stolenpackage,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
"Ji" = (/obj/item/stolenpackage,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
"JJ" = (/obj/structure/loot_pile/surface/bones,/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
"JJ" = (/obj/structure/loot_pile/surface/bones,/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
||||||
|
||||||| parent of db274375dc... Merge pull request #10518 from VOREStation/Arokha/instrumental
|
||||||
|
"Ie" = (/obj/random/tool/power,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
"Ji" = (/obj/item/device/instrument/violin,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
"JJ" = (/obj/structure/loot_pile/surface/bones,/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/obj/effect/spider/stickyweb,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
||||||
|
=======
|
||||||
|
"Ie" = (/obj/random/tool/power,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
"Ji" = (/obj/item/instrument/violin,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
"JJ" = (/obj/structure/loot_pile/surface/bones,/obj/effect/floor_decal/rust,/obj/effect/decal/cleanable/dirt,/obj/effect/decal/cleanable/dirt,/obj/effect/spider/stickyweb,/turf/simulated/floor/tiled/asteroid_steel,/area/submap/Chasm)
|
||||||
|
>>>>>>> db274375dc... Merge pull request #10518 from VOREStation/Arokha/instrumental
|
||||||
"Kv" = (/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Chasm)
|
"Kv" = (/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Chasm)
|
||||||
"Kz" = (/obj/random/trash,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Chasm)
|
"Kz" = (/obj/random/trash,/turf/simulated/floor/outdoors/dirt{outdoors = 0},/area/submap/Chasm)
|
||||||
"KX" = (/obj/structure/loot_pile/surface/bones,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
"KX" = (/obj/structure/loot_pile/surface/bones,/turf/simulated/floor/outdoors/rocks{outdoors = 0},/area/submap/Chasm)
|
||||||
|
|||||||
@@ -20880,10 +20880,10 @@
|
|||||||
/turf/simulated/floor/tiled/white,
|
/turf/simulated/floor/tiled/white,
|
||||||
/area/crew_quarters/kitchen)
|
/area/crew_quarters/kitchen)
|
||||||
"aHz" = (
|
"aHz" = (
|
||||||
/obj/structure/device/piano,
|
|
||||||
/obj/effect/floor_decal/spline/plain{
|
/obj/effect/floor_decal/spline/plain{
|
||||||
dir = 1
|
dir = 1
|
||||||
},
|
},
|
||||||
|
/obj/structure/musician/piano,
|
||||||
/turf/simulated/floor/lino,
|
/turf/simulated/floor/lino,
|
||||||
/area/tether/surfacebase/entertainment/stage)
|
/area/tether/surfacebase/entertainment/stage)
|
||||||
"aHA" = (
|
"aHA" = (
|
||||||
@@ -32556,10 +32556,12 @@
|
|||||||
dir = 4
|
dir = 4
|
||||||
},
|
},
|
||||||
/obj/structure/table/rack/steel,
|
/obj/structure/table/rack/steel,
|
||||||
/obj/item/device/instrument/violin,
|
|
||||||
/obj/effect/floor_decal/spline/plain{
|
/obj/effect/floor_decal/spline/plain{
|
||||||
dir = 1
|
dir = 1
|
||||||
},
|
},
|
||||||
|
/obj/item/instrument/violin,
|
||||||
|
/obj/item/instrument/piano_synth,
|
||||||
|
/obj/item/instrument/recorder,
|
||||||
/turf/simulated/floor/lino,
|
/turf/simulated/floor/lino,
|
||||||
/area/tether/surfacebase/entertainment/stage)
|
/area/tether/surfacebase/entertainment/stage)
|
||||||
"bcW" = (
|
"bcW" = (
|
||||||
|
|||||||
@@ -142,7 +142,7 @@
|
|||||||
|
|
||||||
/area/tether/surfacebase/outside
|
/area/tether/surfacebase/outside
|
||||||
name = "Outside - Surface"
|
name = "Outside - Surface"
|
||||||
sound_env = MOUNTAINS
|
sound_env = SOUND_ENVIRONMENT_MOUNTAINS
|
||||||
/area/tether/surfacebase/outside/outside1
|
/area/tether/surfacebase/outside/outside1
|
||||||
icon_state = "outside1"
|
icon_state = "outside1"
|
||||||
/area/tether/surfacebase/outside/outside2
|
/area/tether/surfacebase/outside/outside2
|
||||||
@@ -541,7 +541,7 @@
|
|||||||
/area/tether/surfacebase/security/solitary
|
/area/tether/surfacebase/security/solitary
|
||||||
name = "\improper Surface Security Solitary Confinement"
|
name = "\improper Surface Security Solitary Confinement"
|
||||||
lightswitch = 0
|
lightswitch = 0
|
||||||
sound_env =PADDED_CELL
|
sound_env = SOUND_ENVIRONMENT_PADDED_CELL
|
||||||
/area/tether/surfacebase/security/gasstorage
|
/area/tether/surfacebase/security/gasstorage
|
||||||
name = "\improper Surface Security Gas Storage"
|
name = "\improper Surface Security Gas Storage"
|
||||||
lightswitch = 0
|
lightswitch = 0
|
||||||
@@ -639,7 +639,7 @@
|
|||||||
/area/engineering/atmos_intake
|
/area/engineering/atmos_intake
|
||||||
name = "\improper Atmospherics Intake"
|
name = "\improper Atmospherics Intake"
|
||||||
icon_state = "atmos"
|
icon_state = "atmos"
|
||||||
sound_env = MOUNTAINS
|
sound_env = SOUND_ENVIRONMENT_MOUNTAINS
|
||||||
|
|
||||||
/area/engineering/atmos/hallway
|
/area/engineering/atmos/hallway
|
||||||
name = "\improper Atmospherics Main Hallway"
|
name = "\improper Atmospherics Main Hallway"
|
||||||
@@ -1360,7 +1360,7 @@
|
|||||||
name = "\improper Virology Maintenance"
|
name = "\improper Virology Maintenance"
|
||||||
/area/maintenance/station/ai
|
/area/maintenance/station/ai
|
||||||
name = "\improper AI Maintenance"
|
name = "\improper AI Maintenance"
|
||||||
sound_env = SEWER_PIPE
|
sound_env = SOUND_ENVIRONMENT_SEWER_PIPE
|
||||||
/area/maintenance/station/exploration
|
/area/maintenance/station/exploration
|
||||||
name = "\improper Exploration Maintenance"
|
name = "\improper Exploration Maintenance"
|
||||||
/area/maintenance/abandonedlibrary
|
/area/maintenance/abandonedlibrary
|
||||||
@@ -1372,7 +1372,7 @@
|
|||||||
/area/maintenance/station/spacecommandmaint
|
/area/maintenance/station/spacecommandmaint
|
||||||
name = "\improper Secondary Command Maintenance"
|
name = "\improper Secondary Command Maintenance"
|
||||||
icon_state = "bridge"
|
icon_state = "bridge"
|
||||||
sound_env = SEWER_PIPE
|
sound_env = SOUND_ENVIRONMENT_SEWER_PIPE
|
||||||
/area/maintenance/substation/spacecommand
|
/area/maintenance/substation/spacecommand
|
||||||
name = "\improper Secondary Command Substation"
|
name = "\improper Secondary Command Substation"
|
||||||
icon_state = "substation"
|
icon_state = "substation"
|
||||||
|
|||||||
BIN
sound/instruments/banjo/Ab3.ogg
Normal file
BIN
sound/instruments/banjo/Ab3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Ab4.ogg
Normal file
BIN
sound/instruments/banjo/Ab4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Ab5.ogg
Normal file
BIN
sound/instruments/banjo/Ab5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/An3.ogg
Normal file
BIN
sound/instruments/banjo/An3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/An4.ogg
Normal file
BIN
sound/instruments/banjo/An4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/An5.ogg
Normal file
BIN
sound/instruments/banjo/An5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bb3.ogg
Normal file
BIN
sound/instruments/banjo/Bb3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bb4.ogg
Normal file
BIN
sound/instruments/banjo/Bb4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bb5.ogg
Normal file
BIN
sound/instruments/banjo/Bb5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bn2.ogg
Normal file
BIN
sound/instruments/banjo/Bn2.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bn3.ogg
Normal file
BIN
sound/instruments/banjo/Bn3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bn4.ogg
Normal file
BIN
sound/instruments/banjo/Bn4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Bn5.ogg
Normal file
BIN
sound/instruments/banjo/Bn5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Cn3.ogg
Normal file
BIN
sound/instruments/banjo/Cn3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Cn4.ogg
Normal file
BIN
sound/instruments/banjo/Cn4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Cn5.ogg
Normal file
BIN
sound/instruments/banjo/Cn5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Cn6.ogg
Normal file
BIN
sound/instruments/banjo/Cn6.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Db3.ogg
Normal file
BIN
sound/instruments/banjo/Db3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Db4.ogg
Normal file
BIN
sound/instruments/banjo/Db4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Db5.ogg
Normal file
BIN
sound/instruments/banjo/Db5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Db6.ogg
Normal file
BIN
sound/instruments/banjo/Db6.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Dn3.ogg
Normal file
BIN
sound/instruments/banjo/Dn3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Dn4.ogg
Normal file
BIN
sound/instruments/banjo/Dn4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Dn5.ogg
Normal file
BIN
sound/instruments/banjo/Dn5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Dn6.ogg
Normal file
BIN
sound/instruments/banjo/Dn6.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Eb3.ogg
Normal file
BIN
sound/instruments/banjo/Eb3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Eb4.ogg
Normal file
BIN
sound/instruments/banjo/Eb4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Eb5.ogg
Normal file
BIN
sound/instruments/banjo/Eb5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/En3.ogg
Normal file
BIN
sound/instruments/banjo/En3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/En4.ogg
Normal file
BIN
sound/instruments/banjo/En4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/En5.ogg
Normal file
BIN
sound/instruments/banjo/En5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Fn3.ogg
Normal file
BIN
sound/instruments/banjo/Fn3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Fn4.ogg
Normal file
BIN
sound/instruments/banjo/Fn4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Fn5.ogg
Normal file
BIN
sound/instruments/banjo/Fn5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gb3.ogg
Normal file
BIN
sound/instruments/banjo/Gb3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gb4.ogg
Normal file
BIN
sound/instruments/banjo/Gb4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gb5.ogg
Normal file
BIN
sound/instruments/banjo/Gb5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gn3.ogg
Normal file
BIN
sound/instruments/banjo/Gn3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gn4.ogg
Normal file
BIN
sound/instruments/banjo/Gn4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/banjo/Gn5.ogg
Normal file
BIN
sound/instruments/banjo/Gn5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c2.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_brass/c5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C2.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C2.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C3.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C3.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C4.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C5.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trombone/C5.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trumpet/C4.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trumpet/C4.ogg
Normal file
Binary file not shown.
BIN
sound/instruments/synthesis_samples/brass/crisis_trumpet/C5.ogg
Normal file
BIN
sound/instruments/synthesis_samples/brass/crisis_trumpet/C5.ogg
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user