mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-16 09:34:21 +01:00
Initial commit of media suite
Conflicts: baystation12.dme code/controllers/configuration.dm code/game/area/areas.dm code/modules/client/client defines.dm
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
// Called when a mob moves from one MASTER area to another.
|
||||
// (Master, as opposed to lighting subareas)
|
||||
/hook/mobAreaChange
|
||||
name = "MobAreaChange"
|
||||
@@ -0,0 +1,54 @@
|
||||
/************
|
||||
* D2K5-STYLE HOOKS
|
||||
*
|
||||
* BLATANTLY STOLEN FROM D2K5 AND MODIFIED
|
||||
*
|
||||
* SOMEHOW SUCKS LESS THAN BAY'S HOOKS
|
||||
************
|
||||
|
||||
The major change is to standardize them a bit
|
||||
by changing the event prefix to On instead of Hook.
|
||||
|
||||
Oh and it's documented and cleaned up. - N3X
|
||||
*/
|
||||
|
||||
/hook
|
||||
var/name = "DefaultHookName"
|
||||
var/list/handlers = list()
|
||||
|
||||
proc/Called(var/list/args) // When the hook is called
|
||||
return 0
|
||||
|
||||
proc/Setup() // Called when the setup things is ran for the hook, objs contain all objects with that is hooking
|
||||
|
||||
/hook_handler
|
||||
// Your hook handler should do this:
|
||||
// proc/OnThingHappened(var/list/args)
|
||||
// return handled // boolean
|
||||
|
||||
var/global/list/hooks = list()
|
||||
|
||||
/proc/SetupHooks()
|
||||
for (var/hook_path in typesof(/hook))
|
||||
var/hook/hook = new hook_path
|
||||
hooks[hook.name] = hook
|
||||
//world.log << "Found hook: " + hook.name
|
||||
for (var/hook_path in typesof(/hook_handler))
|
||||
var/hook_handler/hook_handler = new hook_path
|
||||
for (var/name in hooks)
|
||||
if (hascall(hook_handler, "On" + name))
|
||||
var/hook/hook = hooks[name]
|
||||
hook.handlers += hook_handler
|
||||
//world.log << "Found hook handler for: " + name
|
||||
for (var/hook/hook in hooks)
|
||||
hook.Setup()
|
||||
|
||||
/proc/CallHook(var/name as text, var/list/args)
|
||||
var/hook/hook = hooks[name]
|
||||
if (!hook)
|
||||
//world.log << "WARNING: Hook with name " + name + " does not exist"
|
||||
return
|
||||
if (hook.Called(args))
|
||||
return
|
||||
for (var/hook_handler/hook_handler in hook.handlers)
|
||||
call(hook_handler, "On" + hook.name)(args)
|
||||
@@ -72,6 +72,8 @@
|
||||
var/wikiurl = "http://baystation12.net/wiki/index.php?title=Main_Page"
|
||||
var/forumurl = "http://baystation12.net/forums/"
|
||||
|
||||
var/media_base_url = "http://80.244.78.90/media" // http://ss13.nexisonline.net/media
|
||||
|
||||
//Alert level description
|
||||
var/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
|
||||
var/alert_desc_blue_upto = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
|
||||
@@ -450,6 +452,10 @@
|
||||
|
||||
if("assistant_ratio")
|
||||
config.assistantratio = text2num(value)
|
||||
|
||||
if("media_base_url")
|
||||
media_base_url = value
|
||||
|
||||
else
|
||||
diary << "Unknown setting in configuration: '[name]'"
|
||||
|
||||
|
||||
+36
-30
@@ -323,46 +323,52 @@
|
||||
|
||||
if(!L.lastarea)
|
||||
L.lastarea = get_area(L.loc)
|
||||
if(L.lastarea.master)
|
||||
L.lastarea = L.lastarea.master
|
||||
var/area/newarea = get_area(L.loc)
|
||||
if(newarea.master)
|
||||
newarea = newarea.master
|
||||
var/area/oldarea = L.lastarea
|
||||
if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together.
|
||||
thunk(L)
|
||||
|
||||
L.lastarea = newarea
|
||||
|
||||
// /vg/ - EVENTS!
|
||||
CallHook("MobAreaChange", list("mob" = L, "new" = newarea, "old" = oldarea))
|
||||
|
||||
// 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.prefs.sound & SOUND_AMBIENCE))) return
|
||||
if(L && L.client && (L.client.prefs.toggles & SOUND_AMBIENCE))
|
||||
if(!L.client.ambience_playing)
|
||||
L.client.ambience_playing = 1
|
||||
L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
|
||||
|
||||
if(!L.client.ambience_playing)
|
||||
L.client.ambience_playing = 1
|
||||
L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
|
||||
if(prob(35) && !newarea.media_source)
|
||||
// TODO: This is dumb. - N3X
|
||||
if(istype(src, /area/chapel))
|
||||
sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/medical/morgue))
|
||||
sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg')
|
||||
else if(type == /area)
|
||||
sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/engine))
|
||||
sound = pick('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
|
||||
else if(istype(src, /area/AIsattele) || istype(src, /area/turret_protected/ai) || istype(src, /area/turret_protected/ai_upload) || istype(src, /area/turret_protected/ai_upload_foyer))
|
||||
sound = pick('sound/ambience/ambimalf.ogg')
|
||||
else if(istype(src, /area/mine/explored) || istype(src, /area/mine/unexplored))
|
||||
sound = pick('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg')
|
||||
musVolume = 25
|
||||
else if(istype(src, /area/tcommsat) || istype(src, /area/turret_protected/tcomwest) || istype(src, /area/turret_protected/tcomeast) || istype(src, /area/turret_protected/tcomfoyer) || istype(src, /area/turret_protected/tcomsat))
|
||||
sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
else
|
||||
sound = pick('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
|
||||
|
||||
if(prob(35))
|
||||
|
||||
if(istype(src, /area/chapel))
|
||||
sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/medical/morgue))
|
||||
sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg')
|
||||
else if(type == /area)
|
||||
sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/engine))
|
||||
sound = pick('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
|
||||
else if(istype(src, /area/AIsattele) || istype(src, /area/turret_protected/ai) || istype(src, /area/turret_protected/ai_upload) || istype(src, /area/turret_protected/ai_upload_foyer))
|
||||
sound = pick('sound/ambience/ambimalf.ogg')
|
||||
else if(istype(src, /area/mine/explored) || istype(src, /area/mine/unexplored))
|
||||
sound = pick('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg')
|
||||
musVolume = 25
|
||||
else if(istype(src, /area/tcommsat) || istype(src, /area/turret_protected/tcomwest) || istype(src, /area/turret_protected/tcomeast) || istype(src, /area/turret_protected/tcomfoyer) || istype(src, /area/turret_protected/tcomsat))
|
||||
sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
else
|
||||
sound = pick('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
|
||||
|
||||
if(!L.client.played)
|
||||
L << sound(sound, repeat = 0, wait = 0, volume = musVolume, channel = 1)
|
||||
L.client.played = 1
|
||||
spawn(600) //ewww - this is very very bad
|
||||
if(L.&& L.client)
|
||||
L.client.played = 0
|
||||
if(!L.client.played)
|
||||
L << sound(sound, repeat = 0, wait = 0, volume = musVolume, channel = 1)
|
||||
L.client.played = 1
|
||||
spawn(600) //ewww - this is very very bad
|
||||
if(L.&& L.client)
|
||||
L.client.played = 0
|
||||
|
||||
/area/proc/gravitychange(var/gravitystate = 0, var/area/A)
|
||||
|
||||
|
||||
@@ -40,8 +40,13 @@
|
||||
var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip
|
||||
var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id
|
||||
|
||||
preload_rsc = 0 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
|
||||
preload_rsc = 1 // This is 0 so we can set it to an URL once the player logs in and have them download the resources from a different server.
|
||||
|
||||
|
||||
var/karma = 0
|
||||
var/karma_spent = 0
|
||||
var/karma_spent = 0
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// /vg/: MEDIAAAAAAAA
|
||||
// Set on login.
|
||||
var/datum/media_manager/media = null
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*******************************
|
||||
* Largely a rewrite of the Jukebox from D2K5
|
||||
*
|
||||
* By N3X15
|
||||
*******************************/
|
||||
|
||||
#define JUKEMODE_SHUFFLE 1 // Default
|
||||
#define JUKEMODE_REPEAT_SONG 2
|
||||
#define JUKEMODE_PLAY_ONCE 3 // Play, then stop.
|
||||
#define JUKEMODE_COUNT 3
|
||||
|
||||
// Represents a record returned.
|
||||
/datum/song_info
|
||||
var/title = ""
|
||||
var/artist = ""
|
||||
var/album = ""
|
||||
|
||||
var/url = ""
|
||||
var/length = 0 // decaseconds
|
||||
|
||||
New(var/list/json)
|
||||
title = json["title"]
|
||||
artist = json["artist"]
|
||||
album = json["album"]
|
||||
|
||||
url = json["url"]
|
||||
|
||||
length = text2num(json["length"])
|
||||
|
||||
|
||||
var/global/loopModeNames=list(
|
||||
JUKEMODE_SHUFFLE = "Shuffle",
|
||||
JUKEMODE_REPEAT_SONG = "Single",
|
||||
JUKEMODE_PLAY_ONCE= "Once",
|
||||
)
|
||||
/obj/machinery/media/jukebox
|
||||
name = "Jukebox"
|
||||
desc = "A jukebox used for parties and shit."
|
||||
icon = 'icons/obj/jukebox.dmi'
|
||||
icon_state = "jukebox"
|
||||
density = 1
|
||||
|
||||
anchored = 1
|
||||
luminosity = 4 // Why was this 16
|
||||
|
||||
var/loop_mode = JUKEMODE_SHUFFLE
|
||||
// /datum/song_info
|
||||
var/list/playlist
|
||||
var/current_song=0
|
||||
|
||||
/obj/machinery/media/jukebox/attack_ai()
|
||||
return
|
||||
|
||||
/obj/machinery/media/jukebox/attack_paw()
|
||||
return
|
||||
|
||||
/obj/machinery/media/jukebox/attack_hand(var/mob/user)
|
||||
var/t = "<h1>Jukebox Interface</h1>"
|
||||
t += "<b>Power:</b> <a href='?src=\ref[src];power=1'>[playing?"On":"Off"]</a><br />"
|
||||
t += "<b>Play Mode:</b> <a href='?src=\ref[src];loop=1'>[loopModeNames[loop_mode]]</a><br />"
|
||||
if(current_song)
|
||||
var/datum/song_info/song=playlist[current_song]
|
||||
t += "<b>Current song:</b> [song.artist] - [song.title]<br />"
|
||||
t += "<table class='prettytable'><tr><th colspan='2'>Artist - Title</th><th>Album</th></tr>"
|
||||
var/i
|
||||
for(i = 1,i <= playlist.len,i++)
|
||||
var/datum/song_info/song=playlist[i]
|
||||
t += "<tr><th>#[i]</th><td><A href='?src=\ref[src];song=[i]'>[song.artist] - [song.title]</A></td><td>[song.album]</td></tr>"
|
||||
t += "</table>"
|
||||
user.set_machine(src)
|
||||
var/datum/browser/popup = new (user,"jukebox",name,420,700)
|
||||
popup.set_content(t)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/media/jukebox/Topic(href, href_list)
|
||||
..()
|
||||
if (href_list["power"])
|
||||
playing=!playing
|
||||
|
||||
if (href_list["song"])
|
||||
current_song=Clamp(text2num(href_list["song"]),1,playlist.len)
|
||||
update_music()
|
||||
|
||||
if (href_list["mode"])
|
||||
// Theoretically, this should barrel shift.
|
||||
loop_mode = (loop_mode % JUKEMODE_COUNT)+1
|
||||
return attack_hand(usr)
|
||||
|
||||
/obj/machinery/media/jukebox/process()
|
||||
if(!playlist)
|
||||
var/url="[config.media_base_url]/index.php"
|
||||
var/response = world.Export(url)
|
||||
playlist=list()
|
||||
if(response)
|
||||
var/json = file2text(response["CONTENT"])
|
||||
var/json_reader/reader = new()
|
||||
reader.tokens = reader.ScanJson(json)
|
||||
reader.i = 1
|
||||
var/songdata = reader.read_value()
|
||||
for(var/list/record in songdata)
|
||||
playlist += new /datum/song_info(record)
|
||||
else
|
||||
stat &= BROKEN
|
||||
update_icon()
|
||||
return
|
||||
if(playing)
|
||||
var/datum/song_info/song
|
||||
if(current_song)
|
||||
song = playlist[current_song]
|
||||
if(!current_song || (song && world.time >= media_start_time + song.length))
|
||||
current_song=1
|
||||
switch(loop_mode)
|
||||
if(JUKEMODE_SHUFFLE)
|
||||
current_song=rand(1,playlist.len)
|
||||
if(JUKEMODE_REPEAT_SONG)
|
||||
current_song=current_song
|
||||
if(JUKEMODE_PLAY_ONCE)
|
||||
playing=0
|
||||
return
|
||||
if(!playing) return
|
||||
update_music()
|
||||
|
||||
/obj/machinery/media/jukebox/update_music()
|
||||
var/datum/song_info/song = playlist[current_song]
|
||||
media_url = song.url
|
||||
media_start_time = world.time
|
||||
visible_message("<span class='notice'>\icon[src] \The [src] begins to play \"[song.title]\", by [song.artist].</notice>","<em>You hear music.</em>")
|
||||
visible_message("<span class='notice'>\icon[src] \The [src] warbles: [song.length]ds, [song.url]</notice>")
|
||||
..()
|
||||
@@ -0,0 +1,15 @@
|
||||
// Machinery serving as a media source.
|
||||
/obj/machinery/media
|
||||
var/playing=0
|
||||
var/media_url=""
|
||||
var/media_start_time=0
|
||||
|
||||
// Notify everyone in the area of new music.
|
||||
// YOU MUST SET MEDIA_URL AND MEDIA_START_TIME YOURSELF!
|
||||
/obj/machinery/media/proc/update_music()
|
||||
var/area/A = get_area(src)
|
||||
if(A.master)
|
||||
A=A.master
|
||||
for(var/mob/M in A)
|
||||
if(M && M.client)
|
||||
M.update_music()
|
||||
@@ -0,0 +1,84 @@
|
||||
/**********************
|
||||
* AWW SHIT IT'S TIME FOR RADIO
|
||||
*
|
||||
* Concept stolen from D2K5
|
||||
*
|
||||
* Rewritten (except for player HTML) by N3X15
|
||||
***********************/
|
||||
|
||||
// Open up WMP and play musique.
|
||||
// TODO: Convert to VLC for cross-platform and ogg support. - N3X
|
||||
var/const/PLAYER_HTML={"
|
||||
<OBJECT id='player' CLASSID='CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6' type='application/x-oleobject'></OBJECT>
|
||||
<script>
|
||||
function noErrorMessages () { return true; }
|
||||
window.onerror = noErrorMessages;
|
||||
function SetMusic(url, time, volume) {
|
||||
var player = document.getElementById('player');
|
||||
player.URL = url;
|
||||
player.Controls.currentPosition = time;
|
||||
player.Settings.volume = volume;
|
||||
}
|
||||
</script>"}
|
||||
|
||||
// Hook into the events we desire.
|
||||
/hook_handler/soundmanager
|
||||
// Set up player on login
|
||||
proc/OnLogin(var/list/args)
|
||||
var/client/C = args["client"]
|
||||
C.media = new /datum/media_manager(C)
|
||||
C.media.open()
|
||||
|
||||
// Update when moving between areas.
|
||||
proc/OnMobAreaChange(var/list/args)
|
||||
var/mob/M = args["mob"]
|
||||
|
||||
M.update_music()
|
||||
|
||||
/mob/proc/update_music()
|
||||
if (client)
|
||||
if(client.media)
|
||||
client.media.update_music()
|
||||
|
||||
/area
|
||||
// One media source per area.
|
||||
var/obj/machinery/media/media_source = null
|
||||
|
||||
/datum/media_manager
|
||||
var/url = ""
|
||||
var/start_time = 0
|
||||
var/volume = 100
|
||||
|
||||
var/client/owner
|
||||
|
||||
New(var/mob/holder)
|
||||
src.owner=holder
|
||||
|
||||
// Actually pop open the player in the background.
|
||||
proc/open()
|
||||
owner << browse(PLAYER_HTML, "window=rpane.hosttracker")
|
||||
send_update()
|
||||
|
||||
// Tell the player to play something via JS.
|
||||
proc/send_update()
|
||||
owner << output(list2params(list(url, (world.timeofday - start_time) / 10, volume)), "rpane.hosttracker:SetMusic")
|
||||
|
||||
// Scan for media sources and use them.
|
||||
proc/update_music()
|
||||
var/targetURL = ""
|
||||
var/targetStartTime = 0
|
||||
var/targetVolume = 100
|
||||
|
||||
if (owner)
|
||||
var/area/A = get_area()
|
||||
var/obj/machinery/media/M = A.media_source
|
||||
if(M.playing)
|
||||
targetURL = M.media_url
|
||||
targetStartTime = M.media_start_time
|
||||
|
||||
if (url != targetURL || abs(targetStartTime - start_time) > 1 || targetVolume != volume)
|
||||
url = targetURL
|
||||
start_time = targetStartTime
|
||||
volume = targetVolume
|
||||
|
||||
send_update()
|
||||
@@ -54,4 +54,6 @@
|
||||
if(istype(src,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(H.species && H.species.abilities)
|
||||
client.verbs |= H.species.abilities
|
||||
client.verbs |= H.species.abilities
|
||||
|
||||
CallHook("Login", list("client" = src.client, "mob" = src))
|
||||
|
||||
@@ -59,11 +59,13 @@ json_reader
|
||||
while(++i <= lentext(json))
|
||||
var/char = get_char()
|
||||
if(escape)
|
||||
escape=FALSE // WHICH STUPID ASSHOLE FORGOT THIS - N3X
|
||||
switch(char)
|
||||
if("\\", "'", "\"", "/", "u")
|
||||
val += char
|
||||
else
|
||||
// TODO: support octal, hex, unicode sequences
|
||||
//testing("Having trouble with \"\\[char]\" in string \"[val]\"")
|
||||
ASSERT(sequences.Find(char))
|
||||
val += ascii2text(sequences[char])
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user