Adds the Volume Mixer to adjust individual channel volumes (#15507)

* Adds the Volume Mixer

* Address AA

* LF -> CRLF

* Puts thunderdome.ogg on CHANNEL_ADMIN

* Update interface name
This commit is contained in:
dearmochi
2021-02-25 22:30:19 +00:00
committed by GitHub
parent 2f9ee7f2b8
commit 3c87d9a396
20 changed files with 722 additions and 447 deletions
+1 -1
View File
@@ -268,7 +268,7 @@ CREATE TABLE `player` (
`toggles` int(11) DEFAULT NULL,
`toggles_2` int(11) DEFAULT '0',
`sound` mediumint(8) DEFAULT '31',
`volume` smallint(4) DEFAULT '100',
`volume_mixer` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`lastchangelog` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`exp` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`clientfps` smallint(4) DEFAULT '0',
+1 -1
View File
@@ -267,7 +267,7 @@ CREATE TABLE `SS13_player` (
`toggles` int(11) DEFAULT NULL,
`toggles_2` int(11) DEFAULT '0',
`sound` mediumint(8) DEFAULT '31',
`volume` smallint(4) DEFAULT '100',
`volume_mixer` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`lastchangelog` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
`exp` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`clientfps` smallint(4) DEFAULT '0',
+8
View File
@@ -0,0 +1,8 @@
# Updating DB from 20-21
# Replaces volume (number) column by volume_mixer (text) ~dearmochi
# Add column to player
ALTER TABLE `player` ADD COLUMN `volume_mixer` longtext COLLATE utf8mb4_unicode_ci DEFAULT NULL AFTER `volume`;
# Remove column from player
ALTER TABLE `player` DROP COLUMN `volume`;
+1 -1
View File
@@ -363,7 +363,7 @@
#define INVESTIGATE_BOMB "bombs"
// The SQL version required by this version of the code
#define SQL_VERSION 20
#define SQL_VERSION 21
// Vending machine stuff
#define CAT_NORMAL 1
+23
View File
@@ -2094,6 +2094,29 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
query_accesslog.warn_execute()
qdel(query_accesslog)
/**
* Returns the clean name of an audio channel.
*
* Arguments:
* * channel - The channel number.
*/
/proc/get_channel_name(channel)
switch(channel)
if(CHANNEL_LOBBYMUSIC)
return "Lobby Music"
if(CHANNEL_ADMIN)
return "Admin MIDIs"
if(CHANNEL_VOX)
return "AI Announcements"
if(CHANNEL_JUKEBOX)
return "Dance Machines"
if(CHANNEL_HEARTBEAT)
return "Heartbeat"
if(CHANNEL_BUZZ)
return "White Noise"
if(CHANNEL_AMBIENCE)
return "Ambience"
/proc/slot_bitfield_to_slot(input_slot_flags) // Kill off this garbage ASAP; slot flags and clothing flags should be IDENTICAL. GOSH DARN IT. Doesn't work with ears or pockets, either.
switch(input_slot_flags)
if(SLOT_OCLOTHING)
+2 -2
View File
@@ -479,7 +479,7 @@
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(L && L.client && !L.client.ambience_playing && (L.client.prefs.sound & SOUND_BUZZ)) //split off the white noise from the rest of the ambience because of annoyance complaints - Kluys
L.client.ambience_playing = TRUE
SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = TRUE, wait = FALSE, volume = 35, channel = CHANNEL_BUZZ))
SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = TRUE, wait = FALSE, volume = 35 * L.client.prefs.get_channel_volume(CHANNEL_BUZZ), channel = CHANNEL_BUZZ))
else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ))
L.client.ambience_playing = FALSE
@@ -487,7 +487,7 @@
var/sound = pick(ambientsounds)
if(!L.client.played)
SEND_SOUND(L, sound(sound, repeat = FALSE, wait = FALSE, volume = 25, channel = CHANNEL_AMBIENCE))
SEND_SOUND(L, sound(sound, repeat = FALSE, wait = FALSE, volume = 25 * L.client.prefs.get_channel_volume(CHANNEL_AMBIENCE), channel = CHANNEL_AMBIENCE))
L.client.played = TRUE
addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600)
+4 -1
View File
@@ -70,6 +70,9 @@
S.channel = channel || SSsounds.random_available_channel()
S.volume = vol
if(channel)
S.volume *= client.prefs.get_channel_volume(channel)
if(vary)
if(frequency)
S.frequency = frequency
@@ -150,7 +153,7 @@
if(!SSticker || !SSticker.login_music || config.disable_lobby_music)
return
if(prefs.sound & SOUND_LOBBY)
SEND_SOUND(src, sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC)) // MAD JAMS
SEND_SOUND(src, sound(SSticker.login_music, repeat = 0, wait = 0, volume = 85 * prefs.get_channel_volume(CHANNEL_LOBBYMUSIC), channel = CHANNEL_LOBBYMUSIC)) // MAD JAMS
/proc/get_rand_frequency()
return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs.
+16 -2
View File
@@ -55,7 +55,14 @@
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
log_admin("[key_name(usr)] used there can be only one.")
GLOB.nologevent = 1
world << sound('sound/music/thunderdome.ogg')
var/sound/music = sound('sound/music/thunderdome.ogg', channel = CHANNEL_ADMIN)
for(var/mob/M in GLOB.player_list)
if(M.client.prefs.sound & SOUND_MIDI)
if(isnewplayer(M) && (M.client.prefs.sound & SOUND_LOBBY))
M.stop_sound_channel(CHANNEL_LOBBYMUSIC)
music.volume = 100 * M.client.prefs.get_channel_volume(CHANNEL_ADMIN)
SEND_SOUND(M, music)
/client/proc/only_me()
if(!SSticker)
@@ -101,4 +108,11 @@
message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ME! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1)
log_admin("[key_name(usr)] used there can be only me.")
GLOB.nologevent = 1
world << sound('sound/music/thunderdome.ogg')
var/sound/music = sound('sound/music/thunderdome.ogg', channel = CHANNEL_ADMIN)
for(var/mob/M in GLOB.player_list)
if(M.client.prefs.sound & SOUND_MIDI)
if(isnewplayer(M) && (M.client.prefs.sound & SOUND_LOBBY))
M.stop_sound_channel(CHANNEL_LOBBYMUSIC)
music.volume = 100 * M.client.prefs.get_channel_volume(CHANNEL_ADMIN)
SEND_SOUND(M, music)
+1
View File
@@ -33,6 +33,7 @@ GLOBAL_LIST_EMPTY(sounds_cache)
if(M.client.prefs.sound & SOUND_MIDI)
if(isnewplayer(M) && (M.client.prefs.sound & SOUND_LOBBY))
M.stop_sound_channel(CHANNEL_LOBBYMUSIC)
uploaded_sound.volume = 100 * M.client.prefs.get_channel_volume(CHANNEL_ADMIN)
SEND_SOUND(M, uploaded_sound)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Play Global Sound") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+12 -2
View File
@@ -184,8 +184,18 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
var/slot_name = ""
var/saved = FALSE // Indicates whether the character comes from the database or not
// jukebox volume
var/volume = 100
/// Volume mixer, indexed by channel as TEXT (numerical indexes will not work). Volume goes from 0 to 100.
var/list/volume_mixer = list(
"1024" = 100, // CHANNEL_LOBBYMUSIC
"1023" = 100, // CHANNEL_ADMIN
"1022" = 100, // CHANNEL_VOX
"1021" = 100, // CHANNEL_JUKEBOX
"1020" = 100, // CHANNEL_HEARTBEAT
"1019" = 100, // CHANNEL_BUZZ
"1018" = 100, // CHANNEL_AMBIENCE
)
/// The volume mixer save timer handle. Used to debounce the DB call to save, to avoid spamming.
var/volume_mixer_saving = null
// BYOND membership
var/unlock_content = 0
@@ -10,7 +10,7 @@
toggles,
toggles_2,
sound,
volume,
volume_mixer,
lastchangelog,
exp,
clientfps,
@@ -38,7 +38,7 @@
toggles = text2num(query.item[7])
toggles2 = text2num(query.item[8])
sound = text2num(query.item[9])
volume = text2num(query.item[10])
volume_mixer = deserialize_volume_mixer(query.item[10])
lastchangelog = query.item[11]
exp = query.item[12]
clientfps = text2num(query.item[13])
@@ -57,7 +57,6 @@
sound = sanitize_integer(sound, 0, 65535, initial(sound))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
volume = sanitize_integer(volume, 0, 100, initial(volume))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
exp = sanitize_text(exp, initial(exp))
clientfps = sanitize_integer(clientfps, 0, 1000, initial(clientfps))
@@ -74,6 +73,11 @@
log_runtime(EXCEPTION("[C.key] had a malformed role entry: '[role]'. Removing!"), src)
be_special -= role
// We're saving volume_mixer here as well, so no point in keeping the timer running
if(volume_mixer_saving)
deltimer(volume_mixer_saving)
volume_mixer_saving = null
var/datum/db_query/query = SSdbcore.NewQuery({"UPDATE [format_table_name("player")]
SET
ooccolor=:ooccolour,
@@ -86,7 +90,7 @@
toggles_2=:toggles2,
atklog=:atklog,
sound=:sound,
volume=:volume,
volume_mixer=:volume_mixer,
lastchangelog=:lastchangelog,
clientfps=:clientfps,
parallax=:parallax
@@ -103,7 +107,7 @@
"toggles2" = num2text(toggles2, CEILING(log(10, (TOGGLES_2_TOTAL)), 1)),
"atklog" = atklog,
"sound" = sound,
"volume" = volume,
"volume_mixer" = serialize_volume_mixer(volume_mixer),
"lastchangelog" = lastchangelog,
"clientfps" = clientfps,
"parallax" = parallax,
@@ -657,3 +661,24 @@
saved = FALSE
return TRUE
/**
* Saves [/datum/preferences/proc/volume_mixer] for the current client.
*/
/datum/preferences/proc/save_volume_mixer()
volume_mixer_saving = null
var/datum/db_query/update_query = SSdbcore.NewQuery(
"UPDATE [format_table_name("player")] SET volume_mixer=:volume_mixer WHERE ckey=:ckey",
list(
"volume_mixer" = serialize_volume_mixer(volume_mixer),
"ckey" = parent.ckey
)
)
if(!update_query.warn_execute())
qdel(update_query)
return FALSE
qdel(update_query)
return TRUE
@@ -0,0 +1,84 @@
/**
* Returns a DB-friendly version of a volume mixer list.
*
* Arguments
* * vm - The volume mixer list to serialize.
*/
/datum/preferences/proc/serialize_volume_mixer(list/vm)
var/list/temp = list()
for(var/channel in vm)
if(!get_channel_name(text2num(channel)))
continue
temp["[channel]"] = vm[channel]
return json_encode(temp)
/**
* Returns a volume mixer list from text, usually from the DB.
*
* Failure to deserialize will return the current value.
*
* Arguments
* * vmt - The volume mixer list to deserialize.
*/
/datum/preferences/proc/deserialize_volume_mixer(vmt)
if(!istext(vmt))
return volume_mixer
var/list/vm = json_decode(vmt)
if(!islist(vm))
return volume_mixer
var/list/temp = list()
// Ensure the default values are present
for(var/channel in volume_mixer)
temp[channel] = volume_mixer[channel]
for(var/channel in vm)
if(!get_channel_name(text2num(channel)))
continue
temp[channel] = vm[channel]
return temp
/**
* Changes a channel's volume then queues it for DB save.
*
* Arguments:
* * channel - The channel whose volume to change.
* * volume - The new volume, clamped between 0 and 100.
* * debounce_save - Whether to debounce the save call to prevent spamming of DB calls.
*/
/datum/preferences/proc/set_channel_volume(channel, volume, debounce_save = TRUE)
if(!get_channel_name(channel))
return
// Set the volume
volume = clamp(volume, 0, 100)
volume_mixer["[channel]"] = volume
// Update the sound channel
var/sound/S = sound(null, channel = channel, volume = volume)
S.status = SOUND_UPDATE
SEND_SOUND(parent, S)
// Save it
if(debounce_save)
volume_mixer_saving = addtimer(CALLBACK(src, .proc/save_volume_mixer), 3 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE)
else
if(volume_mixer_saving)
deltimer(volume_mixer_saving)
save_volume_mixer()
/**
* Returns a volume multiplier for the given channel, from 0 to 1 (default).
*
* Arguments:
* * channel - The channel whose volume to get.
*/
/datum/preferences/proc/get_channel_volume(channel)
if(!istext(channel))
channel = "[channel]"
if(isnull(volume_mixer[channel]))
return 1
return clamp(volume_mixer[channel] / 100, 0, 1)
/client/verb/volume_mixer()
set name = "Open Volume Mixer"
set category = "Preferences"
set hidden = TRUE
var/datum/ui_module/volume_mixer/VM = new()
VM.ui_interact(usr)
@@ -179,6 +179,7 @@ GLOBAL_VAR_INIT(announcing_vox, 0) // Stores the time of the last announcement
if(M.client && M.client.prefs.sound & SOUND_AI_VOICE)
var/turf/T = get_turf(M)
if(T && T.z == z_level && M.can_hear())
voice.volume = 100 * M.client.prefs.get_channel_volume(CHANNEL_VOX)
M << voice
else
only_listener << voice
+38
View File
@@ -0,0 +1,38 @@
/datum/ui_module/volume_mixer
name = "Volume Mixer"
/datum/ui_module/volume_mixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "VolumeMixer", name, 400, clamp(80 + 50 * length(user.client.prefs.volume_mixer), 300, 600), master_ui, state)
ui.set_autoupdate(FALSE)
ui.open()
/datum/ui_module/volume_mixer/ui_data(mob/user)
var/list/data = list()
var/list/channels = list()
for(var/channel in user.client.prefs.volume_mixer)
channels += list(list(
"num" = channel,
"name" = get_channel_name(text2num(channel)),
"volume" = user.client.prefs.volume_mixer[channel]
))
data["channels"] = channels
return data
/datum/ui_module/volume_mixer/ui_act(action, list/params)
if(..())
return
. = TRUE
switch(action)
if("volume")
var/channel = text2num(params["channel"])
var/volume = text2num(params["volume"])
if(isnull(channel) || isnull(volume))
return FALSE
usr.client.prefs.set_channel_volume(channel, volume)
else
return FALSE
+1 -1
View File
@@ -9,7 +9,7 @@
## This value must be set to the version of the paradise schema in use.
## If this value does not match, the SQL database will not be loaded and an error will be generated.
## Roundstart will be delayed.
DB_VERSION 20
DB_VERSION 21
## Server the MySQL database can be found at.
# Examples: localhost, 200.135.5.43, www.mysqldb.com, etc.
+438 -429
View File
@@ -1,429 +1,438 @@
macro "default"
menu "menu"
elem
name = "&File"
command = ""
saved-params = "is-checked"
elem
name = "&Quick screenshot\tF2"
command = ".screenshot auto"
category = "&File"
saved-params = "is-checked"
elem
name = "&Save screenshot as...\tShift+F2"
command = ".screenshot"
category = "&File"
saved-params = "is-checked"
elem "reconnectbutton"
name = "&Reconnect"
command = ".reconnect"
category = "&File"
saved-params = "is-checked"
elem
name = ""
command = ""
category = "&File"
saved-params = "is-checked"
elem
name = "&Quit"
command = ".quit"
category = "&File"
saved-params = "is-checked"
elem
name = "&Icons"
command = ""
saved-params = "is-checked"
elem
name = "&Size"
command = ""
category = "&Icons"
saved-params = "is-checked"
elem "stretch"
name = "&Stretch to fit"
command = ".winset \"mapwindow.map.icon-size=0\""
category = "&Size"
is-checked = true
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon128"
name = "&128x128 (4x)"
command = ".winset \"mapwindow.map.icon-size=128\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon96"
name = "&96x96 (3x)"
command = ".winset \"mapwindow.map.icon-size=96\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon64"
name = "&64x64 (2x)"
command = ".winset \"mapwindow.map.icon-size=64\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon48"
name = "&48x48 (1.5x)"
command = ".winset \"mapwindow.map.icon-size=48\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon32"
name = "&32x32"
command = ".winset \"mapwindow.map.icon-size=32\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem
name = "&Scaling"
command = ""
category = "&Icons"
saved-params = "is-checked"
elem "NN"
name = "&Nearest Neighbor"
command = ".winset \"mapwindow.map.zoom-mode=distort\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "PS"
name = "&Point Sampling"
command = ".winset \"mapwindow.map.zoom-mode=normal\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "BL"
name = "&Bilinear"
command = ".winset \"mapwindow.map.zoom-mode=blur\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "textmode"
name = "&Text"
command = ".winset \"menu.textmode.is-checked=true?mapwindow.map.text-mode=true:mapwindow.map.text-mode=false\""
category = "&Icons"
can-check = true
saved-params = "is-checked"
elem
name = "&Help"
command = ""
saved-params = "is-checked"
elem
name = "&Admin help\tF1"
command = "adminhelp"
category = "&Help"
saved-params = "is-checked"
elem
name = "&Hotkeys"
command = "Hotkey-Help"
category = "&Help"
saved-params = "is-checked"
window "mainwindow"
elem "mainwindow"
type = MAIN
pos = 0,0
size = 640x440
anchor1 = none
anchor2 = none
is-default = true
saved-params = "pos;size;is-minimized;is-maximized"
title = "Paradise Station 13"
is-maximized = true
icon = 'icons\\paradise.png'
macro = "default"
menu = "menu"
elem "asset_cache_browser"
type = BROWSER
pos = 0,0
size = 200x200
anchor1 = none
anchor2 = none
is-visible = false
saved-params = ""
elem "mainvsplit"
type = CHILD
pos = 3,0
size = 634x416
anchor1 = 0,0
anchor2 = 100,100
saved-params = "splitter"
left = "mapwindow"
right = "rpane"
is-vert = true
elem "input"
type = INPUT
pos = 3,420
size = 477x20
anchor1 = 0,100
anchor2 = 100,100
background-color = #d3b5b5
is-default = true
border = sunken
saved-params = "command"
elem "saybutton"
type = BUTTON
pos = 480,420
size = 80x20
anchor1 = 100,100
anchor2 = none
saved-params = "is-checked"
text = "Chat"
command = ".winset \"saybutton.is-checked=true?input.command=\"!say \\\"\" macrobutton.is-checked=false:input.command=\"\"saybutton.is-checked=true?mebutton.is-checked=false\""
button-type = pushbox
elem "mebutton"
type = BUTTON
pos = 560,420
size = 80x20
anchor1 = 100,100
anchor2 = none
saved-params = "is-checked"
text = "Me"
command = ".winset \"mebutton.is-checked=true?input.command=\"!me \\\"\" macrobutton.is-checked=false:input.command=\"\"mebutton.is-checked=true?saybutton.is-checked=false\""
button-type = pushbox
elem "tooltip"
type = BROWSER
pos = 0,0
size = 999x999
anchor1 = none
anchor2 = none
is-visible = false
saved-params = ""
window "mapwindow"
elem "mapwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Map window"
is-pane = true
elem "map"
type = MAP
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
font-family = "Arial"
font-size = 7
text-color = none
is-default = true
saved-params = "icon-size"
style=".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .clown { color: #FF69Bf;} .tajaran {color: #803B56;} .skrell {color: #00CED1;} .solcom {color: #22228B;} .com_srus {color: #7c4848;} .zombie {color: #ff0000;} .soghun {color: #228B22;} .vox {color: #AA00AA;} .diona {color: #804000; font-weight: bold;} .trinary {color: #727272;} .kidan {color: #664205;} .slime {color: #0077AA;} .drask {color: #a3d4eb;} .vulpkanin {color: #B97A57;} .abductor {color: #800080; font-style: italic;} .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; }"
window "outputwindow"
elem "outputwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Output window"
can-close = false
can-minimize = false
is-pane = true
elem "browseroutput"
type = BROWSER
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
background-color = #ffffff
is-disabled = true
saved-params = ""
auto-format = false
window "rpane"
elem "rpane"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "rpanewindow"
type = CHILD
pos = -9,15
size = 636x449
anchor1 = 0,0
anchor2 = 100,100
saved-params = "splitter"
right = "outputwindow"
is-vert = false
elem "textb"
type = BUTTON
pos = 0,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Text"
command = ".winset \"rpanewindow.left=;\""
is-checked = true
group = "rpanemode"
button-type = pushbox
elem "infob"
type = BUTTON
pos = 64,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Info"
command = ".winset \"rpanewindow.left=infowindow\""
group = "rpanemode"
button-type = pushbox
elem "wikib"
type = BUTTON
pos = 155,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Wiki"
command = "wiki"
elem "forumb"
type = BUTTON
pos = 220,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Forum"
command = "forum"
elem "rulesb"
type = BUTTON
pos = 285,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Rules"
command = "rules"
elem "githubb"
type = BUTTON
pos = 350,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "GitHub"
command = "github"
elem "changelog"
type = BUTTON
pos = 415,7
size = 67x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Changelog"
command = "Changelog"
elem "discordb"
type = BUTTON
pos = 487,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #7289da
saved-params = "is-checked"
text = "Discord"
command = "discord"
elem "karma"
type = BUTTON
pos = 552,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #ff4500
saved-params = "is-checked"
text = "Karma"
command = "karmashop"
elem "donate"
type = BUTTON
pos = 617,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #008000
saved-params = "is-checked"
text = "Donate"
command = "Donate"
elem "browseb"
type = BUTTON
pos = 561,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Browser"
command = ".winset \"rpanewindow.left=browserwindow\""
group = "rpanemode"
button-type = pushbox
window "browserwindow"
elem "browserwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Browser"
is-pane = true
elem "browser"
type = BROWSER
pos = 0,0
size = 640x499
anchor1 = 0,0
anchor2 = 100,100
is-default = true
saved-params = ""
on-show = ".winset\"rpane.infob.is-visible=true?rpane.infob.pos=130,7;rpane.textb.is-visible=true;rpane.browseb.is-visible=true;rpane.browseb.is-checked=true;rpane.rpanewindow.pos=0,30;rpane.rpanewindow.size=0x0;rpane.rpanewindow.left=browserwindow\""
on-hide = ".winset\"rpane.infob.is-visible=true?rpane.infob.is-checked=true rpane.infob.pos=65,7 rpane.rpanewindow.left=infowindow:rpane.rpanewindow.left=textwindow rpane.textb.is-visible=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0\""
window "infowindow"
elem "infowindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Info"
is-pane = true
elem "info"
type = INFO
pos = 0,0
size = 638x475
anchor1 = 0,0
anchor2 = 100,100
is-default = true
saved-params = ""
highlight-color = #00aa00
on-show = ".winset\"rpane.infob.is-visible=true;rpane.browseb.is-visible=true?rpane.infob.pos=130,7:rpane.infob.pos=65,7 rpane.textb.is-visible=true rpane.infob.is-checked=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=infowindow\""
on-hide = ".winset\"rpane.infob.is-visible=false;rpane.browseb.is-visible=true?rpane.browseb.is-checked=true rpane.rpanewindow.left=browserwindow:rpane.textb.is-visible=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=\""
macro "default"
menu "menu"
elem
name = "&File"
command = ""
saved-params = "is-checked"
elem
name = "&Quick screenshot\tF2"
command = ".screenshot auto"
category = "&File"
saved-params = "is-checked"
elem
name = "&Save screenshot as...\tShift+F2"
command = ".screenshot"
category = "&File"
saved-params = "is-checked"
elem "reconnectbutton"
name = "&Reconnect"
command = ".reconnect"
category = "&File"
saved-params = "is-checked"
elem
name = ""
command = ""
category = "&File"
saved-params = "is-checked"
elem
name = "&Quit"
command = ".quit"
category = "&File"
saved-params = "is-checked"
elem
name = "&Icons"
command = ""
saved-params = "is-checked"
elem
name = "&Size"
command = ""
category = "&Icons"
saved-params = "is-checked"
elem "stretch"
name = "&Stretch to fit"
command = ".winset \"mapwindow.map.icon-size=0\""
category = "&Size"
is-checked = true
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon128"
name = "&128x128 (4x)"
command = ".winset \"mapwindow.map.icon-size=128\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon96"
name = "&96x96 (3x)"
command = ".winset \"mapwindow.map.icon-size=96\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon64"
name = "&64x64 (2x)"
command = ".winset \"mapwindow.map.icon-size=64\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon48"
name = "&48x48 (1.5x)"
command = ".winset \"mapwindow.map.icon-size=48\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem "icon32"
name = "&32x32"
command = ".winset \"mapwindow.map.icon-size=32\""
category = "&Size"
can-check = true
group = "size"
saved-params = "is-checked"
elem
name = "&Scaling"
command = ""
category = "&Icons"
saved-params = "is-checked"
elem "NN"
name = "&Nearest Neighbor"
command = ".winset \"mapwindow.map.zoom-mode=distort\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "PS"
name = "&Point Sampling"
command = ".winset \"mapwindow.map.zoom-mode=normal\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "BL"
name = "&Bilinear"
command = ".winset \"mapwindow.map.zoom-mode=blur\""
category = "&Scaling"
can-check = true
group = "scale"
saved-params = "is-checked"
elem "textmode"
name = "&Text"
command = ".winset \"menu.textmode.is-checked=true?mapwindow.map.text-mode=true:mapwindow.map.text-mode=false\""
category = "&Icons"
can-check = true
saved-params = "is-checked"
elem
name = "&Volume"
command = ""
saved-params = "is-checked"
elem
name = "&Open Volume Mixer"
command = "Open-Volume-Mixer"
category = "&Volume"
saved-params = "is-checked"
elem
name = "&Help"
command = ""
saved-params = "is-checked"
elem
name = "&Admin help\tF1"
command = "adminhelp"
category = "&Help"
saved-params = "is-checked"
elem
name = "&Hotkeys"
command = "Hotkey-Help"
category = "&Help"
saved-params = "is-checked"
window "mainwindow"
elem "mainwindow"
type = MAIN
pos = 0,0
size = 640x440
anchor1 = none
anchor2 = none
is-default = true
saved-params = "pos;size;is-minimized;is-maximized"
title = "Paradise Station 13"
is-maximized = true
icon = 'icons\\paradise.png'
macro = "default"
menu = "menu"
elem "asset_cache_browser"
type = BROWSER
pos = 0,0
size = 200x200
anchor1 = none
anchor2 = none
is-visible = false
saved-params = ""
elem "mainvsplit"
type = CHILD
pos = 3,0
size = 634x416
anchor1 = 0,0
anchor2 = 100,100
saved-params = "splitter"
left = "mapwindow"
right = "rpane"
is-vert = true
elem "input"
type = INPUT
pos = 3,420
size = 477x20
anchor1 = 0,100
anchor2 = 100,100
background-color = #d3b5b5
is-default = true
border = sunken
saved-params = "command"
elem "saybutton"
type = BUTTON
pos = 480,420
size = 80x20
anchor1 = 100,100
anchor2 = none
saved-params = "is-checked"
text = "Chat"
command = ".winset \"saybutton.is-checked=true?input.command=\"!say \\\"\" macrobutton.is-checked=false:input.command=\"\"saybutton.is-checked=true?mebutton.is-checked=false\""
button-type = pushbox
elem "mebutton"
type = BUTTON
pos = 560,420
size = 80x20
anchor1 = 100,100
anchor2 = none
saved-params = "is-checked"
text = "Me"
command = ".winset \"mebutton.is-checked=true?input.command=\"!me \\\"\" macrobutton.is-checked=false:input.command=\"\"mebutton.is-checked=true?saybutton.is-checked=false\""
button-type = pushbox
elem "tooltip"
type = BROWSER
pos = 0,0
size = 999x999
anchor1 = none
anchor2 = none
is-visible = false
saved-params = ""
window "mapwindow"
elem "mapwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Map window"
is-pane = true
elem "map"
type = MAP
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
font-family = "Arial"
font-size = 7
text-color = none
is-default = true
saved-params = "icon-size"
style=".center { text-align: center; } .maptext { font-family: 'Small Fonts'; font-size: 7px; -dm-text-outline: 1px black; color: white; line-height: 1.1; } .small { font-size: 6px; } .big { font-size: 8px; } .reallybig { font-size: 8px; } .extremelybig { font-size: 8px; } .clown { color: #FF69Bf;} .tajaran {color: #803B56;} .skrell {color: #00CED1;} .solcom {color: #22228B;} .com_srus {color: #7c4848;} .zombie {color: #ff0000;} .soghun {color: #228B22;} .vox {color: #AA00AA;} .diona {color: #804000; font-weight: bold;} .trinary {color: #727272;} .kidan {color: #664205;} .slime {color: #0077AA;} .drask {color: #a3d4eb;} .vulpkanin {color: #B97A57;} .abductor {color: #800080; font-style: italic;} .his_grace { color: #15D512; } .hypnophrase { color: #0d0d0d; font-weight: bold; } .yell { font-weight: bold; }"
window "outputwindow"
elem "outputwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Output window"
can-close = false
can-minimize = false
is-pane = true
elem "browseroutput"
type = BROWSER
pos = 0,0
size = 640x480
anchor1 = 0,0
anchor2 = 100,100
background-color = #ffffff
is-disabled = true
saved-params = ""
auto-format = false
window "rpane"
elem "rpane"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
is-pane = true
elem "rpanewindow"
type = CHILD
pos = -9,15
size = 636x449
anchor1 = 0,0
anchor2 = 100,100
saved-params = "splitter"
right = "outputwindow"
is-vert = false
elem "textb"
type = BUTTON
pos = 0,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Text"
command = ".winset \"rpanewindow.left=;\""
is-checked = true
group = "rpanemode"
button-type = pushbox
elem "infob"
type = BUTTON
pos = 64,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Info"
command = ".winset \"rpanewindow.left=infowindow\""
group = "rpanemode"
button-type = pushbox
elem "wikib"
type = BUTTON
pos = 155,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Wiki"
command = "wiki"
elem "forumb"
type = BUTTON
pos = 220,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Forum"
command = "forum"
elem "rulesb"
type = BUTTON
pos = 285,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Rules"
command = "rules"
elem "githubb"
type = BUTTON
pos = 350,7
size = 60x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "GitHub"
command = "github"
elem "changelog"
type = BUTTON
pos = 415,7
size = 67x16
anchor1 = none
anchor2 = none
saved-params = "is-checked"
text = "Changelog"
command = "Changelog"
elem "discordb"
type = BUTTON
pos = 487,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #7289da
saved-params = "is-checked"
text = "Discord"
command = "discord"
elem "karma"
type = BUTTON
pos = 552,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #ff4500
saved-params = "is-checked"
text = "Karma"
command = "karmashop"
elem "donate"
type = BUTTON
pos = 617,7
size = 60x16
anchor1 = none
anchor2 = none
font-style = "bold"
text-color = #ffffff
background-color = #008000
saved-params = "is-checked"
text = "Donate"
command = "Donate"
elem "browseb"
type = BUTTON
pos = 561,7
size = 60x16
anchor1 = none
anchor2 = none
is-visible = false
saved-params = "is-checked"
text = "Browser"
command = ".winset \"rpanewindow.left=browserwindow\""
group = "rpanemode"
button-type = pushbox
window "browserwindow"
elem "browserwindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Browser"
is-pane = true
elem "browser"
type = BROWSER
pos = 0,0
size = 640x499
anchor1 = 0,0
anchor2 = 100,100
is-default = true
saved-params = ""
on-show = ".winset\"rpane.infob.is-visible=true?rpane.infob.pos=130,7;rpane.textb.is-visible=true;rpane.browseb.is-visible=true;rpane.browseb.is-checked=true;rpane.rpanewindow.pos=0,30;rpane.rpanewindow.size=0x0;rpane.rpanewindow.left=browserwindow\""
on-hide = ".winset\"rpane.infob.is-visible=true?rpane.infob.is-checked=true rpane.infob.pos=65,7 rpane.rpanewindow.left=infowindow:rpane.rpanewindow.left=textwindow rpane.textb.is-visible=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0\""
window "infowindow"
elem "infowindow"
type = MAIN
pos = 0,0
size = 640x480
anchor1 = none
anchor2 = none
saved-params = "pos;size;is-minimized;is-maximized"
title = "Info"
is-pane = true
elem "info"
type = INFO
pos = 0,0
size = 638x475
anchor1 = 0,0
anchor2 = 100,100
is-default = true
saved-params = ""
highlight-color = #00aa00
on-show = ".winset\"rpane.infob.is-visible=true;rpane.browseb.is-visible=true?rpane.infob.pos=130,7:rpane.infob.pos=65,7 rpane.textb.is-visible=true rpane.infob.is-checked=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=infowindow\""
on-hide = ".winset\"rpane.infob.is-visible=false;rpane.browseb.is-visible=true?rpane.browseb.is-checked=true rpane.rpanewindow.left=browserwindow:rpane.textb.is-visible=true rpane.rpanewindow.pos=0,30 rpane.rpanewindow.size=0x0 rpane.rpanewindow.left=\""
+2
View File
@@ -1362,6 +1362,7 @@
#include "code\modules\client\preference\preferences_mysql.dm"
#include "code\modules\client\preference\preferences_spawnpoints.dm"
#include "code\modules\client\preference\preferences_toggles.dm"
#include "code\modules\client\preference\preferences_volume_mixer.dm"
#include "code\modules\client\preference\loadout\gear_tweaks.dm"
#include "code\modules\client\preference\loadout\loadout.dm"
#include "code\modules\client\preference\loadout\loadout_accessories.dm"
@@ -2465,6 +2466,7 @@
#include "code\modules\tgui\modules\ert_manager.dm"
#include "code\modules\tgui\modules\law_manager.dm"
#include "code\modules\tgui\modules\power_monitor.dm"
#include "code\modules\tgui\modules\volume_mixer.dm"
#include "code\modules\tgui\plugins\login.dm"
#include "code\modules\tgui\plugins\modal.dm"
#include "code\modules\tgui\states\admin.dm"
@@ -0,0 +1,57 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Flex, Icon, Section, Slider } from '../components';
import { Window } from '../layouts';
export const VolumeMixer = (properties, context) => {
const { act, data } = useBackend(context);
const {
channels,
} = data;
return (
<Window>
<Window.Content>
<Section height="100%" overflow="auto">
{channels.map((channel, key) => (
<Fragment key={channel.num}>
<Box fontSize="1.25rem" color="label" mt={key > 0 && "0.5rem"}>{channel.name}</Box>
<Box mt="0.5rem">
<Flex>
<Flex.Item>
<Button width="24px" color="transparent">
<Icon
name="volume-off"
size="1.5"
mt="0.1rem"
onClick={() => act("volume", { channel: channel.num, volume: 0 })}
/>
</Button>
</Flex.Item>
<Flex.Item grow="1" mx="1rem">
<Slider
minValue={0}
maxValue={100}
stepPixelSize={3.13}
value={channel.volume}
onChange={(e, value) => act("volume", { channel: channel.num, volume: value })}
/>
</Flex.Item>
<Flex.Item>
<Button width="24px" color="transparent">
<Icon
name="volume-up"
size="1.5"
mt="0.1rem"
onClick={() => act("volume", { channel: channel.num, volume: 100 })}
/>
</Button>
</Flex.Item>
</Flex>
</Box>
</Fragment>
))}
</Section>
</Window.Content>
</Window>
);
};
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -2,7 +2,7 @@
# Dont use it ingame
# Remember to update this when you increase the SQL version! -aa
SQL_ENABLED
DB_VERSION 20
DB_VERSION 21
ADDRESS 127.0.0.1
PORT 3306
FEEDBACK_DATABASE feedback