diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index e7818d7bf3..dc2ac19e65 100644 --- a/code/__DEFINES/language.dm +++ b/code/__DEFINES/language.dm @@ -2,3 +2,6 @@ #define TONGUELESS_SPEECH 2 #define LANGUAGE_HIDE_ICON_IF_UNDERSTOOD 4 #define LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD 8 + +#define LANGUAGE_KNOWN "language_known" +#define LANGUAGE_SHADOWED "language_shadowed" diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index c0b9a20d3b..0a1d66c2ed 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -46,6 +46,7 @@ #define INIT_ORDER_TICKER 13 #define INIT_ORDER_MAPPING 12 #define INIT_ORDER_ATOMS 11 +#define INIT_ORDER_LANGUAGE 10 #define INIT_ORDER_MACHINES 9 #define INIT_ORDER_SHUTTLE 3 #define INIT_ORDER_TIMER 1 diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index e378970225..acb60ee68e 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -19,5 +19,7 @@ GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs GLOBAL_LIST_EMPTY(ai_list) GLOBAL_LIST_EMPTY(pai_list) GLOBAL_LIST_EMPTY(available_ai_shells) -GLOBAL_LIST_EMPTY(language_datums) -GLOBAL_LIST_EMPTY(simple_animals) \ No newline at end of file +GLOBAL_LIST_EMPTY(simple_animals) + +GLOBAL_LIST_EMPTY(language_datum_instances) +GLOBAL_LIST_EMPTY(all_languages) diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm index 04655315b7..c2448ceb87 100644 --- a/code/_onclick/hud/ghost.dm +++ b/code/_onclick/hud/ghost.dm @@ -68,6 +68,10 @@ using.screen_loc = ui_ghost_pai static_inventory += using + using = new /obj/screen/language_menu + using.icon = ui_style + static_inventory += using + /datum/hud/ghost/show_hud(version = 0, mob/viewmob) ..() if(!mymob.client.prefs.ghost_hud) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index bfab19ba5f..3cd0d5bdbd 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -91,10 +91,9 @@ screen_loc = ui_language_menu /obj/screen/language_menu/Click() - var/mob/living/L = usr - if(!istype(L)) - return - L.open_language_menu(usr) + var/mob/M = usr + var/datum/language_holder/H = M.get_language_holder() + H.open_language_menu(usr) /obj/screen/inventory var/slot_id // The indentifier for the slot. It has nothing to do with ID cards. diff --git a/code/controllers/subsystem/language.dm b/code/controllers/subsystem/language.dm new file mode 100644 index 0000000000..e80a7096d8 --- /dev/null +++ b/code/controllers/subsystem/language.dm @@ -0,0 +1,18 @@ +SUBSYSTEM_DEF(language) + name = "Language" + init_order = INIT_ORDER_LANGUAGE + flags = SS_NO_FIRE + +/datum/controller/subsystem/language/Initialize(timeofday) + for(var/L in subtypesof(/datum/language)) + var/datum/language/language = L + if(!initial(language.key)) + continue + + GLOB.all_languages += language + + var/datum/language/instance = new language + + GLOB.language_datum_instances[language] = instance + + return ..() diff --git a/code/datums/action.dm b/code/datums/action.dm index 08239492f3..5a397fe3bd 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -482,6 +482,7 @@ /datum/action/language_menu/Trigger() if(!..()) return FALSE - if(isliving(owner)) - var/mob/living/L = owner - L.open_language_menu(usr) + if(ismob(owner)) + var/mob/M = owner + var/datum/language_holder/H = M.get_language_holder() + H.open_language_menu(usr) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 24774da158..66085de7d1 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -1,159 +1,160 @@ -#define HOLOPAD_MAX_DIAL_TIME 200 - -/mob/camera/aiEye/remote/holo/setLoc() - . = ..() - var/obj/machinery/holopad/H = origin - H.move_hologram(eye_user, loc) - -//this datum manages it's own references - -/datum/holocall - var/mob/living/user //the one that called - var/obj/machinery/holopad/calling_holopad //the one that sent the call - var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null) - var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered - - var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected - var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected - - var/call_start_time - -//creates a holocall made by `caller` from `calling_pad` to `callees` -/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) - call_start_time = world.time - user = caller - calling_pad.outgoing_call = src - calling_holopad = calling_pad - dialed_holopads = list() - - for(var/I in callees) - var/obj/machinery/holopad/H = I - if(!QDELETED(H) && H.is_operational()) - dialed_holopads += H - LAZYADD(H.holo_calls, src) - - if(!dialed_holopads.len) - calling_pad.say("Connection failure.") - qdel(src) - return - - testing("Holocall started") - -//cleans up ALL references :) -/datum/holocall/Destroy() - QDEL_NULL(eye) - - user.reset_perspective() - - user = null - hologram.HC = null - hologram = null - calling_holopad.outgoing_call = null - - for(var/I in dialed_holopads) - var/obj/machinery/holopad/H = I - LAZYREMOVE(H.holo_calls, src) - dialed_holopads.Cut() - - if(calling_holopad) - calling_holopad.SetLightsAndPower() - calling_holopad = null - if(connected_holopad) - connected_holopad.SetLightsAndPower() - connected_holopad = null - - testing("Holocall destroyed") - - return ..() - -//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection -/datum/holocall/proc/Disconnect(obj/machinery/holopad/H) - testing("Holocall disconnect") - if(H == connected_holopad) - calling_holopad.say("[usr] disconnected.") - else if(H == calling_holopad && connected_holopad) - connected_holopad.say("[usr] disconnected.") - - ConnectionFailure(H, TRUE) - -//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored. -/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE) - testing("Holocall connection failure: graceful [graceful]") - if(H == connected_holopad || H == calling_holopad) - if(!graceful) - calling_holopad.say("Connection failure.") - qdel(src) - return - - LAZYREMOVE(H.holo_calls, src) - dialed_holopads -= H - if(!dialed_holopads.len) - if(graceful) - calling_holopad.say("Call rejected.") - testing("No recipients, terminating") - qdel(src) - -//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored -/datum/holocall/proc/Answer(obj/machinery/holopad/H) - testing("Holocall answer") - if(H == calling_holopad) - CRASH("How cute, a holopad tried to answer itself.") - - if(!(H in dialed_holopads)) - return - - if(connected_holopad) - CRASH("Multi-connection holocall") - - for(var/I in dialed_holopads) - if(I == H) - continue - Disconnect(I) - - for(var/I in H.holo_calls) - var/datum/holocall/HC = I - if(HC != src) - HC.Disconnect(H) - - connected_holopad = H - - if(!Check()) - return - - hologram = H.activate_holo(user) - hologram.HC = src - - //eyeobj code is horrid, this is the best copypasta I could make - eye = new - eye.origin = H - eye.eye_initialized = TRUE - eye.eye_user = user - eye.name = "Camera Eye ([user.name])" - user.remote_control = eye - user.reset_perspective(eye) - eye.setLoc(H.loc) - -//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise -/datum/holocall/proc/Check() - for(var/I in dialed_holopads) - var/obj/machinery/holopad/H = I - if(!H.is_operational()) - ConnectionFailure(H) - - if(QDELETED(src)) - return FALSE - - . = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc - - if(.) - if(connected_holopad) - . = !QDELETED(connected_holopad) && connected_holopad.is_operational() - else - . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) - if(!.) - calling_holopad.say("No answer recieved.") - calling_holopad.temp = "" - - if(!.) - testing("Holocall Check fail") - qdel(src) + +#define HOLOPAD_MAX_DIAL_TIME 200 + +/mob/camera/aiEye/remote/holo/setLoc() + . = ..() + var/obj/machinery/holopad/H = origin + H.move_hologram(eye_user, loc) + +//this datum manages it's own references + +/datum/holocall + var/mob/living/user //the one that called + var/obj/machinery/holopad/calling_holopad //the one that sent the call + var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null) + var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered + + var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected + var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected + + var/call_start_time + +//creates a holocall made by `caller` from `calling_pad` to `callees` +/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) + call_start_time = world.time + user = caller + calling_pad.outgoing_call = src + calling_holopad = calling_pad + dialed_holopads = list() + + for(var/I in callees) + var/obj/machinery/holopad/H = I + if(!QDELETED(H) && H.is_operational()) + dialed_holopads += H + LAZYADD(H.holo_calls, src) + + if(!dialed_holopads.len) + calling_pad.say("Connection failure.") + qdel(src) + return + + testing("Holocall started") + +//cleans up ALL references :) +/datum/holocall/Destroy() + QDEL_NULL(eye) + + user.reset_perspective() + + user = null + hologram.HC = null + hologram = null + calling_holopad.outgoing_call = null + + for(var/I in dialed_holopads) + var/obj/machinery/holopad/H = I + LAZYREMOVE(H.holo_calls, src) + dialed_holopads.Cut() + + if(calling_holopad) + calling_holopad.SetLightsAndPower() + calling_holopad = null + if(connected_holopad) + connected_holopad.SetLightsAndPower() + connected_holopad = null + + testing("Holocall destroyed") + + return ..() + +//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection +/datum/holocall/proc/Disconnect(obj/machinery/holopad/H) + testing("Holocall disconnect") + if(H == connected_holopad) + calling_holopad.say("[usr] disconnected.") + else if(H == calling_holopad && connected_holopad) + connected_holopad.say("[usr] disconnected.") + + ConnectionFailure(H, TRUE) + +//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored. +/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE) + testing("Holocall connection failure: graceful [graceful]") + if(H == connected_holopad || H == calling_holopad) + if(!graceful) + calling_holopad.say("Connection failure.") + qdel(src) + return + + LAZYREMOVE(H.holo_calls, src) + dialed_holopads -= H + if(!dialed_holopads.len) + if(graceful) + calling_holopad.say("Call rejected.") + testing("No recipients, terminating") + qdel(src) + +//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored +/datum/holocall/proc/Answer(obj/machinery/holopad/H) + testing("Holocall answer") + if(H == calling_holopad) + CRASH("How cute, a holopad tried to answer itself.") + + if(!(H in dialed_holopads)) + return + + if(connected_holopad) + CRASH("Multi-connection holocall") + + for(var/I in dialed_holopads) + if(I == H) + continue + Disconnect(I) + + for(var/I in H.holo_calls) + var/datum/holocall/HC = I + if(HC != src) + HC.Disconnect(H) + + connected_holopad = H + + if(!Check()) + return + + hologram = H.activate_holo(user) + hologram.HC = src + + //eyeobj code is horrid, this is the best copypasta I could make + eye = new + eye.origin = H + eye.eye_initialized = TRUE + eye.eye_user = user + eye.name = "Camera Eye ([user.name])" + user.remote_control = eye + user.reset_perspective(eye) + eye.setLoc(H.loc) + +//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise +/datum/holocall/proc/Check() + for(var/I in dialed_holopads) + var/obj/machinery/holopad/H = I + if(!H.is_operational()) + ConnectionFailure(H) + + if(QDELETED(src)) + return FALSE + + . = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc + + if(.) + if(connected_holopad) + . = !QDELETED(connected_holopad) && connected_holopad.is_operational() + else + . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) + if(!.) + calling_holopad.say("No answer recieved.") + calling_holopad.temp = "" + + if(!.) + testing("Holocall Check fail") + qdel(src) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index aee8b80c31..b0361e9296 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -63,6 +63,8 @@ var/mob/living/enslaved_to //If this mind's master is another mob (i.e. adamantine golems) + var/datum/language_holder + /datum/mind/New(var/key) src.key = key soulOwner = src @@ -75,11 +77,21 @@ antag_datums = null return ..() +/datum/mind/proc/get_language_holder() + if(!language_holder) + var/datum/language_holder/L = current.get_language_holder(shadow=FALSE) + language_holder = L.copy(src) + + return language_holder + /datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0) if(current) // remove ourself from our old body's mind variable current.mind = null SStgui.on_transfer(current, new_character) + if(!language_holder) + language_holder = new_character.language_holder.copy(src) + if(key) if(new_character.key != key) //if we're transfering into a body with a key associated which is not ours new_character.ghostize(1) //we'll need to ghostize so that key isn't mobless. diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e4adbb91ef..4a0f05602b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -43,7 +43,7 @@ if(SSatoms.InitAtom(src, args)) //we were deleted return - + var/list/created = SSatoms.created_atoms if(created) created += src diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index dc418cbf89..02d0d38cca 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -13,9 +13,9 @@ var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported var/throw_range = 7 var/mob/pulledby = null - var/list/languages - var/list/initial_languages = list(/datum/language/common) - var/only_speaks_language = null + var/initial_language_holder = /datum/language_holder + var/datum/language_holder/language_holder + var/datum/language_menu/language_menu = null var/verb_say = "says" var/verb_ask = "asks" var/verb_exclaim = "exclaims" @@ -44,10 +44,6 @@ return FALSE return ..() -/atom/movable/Initialize(mapload) - . = ..() - for(var/L in initial_languages) - grant_language(L) /atom/movable/Move(atom/newloc, direct = 0) if(!loc || !newloc) return 0 @@ -177,6 +173,7 @@ STOP_PROCESSING(SSinbounds, src) QDEL_NULL(proximity_monitor) + QDEL_NULL(language_holder) . = ..() if(loc) @@ -576,44 +573,70 @@ /* Language procs */ +/atom/movable/proc/get_language_holder(shadow=TRUE) + if(language_holder) + return language_holder + else + language_holder = new initial_language_holder(src) + return language_holder + + /atom/movable/proc/grant_language(datum/language/dt) - LAZYINITLIST(languages) - languages[dt] = TRUE + var/datum/language_holder/H = get_language_holder() + H.grant_language(dt) /atom/movable/proc/grant_all_languages(omnitongue=FALSE) - for(var/la in subtypesof(/datum/language)) - grant_language(la) - - if(omnitongue) - SET_SECONDARY_FLAG(src, OMNITONGUE) + var/datum/language_holder/H = get_language_holder() + H.grant_all_languages(omnitongue) /atom/movable/proc/get_random_understood_language() - var/list/possible = list() - for(var/dt in languages) - possible += dt - . = safepick(possible) + var/datum/language_holder/H = get_language_holder() + . = H.get_random_understood_language() /atom/movable/proc/remove_language(datum/language/dt) - LAZYREMOVE(languages, dt) + var/datum/language_holder/H = get_language_holder() + H.remove_language(dt) /atom/movable/proc/remove_all_languages() - LAZYCLEARLIST(languages) + var/datum/language_holder/H = get_language_holder() + H.remove_all_languages() /atom/movable/proc/has_language(datum/language/dt) - . = is_type_in_typecache(dt, languages) + var/datum/language_holder/H = get_language_holder() + . = H.has_language(dt) + +// Whether an AM can speak in a language or not, independent of whether +// it KNOWS the language +/atom/movable/proc/could_speak_in_language(datum/language/dt) + . = TRUE /atom/movable/proc/can_speak_in_language(datum/language/dt) - . = has_language(dt) - if(only_speaks_language && !HAS_SECONDARY_FLAG(src, OMNITONGUE)) - . = . && ispath(only_speaks_language, dt) + var/datum/language_holder/H = get_language_holder() + + if(!H.has_language(dt)) + return FALSE + else if(H.omnitongue || could_speak_in_language(dt)) + return TRUE + else + return FALSE /atom/movable/proc/get_default_language() // if no language is specified, and we want to say() something, which // language do we use? + var/datum/language_holder/H = get_language_holder() + + if(H.selected_default_language) + if(H.has_language(H.selected_default_language)) + return H.selected_default_language + else + H.selected_default_language = null + + + var/datum/language/chosen_langtype var/highest_priority - for(var/lt in languages) + for(var/lt in H.languages) var/datum/language/langtype = lt if(!can_speak_in_language(langtype)) continue @@ -622,8 +645,10 @@ if(!highest_priority || (pri > highest_priority)) chosen_langtype = langtype highest_priority = pri - + H.selected_default_language = . . = chosen_langtype + +/* End language procs */ /atom/movable/proc/ConveyorMove(movedir) set waitfor = FALSE if(!anchored && has_gravity()) diff --git a/code/game/atoms_movable.dm.rej b/code/game/atoms_movable.dm.rej new file mode 100644 index 0000000000..9ef1e78e27 --- /dev/null +++ b/code/game/atoms_movable.dm.rej @@ -0,0 +1,10 @@ +diff a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm (rejected hunks) +@@ -571,7 +571,7 @@ + + + /* Language procs */ +-/atom/movable/proc/get_language_holder() ++/atom/movable/proc/get_language_holder(shadow=TRUE) + if(language_holder) + return language_holder + else diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm index a5e7dee4cb..d3a33c0c40 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs.dm @@ -14,8 +14,7 @@ verb_ask = "requests" verb_exclaim = "proclaims" verb_yell = "harangues" - initial_languages = list(/datum/language/common, /datum/language/ratvar) - only_speaks_language = /datum/language/ratvar + initial_language_holder = /datum/language_holder/clockmob bubble_icon = "clock" light_color = "#E42742" death_sound = 'sound/magic/clockwork/anima_fragment_death.ogg' diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index c6248b03cc..3b315bb668 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -62,7 +62,7 @@ icon = 'icons/mob/swarmer.dmi' desc = "A robot of unknown design, they seek only to consume materials and replicate themselves indefinitely." speak_emote = list("tones") - initial_languages = list(/datum/language/swarmer) + initial_language_holder = /datum/language_holder/swarmer bubble_icon = "swarmer" health = 40 maxHealth = 40 diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 03ec33ca25..12fcd5ec91 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -61,7 +61,6 @@ GLOBAL_LIST_EMPTY(holopads) /obj/machinery/holopad/Destroy() if(outgoing_call) LAZYADD(holo_calls, outgoing_call) - outgoing_call = null for(var/I in holo_calls) var/datum/holocall/HC = I @@ -295,7 +294,9 @@ GLOBAL_LIST_EMPTY(holopads) Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) Hologram.Impersonation = user - Hologram.languages = user.languages + + Hologram.language_holder = user.get_language_holder() + Hologram.mouse_opacity = 0//So you can't click on it. Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. Hologram.anchored = 1//So space wind cannot drag it. diff --git a/code/game/machinery/hologram.dm.rej b/code/game/machinery/hologram.dm.rej new file mode 100644 index 0000000000..b8d8bbbddc --- /dev/null +++ b/code/game/machinery/hologram.dm.rej @@ -0,0 +1,17 @@ +diff a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm (rejected hunks) +@@ -294,7 +294,7 @@ GLOBAL_LIST_EMPTY(holopads) + Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY) + Hologram.Impersonation = user + +- Hologram.languages = user.languages ++ Hologram.language_holder = user.get_language_holder() + Hologram.mouse_opacity = 0//So you can't click on it. + Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them. + Hologram.anchored = 1//So space wind cannot drag it. +@@ -392,4 +392,4 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ + req_components = list(/obj/item/weapon/stock_parts/capacitor = 1) + + #undef HOLOPAD_PASSIVE_POWER_USAGE +-#undef HOLOGRAM_POWER_USAGE +\ No newline at end of file ++#undef HOLOGRAM_POWER_USAGE diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index e29d372a6c..9766dbc26d 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -23,7 +23,7 @@ var/persistence_replacement //have something WAY too amazing to live to the next round? Set a new path here. Overuse of this var will make me upset. var/unique_rename = FALSE // can you customize the description/name of the thing? - + var/dangerous_possession = FALSE //Admin possession yes/no /obj/vv_edit_var(vname, vval) diff --git a/code/game/say.dm b/code/game/say.dm index deab83ad10..358fc9698d 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -61,7 +61,7 @@ GLOBAL_LIST_INIT(freqtospan, list( var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans)]" var/languageicon = "" - var/datum/language/D = get_language_instance(message_language) + var/datum/language/D = GLOB.language_datum_instances[message_language] if(D.display_icon(src)) languageicon = "[D.get_icon()] " @@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(freqtospan, list( return speaker.say_quote(raw_message, spans, message_mode) else if(language) var/atom/movable/AM = speaker.GetSource() - var/datum/language/D = get_language_instance(language) + var/datum/language/D = GLOB.language_datum_instances[language] raw_message = D.scramble(raw_message) if(AM) return AM.say_quote(raw_message, spans, message_mode) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a2f124df6d..71a695f57a 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1799,12 +1799,12 @@ if(!check_rights(R_ADMIN)) return - var/mob/living/L = locate(href_list["languagemenu"]) in GLOB.mob_list - if(!isliving(L)) - to_chat(usr, "This can only be used on instances of type /mob/living.") + var/mob/M = locate(href_list["languagemenu"]) in GLOB.mob_list + if(!ismob(M)) + to_chat(usr, "This can only be used on instances of type /mob.") return - - L.open_language_menu(usr) + var/datum/language_holder/H = M.get_language_holder() + H.open_language_menu(usr) else if(href_list["traitor"]) if(!check_rights(R_ADMIN)) diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index 4222982182..efeabfe73d 100644 --- a/code/modules/language/language.dm +++ b/code/modules/language/language.dm @@ -12,7 +12,8 @@ var/exclaim_verb = "exclaims" // Used when sentence ends in a ! var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead. var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags - var/key = "x" // Character used to speak in language + var/key // Character used to speak in language + // If key is null, then the language isn't real or learnable. var/flags // Various language flags. var/list/syllables // Used when scrambling text for a non-speaker. var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable. @@ -108,13 +109,3 @@ return speech_verb #undef SCRAMBLE_CACHE_LEN - -/proc/get_language_instance(langtype) - if(!ispath(langtype, /datum/language)) - return - - if(!GLOB.language_datums[langtype]) - var/datum/language/langdatum = new langtype - GLOB.language_datums[langtype] = langdatum - - . = GLOB.language_datums[langtype] diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm new file mode 100644 index 0000000000..cd0ce23b23 --- /dev/null +++ b/code/modules/language/language_holder.dm @@ -0,0 +1,110 @@ +/datum/language_holder + var/list/languages = list(/datum/language/common) + var/list/shadow_languages = list() + var/only_speaks_language = null + var/selected_default_language = null + var/datum/language_menu/language_menu + + var/omnitongue = FALSE + var/owner + +/datum/language_holder/New(owner) + src.owner = owner + + languages = typecacheof(languages) + shadow_languages = typecacheof(shadow_languages) + +/datum/language_holder/Destroy() + owner = null + QDEL_NULL(language_menu) + +/datum/language_holder/proc/copy(newowner) + var/datum/language_holder/copy = new(newowner) + copy.languages = src.languages.Copy() + // shadow languages are not copied. + copy.only_speaks_language = src.only_speaks_language + copy.selected_default_language = src.selected_default_language + // language menu is not copied, that's tied to the holder. + copy.omnitongue = src.omnitongue + return copy + +/datum/language_holder/proc/grant_language(datum/language/dt) + languages[dt] = TRUE + +/datum/language_holder/proc/grant_all_languages(omnitongue=FALSE) + for(var/la in GLOB.all_languages) + grant_language(la) + + if(omnitongue) + src.omnitongue = TRUE + +/datum/language_holder/proc/get_random_understood_language() + var/list/possible = list() + for(var/dt in languages) + possible += dt + . = safepick(possible) + +/datum/language_holder/proc/remove_language(datum/language/dt) + languages -= dt + +/datum/language_holder/proc/remove_all_languages() + languages.Cut() + +/datum/language_holder/proc/has_language(datum/language/dt) + if(is_type_in_typecache(dt, languages)) + return LANGUAGE_KNOWN + else + var/atom/movable/AM = get_atom() + var/datum/language_holder/L = AM.get_language_holder(shadow=FALSE) + if(L != src) + if(is_type_in_typecache(dt, L.shadow_languages)) + return LANGUAGE_SHADOWED + return FALSE + +/datum/language_holder/proc/open_language_menu(mob/user) + if(!language_menu) + language_menu = new(src) + language_menu.ui_interact(user) + +/datum/language_holder/proc/get_atom() + if(istype(owner, /atom/movable)) + . = owner + else if(istype(owner, /datum/mind)) + var/datum/mind/M = owner + if(M.current) + . = M.current + +/datum/language_holder/alien + languages = list(/datum/language/xenocommon) + +/datum/language_holder/monkey + languages = list(/datum/language/monkey) + +/datum/language_holder/swarmer + languages = list(/datum/language/swarmer) + +/datum/language_holder/clockmob + languages = list(/datum/language/common, /datum/language/ratvar) + only_speaks_language = /datum/language/ratvar + +/datum/language_holder/drone + languages = list(/datum/language/common, /datum/language/drone, /datum/language/machine) + only_speaks_language = /datum/language/drone + +/datum/language_holder/drone/syndicate + only_speaks_language = null + +/datum/language_holder/slime + languages = list(/datum/language/common, /datum/language/slime) + +/datum/language_holder/lightbringer + // TODO change to a lightbringer specific sign language + languages = list(/datum/language/slime) + +/datum/language_holder/synthetic + languages = list(/datum/language/common) + shadow_languages = list(/datum/language/machine, /datum/language/draconic) + +/datum/language_holder/universal/New() + ..() + grant_all_languages(omnitongue=TRUE) diff --git a/code/modules/language/language_menu.dm b/code/modules/language/language_menu.dm index 43af26a972..87fc1e0d52 100644 --- a/code/modules/language/language_menu.dm +++ b/code/modules/language/language_menu.dm @@ -1,11 +1,11 @@ /datum/language_menu - var/mob/living/owner + var/datum/language_holder/language_holder -/datum/language_menu/New(new_owner) - owner = new_owner +/datum/language_menu/New(language_holder) + src.language_holder = language_holder /datum/language_menu/Destroy() - owner = null + language_holder = null . = ..() /datum/language_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.language_menu_state) @@ -17,28 +17,38 @@ /datum/language_menu/ui_data(mob/user) var/list/data = list() - var/datum/language/mob_default_language = owner.get_default_language() + var/atom/movable/AM = language_holder.get_atom() + if(isliving(AM)) + data["is_living"] = TRUE + else + data["is_living"] = FALSE data["languages"] = list() - for(var/ld in owner.languages) + for(var/ld in GLOB.all_languages) + var/result = language_holder.has_language(ld) + if(!result) + continue + var/shadow = result == LANGUAGE_SHADOWED var/datum/language/LD = ld var/list/L = list() L["name"] = initial(LD.name) L["desc"] = initial(LD.desc) L["key"] = initial(LD.key) - L["is_default"] = (LD == mob_default_language) - L["can_speak"] = owner.can_speak_in_language(LD) + L["is_default"] = (LD == language_holder.selected_default_language) + L["shadow"] = shadow + if(AM) + L["can_speak"] = AM.can_speak_in_language(LD) data["languages"] += list(L) - if(check_rights_for(user.client, R_ADMIN)) + if(check_rights_for(user.client, R_ADMIN) || isobserver(AM)) data["admin_mode"] = TRUE - data["omnitongue"] = HAS_SECONDARY_FLAG(owner, OMNITONGUE) + data["omnitongue"] = language_holder.omnitongue data["unknown_languages"] = list() - for(var/ld in subtypesof(/datum/language)) - if(owner.has_language(ld)) + for(var/ld in GLOB.all_languages) + if(language_holder.has_language(ld)) continue var/datum/language/LD = ld var/list/L = list() @@ -54,10 +64,11 @@ if(..()) return var/mob/user = usr + var/atom/movable/AM = language_holder.get_atom() var/language_name = params["language_name"] var/datum/language/language_datum - for(var/ld in subtypesof(/datum/language)) + for(var/ld in GLOB.all_languages) var/datum/language/LD = ld if(language_name == initial(LD.name)) language_datum = LD @@ -66,23 +77,26 @@ switch(action) if("select_default") if(language_datum) - owner.selected_default_language = language_datum + language_holder.selected_default_language = language_datum . = TRUE if("grant_language") - if(is_admin && language_datum) - owner.grant_language(language_datum) - message_admins("[key_name_admin(user)] granted the [language_name] language to [key_name_admin(owner)].") - log_admin("[key_name(user)] granted the language [language_name] to [key_name(owner)].") + if((is_admin || isobserver(AM)) && language_datum) + language_holder.grant_language(language_datum) + if(is_admin) + message_admins("[key_name_admin(user)] granted the [language_name] language to [key_name_admin(AM)].") + log_admin("[key_name(user)] granted the language [language_name] to [key_name(AM)].") . = TRUE if("remove_language") - if(is_admin && language_datum) - owner.remove_language(language_datum) - message_admins("[key_name_admin(user)] removed the [language_name] language to [key_name_admin(owner)].") - log_admin("[key_name(user)] removed the language [language_name] to [key_name(owner)].") + if((is_admin || isobserver(AM)) && language_datum) + language_holder.remove_language(language_datum) + if(is_admin) + message_admins("[key_name_admin(user)] removed the [language_name] language to [key_name_admin(AM)].") + log_admin("[key_name(user)] removed the language [language_name] to [key_name(AM)].") . = TRUE if("toggle_omnitongue") - if(is_admin) - TOGGLE_SECONDARY_FLAG(owner, OMNITONGUE) - message_admins("[key_name_admin(user)] [HAS_SECONDARY_FLAG(owner, OMNITONGUE) ? "enabled" : "disabled"] the ability to speak all languages (that they know) of [key_name_admin(owner)].") - log_admin("[key_name(user)] [HAS_SECONDARY_FLAG(owner, OMNITONGUE) ? "enabled" : "disabled"] the ability to speak all languages (that_they know) of [key_name(owner)].") + if(is_admin || isobserver(AM)) + language_holder.omnitongue = !language_holder.omnitongue + if(is_admin) + message_admins("[key_name_admin(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that they know) of [key_name_admin(AM)].") + log_admin("[key_name(user)] [language_holder.omnitongue ? "enabled" : "disabled"] the ability to speak all languages (that_they know) of [key_name(AM)].") . = TRUE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 00df173551..316a7a3b83 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -117,10 +117,13 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) animate(src, pixel_y = 2, time = 10, loop = -1) - grant_all_languages() + GLOB.dead_mob_list += src + ..() + grant_all_languages() + /mob/dead/observer/narsie_act() var/old_color = color color = "#960000" @@ -270,25 +273,24 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/Move(NewLoc, direct) if(updatedir) - setDir(direct )//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own + setDir(direct)//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own + var/oldloc = loc + if(NewLoc) loc = NewLoc - for(var/obj/effect/step_trigger/S in NewLoc) - S.Crossed(src) update_parallax_contents() - return - loc = get_turf(src) //Get out of closets and such as a ghost - if((direct & NORTH) && y < world.maxy) - y++ - else if((direct & SOUTH) && y > 1) - y-- - if((direct & EAST) && x < world.maxx) - x++ - else if((direct & WEST) && x > 1) - x-- + else + loc = get_turf(src) //Get out of closets and such as a ghost + if((direct & NORTH) && y < world.maxy) + y++ + else if((direct & SOUTH) && y > 1) + y-- + if((direct & EAST) && x < world.maxx) + x++ + else if((direct & WEST) && x > 1) + x-- - for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb - S.Crossed(src) + Moved(oldloc, direct) /mob/dead/observer/is_active() return 0 @@ -297,9 +299,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ..() if(statpanel("Status")) if(SSticker.HasRoundStarted()) - for(var/datum/gang/G in SSticker.mode.gangs) - if(G.is_dominating) - stat(null, "[G.name] Gang Takeover: [max(G.domination_time_remaining(), 0)]") if(istype(SSticker.mode, /datum/game_mode/blob)) var/datum/game_mode/blob/B = SSticker.mode if(B.message_sent) diff --git a/code/modules/mob/dead/observer/observer.dm.rej b/code/modules/mob/dead/observer/observer.dm.rej new file mode 100644 index 0000000000..3546c64da4 --- /dev/null +++ b/code/modules/mob/dead/observer/observer.dm.rej @@ -0,0 +1,15 @@ +diff a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm (rejected hunks) +@@ -117,10 +117,12 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) + + animate(src, pixel_y = 2, time = 10, loop = -1) + +- grant_all_languages() + GLOB.dead_mob_list += src ++ + ..() + ++ grant_all_languages() ++ + /mob/dead/observer/narsie_act() + var/old_color = color + color = "#960000" diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm index 5751c65b36..0cfbf5d170 100644 --- a/code/modules/mob/living/brain/say.dm +++ b/code/modules/mob/living/brain/say.dm @@ -27,10 +27,9 @@ message = capitalize(message) return message -/mob/living/brain/can_speak_in_language(datum/language/dt) - if(HAS_SECONDARY_FLAG(src, OMNITONGUE)) - . = has_language(dt) - else if(istype(container, /obj/item/device/mmi/posibrain/soul_vessel)) - . = has_language(dt) && ispath(dt, /datum/language/ratvar) +/mob/living/brain/could_speak_in_language(datum/language/dt) + if(istype(container, /obj/item/device/mmi/posibrain/soul_vessel)) + // soul vessels can only speak ratvarian. + . = ispath(dt, /datum/language/ratvar) else . = ..() diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 5e1a91113f..322726aa62 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -14,7 +14,7 @@ sight = SEE_MOBS see_in_dark = 4 verb_say = "hisses" - initial_languages = list(/datum/language/xenocommon) + initial_language_holder = /datum/language_holder/alien bubble_icon = "alien" type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno var/nightvision = 1 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6cb45fb9d7..be7e851a8e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1,952 +1,947 @@ -/mob/living/carbon/human - name = "Unknown" - real_name = "Unknown" - voice_name = "Unknown" - icon = 'icons/mob/human.dmi' - icon_state = "caucasian_m" - - // ME TARZAN, YOU JANEBOT - initial_languages = list(/datum/language/common) - - - -/mob/living/carbon/human/dummy - real_name = "Test Dummy" - status_flags = GODMODE|CANPUSH - -/mob/living/carbon/human/dummy/New(loc) - ..() - if(!initialized) - args[1] = FALSE - Initialize(arglist(args)) - -/mob/living/carbon/human/dummy/Life() - return - -/mob/living/carbon/human/Initialize() - verbs += /mob/living/proc/mob_sleep - verbs += /mob/living/proc/lay_down - - //initialize limbs first - create_bodyparts() - - //initialize dna. for spawned humans; overwritten by other code - create_dna(src) - randomize_human(src) - dna.initialize_dna() - - if(dna.species) - set_species(dna.species.type) - - //initialise organs - create_internal_organs() - - martial_art = default_martial_art - - handcrafting = new() - - ..() - -/mob/living/carbon/human/create_internal_organs() - if(!(NOHUNGER in dna.species.species_traits)) - internal_organs += new /obj/item/organ/appendix - if(!(NOBREATH in dna.species.species_traits)) - if(dna.species.mutantlungs) - internal_organs += new dna.species.mutantlungs() - else - internal_organs += new /obj/item/organ/lungs() - if(!(NOBLOOD in dna.species.species_traits)) - internal_organs += new /obj/item/organ/heart - - internal_organs += new dna.species.mutanteyes - internal_organs += new dna.species.mutantears - internal_organs += new /obj/item/organ/brain - internal_organs += new dna.species.mutanttongue - give_genitals() - ..() - -/mob/living/carbon/human/OpenCraftingMenu() - handcrafting.ui_interact(src) - -/mob/living/carbon/human/prepare_data_huds() - //Update med hud images... - ..() - //...sec hud images... - sec_hud_set_ID() - sec_hud_set_implants() - sec_hud_set_security_status() - //...and display them. - add_to_all_human_data_huds() - -/mob/living/carbon/human/Stat() - ..() - - if(statpanel("Status")) - stat(null, "Intent: [a_intent]") - stat(null, "Move Mode: [m_intent]") - if (internal) - if (!internal.air_contents) - qdel(internal) - else - stat("Internal Atmosphere Info", internal.name) - stat("Tank Pressure", internal.air_contents.return_pressure()) - stat("Distribution Pressure", internal.distribute_pressure) - - var/mob/living/simple_animal/borer/B = has_brain_worms() - if(B && B.controlling) - stat("Chemicals", B.chemicals) - - if(mind) - if(mind.changeling) - stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]") - stat("Absorbed DNA", mind.changeling.absorbedcount) - - - //NINJACODE - if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja. - var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit - if(statpanel("SpiderOS")) - stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]") - stat("Current Time:", "[worldtime2text()]") - if(SN.s_initialized) - //Suit gear - stat("Energy Charge:", "[round(SN.cell.charge/100)]%") - stat("Smoke Bombs:", "\Roman [SN.s_bombs]") - //Ninja status - stat("Fingerprints:", "[md5(dna.uni_identity)]") - stat("Unique Identity:", "[dna.unique_enzymes]") - stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") - stat("Nutrition Status:", "[nutrition]") - stat("Oxygen Loss:", "[getOxyLoss()]") - stat("Toxin Levels:", "[getToxLoss()]") - stat("Burn Severity:", "[getFireLoss()]") - stat("Brute Trauma:", "[getBruteLoss()]") - stat("Radiation Levels:","[radiation] rad") - stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)") - - //Virsuses - if(viruses.len) - stat("Viruses:", null) - for(var/datum/disease/D in viruses) - stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]") - - -/mob/living/carbon/human/show_inv(mob/user) - user.set_machine(src) - var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) - var/list/obscured = check_obscured_slots() - var/list/dat = list() - - dat += "" - for(var/i in 1 to held_items.len) - var/obj/item/I = get_item_for_held_index(i) - dat += "" - dat += "" - - dat += "" - - dat += "" - - if(slot_wear_mask in obscured) - dat += "" - else - dat += "" - - if(slot_neck in obscured) - dat += "" - else - dat += "" - - if(slot_glasses in obscured) - dat += "" - else - dat += "" - - if(slot_ears in obscured) - dat += "" - else - dat += "" - - dat += "" - - dat += "" - if(wear_suit) - dat += "" - else - dat += "" - - if(slot_shoes in obscured) - dat += "" - else - dat += "" - - if(slot_gloves in obscured) - dat += "" - else - dat += "" - - if(slot_w_uniform in obscured) - dat += "" - else - dat += "" - - if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (slot_w_uniform in obscured)) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "" - - if(handcuffed) - dat += "" - if(legcuffed) - dat += "" - - dat += {"
[get_held_index_name(i)]:[(I && !(I.flags & ABSTRACT)) ? I : "Empty"]
 
Back:[(back && !(back.flags&ABSTRACT)) ? back : "Empty"]" - if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) - dat += " [internal ? "Disable Internals" : "Set Internals"]" - - dat += "
 
Head:[(head && !(head.flags&ABSTRACT)) ? head : "Empty"]
Mask:Obscured
Mask:[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Empty"]
Neck:Obscured
Neck:[(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "Empty"]
Eyes:Obscured
Eyes:[(glasses && !(glasses.flags&ABSTRACT)) ? glasses : "Empty"]
Ears:Obscured
Ears:[(ears && !(ears.flags&ABSTRACT)) ? ears : "Empty"]
 
Exosuit:[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "Empty"]
 ↳Suit Storage:[(s_store && !(s_store.flags&ABSTRACT)) ? s_store : "Empty"]" - if(has_breathable_mask && istype(s_store, /obj/item/weapon/tank)) - dat += " [internal ? "Disable Internals" : "Set Internals"]" - dat += "
 ↳Suit Storage:
Shoes:Obscured
Shoes:[(shoes && !(shoes.flags&ABSTRACT)) ? shoes : "Empty"]
Gloves:Obscured
Gloves:[(gloves && !(gloves.flags&ABSTRACT)) ? gloves : "Empty"]
Uniform:Obscured
Uniform:[(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Empty"]
 ↳Pockets:
 ↳ID:
 ↳Belt:
 ↳Belt:[(belt && !(belt.flags&ABSTRACT)) ? belt : "Empty"]" - if(has_breathable_mask && istype(belt, /obj/item/weapon/tank)) - dat += " [internal ? "Disable Internals" : "Set Internals"]" - dat += "
 ↳Pockets:[(l_store && !(l_store.flags&ABSTRACT)) ? "Left (Full)" : "Left (Empty)"]" - dat += " [(r_store && !(r_store.flags&ABSTRACT)) ? "Right (Full)" : "Right (Empty)"]
 ↳ID:[(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Empty"]
Handcuffed: Remove
Legcuffed
- Close - "} - - var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 510) - popup.set_content(dat.Join()) - popup.open() - -// called when something steps onto a human -// this could be made more general, but for now just handle mulebot -/mob/living/carbon/human/Crossed(atom/movable/AM) - var/mob/living/simple_animal/bot/mulebot/MB = AM - if(istype(MB)) - MB.RunOver(src) - - spreadFire(AM) - - -/mob/living/carbon/human/Topic(href, href_list) - if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) - - if(href_list["embedded_object"]) - var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts - if(!L) - return - var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects - if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore - return - var/time_taken = I.embedded_unsafe_removal_time*I.w_class - usr.visible_message("[usr] attempts to remove [I] from their [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)") - if(do_after(usr, time_taken, needhand = 1, target = src)) - if(!I || !L || I.loc != src || !(I in L.embedded_objects)) - return - L.embedded_objects -= I - L.receive_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus. - I.forceMove(get_turf(src)) - usr.put_in_hands(I) - usr.emote("scream") - usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","You successfully remove [I] from your [L.name].") - if(!has_embedded_objects()) - clear_alert("embeddedobject") - return - - if(href_list["item"]) - var/slot = text2num(href_list["item"]) - if(slot in check_obscured_slots()) - to_chat(usr, "You can't reach that! Something is covering it.") - return - - if(href_list["pockets"]) - var/pocket_side = href_list["pockets"] - var/pocket_id = (pocket_side == "right" ? slot_r_store : slot_l_store) - var/obj/item/pocket_item = (pocket_id == slot_r_store ? r_store : l_store) - var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty - - var/delay_denominator = 1 - if(pocket_item && !(pocket_item.flags&ABSTRACT)) - if(pocket_item.flags & NODROP) - to_chat(usr, "You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!") - to_chat(usr, "You try to empty [src]'s [pocket_side] pocket.") - else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.flags&ABSTRACT)) - to_chat(usr, "You try to place [place_item] into [src]'s [pocket_side] pocket.") - delay_denominator = 4 - else - return - - if(do_mob(usr, src, POCKET_STRIP_DELAY/delay_denominator)) //placing an item into the pocket is 4 times faster - if(pocket_item) - if(pocket_item == (pocket_id == slot_r_store ? r_store : l_store)) //item still in the pocket we search - dropItemToGround(pocket_item) - else - if(place_item) - if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE)) - usr.temporarilyRemoveItemFromInventory(place_item, TRUE) - equip_to_slot(place_item, pocket_id, TRUE) - //do nothing otherwise - - // Update strip window - if(usr.machine == src && in_range(src, usr)) - show_inv(usr) - else - // Display a warning if the user mocks up - to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") - - ..() - - -///////HUDs/////// - if(href_list["hud"]) - if(ishuman(usr)) - var/mob/living/carbon/human/H = usr - var/perpname = get_face_name(get_id_name("")) - if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud)) - var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general) - if(href_list["photo_front"] || href_list["photo_side"]) - if(R) - if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) - return - var/obj/item/weapon/photo/P = null - if(href_list["photo_front"]) - P = R.fields["photo_front"] - else if(href_list["photo_side"]) - P = R.fields["photo_side"] - if(P) - P.show(H) - - if(href_list["hud"] == "m") - if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) - if(href_list["p_stat"]) - var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel") - if(R) - if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) - return - if(health_status && health_status != "Cancel") - R.fields["p_stat"] = health_status - return - if(href_list["m_stat"]) - var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel") - if(R) - if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) - return - if(health_status && health_status != "Cancel") - R.fields["m_stat"] = health_status - return - if(href_list["evaluation"]) - if(!getBruteLoss() && !getFireLoss() && !getOxyLoss() && getToxLoss() < 20) - to_chat(usr, "No external injuries detected.
") - return - var/span = "notice" - var/status = "" - if(getBruteLoss()) - to_chat(usr, "Physical trauma analysis:") - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - var/brutedamage = BP.brute_dam - if(brutedamage > 0) - status = "received minor physical injuries." - span = "notice" - if(brutedamage > 20) - status = "been seriously damaged." - span = "danger" - if(brutedamage > 40) - status = "sustained major trauma!" - span = "userdanger" - if(brutedamage) - to_chat(usr, "[BP] appears to have [status]") - if(getFireLoss()) - to_chat(usr, "Analysis of skin burns:") - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - var/burndamage = BP.burn_dam - if(burndamage > 0) - status = "signs of minor burns." - span = "notice" - if(burndamage > 20) - status = "serious burns." - span = "danger" - if(burndamage > 40) - status = "major burns!" - span = "userdanger" - if(burndamage) - to_chat(usr, "[BP] appears to have [status]") - if(getOxyLoss()) - to_chat(usr, "Patient has signs of suffocation, emergency treatment may be required!") - if(getToxLoss() > 20) - to_chat(usr, "Gathered data is inconsistent with the analysis, possible cause: poisoning.") - - if(href_list["hud"] == "s") - if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at. - return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten - // Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access - var/allowed_access = null - var/obj/item/clothing/glasses/G = H.glasses - if (!G.emagged) - if(H.wear_id) - var/list/access = H.wear_id.GetAccess() - if(GLOB.access_sec_doors in access) - allowed_access = H.get_authentification_name() - else - allowed_access = "@%&ERROR_%$*" - - - if(!allowed_access) - to_chat(H, "ERROR: Invalid Access") - return - - if(perpname) - R = find_record("name", perpname, GLOB.data_core.security) - if(R) - if(href_list["status"]) - var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Parolled", "Discharged", "Cancel") - if(setcriminal != "Cancel") - if(R) - if(H.canUseHUD()) - if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - investigate_log("[src.key] has been set from [R.fields["criminal"]] to [setcriminal] by [usr.name] ([usr.key]).", "records") - R.fields["criminal"] = setcriminal - sec_hud_set_security_status() - return - - if(href_list["view"]) - if(R) - if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - return - to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") - to_chat(usr, "Minor Crimes:") - for(var/datum/data/crime/c in R.fields["mi_crim"]) - to_chat(usr, "Crime: [c.crimeName]") - to_chat(usr, "Details: [c.crimeDetails]") - to_chat(usr, "Added by [c.author] at [c.time]") - to_chat(usr, "----------") - to_chat(usr, "Major Crimes:") - for(var/datum/data/crime/c in R.fields["ma_crim"]) - to_chat(usr, "Crime: [c.crimeName]") - to_chat(usr, "Details: [c.crimeDetails]") - to_chat(usr, "Added by [c.author] at [c.time]") - to_chat(usr, "----------") - to_chat(usr, "Notes: [R.fields["notes"]]") - return - - if(href_list["add_crime"]) - switch(alert("What crime would you like to add?","Security HUD","Minor Crime","Major Crime","Cancel")) - if("Minor Crime") - if(R) - var/t1 = stripped_input("Please input minor crime names:", "Security HUD", "", null) - var/t2 = stripped_multiline_input("Please input minor crime details:", "Security HUD", "", null) - if(R) - if (!t1 || !t2 || !allowed_access) - return - else if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text()) - GLOB.data_core.addMinorCrime(R.fields["id"], crime) - to_chat(usr, "Successfully added a minor crime.") - return - if("Major Crime") - if(R) - var/t1 = stripped_input("Please input major crime names:", "Security HUD", "", null) - var/t2 = stripped_multiline_input("Please input major crime details:", "Security HUD", "", null) - if(R) - if (!t1 || !t2 || !allowed_access) - return - else if (!H.canUseHUD()) - return - else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - return - var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text()) - GLOB.data_core.addMajorCrime(R.fields["id"], crime) - to_chat(usr, "Successfully added a major crime.") - return - - if(href_list["view_comment"]) - if(R) - if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - return - to_chat(usr, "Comments/Log:") - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - to_chat(usr, R.fields[text("com_[]", counter)]) - to_chat(usr, "----------") - counter++ - return - - if(href_list["add_comment"]) - if(R) - var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null) - if(R) - if (!t1 || !allowed_access) - return - else if(!H.canUseHUD()) - return - else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) - return - var/counter = 1 - while(R.fields[text("com_[]", counter)]) - counter++ - R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []
[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1) - to_chat(usr, "Successfully added comment.") - return - to_chat(usr, "Unable to locate a data core entry for this person.") - -/mob/living/carbon/human/proc/canUseHUD() - return !(src.stat || src.weakened || src.stunned || src.restrained()) - -/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, var/penetrate_thick = 0) - . = 1 // Default to returning true. - if(user && !target_zone) - target_zone = user.zone_selected - if(dna && (PIERCEIMMUNE in dna.species.species_traits)) - . = 0 - // If targeting the head, see if the head item is thin enough. - // If targeting anything else, see if the wear suit is thin enough. - if(above_neck(target_zone)) - if(head && head.flags & THICKMATERIAL && !penetrate_thick) - . = 0 - else - if(wear_suit && wear_suit.flags & THICKMATERIAL && !penetrate_thick) - . = 0 - if(!. && error_msg && user) - // Might need re-wording. - to_chat(user, "There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].") - -/mob/living/carbon/human/proc/check_obscured_slots() - var/list/obscured = list() - - if(wear_suit) - if(wear_suit.flags_inv & HIDEGLOVES) - obscured |= slot_gloves - if(wear_suit.flags_inv & HIDEJUMPSUIT) - obscured |= slot_w_uniform - if(wear_suit.flags_inv & HIDESHOES) - obscured |= slot_shoes - - if(head) - if(head.flags_inv & HIDEMASK) - obscured |= slot_wear_mask - if(head.flags_inv & HIDEEYES) - obscured |= slot_glasses - if(head.flags_inv & HIDEEARS) - obscured |= slot_ears - - if(wear_mask) - if(wear_mask.flags_inv & HIDEEYES) - obscured |= slot_glasses - - if(obscured.len) - return obscured - else - return null - -/mob/living/carbon/human/assess_threat(mob/living/simple_animal/bot/secbot/judgebot, lasercolor) - if(judgebot.emagged == 2) - return 10 //Everyone is a criminal! - - var/threatcount = 0 - - //Lasertag bullshit - if(lasercolor) - if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve - if(istype(wear_suit, /obj/item/clothing/suit/redtag)) - threatcount += 4 - if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 4 - if(istype(belt, /obj/item/weapon/gun/energy/laser/redtag)) - threatcount += 2 - - if(lasercolor == "r") - if(istype(wear_suit, /obj/item/clothing/suit/bluetag)) - threatcount += 4 - if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 4 - if(istype(belt, /obj/item/weapon/gun/energy/laser/bluetag)) - threatcount += 2 - - return threatcount - - //Check for ID - var/obj/item/weapon/card/id/idcard = get_idcard() - if(judgebot.idcheck && !idcard && name=="Unknown") - threatcount += 4 - - //Check for weapons - if(judgebot.weaponscheck) - if(!idcard || !(GLOB.access_weapons in idcard.access)) - for(var/obj/item/I in held_items) - if(judgebot.check_for_weapons(I)) - threatcount += 4 - if(judgebot.check_for_weapons(belt)) - threatcount += 2 - - //Check for arrest warrant - if(judgebot.check_records) - var/perpname = get_face_name(get_id_name()) - var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) - if(R && R.fields["criminal"]) - switch(R.fields["criminal"]) - if("*Arrest*") - threatcount += 5 - if("Incarcerated") - threatcount += 2 - if("Parolled") - threatcount += 2 - - //Check for dresscode violations - if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/syndi) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi)) - threatcount += 5 - - //Check for nonhuman scum - if(dna && dna.species.id && dna.species.id != "human" || "lizard" || "mammal" || "avian" || "aquatic" || "insect") - threatcount += 1 - - //mindshield implants imply trustworthyness - if(isloyal()) - threatcount -= 1 - - //Agent cards lower threatlevel. - if(istype(idcard, /obj/item/weapon/card/id/syndicate)) - threatcount -= 2 - - return threatcount - - -//Used for new human mobs created by cloning/goleming/podding -/mob/living/carbon/human/proc/set_cloned_appearance() - if(gender == MALE) - facial_hair_style = "Full Beard" - else - facial_hair_style = "Shaved" - hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") - underwear = "Nude" - update_body() - update_genitals() - update_hair() - -/mob/living/carbon/human/singularity_pull(S, current_size) - if(current_size >= STAGE_THREE) - for(var/obj/item/hand in held_items) - if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand)) - step_towards(hand, src) - to_chat(src, "\The [S] pulls \the [hand] from your grip!") - rad_act(current_size * 3) - if(mob_negates_gravity()) - return - ..() - -/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C) - CHECK_DNA_AND_SPECIES(C) - - if(C.stat == DEAD || (C.status_flags & FAKEDEATH)) - to_chat(src, "[C.name] is dead!") - return - if(is_mouth_covered()) - to_chat(src, "Remove your mask first!") - return 0 - if(C.is_mouth_covered()) - to_chat(src, "Remove [p_their()] mask first!") - return 0 - - if(C.cpr_time < world.time + 30) - visible_message("[src] is trying to perform CPR on [C.name]!", \ - "You try to perform CPR on [C.name]... Hold still!") - if(!do_mob(src, C)) - to_chat(src, "You fail to perform CPR on [C]!") - return 0 - - var/they_breathe = (!(NOBREATH in C.dna.species.species_traits)) - var/they_lung = C.getorganslot("lungs") - - if(C.health > HEALTH_THRESHOLD_CRIT) - return - - src.visible_message("[src] performs CPR on [C.name]!", "You perform CPR on [C.name].") - C.cpr_time = world.time - add_logs(src, C, "CPRed") - - if(they_breathe && they_lung) - var/suff = min(C.getOxyLoss(), 7) - C.adjustOxyLoss(-suff) - C.updatehealth() - to_chat(C, "You feel a breath of fresh air enter your lungs... It feels good...") - else if(they_breathe && !they_lung) - to_chat(C, "You feel a breath of fresh air... but you don't feel any better...") - else - to_chat(C, "You feel a breath of fresh air... which is a sensation you don't recognise...") - -/mob/living/carbon/human/generateStaticOverlay() - var/image/staticOverlay = image(icon('icons/effects/effects.dmi', "static"), loc = src) - staticOverlay.override = 1 - staticOverlays["static"] = staticOverlay - - staticOverlay = image(icon('icons/effects/effects.dmi', "blank"), loc = src) - staticOverlay.override = 1 - staticOverlays["blank"] = staticOverlay - - staticOverlay = getLetterImage(src, "H", 1) - staticOverlay.override = 1 - staticOverlays["letter"] = staticOverlay - - staticOverlay = getRandomAnimalImage(src) - staticOverlay.override = 1 - staticOverlays["animal"] = staticOverlay - -/mob/living/carbon/human/cuff_resist(obj/item/I) - if(dna && dna.check_mutation(HULK)) - say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - if(..(I, cuff_break = FAST_CUFFBREAK)) - dropItemToGround(I) - else - if(..()) - dropItemToGround(I) - -/mob/living/carbon/human/clean_blood() - var/mob/living/carbon/human/H = src - if(H.gloves) - if(H.gloves.clean_blood()) - H.update_inv_gloves() - else - ..() // Clear the Blood_DNA list - if(H.bloody_hands) - H.bloody_hands = 0 - H.update_inv_gloves() - update_icons() //apply the now updated overlays to the mob - - -/mob/living/carbon/human/wash_cream() - //clean both to prevent a rare bug - cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard")) - cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human")) - - -//Turns a mob black, flashes a skeleton overlay -//Just like a cartoon! -/mob/living/carbon/human/proc/electrocution_animation(anim_duration) - //Handle mutant parts if possible - if(dna && dna.species) - add_atom_colour("#000000", TEMPORARY_COLOUR_PRIORITY) - var/static/mutable_appearance/electrocution_skeleton_anim - if(!electrocution_skeleton_anim) - electrocution_skeleton_anim = mutable_appearance(icon, "electrocuted_base") - electrocution_skeleton_anim.appearance_flags |= RESET_COLOR - add_overlay(electrocution_skeleton_anim) - addtimer(CALLBACK(src, .proc/end_electrocution_animation, electrocution_skeleton_anim), anim_duration) - - else //or just do a generic animation - flick_overlay_view(image(icon,src,"electrocuted_generic",ABOVE_MOB_LAYER), src, anim_duration) - -/mob/living/carbon/human/proc/end_electrocution_animation(mutable_appearance/MA) - remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000") - cut_overlay(MA) - -/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close = 0) - if(incapacitated() || lying ) - return - if(!Adjacent(M) && (M.loc != src)) - if((be_close == 0) && (dna.check_mutation(TK))) - if(tkMaxRangeCheck(src, M)) - return 1 - return - return 1 - -/mob/living/carbon/human/resist_restraints() - if(wear_suit && wear_suit.breakouttime) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT - cuff_resist(wear_suit) - else - ..() - -/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed. - for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked)) - var/datum/data/record/R = find_record("name", oldname, L) - if(R) - R.fields["name"] = newname - -/mob/living/carbon/human/get_total_tint() - . = ..() - if(glasses) - . += glasses.tint - -/mob/living/carbon/human/update_health_hud() - if(!client || !hud_used) - return - if(dna.species.update_health_hud()) - return - else - if(hud_used.healths) - var/health_amount = health - staminaloss - if(..(health_amount)) //not dead - switch(hal_screwyhud) - if(SCREWYHUD_CRIT) - hud_used.healths.icon_state = "health6" - if(SCREWYHUD_DEAD) - hud_used.healths.icon_state = "health7" - if(SCREWYHUD_HEALTHY) - hud_used.healths.icon_state = "health0" - if(hud_used.healthdoll) - hud_used.healthdoll.cut_overlays() - if(stat != DEAD) - hud_used.healthdoll.icon_state = "healthdoll_OVERLAY" - for(var/X in bodyparts) - var/obj/item/bodypart/BP = X - var/damage = BP.burn_dam + BP.brute_dam - var/comparison = (BP.max_damage/5) - var/icon_num = 0 - if(damage) - icon_num = 1 - if(damage > (comparison)) - icon_num = 2 - if(damage > (comparison*2)) - icon_num = 3 - if(damage > (comparison*3)) - icon_num = 4 - if(damage > (comparison*4)) - icon_num = 5 - if(hal_screwyhud == SCREWYHUD_HEALTHY) - icon_num = 0 - if(icon_num) - hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[BP.body_zone][icon_num]")) - for(var/t in get_missing_limbs()) //Missing limbs - hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]6")) - else - hud_used.healthdoll.icon_state = "healthdoll_DEAD" - -/mob/living/carbon/human/fully_heal(admin_revive = 0) - if(admin_revive) - regenerate_limbs() - regenerate_organs() - remove_all_embedded_objects() - set_heartattack(FALSE) - drunkenness = 0 - for(var/datum/mutation/human/HM in dna.mutations) - if(HM.quality != POSITIVE) - dna.remove_mutation(HM.name) - ..() - -/mob/living/carbon/human/proc/influenceSin() - var/datum/objective/sintouched/O - switch(rand(1,7))//traditional seven deadly sins... except lust. - if(1) // acedia - log_game("[src] was influenced by the sin of Acedia.") - O = new /datum/objective/sintouched/acedia - if(2) // Gluttony - log_game("[src] was influenced by the sin of gluttony.") - O = new /datum/objective/sintouched/gluttony - if(3) // Greed - log_game("[src] was influenced by the sin of greed.") - O = new /datum/objective/sintouched/greed - if(4) // sloth - log_game("[src] was influenced by the sin of sloth.") - O = new /datum/objective/sintouched/sloth - if(5) // Wrath - log_game("[src] was influenced by the sin of wrath.") - O = new /datum/objective/sintouched/wrath - if(6) // Envy - log_game("[src] was influenced by the sin of envy.") - O = new /datum/objective/sintouched/envy - if(7) // Pride - log_game("[src] was influenced by the sin of pride.") - O = new /datum/objective/sintouched/pride - SSticker.mode.sintouched += src.mind - src.mind.objectives += O - src.mind.announce_objectives() - -/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker) - . = ..() - if (dna && dna.species) - . += dna.species.check_weakness(weapon, attacker) - -/mob/living/carbon/human/is_literate() - return 1 - -/mob/living/carbon/human/can_hold_items() - return TRUE - -/mob/living/carbon/human/update_gravity(has_gravity,override = 0) - override = dna.species.override_float - ..() - -/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = 0, stun = 1, distance = 0, message = 1, toxic = 0) - if(blood && (NOBLOOD in dna.species.species_traits)) - if(message) - visible_message("[src] dry heaves!", \ - "You try to throw up, but there's nothing in your stomach!") - if(stun) - Weaken(10) - return 1 - ..() - -/mob/living/carbon/human/Bump(atom/A) - ..() - var/crashdir = get_dir(src, A) - var/obj/item/device/flightpack/FP = get_flightpack() - if(FP) - FP.flight_impact(A, crashdir) - -/mob/living/carbon/human/vv_get_dropdown() - . = ..() - . += "---" - .["Make monkey"] = "?_src_=vars;makemonkey=\ref[src]" - .["Set Species"] = "?_src_=vars;setspecies=\ref[src]" - .["Make cyborg"] = "?_src_=vars;makerobot=\ref[src]" - .["Make alien"] = "?_src_=vars;makealien=\ref[src]" - .["Make slime"] = "?_src_=vars;makeslime=\ref[src]" - .["Toggle Purrbation"] = "?_src_=vars;purrbation=\ref[src]" - -/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user) - if((target != pulling) || (grab_state < GRAB_AGGRESSIVE) || (user != target) || !isliving(user) || stat || user.stat)//Get consent first :^) - . = ..() - return - buckle_mob(target, TRUE, TRUE) - . = ..() - -/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) - if(!force)//humans are only meant to be ridden through piggybacking and special cases - return - if(!is_type_in_typecache(M, can_ride_typecache)) - M.visible_message("[M] really can't seem to mount [src]...") - return - if(!riding_datum) - riding_datum = new /datum/riding/human(src) - if(buckled_mobs && ((M in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled || (M.stat != CONSCIOUS)) - return - visible_message("[M] starts to climb onto [src]...") - if(do_after(M, 15, target = src)) - if(iscarbon(M)) - if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE)) - M.visible_message("[M] can't hang onto [src]!") - return - if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!! - M.visible_message("[M] can't climb onto [src]!") - return - . = ..(M, force, check_loc) - stop_pulling() - else - visible_message("[M] fails to climb onto [src]!") - -/mob/living/carbon/human/unbuckle_mob(mob/living/M, force=FALSE) - if(iscarbon(M)) - if(riding_datum) - riding_datum.unequip_buckle_inhands(M) - riding_datum.restore_position(M) - . = ..(M, force) +/mob/living/carbon/human + name = "Unknown" + real_name = "Unknown" + voice_name = "Unknown" + icon = 'icons/mob/human.dmi' + icon_state = "caucasian_m" + +/mob/living/carbon/human/dummy + real_name = "Test Dummy" + status_flags = GODMODE|CANPUSH + +/mob/living/carbon/human/dummy/New(loc) + ..() + if(!initialized) + args[1] = FALSE + Initialize(arglist(args)) + +/mob/living/carbon/human/dummy/Life() + return + +/mob/living/carbon/human/Initialize() + verbs += /mob/living/proc/mob_sleep + verbs += /mob/living/proc/lay_down + + //initialize limbs first + create_bodyparts() + + //initialize dna. for spawned humans; overwritten by other code + create_dna(src) + randomize_human(src) + dna.initialize_dna() + + if(dna.species) + set_species(dna.species.type) + + //initialise organs + create_internal_organs() + + martial_art = default_martial_art + + handcrafting = new() + + ..() + +/mob/living/carbon/human/create_internal_organs() + if(!(NOHUNGER in dna.species.species_traits)) + internal_organs += new /obj/item/organ/appendix + if(!(NOBREATH in dna.species.species_traits)) + if(dna.species.mutantlungs) + internal_organs += new dna.species.mutantlungs() + else + internal_organs += new /obj/item/organ/lungs() + if(!(NOBLOOD in dna.species.species_traits)) + internal_organs += new /obj/item/organ/heart + + internal_organs += new dna.species.mutanteyes + internal_organs += new dna.species.mutantears + internal_organs += new /obj/item/organ/brain + internal_organs += new dna.species.mutanttongue + give_genitals() + ..() + +/mob/living/carbon/human/OpenCraftingMenu() + handcrafting.ui_interact(src) + +/mob/living/carbon/human/prepare_data_huds() + //Update med hud images... + ..() + //...sec hud images... + sec_hud_set_ID() + sec_hud_set_implants() + sec_hud_set_security_status() + //...and display them. + add_to_all_human_data_huds() + +/mob/living/carbon/human/Stat() + ..() + + if(statpanel("Status")) + stat(null, "Intent: [a_intent]") + stat(null, "Move Mode: [m_intent]") + if (internal) + if (!internal.air_contents) + qdel(internal) + else + stat("Internal Atmosphere Info", internal.name) + stat("Tank Pressure", internal.air_contents.return_pressure()) + stat("Distribution Pressure", internal.distribute_pressure) + + var/mob/living/simple_animal/borer/B = has_brain_worms() + if(B && B.controlling) + stat("Chemicals", B.chemicals) + + if(mind) + if(mind.changeling) + stat("Chemical Storage", "[mind.changeling.chem_charges]/[mind.changeling.chem_storage]") + stat("Absorbed DNA", mind.changeling.absorbedcount) + + + //NINJACODE + if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja. + var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit + if(statpanel("SpiderOS")) + stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]") + stat("Current Time:", "[worldtime2text()]") + if(SN.s_initialized) + //Suit gear + stat("Energy Charge:", "[round(SN.cell.charge/100)]%") + stat("Smoke Bombs:", "\Roman [SN.s_bombs]") + //Ninja status + stat("Fingerprints:", "[md5(dna.uni_identity)]") + stat("Unique Identity:", "[dna.unique_enzymes]") + stat("Overall Status:", "[stat > 1 ? "dead" : "[health]% healthy"]") + stat("Nutrition Status:", "[nutrition]") + stat("Oxygen Loss:", "[getOxyLoss()]") + stat("Toxin Levels:", "[getToxLoss()]") + stat("Burn Severity:", "[getFireLoss()]") + stat("Brute Trauma:", "[getBruteLoss()]") + stat("Radiation Levels:","[radiation] rad") + stat("Body Temperature:","[bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)") + + //Virsuses + if(viruses.len) + stat("Viruses:", null) + for(var/datum/disease/D in viruses) + stat("*", "[D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]") + + +/mob/living/carbon/human/show_inv(mob/user) + user.set_machine(src) + var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) + var/list/obscured = check_obscured_slots() + var/list/dat = list() + + dat += "" + for(var/i in 1 to held_items.len) + var/obj/item/I = get_item_for_held_index(i) + dat += "" + dat += "" + + dat += "" + + dat += "" + + if(slot_wear_mask in obscured) + dat += "" + else + dat += "" + + if(slot_neck in obscured) + dat += "" + else + dat += "" + + if(slot_glasses in obscured) + dat += "" + else + dat += "" + + if(slot_ears in obscured) + dat += "" + else + dat += "" + + dat += "" + + dat += "" + if(wear_suit) + dat += "" + else + dat += "" + + if(slot_shoes in obscured) + dat += "" + else + dat += "" + + if(slot_gloves in obscured) + dat += "" + else + dat += "" + + if(slot_w_uniform in obscured) + dat += "" + else + dat += "" + + if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (slot_w_uniform in obscured)) + dat += "" + dat += "" + dat += "" + else + dat += "" + dat += "" + dat += "" + + if(handcuffed) + dat += "" + if(legcuffed) + dat += "" + + dat += {"
[get_held_index_name(i)]:[(I && !(I.flags & ABSTRACT)) ? I : "Empty"]
 
Back:[(back && !(back.flags&ABSTRACT)) ? back : "Empty"]" + if(has_breathable_mask && istype(back, /obj/item/weapon/tank)) + dat += " [internal ? "Disable Internals" : "Set Internals"]" + + dat += "
 
Head:[(head && !(head.flags&ABSTRACT)) ? head : "Empty"]
Mask:Obscured
Mask:[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Empty"]
Neck:Obscured
Neck:[(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "Empty"]
Eyes:Obscured
Eyes:[(glasses && !(glasses.flags&ABSTRACT)) ? glasses : "Empty"]
Ears:Obscured
Ears:[(ears && !(ears.flags&ABSTRACT)) ? ears : "Empty"]
 
Exosuit:[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "Empty"]
 ↳Suit Storage:[(s_store && !(s_store.flags&ABSTRACT)) ? s_store : "Empty"]" + if(has_breathable_mask && istype(s_store, /obj/item/weapon/tank)) + dat += " [internal ? "Disable Internals" : "Set Internals"]" + dat += "
 ↳Suit Storage:
Shoes:Obscured
Shoes:[(shoes && !(shoes.flags&ABSTRACT)) ? shoes : "Empty"]
Gloves:Obscured
Gloves:[(gloves && !(gloves.flags&ABSTRACT)) ? gloves : "Empty"]
Uniform:Obscured
Uniform:[(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "Empty"]
 ↳Pockets:
 ↳ID:
 ↳Belt:
 ↳Belt:[(belt && !(belt.flags&ABSTRACT)) ? belt : "Empty"]" + if(has_breathable_mask && istype(belt, /obj/item/weapon/tank)) + dat += " [internal ? "Disable Internals" : "Set Internals"]" + dat += "
 ↳Pockets:[(l_store && !(l_store.flags&ABSTRACT)) ? "Left (Full)" : "Left (Empty)"]" + dat += " [(r_store && !(r_store.flags&ABSTRACT)) ? "Right (Full)" : "Right (Empty)"]
 ↳ID:[(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "Empty"]
Handcuffed: Remove
Legcuffed
+ Close + "} + + var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 510) + popup.set_content(dat.Join()) + popup.open() + +// called when something steps onto a human +// this could be made more general, but for now just handle mulebot +/mob/living/carbon/human/Crossed(atom/movable/AM) + var/mob/living/simple_animal/bot/mulebot/MB = AM + if(istype(MB)) + MB.RunOver(src) + + spreadFire(AM) + + +/mob/living/carbon/human/Topic(href, href_list) + if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + + if(href_list["embedded_object"]) + var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts + if(!L) + return + var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects + if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore + return + var/time_taken = I.embedded_unsafe_removal_time*I.w_class + usr.visible_message("[usr] attempts to remove [I] from their [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)") + if(do_after(usr, time_taken, needhand = 1, target = src)) + if(!I || !L || I.loc != src || !(I in L.embedded_objects)) + return + L.embedded_objects -= I + L.receive_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus. + I.forceMove(get_turf(src)) + usr.put_in_hands(I) + usr.emote("scream") + usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","You successfully remove [I] from your [L.name].") + if(!has_embedded_objects()) + clear_alert("embeddedobject") + return + + if(href_list["item"]) + var/slot = text2num(href_list["item"]) + if(slot in check_obscured_slots()) + to_chat(usr, "You can't reach that! Something is covering it.") + return + + if(href_list["pockets"]) + var/pocket_side = href_list["pockets"] + var/pocket_id = (pocket_side == "right" ? slot_r_store : slot_l_store) + var/obj/item/pocket_item = (pocket_id == slot_r_store ? r_store : l_store) + var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty + + var/delay_denominator = 1 + if(pocket_item && !(pocket_item.flags&ABSTRACT)) + if(pocket_item.flags & NODROP) + to_chat(usr, "You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!") + to_chat(usr, "You try to empty [src]'s [pocket_side] pocket.") + else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.flags&ABSTRACT)) + to_chat(usr, "You try to place [place_item] into [src]'s [pocket_side] pocket.") + delay_denominator = 4 + else + return + + if(do_mob(usr, src, POCKET_STRIP_DELAY/delay_denominator)) //placing an item into the pocket is 4 times faster + if(pocket_item) + if(pocket_item == (pocket_id == slot_r_store ? r_store : l_store)) //item still in the pocket we search + dropItemToGround(pocket_item) + else + if(place_item) + if(place_item.mob_can_equip(src, usr, pocket_id, FALSE, TRUE)) + usr.temporarilyRemoveItemFromInventory(place_item, TRUE) + equip_to_slot(place_item, pocket_id, TRUE) + //do nothing otherwise + + // Update strip window + if(usr.machine == src && in_range(src, usr)) + show_inv(usr) + else + // Display a warning if the user mocks up + to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") + + ..() + + +///////HUDs/////// + if(href_list["hud"]) + if(ishuman(usr)) + var/mob/living/carbon/human/H = usr + var/perpname = get_face_name(get_id_name("")) + if(istype(H.glasses, /obj/item/clothing/glasses/hud) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud)) + var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.general) + if(href_list["photo_front"] || href_list["photo_side"]) + if(R) + if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) + return + var/obj/item/weapon/photo/P = null + if(href_list["photo_front"]) + P = R.fields["photo_front"] + else if(href_list["photo_side"]) + P = R.fields["photo_side"] + if(P) + P.show(H) + + if(href_list["hud"] == "m") + if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) + if(href_list["p_stat"]) + var/health_status = input(usr, "Specify a new physical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("Active", "Physically Unfit", "*Unconscious*", "*Deceased*", "Cancel") + if(R) + if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) + return + if(health_status && health_status != "Cancel") + R.fields["p_stat"] = health_status + return + if(href_list["m_stat"]) + var/health_status = input(usr, "Specify a new mental status for this person.", "Medical HUD", R.fields["m_stat"]) in list("Stable", "*Watch*", "*Unstable*", "*Insane*", "Cancel") + if(R) + if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/health) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical)) + return + if(health_status && health_status != "Cancel") + R.fields["m_stat"] = health_status + return + if(href_list["evaluation"]) + if(!getBruteLoss() && !getFireLoss() && !getOxyLoss() && getToxLoss() < 20) + to_chat(usr, "No external injuries detected.
") + return + var/span = "notice" + var/status = "" + if(getBruteLoss()) + to_chat(usr, "Physical trauma analysis:") + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + var/brutedamage = BP.brute_dam + if(brutedamage > 0) + status = "received minor physical injuries." + span = "notice" + if(brutedamage > 20) + status = "been seriously damaged." + span = "danger" + if(brutedamage > 40) + status = "sustained major trauma!" + span = "userdanger" + if(brutedamage) + to_chat(usr, "[BP] appears to have [status]") + if(getFireLoss()) + to_chat(usr, "Analysis of skin burns:") + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + var/burndamage = BP.burn_dam + if(burndamage > 0) + status = "signs of minor burns." + span = "notice" + if(burndamage > 20) + status = "serious burns." + span = "danger" + if(burndamage > 40) + status = "major burns!" + span = "userdanger" + if(burndamage) + to_chat(usr, "[BP] appears to have [status]") + if(getOxyLoss()) + to_chat(usr, "Patient has signs of suffocation, emergency treatment may be required!") + if(getToxLoss() > 20) + to_chat(usr, "Gathered data is inconsistent with the analysis, possible cause: poisoning.") + + if(href_list["hud"] == "s") + if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + if(usr.stat || usr == src) //|| !usr.canmove || usr.restrained()) Fluff: Sechuds have eye-tracking technology and sets 'arrest' to people that the wearer looks and blinks at. + return //Non-fluff: This allows sec to set people to arrest as they get disarmed or beaten + // Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access + var/allowed_access = null + var/obj/item/clothing/glasses/G = H.glasses + if (!G.emagged) + if(H.wear_id) + var/list/access = H.wear_id.GetAccess() + if(GLOB.access_sec_doors in access) + allowed_access = H.get_authentification_name() + else + allowed_access = "@%&ERROR_%$*" + + + if(!allowed_access) + to_chat(H, "ERROR: Invalid Access") + return + + if(perpname) + R = find_record("name", perpname, GLOB.data_core.security) + if(R) + if(href_list["status"]) + var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Parolled", "Discharged", "Cancel") + if(setcriminal != "Cancel") + if(R) + if(H.canUseHUD()) + if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + investigate_log("[src.key] has been set from [R.fields["criminal"]] to [setcriminal] by [usr.name] ([usr.key]).", "records") + R.fields["criminal"] = setcriminal + sec_hud_set_security_status() + return + + if(href_list["view"]) + if(R) + if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + return + to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") + to_chat(usr, "Minor Crimes:") + for(var/datum/data/crime/c in R.fields["mi_crim"]) + to_chat(usr, "Crime: [c.crimeName]") + to_chat(usr, "Details: [c.crimeDetails]") + to_chat(usr, "Added by [c.author] at [c.time]") + to_chat(usr, "----------") + to_chat(usr, "Major Crimes:") + for(var/datum/data/crime/c in R.fields["ma_crim"]) + to_chat(usr, "Crime: [c.crimeName]") + to_chat(usr, "Details: [c.crimeDetails]") + to_chat(usr, "Added by [c.author] at [c.time]") + to_chat(usr, "----------") + to_chat(usr, "Notes: [R.fields["notes"]]") + return + + if(href_list["add_crime"]) + switch(alert("What crime would you like to add?","Security HUD","Minor Crime","Major Crime","Cancel")) + if("Minor Crime") + if(R) + var/t1 = stripped_input("Please input minor crime names:", "Security HUD", "", null) + var/t2 = stripped_multiline_input("Please input minor crime details:", "Security HUD", "", null) + if(R) + if (!t1 || !t2 || !allowed_access) + return + else if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + return + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text()) + GLOB.data_core.addMinorCrime(R.fields["id"], crime) + to_chat(usr, "Successfully added a minor crime.") + return + if("Major Crime") + if(R) + var/t1 = stripped_input("Please input major crime names:", "Security HUD", "", null) + var/t2 = stripped_multiline_input("Please input major crime details:", "Security HUD", "", null) + if(R) + if (!t1 || !t2 || !allowed_access) + return + else if (!H.canUseHUD()) + return + else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + return + var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, worldtime2text()) + GLOB.data_core.addMajorCrime(R.fields["id"], crime) + to_chat(usr, "Successfully added a major crime.") + return + + if(href_list["view_comment"]) + if(R) + if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + return + to_chat(usr, "Comments/Log:") + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + to_chat(usr, R.fields[text("com_[]", counter)]) + to_chat(usr, "----------") + counter++ + return + + if(href_list["add_comment"]) + if(R) + var/t1 = stripped_multiline_input("Add Comment:", "Secure. records", null, null) + if(R) + if (!t1 || !allowed_access) + return + else if(!H.canUseHUD()) + return + else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/security)) + return + var/counter = 1 + while(R.fields[text("com_[]", counter)]) + counter++ + R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []
[]", allowed_access, worldtime2text(), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1) + to_chat(usr, "Successfully added comment.") + return + to_chat(usr, "Unable to locate a data core entry for this person.") + +/mob/living/carbon/human/proc/canUseHUD() + return !(src.stat || src.weakened || src.stunned || src.restrained()) + +/mob/living/carbon/human/can_inject(mob/user, error_msg, target_zone, var/penetrate_thick = 0) + . = 1 // Default to returning true. + if(user && !target_zone) + target_zone = user.zone_selected + if(dna && (PIERCEIMMUNE in dna.species.species_traits)) + . = 0 + // If targeting the head, see if the head item is thin enough. + // If targeting anything else, see if the wear suit is thin enough. + if(above_neck(target_zone)) + if(head && head.flags & THICKMATERIAL && !penetrate_thick) + . = 0 + else + if(wear_suit && wear_suit.flags & THICKMATERIAL && !penetrate_thick) + . = 0 + if(!. && error_msg && user) + // Might need re-wording. + to_chat(user, "There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].") + +/mob/living/carbon/human/proc/check_obscured_slots() + var/list/obscured = list() + + if(wear_suit) + if(wear_suit.flags_inv & HIDEGLOVES) + obscured |= slot_gloves + if(wear_suit.flags_inv & HIDEJUMPSUIT) + obscured |= slot_w_uniform + if(wear_suit.flags_inv & HIDESHOES) + obscured |= slot_shoes + + if(head) + if(head.flags_inv & HIDEMASK) + obscured |= slot_wear_mask + if(head.flags_inv & HIDEEYES) + obscured |= slot_glasses + if(head.flags_inv & HIDEEARS) + obscured |= slot_ears + + if(wear_mask) + if(wear_mask.flags_inv & HIDEEYES) + obscured |= slot_glasses + + if(obscured.len) + return obscured + else + return null + +/mob/living/carbon/human/assess_threat(mob/living/simple_animal/bot/secbot/judgebot, lasercolor) + if(judgebot.emagged == 2) + return 10 //Everyone is a criminal! + + var/threatcount = 0 + + //Lasertag bullshit + if(lasercolor) + if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve + if(istype(wear_suit, /obj/item/clothing/suit/redtag)) + threatcount += 4 + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 4 + if(istype(belt, /obj/item/weapon/gun/energy/laser/redtag)) + threatcount += 2 + + if(lasercolor == "r") + if(istype(wear_suit, /obj/item/clothing/suit/bluetag)) + threatcount += 4 + if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 4 + if(istype(belt, /obj/item/weapon/gun/energy/laser/bluetag)) + threatcount += 2 + + return threatcount + + //Check for ID + var/obj/item/weapon/card/id/idcard = get_idcard() + if(judgebot.idcheck && !idcard && name=="Unknown") + threatcount += 4 + + //Check for weapons + if(judgebot.weaponscheck) + if(!idcard || !(GLOB.access_weapons in idcard.access)) + for(var/obj/item/I in held_items) + if(judgebot.check_for_weapons(I)) + threatcount += 4 + if(judgebot.check_for_weapons(belt)) + threatcount += 2 + + //Check for arrest warrant + if(judgebot.check_records) + var/perpname = get_face_name(get_id_name()) + var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) + if(R && R.fields["criminal"]) + switch(R.fields["criminal"]) + if("*Arrest*") + threatcount += 5 + if("Incarcerated") + threatcount += 2 + if("Parolled") + threatcount += 2 + + //Check for dresscode violations + if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/syndi) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi)) + threatcount += 5 + + //Check for nonhuman scum + if(dna && dna.species.id && dna.species.id != "human" || "lizard" || "mammal" || "avian" || "aquatic" || "insect") + threatcount += 1 + + //mindshield implants imply trustworthyness + if(isloyal()) + threatcount -= 1 + + //Agent cards lower threatlevel. + if(istype(idcard, /obj/item/weapon/card/id/syndicate)) + threatcount -= 2 + + return threatcount + + +//Used for new human mobs created by cloning/goleming/podding +/mob/living/carbon/human/proc/set_cloned_appearance() + if(gender == MALE) + facial_hair_style = "Full Beard" + else + facial_hair_style = "Shaved" + hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") + underwear = "Nude" + update_body() + update_genitals() + update_hair() + +/mob/living/carbon/human/singularity_pull(S, current_size) + if(current_size >= STAGE_THREE) + for(var/obj/item/hand in held_items) + if(prob(current_size * 5) && hand.w_class >= ((11-current_size)/2) && dropItemToGround(hand)) + step_towards(hand, src) + to_chat(src, "\The [S] pulls \the [hand] from your grip!") + rad_act(current_size * 3) + if(mob_negates_gravity()) + return + ..() + +/mob/living/carbon/human/proc/do_cpr(mob/living/carbon/C) + CHECK_DNA_AND_SPECIES(C) + + if(C.stat == DEAD || (C.status_flags & FAKEDEATH)) + to_chat(src, "[C.name] is dead!") + return + if(is_mouth_covered()) + to_chat(src, "Remove your mask first!") + return 0 + if(C.is_mouth_covered()) + to_chat(src, "Remove [p_their()] mask first!") + return 0 + + if(C.cpr_time < world.time + 30) + visible_message("[src] is trying to perform CPR on [C.name]!", \ + "You try to perform CPR on [C.name]... Hold still!") + if(!do_mob(src, C)) + to_chat(src, "You fail to perform CPR on [C]!") + return 0 + + var/they_breathe = (!(NOBREATH in C.dna.species.species_traits)) + var/they_lung = C.getorganslot("lungs") + + if(C.health > HEALTH_THRESHOLD_CRIT) + return + + src.visible_message("[src] performs CPR on [C.name]!", "You perform CPR on [C.name].") + C.cpr_time = world.time + add_logs(src, C, "CPRed") + + if(they_breathe && they_lung) + var/suff = min(C.getOxyLoss(), 7) + C.adjustOxyLoss(-suff) + C.updatehealth() + to_chat(C, "You feel a breath of fresh air enter your lungs... It feels good...") + else if(they_breathe && !they_lung) + to_chat(C, "You feel a breath of fresh air... but you don't feel any better...") + else + to_chat(C, "You feel a breath of fresh air... which is a sensation you don't recognise...") + +/mob/living/carbon/human/generateStaticOverlay() + var/image/staticOverlay = image(icon('icons/effects/effects.dmi', "static"), loc = src) + staticOverlay.override = 1 + staticOverlays["static"] = staticOverlay + + staticOverlay = image(icon('icons/effects/effects.dmi', "blank"), loc = src) + staticOverlay.override = 1 + staticOverlays["blank"] = staticOverlay + + staticOverlay = getLetterImage(src, "H", 1) + staticOverlay.override = 1 + staticOverlays["letter"] = staticOverlay + + staticOverlay = getRandomAnimalImage(src) + staticOverlay.override = 1 + staticOverlays["animal"] = staticOverlay + +/mob/living/carbon/human/cuff_resist(obj/item/I) + if(dna && dna.check_mutation(HULK)) + say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + if(..(I, cuff_break = FAST_CUFFBREAK)) + dropItemToGround(I) + else + if(..()) + dropItemToGround(I) + +/mob/living/carbon/human/clean_blood() + var/mob/living/carbon/human/H = src + if(H.gloves) + if(H.gloves.clean_blood()) + H.update_inv_gloves() + else + ..() // Clear the Blood_DNA list + if(H.bloody_hands) + H.bloody_hands = 0 + H.update_inv_gloves() + update_icons() //apply the now updated overlays to the mob + + +/mob/living/carbon/human/wash_cream() + //clean both to prevent a rare bug + cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard")) + cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human")) + + +//Turns a mob black, flashes a skeleton overlay +//Just like a cartoon! +/mob/living/carbon/human/proc/electrocution_animation(anim_duration) + //Handle mutant parts if possible + if(dna && dna.species) + add_atom_colour("#000000", TEMPORARY_COLOUR_PRIORITY) + var/static/mutable_appearance/electrocution_skeleton_anim + if(!electrocution_skeleton_anim) + electrocution_skeleton_anim = mutable_appearance(icon, "electrocuted_base") + electrocution_skeleton_anim.appearance_flags |= RESET_COLOR + add_overlay(electrocution_skeleton_anim) + addtimer(CALLBACK(src, .proc/end_electrocution_animation, electrocution_skeleton_anim), anim_duration) + + else //or just do a generic animation + flick_overlay_view(image(icon,src,"electrocuted_generic",ABOVE_MOB_LAYER), src, anim_duration) + +/mob/living/carbon/human/proc/end_electrocution_animation(mutable_appearance/MA) + remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000") + cut_overlay(MA) + +/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close = 0) + if(incapacitated() || lying ) + return + if(!Adjacent(M) && (M.loc != src)) + if((be_close == 0) && (dna.check_mutation(TK))) + if(tkMaxRangeCheck(src, M)) + return 1 + return + return 1 + +/mob/living/carbon/human/resist_restraints() + if(wear_suit && wear_suit.breakouttime) + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + cuff_resist(wear_suit) + else + ..() + +/mob/living/carbon/human/replace_records_name(oldname,newname) // Only humans have records right now, move this up if changed. + for(var/list/L in list(GLOB.data_core.general,GLOB.data_core.medical,GLOB.data_core.security,GLOB.data_core.locked)) + var/datum/data/record/R = find_record("name", oldname, L) + if(R) + R.fields["name"] = newname + +/mob/living/carbon/human/get_total_tint() + . = ..() + if(glasses) + . += glasses.tint + +/mob/living/carbon/human/update_health_hud() + if(!client || !hud_used) + return + if(dna.species.update_health_hud()) + return + else + if(hud_used.healths) + var/health_amount = health - staminaloss + if(..(health_amount)) //not dead + switch(hal_screwyhud) + if(SCREWYHUD_CRIT) + hud_used.healths.icon_state = "health6" + if(SCREWYHUD_DEAD) + hud_used.healths.icon_state = "health7" + if(SCREWYHUD_HEALTHY) + hud_used.healths.icon_state = "health0" + if(hud_used.healthdoll) + hud_used.healthdoll.cut_overlays() + if(stat != DEAD) + hud_used.healthdoll.icon_state = "healthdoll_OVERLAY" + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + var/damage = BP.burn_dam + BP.brute_dam + var/comparison = (BP.max_damage/5) + var/icon_num = 0 + if(damage) + icon_num = 1 + if(damage > (comparison)) + icon_num = 2 + if(damage > (comparison*2)) + icon_num = 3 + if(damage > (comparison*3)) + icon_num = 4 + if(damage > (comparison*4)) + icon_num = 5 + if(hal_screwyhud == SCREWYHUD_HEALTHY) + icon_num = 0 + if(icon_num) + hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[BP.body_zone][icon_num]")) + for(var/t in get_missing_limbs()) //Missing limbs + hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]6")) + else + hud_used.healthdoll.icon_state = "healthdoll_DEAD" + +/mob/living/carbon/human/fully_heal(admin_revive = 0) + if(admin_revive) + regenerate_limbs() + regenerate_organs() + remove_all_embedded_objects() + set_heartattack(FALSE) + drunkenness = 0 + for(var/datum/mutation/human/HM in dna.mutations) + if(HM.quality != POSITIVE) + dna.remove_mutation(HM.name) + ..() + +/mob/living/carbon/human/proc/influenceSin() + var/datum/objective/sintouched/O + switch(rand(1,7))//traditional seven deadly sins... except lust. + if(1) // acedia + log_game("[src] was influenced by the sin of Acedia.") + O = new /datum/objective/sintouched/acedia + if(2) // Gluttony + log_game("[src] was influenced by the sin of gluttony.") + O = new /datum/objective/sintouched/gluttony + if(3) // Greed + log_game("[src] was influenced by the sin of greed.") + O = new /datum/objective/sintouched/greed + if(4) // sloth + log_game("[src] was influenced by the sin of sloth.") + O = new /datum/objective/sintouched/sloth + if(5) // Wrath + log_game("[src] was influenced by the sin of wrath.") + O = new /datum/objective/sintouched/wrath + if(6) // Envy + log_game("[src] was influenced by the sin of envy.") + O = new /datum/objective/sintouched/envy + if(7) // Pride + log_game("[src] was influenced by the sin of pride.") + O = new /datum/objective/sintouched/pride + SSticker.mode.sintouched += src.mind + src.mind.objectives += O + src.mind.announce_objectives() + +/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker) + . = ..() + if (dna && dna.species) + . += dna.species.check_weakness(weapon, attacker) + +/mob/living/carbon/human/is_literate() + return 1 + +/mob/living/carbon/human/can_hold_items() + return TRUE + +/mob/living/carbon/human/update_gravity(has_gravity,override = 0) + override = dna.species.override_float + ..() + +/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = 0, stun = 1, distance = 0, message = 1, toxic = 0) + if(blood && (NOBLOOD in dna.species.species_traits)) + if(message) + visible_message("[src] dry heaves!", \ + "You try to throw up, but there's nothing in your stomach!") + if(stun) + Weaken(10) + return 1 + ..() + +/mob/living/carbon/human/Bump(atom/A) + ..() + var/crashdir = get_dir(src, A) + var/obj/item/device/flightpack/FP = get_flightpack() + if(FP) + FP.flight_impact(A, crashdir) + +/mob/living/carbon/human/vv_get_dropdown() + . = ..() + . += "---" + .["Make monkey"] = "?_src_=vars;makemonkey=\ref[src]" + .["Set Species"] = "?_src_=vars;setspecies=\ref[src]" + .["Make cyborg"] = "?_src_=vars;makerobot=\ref[src]" + .["Make alien"] = "?_src_=vars;makealien=\ref[src]" + .["Make slime"] = "?_src_=vars;makeslime=\ref[src]" + .["Toggle Purrbation"] = "?_src_=vars;purrbation=\ref[src]" + +/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user) + if((target != pulling) || (grab_state < GRAB_AGGRESSIVE) || (user != target) || !isliving(user) || stat || user.stat)//Get consent first :^) + . = ..() + return + buckle_mob(target, TRUE, TRUE) + . = ..() + +/mob/living/carbon/human/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE) + if(!force)//humans are only meant to be ridden through piggybacking and special cases + return + if(!is_type_in_typecache(M, can_ride_typecache)) + M.visible_message("[M] really can't seem to mount [src]...") + return + if(!riding_datum) + riding_datum = new /datum/riding/human(src) + if(buckled_mobs && ((M in buckled_mobs) || (buckled_mobs.len >= max_buckled_mobs)) || buckled || (M.stat != CONSCIOUS)) + return + visible_message("[M] starts to climb onto [src]...") + if(do_after(M, 15, target = src)) + if(iscarbon(M)) + if(M.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE)) + M.visible_message("[M] can't hang onto [src]!") + return + if(!riding_datum.equip_buckle_inhands(M, 2)) //MAKE SURE THIS IS LAST!! + M.visible_message("[M] can't climb onto [src]!") + return + . = ..(M, force, check_loc) + stop_pulling() + else + visible_message("[M] fails to climb onto [src]!") + +/mob/living/carbon/human/unbuckle_mob(mob/living/M, force=FALSE) + if(iscarbon(M)) + if(riding_datum) + riding_datum.unequip_buckle_inhands(M) + riding_datum.restore_position(M) + . = ..(M, force) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 7ca155ec57..8a62b4e058 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,5 +1,4 @@ /mob/living/carbon/human - initial_languages = list(/datum/language/common) hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD) possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM) pressure_resistance = 25 @@ -49,4 +48,4 @@ var/datum/personal_crafting/handcrafting can_buckle = TRUE buckle_lying = FALSE - can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot) \ No newline at end of file + can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot) diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 34017d6728..a05614fe09 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -2,7 +2,7 @@ name = "monkey" voice_name = "monkey" verb_say = "chimpers" - initial_languages = list(/datum/language/monkey) + initial_language_holder = /datum/language_holder/monkey icon = 'icons/mob/monkey.dmi' icon_state = "" gender = NEUTER diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm index 039b40b234..ed1f5f08b5 100644 --- a/code/modules/mob/living/carbon/say.dm +++ b/code/modules/mob/living/carbon/say.dm @@ -29,14 +29,9 @@ if(I) . |= I.get_held_item_speechspans(src) -/mob/living/carbon/can_speak_in_language(datum/language/dt) - if(HAS_SECONDARY_FLAG(src, OMNITONGUE)) - . = has_language(dt) - else if(has_language(dt)) - var/obj/item/organ/tongue/T = getorganslot("tongue") - if(T) - . = T.can_speak_in_language(dt) - else - . = initial(dt.flags) & TONGUELESS_SPEECH +/mob/living/carbon/could_speak_in_language(datum/language/dt) + var/obj/item/organ/tongue/T = getorganslot("tongue") + if(T) + . = T.could_speak_in_language(dt) else - . = FALSE + . = initial(dt.flags) & TONGUELESS_SPEECH diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 75f29408fe..77dada5349 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -17,8 +17,6 @@ medhud.add_to_hud(src) faction += "\ref[src]" - language_menu = new(src) - /mob/living/prepare_huds() ..() @@ -50,8 +48,6 @@ staticOverlays.len = 0 remove_from_all_data_huds() - QDEL_NULL(language_menu) - return ..() /mob/living/ghostize(can_reenter_corpse = 1) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 9c4a2c7e90..fbf9c35303 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -74,4 +74,3 @@ var/datum/riding/riding_datum var/datum/language/selected_default_language - var/datum/language_menu/language_menu diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index bb0628e7f3..ab3dc7bb34 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -167,11 +167,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( spans += get_spans() if(language) - var/datum/language/L = GLOB.language_datums[language] - if(!istype(L)) - L = new language - GLOB.language_datums[language] = L - + var/datum/language/L = GLOB.language_datum_instances[language] spans |= L.spans //Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages @@ -308,13 +304,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list( return GLOB.department_radio_keys[key_symbol] /mob/living/proc/get_message_language(message) - var/static/list/langlist - if(!langlist) - langlist = subtypesof(/datum/language) - if(copytext(message, 1, 2) == ",") var/key = copytext(message, 2, 3) - for(var/ld in langlist) + for(var/ld in GLOB.all_languages) var/datum/language/LD = ld if(initial(LD.key) == key) return LD @@ -435,17 +427,14 @@ GLOBAL_LIST_INIT(department_radio_keys, list( else . = ..() -/mob/living/get_default_language() - if(selected_default_language) - if(has_language(selected_default_language)) - return selected_default_language - else - selected_default_language = null - - . = ..() - -/mob/living/proc/open_language_menu(mob/user) - language_menu.ui_interact(user) - /mob/living/whisper(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null) say("#[message]", bubble_type, spans, sanitize, language) + +/mob/living/get_language_holder(shadow=TRUE) + if(mind && shadow) + // Mind language holders shadow mob holders. + . = mind.get_language_holder() + if(.) + return . + + . = ..() diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 4080cea4fb..58e2b04d9c 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -164,11 +164,9 @@ #endif -/mob/living/silicon/ai/can_speak_in_language(datum/language/dt) - if(HAS_SECONDARY_FLAG(src, OMNITONGUE)) - . = has_language(dt) - else if(is_servant_of_ratvar(src)) +/mob/living/silicon/ai/could_speak_in_language(datum/language/dt) + if(is_servant_of_ratvar(src)) // Ratvarian AIs can only speak Ratvarian - . = ispath(dt, /datum/language/ratvar) && has_language(dt) + . = ispath(dt, /datum/language/ratvar) else . = ..() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a69fe27da7..bb88f69781 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -6,7 +6,7 @@ verb_ask = "queries" verb_exclaim = "declares" verb_yell = "alarms" - initial_languages = list(/datum/language/common, /datum/language/machine) + initial_language_holder = /datum/language_holder/synthetic see_in_dark = 8 bubble_icon = "machine" weather_immunities = list("ash") diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index dd98496dac..ba4e3dc68c 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -20,7 +20,7 @@ verb_ask = "queries" verb_exclaim = "declares" verb_yell = "alarms" - initial_languages = list(/datum/language/common, /datum/language/machine) + initial_language_holder = /datum/language_holder/synthetic bubble_icon = "machine" faction = list("neutral", "silicon" , "turret") diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index e5ba358a25..e98a57d0a6 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -37,8 +37,7 @@ voice_name = "synthesized chirp" speak_emote = list("chirps") bubble_icon = "machine" - initial_languages = list(/datum/language/common, /datum/language/machine, /datum/language/drone) - only_speaks_language = /datum/language/drone + initial_language_holder = /datum/language_holder/drone mob_size = MOB_SIZE_SMALL has_unlimited_silicon_privilege = 1 damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index 7cd6567ecb..1c70ca57e5 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -17,6 +17,7 @@ picked = TRUE //the appearence of syndrones is static, you don't get to change it. health = 30 maxHealth = 120 //If you murder other drones and cannibalize them you can get much stronger + initial_language_holder = /datum/language_holder/drone/syndicate faction = list("syndicate") speak_emote = list("hisses") bubble_icon = "syndibot" @@ -110,8 +111,7 @@ verb_exclaim = "proclaims" verb_yell = "harangues" bubble_icon = "clock" - initial_languages = list(/datum/language/common, /datum/language/ratvar) - only_speaks_language = /datum/language/ratvar + initial_language_holder = /datum/language_holder/clockmob light_color = "#E42742" heavy_emp_damage = 0 laws = "0. Purge all untruths and honor Ratvar." diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index d822a05886..a390ecae71 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -647,8 +647,7 @@ Difficulty: Very Hard verb_ask = "floats inquisitively" verb_exclaim = "zaps" verb_yell = "bangs" - initial_languages = list(/datum/language/common, /datum/language/slime) - only_speaks_language = /datum/language/slime + initial_language_holder = /datum/language_holder/lightbringer damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) light_range = 4 faction = list("neutral") diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 8db43623dc..767d869c8f 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -7,9 +7,6 @@ status_flags = CANPUSH - // goats bray, cows go moo, and the fox says Geckers - initial_languages = list(/datum/language/common) - var/icon_living = "" var/icon_dead = "" //icon when the animal is dead. Don't use animated icons for this. var/icon_gib = null //We only try to show a gibbing animation if this exists. diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index f9bcfe1b6f..6eb688d38f 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -18,7 +18,7 @@ emote_see = list("jiggles", "bounces in place") speak_emote = list("blorbles") bubble_icon = "slime" - initial_languages = list(/datum/language/common, /datum/language/slime) + initial_language_holder = /datum/language_holder/slime atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index c24ee7acd2..aab6e40c2d 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -754,7 +754,6 @@ client.move_delay += movement_delay() return 1 - /mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check return 0 @@ -1017,3 +1016,10 @@ if("logging") return debug_variable(var_name, logging, 0, src, FALSE) . = ..() + +/mob/verb/open_language_menu() + set name = "Open Language Menu" + set category = "IC" + + var/datum/language_holder/H = get_language_holder() + H.open_language_menu(usr) diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 78732d82e4..aa28f2402c 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -60,7 +60,6 @@ obj_integrity = 1000 max_integrity = 1000 verb_say = "chants" - initial_languages = list(/datum/language/common) var/obj/machinery/power/emitter/energycannon/magical/our_statue var/list/mob/living/sleepers = list() var/never_spoken = TRUE @@ -148,11 +147,11 @@ 3. Don't get messed up in their affairs." status_flags = GODMODE // Please don't punch the barkeeper unique_name = FALSE // disables the (123) number suffix + initial_language_holder = /datum/language_holder/universal /mob/living/simple_animal/drone/snowflake/bardrone/Initialize() . = ..() access_card.access |= GLOB.access_cent_bar - grant_all_languages(omnitongue=TRUE) /mob/living/simple_animal/hostile/alien/maid/barmaid gold_core_spawnable = 0 @@ -163,6 +162,7 @@ unique_name = FALSE AIStatus = AI_OFF stop_automated_movement = TRUE + initial_language_holder = /datum/language_holder/universal /mob/living/simple_animal/hostile/alien/maid/barmaid/Initialize() . = ..() @@ -172,8 +172,6 @@ access_card.access |= GLOB.access_cent_bar access_card.flags |= NODROP - grant_all_languages(omnitongue=TRUE) - /mob/living/simple_animal/hostile/alien/maid/barmaid/Destroy() qdel(access_card) . = ..() diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index 1a9d6b98e6..575a634a11 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -34,7 +34,7 @@ if(say_mod && M.dna && M.dna.species) M.dna.species.say_mod = initial(M.dna.species.say_mod) -/obj/item/organ/tongue/can_speak_in_language(datum/language/dt) +/obj/item/organ/tongue/could_speak_in_language(datum/language/dt) . = is_type_in_typecache(dt, languages_possible) /obj/item/organ/tongue/lizard diff --git a/code/modules/tgui/states/language_menu.dm b/code/modules/tgui/states/language_menu.dm index 4a370e8213..fedc4320e4 100644 --- a/code/modules/tgui/states/language_menu.dm +++ b/code/modules/tgui/states/language_menu.dm @@ -10,5 +10,5 @@ GLOBAL_DATUM_INIT(language_menu_state, /datum/ui_state/language_menu, new) . = UI_INTERACTIVE else if(istype(src_object, /datum/language_menu)) var/datum/language_menu/LM = src_object - if(LM.owner == user) + if(LM.language_holder.get_atom() == user) . = UI_INTERACTIVE diff --git a/tgstation.dme b/tgstation.dme index 3d38b202fe..75d9e506aa 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -202,6 +202,7 @@ #include "code\controllers\subsystem\inbounds.dm" #include "code\controllers\subsystem\ipintel.dm" #include "code\controllers\subsystem\job.dm" +#include "code\controllers\subsystem\language.dm" #include "code\controllers\subsystem\lighting.dm" #include "code\controllers\subsystem\machines.dm" #include "code\controllers\subsystem\mapping.dm" @@ -1426,6 +1427,7 @@ #include "code\modules\language\draconic.dm" #include "code\modules\language\drone.dm" #include "code\modules\language\language.dm" +#include "code\modules\language\language_holder.dm" #include "code\modules\language\language_menu.dm" #include "code\modules\language\machine.dm" #include "code\modules\language\monkey.dm" diff --git a/tgstation.dme.rej b/tgstation.dme.rej new file mode 100644 index 0000000000..050e4d5029 --- /dev/null +++ b/tgstation.dme.rej @@ -0,0 +1,9 @@ +diff a/tgstation.dme b/tgstation.dme (rejected hunks) +@@ -1373,6 +1373,7 @@ + #include "code\modules\language\draconic.dm" + #include "code\modules\language\drone.dm" + #include "code\modules\language\language.dm" ++#include "code\modules\language\language_holder.dm" + #include "code\modules\language\language_menu.dm" + #include "code\modules\language\machine.dm" + #include "code\modules\language\monkey.dm" diff --git a/tgui/assets/tgui.css.rej b/tgui/assets/tgui.css.rej new file mode 100644 index 0000000000..a9dbe93889 --- /dev/null +++ b/tgui/assets/tgui.css.rej @@ -0,0 +1,6 @@ +diff a/tgui/assets/tgui.css b/tgui/assets/tgui.css (rejected hunks) +@@ -1 +1 @@ +-@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffb18b25",endColorstr="#ff5f380e",GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input::-webkit-input-placeholder{color:#999}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgNDI1IDIwMCIgb3BhY2l0eT0iLjMzIj4NCiAgPHBhdGggZD0ibSAxNzguMDAzOTksMC4wMzg2OSAtNzEuMjAzOTMsMCBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTYuNzYxMzQsNi4wMjU1NSBsIDAsMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM0LDYuMDI1NTQgbCA1My4xMDcyLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xMDEuNTQ0MDE4IDcyLjIxNjI4LDEwNC42OTkzOTggYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDUuNzYwMTUsMi44NzAxNiBsIDczLjU1NDg3LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIDYuNzYxMzUsLTYuMDI1NTQgbCAwLC0xODcuODcxNDcgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM1LC02LjAyNTU1IGwgLTU0LjcxNjQ0LDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTMzLDYuMDI1NTUgbCAwLDEwMi42MTkzNSBMIDE4My43NjQxMywyLjkwODg2IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNS43NjAxNCwtMi44NzAxNyB6IiAvPg0KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPg0KICA8cGF0aCBkPSJtIDQyMC4xNTUzNSwxNzcuODkxMTkgYSAxMy40MTIwMzgsMTIuNTAxODQyIDAgMCAxIC04LjYzMjk1LDIyLjA2OTUxIGwgLTY2LjExODMyLDAgYSA1LjM2NDgxNTIsNS4wMDA3MzcgMCAwIDEgLTUuMzY0ODIsLTUuMDAwNzQgbCAwLC03OS44NzkzMSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input::-webkit-input-placeholder{color:#999}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4wIiB2aWV3Qm94PSIwIDAgMjAwIDI4OS43NDIiIG9wYWNpdHk9Ii4zMyI+DQogIDxwYXRoIGQ9Im0gOTMuNTM3Njc3LDAgYyAtMTguMTEzMTI1LDAgLTM0LjIyMDEzMywzLjExMTY0IC00OC4zMjM0ODQsOS4zMzQzNyAtMTMuOTY1MDkyLDYuMjIxNjcgLTI0LjYxMjQ0MiwxNS4wNzExNCAtMzEuOTQwNjUxLDI2LjU0NzEgLTcuMTg5OTM5OCwxMS4zMzc4OSAtMTAuMzAxMjI2NiwyNC43NDkxMSAtMTAuMzAxMjI2Niw0MC4yMzQ3OCAwLDEwLjY0NjYyIDIuNzI1MDAyNiwyMC40NjQ2NSA4LjE3NTExMTYsMjkuNDUyNTggNS42MTUyNzcsOC45ODY4NiAxNC4wMzgyNzcsMTcuMzUyMDQgMjUuMjY4ODIxLDI1LjA5NDM2IDExLjIzMDU0NCw3LjYwNTMxIDI2LjUwNzQyMSwxNS40MTgzNSA0NS44MzA1MTQsMjMuNDM3ODIgMTkuOTgzNzQ4LDguMjk1NTcgMzQuODQ4ODQ4LDE1LjU1NDcxIDQ0LjU5Mjk5OCwyMS43NzYzOCA5Ljc0NDE0LDYuMjIyNzMgMTYuNzYxNywxMi44NTg1IDIxLjA1NTcyLDE5LjkwOTUxIDQuMjk0MDQsNy4wNTIwOCA2LjQ0MTkzLDE1Ljc2NDA4IDYuNDQxOTMsMjYuMTM0NTkgMCwxNi4xNzcwMiAtNS4yMDE5NiwyOC40ODIyMiAtMTUuNjA2NzMsMzYuOTE2ODIgLTEwLjIzOTYsOC40MzQ3IC0yNS4wMjIwMywxMi42NTIzIC00NC4zNDUxNjksMTIuNjUyMyAtMTQuMDM4MTcxLDAgLTI1LjUxNTI0NywtMS42NTk0IC0zNC40MzM2MTgsLTQuOTc3NyAtOC45MTgzNywtMy40NTY2IC0xNi4xODU1NzIsLTguNzExMyAtMjEuODAwODM5LC0xNS43NjMzIC01LjYxNTI3NywtNy4wNTIxIC0xMC4wNzQ3OTUsLTE2LjY2MDg4IC0xMy4zNzc4OTksLTI4LjgyODEyIGwgLTI0Ljc3MzE2MjYyOTM5NDUsMCAwLDU2LjgyNjMyIEMgMzMuODU2NzY5LDI4Ni4wNzYwMSA2My43NDkwNCwyODkuNzQyMDEgODkuNjc4MzgzLDI4OS43NDIwMSBjIDE2LjAyMDAyNywwIDMwLjcxOTc4NywtMS4zODI3IDQ0LjA5NzMzNywtNC4xNDc5IDEzLjU0MjcyLC0yLjkwNDMgMjUuMTA0MSwtNy40Njc2IDM0LjY4MzA5LC0xMy42ODkzIDkuNzQ0MTMsLTYuMzU5NyAxNy4zNDA0MiwtMTQuNTE5NSAyMi43OTA1MiwtMjQuNDc0OCA1LjQ1MDEsLTEwLjA5MzMyIDguMTc1MTEsLTIyLjM5OTU5IDguMTc1MTEsLTM2LjkxNjgyIDAsLTEyLjk5NzY0IC0zLjMwMjEsLTI0LjMzNTM5IC05LjkwODI5LC0zNC4wMTQ2IC02LjQ0MTA1LC05LjgxNzI1IC0xNS41MjU0NSwtMTguNTI3MDcgLTI3LjI1MTQ2LC0yNi4xMzEzMyAtMTEuNTYwODUsLTcuNjA0MjcgLTI3LjkxMDgzLC0xNS44MzE0MiAtNDkuMDUwNjYsLTI0LjY4MDIyIC0xNy41MDY0NCwtNy4xOTAxMiAtMzAuNzE5NjY4LC0xMy42ODk0OCAtMzkuNjM4MDM4LC0xOS40OTcwMSAtOC45MTgzNzEsLTUuODA3NTIgLTE4LjYwNzQ3NCwtMTIuNDM0MDkgLTI0LjA5NjUyNCwtMTguODc0MTcgLTUuNDI2MDQzLC02LjM2NjE2IC05LjY1ODgyNiwtMTUuMDcwMDMgLTkuNjU4ODI2LC0yNC44ODcyOSAwLC05LjI2NDAxIDIuMDc1NDE0LC0xNy4yMTM0NSA2LjIyMzQ1NCwtMjMuODUwMzMgMTEuMDk4Mjk4LC0xNC4zOTc0OCA0MS4yODY2MzgsLTEuNzk1MDcgNDUuMDc1NjA5LDI0LjM0NzYyIDQuODM5MzkyLDYuNzc0OTEgOC44NDkzNSwxNi4yNDcyOSAxMi4wMjk1MTUsMjguNDE1NiBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNC40NzgyNSwtNS45MjQ0OCAtOS45NTQ4OCwtMTAuNjMyMjIgLTE1LjkwODM3LC0xNC4zNzQxMSAxLjY0MDU1LDAuNDc5MDUgMy4xOTAzOSwxLjAyMzc2IDQuNjM4NjUsMS42NDAyNCA2LjQ5ODYxLDIuNjI2MDcgMTIuMTY3OTMsNy4zMjc0NyAxNy4wMDczLDE0LjEwMzQ1IDQuODM5MzksNi43NzQ5MSA4Ljg0OTM1LDE2LjI0NTY3IDEyLjAyOTUyLDI4LjQxMzk3IDAsMCA4LjQ4MTI4LC0wLjEyODk0IDguNDg5NzgsLTAuMDAyIDAuNDE3NzYsNi40MTQ5NCAtMS43NTMzOSw5LjQ1Mjg2IC00LjEyMzQyLDEyLjU2MTA0IC0yLjQxNzQsMy4xNjk3OCAtNS4xNDQ4Niw2Ljc4OTczIC00LjAwMjc4LDEzLjAwMjkgMS41MDc4Niw4LjIwMzE4IDEwLjE4MzU0LDEwLjU5NjQyIDE0LjYyMTk0LDkuMzExNTQgLTMuMzE4NDIsLTAuNDk5MTEgLTUuMzE4NTUsLTEuNzQ5NDggLTUuMzE4NTUsLTEuNzQ5NDggMCwwIDEuODc2NDYsMC45OTg2OCA1LjY1MTE3LC0xLjM1OTgxIC0zLjI3Njk1LDAuOTU1NzEgLTEwLjcwNTI5LC0wLjc5NzM4IC0xMS44MDEyNSwtNi43NjMxMyAtMC45NTc1MiwtNS4yMDg2MSAwLjk0NjU0LC03LjI5NTE0IDMuNDAxMTMsLTEwLjUxNDgyIDIuNDU0NjIsLTMuMjE5NjggNS4yODQyNiwtNi45NTgzMSA0LjY4NDMsLTE0LjQ4ODI0IGwgMC4wMDMsMC4wMDIgOC45MjY3NiwwIDAsLTU1Ljk5OTY3IGMgLTE1LjA3MTI1LC0zLjg3MTY4IC0yNy42NTMxNCwtNi4zNjA0MiAtMzcuNzQ2NzEsLTcuNDY1ODYgLTkuOTU1MzEsLTEuMTA3NTUgLTIwLjE4ODIzLC0xLjY1OTgxIC0zMC42OTY2MTMsLTEuNjU5ODEgeiBtIDcwLjMyMTYwMywxNy4zMDg5MyAwLjIzODA1LDQwLjMwNDkgYyAxLjMxODA4LDEuMjI2NjYgMi40Mzk2NSwyLjI3ODE1IDMuMzQwODEsMy4xMDYwMiA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNCwxNi4yNDU2NiAxMi4wMjk1MSwyOC40MTM5NyBsIDIwLjUzMjM0LDAgMCwtNTUuOTk5NjcgYyAtNi42NzczMSwtNC41OTM4MSAtMTkuODM2NDMsLTEwLjQ3MzA5IC0zNi4xNDA3MSwtMTUuODI1MjIgeiBtIC0yOC4xMjA0OSw1LjYwNTUxIDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzcsLTYuNDY2OTcgLTEzLjg0Njc4LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDUsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gMTUuMjIxOTUsMjQuMDA4NDggOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzOCwtNi40NjY5NyAtMTMuODQ2NzksLTkuNzE3MjYgLTguNTY0NzksLTE3LjcxNjU1IHogbSAyMi43OTcwNCwwIGMgMi43NzE1LDcuOTk5MjkgMS43ODc0MSwxMS4yNDk1OCAtNC40OTM1NCwxNy43MTY1NSBsIDQuNDkzNTQsLTE3LjcxNjU1IHogbSAtOTkuMTEzODQsMi4yMDc2NCA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM4MiwtNi40NjY5NyAtMTMuODQ2NzgyLC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk1NDIsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IiAvPg0KPC9zdmc+DQo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4NCjwhLS0gaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyAtLT4NCg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff750000",endColorstr="#ff340404",GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input::-webkit-input-placeholder{color:#999}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} +\ No newline at end of file ++@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff202020',GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffb18b25',endColorstr='#ff5f380e',GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-webkit-transform:translateX(-50%) translateY(-8px);-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-right:after{-webkit-transform:translateX(-8px) translateY(-50%);-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input::-webkit-input-placeholder{color:#999}body.clockwork input::-moz-placeholder{color:#999}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #5f380e;-webkit-transform:rotate(1turn);-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjAiIHZpZXdCb3g9IjAgMCA0MjUgMjAwIiBvcGFjaXR5PSIuMzMiPgogIDxwYXRoIGQ9Im0gMTc4LjAwMzk5LDAuMDM4NjkgLTcxLjIwMzkzLDAgYSA2Ljc2MTM0MjIsNi4wMjU1NDk1IDAgMCAwIC02Ljc2MTM0LDYuMDI1NTUgbCAwLDE4Ny44NzE0NyBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgNi43NjEzNCw2LjAyNTU0IGwgNTMuMTA3MiwwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM1LC02LjAyNTU0IGwgMCwtMTAxLjU0NDAxOCA3Mi4yMTYyOCwxMDQuNjk5Mzk4IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA1Ljc2MDE1LDIuODcwMTYgbCA3My41NTQ4NywwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCA2Ljc2MTM1LC02LjAyNTU0IGwgMCwtMTg3Ljg3MTQ3IGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNi43NjEzNSwtNi4wMjU1NSBsIC01NC43MTY0NCwwIGEgNi43NjEzNDIyLDYuMDI1NTQ5NSAwIDAgMCAtNi43NjEzMyw2LjAyNTU1IGwgMCwxMDIuNjE5MzUgTCAxODMuNzY0MTMsMi45MDg4NiBhIDYuNzYxMzQyMiw2LjAyNTU0OTUgMCAwIDAgLTUuNzYwMTQsLTIuODcwMTcgeiIgLz4KICA8cGF0aCBkPSJNIDQuODQ0NjMzMywyMi4xMDg3NSBBIDEzLjQxMjAzOSwxMi41MDE4NDIgMCAwIDEgMTMuNDc3NTg4LDAuMDM5MjQgbCA2Ni4xMTgzMTUsMCBhIDUuMzY0ODE1OCw1LjAwMDczNyAwIDAgMSA1LjM2NDgyMyw1LjAwMDczIGwgMCw3OS44NzkzMSB6IiAvPgogIDxwYXRoIGQ9Im0gNDIwLjE1NTM1LDE3Ny44OTExOSBhIDEzLjQxMjAzOCwxMi41MDE4NDIgMCAwIDEgLTguNjMyOTUsMjIuMDY5NTEgbCAtNjYuMTE4MzIsMCBhIDUuMzY0ODE1Miw1LjAwMDczNyAwIDAgMSAtNS4zNjQ4MiwtNS4wMDA3NCBsIDAsLTc5Ljg3OTMxIHoiIC8+Cjwvc3ZnPgo8IS0tIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiAtLT4KPCEtLSBodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvIC0tPgo=") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2a2a2a',endColorstr='#ff202020',GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-webkit-transform:translateX(-50%) translateY(-8px);-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:after{-webkit-transform:translateX(-8px) translateY(-50%);-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input::-webkit-input-placeholder{color:#999}body.nanotrasen input::-moz-placeholder{color:#999}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-webkit-transform:rotate(1turn);-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate{background:url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjAiIHZpZXdCb3g9IjAgMCAyMDAgMjg5Ljc0MiIgb3BhY2l0eT0iLjMzIj4KICA8cGF0aCBkPSJtIDkzLjUzNzY3NywwIGMgLTE4LjExMzEyNSwwIC0zNC4yMjAxMzMsMy4xMTE2NCAtNDguMzIzNDg0LDkuMzM0MzcgLTEzLjk2NTA5Miw2LjIyMTY3IC0yNC42MTI0NDIsMTUuMDcxMTQgLTMxLjk0MDY1MSwyNi41NDcxIC03LjE4OTkzOTgsMTEuMzM3ODkgLTEwLjMwMTIyNjYsMjQuNzQ5MTEgLTEwLjMwMTIyNjYsNDAuMjM0NzggMCwxMC42NDY2MiAyLjcyNTAwMjYsMjAuNDY0NjUgOC4xNzUxMTE2LDI5LjQ1MjU4IDUuNjE1Mjc3LDguOTg2ODYgMTQuMDM4Mjc3LDE3LjM1MjA0IDI1LjI2ODgyMSwyNS4wOTQzNiAxMS4yMzA1NDQsNy42MDUzMSAyNi41MDc0MjEsMTUuNDE4MzUgNDUuODMwNTE0LDIzLjQzNzgyIDE5Ljk4Mzc0OCw4LjI5NTU3IDM0Ljg0ODg0OCwxNS41NTQ3MSA0NC41OTI5OTgsMjEuNzc2MzggOS43NDQxNCw2LjIyMjczIDE2Ljc2MTcsMTIuODU4NSAyMS4wNTU3MiwxOS45MDk1MSA0LjI5NDA0LDcuMDUyMDggNi40NDE5MywxNS43NjQwOCA2LjQ0MTkzLDI2LjEzNDU5IDAsMTYuMTc3MDIgLTUuMjAxOTYsMjguNDgyMjIgLTE1LjYwNjczLDM2LjkxNjgyIC0xMC4yMzk2LDguNDM0NyAtMjUuMDIyMDMsMTIuNjUyMyAtNDQuMzQ1MTY5LDEyLjY1MjMgLTE0LjAzODE3MSwwIC0yNS41MTUyNDcsLTEuNjU5NCAtMzQuNDMzNjE4LC00Ljk3NzcgLTguOTE4MzcsLTMuNDU2NiAtMTYuMTg1NTcyLC04LjcxMTMgLTIxLjgwMDgzOSwtMTUuNzYzMyAtNS42MTUyNzcsLTcuMDUyMSAtMTAuMDc0Nzk1LC0xNi42NjA4OCAtMTMuMzc3ODk5LC0yOC44MjgxMiBsIC0yNC43NzMxNjI2MjkzOTQ1LDAgMCw1Ni44MjYzMiBDIDMzLjg1Njc2OSwyODYuMDc2MDEgNjMuNzQ5MDQsMjg5Ljc0MjAxIDg5LjY3ODM4MywyODkuNzQyMDEgYyAxNi4wMjAwMjcsMCAzMC43MTk3ODcsLTEuMzgyNyA0NC4wOTczMzcsLTQuMTQ3OSAxMy41NDI3MiwtMi45MDQzIDI1LjEwNDEsLTcuNDY3NiAzNC42ODMwOSwtMTMuNjg5MyA5Ljc0NDEzLC02LjM1OTcgMTcuMzQwNDIsLTE0LjUxOTUgMjIuNzkwNTIsLTI0LjQ3NDggNS40NTAxLC0xMC4wOTMzMiA4LjE3NTExLC0yMi4zOTk1OSA4LjE3NTExLC0zNi45MTY4MiAwLC0xMi45OTc2NCAtMy4zMDIxLC0yNC4zMzUzOSAtOS45MDgyOSwtMzQuMDE0NiAtNi40NDEwNSwtOS44MTcyNSAtMTUuNTI1NDUsLTE4LjUyNzA3IC0yNy4yNTE0NiwtMjYuMTMxMzMgLTExLjU2MDg1LC03LjYwNDI3IC0yNy45MTA4MywtMTUuODMxNDIgLTQ5LjA1MDY2LC0yNC42ODAyMiAtMTcuNTA2NDQsLTcuMTkwMTIgLTMwLjcxOTY2OCwtMTMuNjg5NDggLTM5LjYzODAzOCwtMTkuNDk3MDEgLTguOTE4MzcxLC01LjgwNzUyIC0xOC42MDc0NzQsLTEyLjQzNDA5IC0yNC4wOTY1MjQsLTE4Ljg3NDE3IC01LjQyNjA0MywtNi4zNjYxNiAtOS42NTg4MjYsLTE1LjA3MDAzIC05LjY1ODgyNiwtMjQuODg3MjkgMCwtOS4yNjQwMSAyLjA3NTQxNCwtMTcuMjEzNDUgNi4yMjM0NTQsLTIzLjg1MDMzIDExLjA5ODI5OCwtMTQuMzk3NDggNDEuMjg2NjM4LC0xLjc5NTA3IDQ1LjA3NTYwOSwyNC4zNDc2MiA0LjgzOTM5Miw2Ljc3NDkxIDguODQ5MzUsMTYuMjQ3MjkgMTIuMDI5NTE1LDI4LjQxNTYgbCAyMC41MzIzNCwwIDAsLTU1Ljk5OTY3IGMgLTQuNDc4MjUsLTUuOTI0NDggLTkuOTU0ODgsLTEwLjYzMjIyIC0xNS45MDgzNywtMTQuMzc0MTEgMS42NDA1NSwwLjQ3OTA1IDMuMTkwMzksMS4wMjM3NiA0LjYzODY1LDEuNjQwMjQgNi40OTg2MSwyLjYyNjA3IDEyLjE2NzkzLDcuMzI3NDcgMTcuMDA3MywxNC4xMDM0NSA0LjgzOTM5LDYuNzc0OTEgOC44NDkzNSwxNi4yNDU2NyAxMi4wMjk1MiwyOC40MTM5NyAwLDAgOC40ODEyOCwtMC4xMjg5NCA4LjQ4OTc4LC0wLjAwMiAwLjQxNzc2LDYuNDE0OTQgLTEuNzUzMzksOS40NTI4NiAtNC4xMjM0MiwxMi41NjEwNCAtMi40MTc0LDMuMTY5NzggLTUuMTQ0ODYsNi43ODk3MyAtNC4wMDI3OCwxMy4wMDI5IDEuNTA3ODYsOC4yMDMxOCAxMC4xODM1NCwxMC41OTY0MiAxNC42MjE5NCw5LjMxMTU0IC0zLjMxODQyLC0wLjQ5OTExIC01LjMxODU1LC0xLjc0OTQ4IC01LjMxODU1LC0xLjc0OTQ4IDAsMCAxLjg3NjQ2LDAuOTk4NjggNS42NTExNywtMS4zNTk4MSAtMy4yNzY5NSwwLjk1NTcxIC0xMC43MDUyOSwtMC43OTczOCAtMTEuODAxMjUsLTYuNzYzMTMgLTAuOTU3NTIsLTUuMjA4NjEgMC45NDY1NCwtNy4yOTUxNCAzLjQwMTEzLC0xMC41MTQ4MiAyLjQ1NDYyLC0zLjIxOTY4IDUuMjg0MjYsLTYuOTU4MzEgNC42ODQzLC0xNC40ODgyNCBsIDAuMDAzLDAuMDAyIDguOTI2NzYsMCAwLC01NS45OTk2NyBjIC0xNS4wNzEyNSwtMy44NzE2OCAtMjcuNjUzMTQsLTYuMzYwNDIgLTM3Ljc0NjcxLC03LjQ2NTg2IC05Ljk1NTMxLC0xLjEwNzU1IC0yMC4xODgyMywtMS42NTk4MSAtMzAuNjk2NjEzLC0xLjY1OTgxIHogbSA3MC4zMjE2MDMsMTcuMzA4OTMgMC4yMzgwNSw0MC4zMDQ5IGMgMS4zMTgwOCwxLjIyNjY2IDIuNDM5NjUsMi4yNzgxNSAzLjM0MDgxLDMuMTA2MDIgNC44MzkzOSw2Ljc3NDkxIDguODQ5MzQsMTYuMjQ1NjYgMTIuMDI5NTEsMjguNDEzOTcgbCAyMC41MzIzNCwwIDAsLTU1Ljk5OTY3IGMgLTYuNjc3MzEsLTQuNTkzODEgLTE5LjgzNjQzLC0xMC40NzMwOSAtMzYuMTQwNzEsLTE1LjgyNTIyIHogbSAtMjguMTIwNDksNS42MDU1MSA4LjU2NDc5LDE3LjcxNjU1IGMgLTExLjk3MDM3LC02LjQ2Njk3IC0xMy44NDY3OCwtOS43MTcyNiAtOC41NjQ3OSwtMTcuNzE2NTUgeiBtIDIyLjc5NzA1LDAgYyAyLjc3MTUsNy45OTkyOSAxLjc4NzQxLDExLjI0OTU4IC00LjQ5MzU0LDE3LjcxNjU1IGwgNC40OTM1NCwtMTcuNzE2NTUgeiBtIDE1LjIyMTk1LDI0LjAwODQ4IDguNTY0NzksMTcuNzE2NTUgYyAtMTEuOTcwMzgsLTYuNDY2OTcgLTEzLjg0Njc5LC05LjcxNzI2IC04LjU2NDc5LC0xNy43MTY1NSB6IG0gMjIuNzk3MDQsMCBjIDIuNzcxNSw3Ljk5OTI5IDEuNzg3NDEsMTEuMjQ5NTggLTQuNDkzNTQsMTcuNzE2NTUgbCA0LjQ5MzU0LC0xNy43MTY1NSB6IG0gLTk5LjExMzg0LDIuMjA3NjQgOC41NjQ3OSwxNy43MTY1NSBjIC0xMS45NzAzODIsLTYuNDY2OTcgLTEzLjg0Njc4MiwtOS43MTcyNiAtOC41NjQ3OSwtMTcuNzE2NTUgeiBtIDIyLjc5NTQyLDAgYyAyLjc3MTUsNy45OTkyOSAxLjc4NzQxLDExLjI0OTU4IC00LjQ5MzU0LDE3LjcxNjU1IGwgNC40OTM1NCwtMTcuNzE2NTUgeiIgLz4KPC9zdmc+CjwhLS0gVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIC0tPgo8IS0tIGh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8gLS0+Cg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff750000',endColorstr='#ff340404',GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden;opacity:0;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{visibility:visible;opacity:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-webkit-transform:translateX(-50%) translateY(-8px);-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-webkit-transform:translateX(-50%) translateY(8px);-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-right:after{-webkit-transform:translateX(-8px) translateY(-50%);-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-webkit-transform:translateX(8px) translateY(-50%);-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input::-webkit-input-placeholder{color:#999}body.syndicate input::-moz-placeholder{color:#999}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-style:solid;border-width:0 0 45px 45px;border-color:transparent transparent #363636;-webkit-transform:rotate(1turn);-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(even){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}.no-icons header.titlebar .statusicon{font-size:20px}.no-icons header.titlebar .statusicon:after{content:"O"}.no-icons header.titlebar .minimize{top:-2px;font-size:20px}.no-icons header.titlebar .minimize:after{content:"—"}.no-icons header.titlebar .close{font-size:20px}.no-icons header.titlebar .close:after{content:"X"} +\ No newline at end of file diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index 129d3e1eb8..9149710c78 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,16 +1,18 @@ -require=function t(e,n,a){function r(o,s){if(!n[o]){if(!e[o]){var p="function"==typeof require&&require;if(!s&&p)return p(o,!0);if(i)return i(o,!0);var u=Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[o]={exports:{}};e[o][0].call(c.exports,function(t){var n=e[o][1][t];return r(n?n:t)},c,c.exports,t,e,n,a)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o2?u[2]:void 0,l=Math.min((void 0===c?o:r(c,o))-p,o-s),f=1;for(s>p&&p+l>s&&(f=-1,p+=l-1,s+=l-1);l-- >0;)p in n?n[s]=n[p]:delete n[s],s+=f,p+=f;return n}},{76:76,79:79,80:80}],6:[function(t,e,n){"use strict";var a=t(80),r=t(76),i=t(79);e.exports=[].fill||function(t){for(var e=a(this),n=i(e.length),o=arguments,s=o.length,p=r(s>1?o[1]:void 0,n),u=s>2?o[2]:void 0,c=void 0===u?n:r(u,n);c>p;)e[p++]=t;return e}},{76:76,79:79,80:80}],7:[function(t,e,n){var a=t(78),r=t(79),i=t(76);e.exports=function(t){return function(e,n,o){var s,p=a(e),u=r(p.length),c=i(o,u);if(t&&n!=n){for(;u>c;)if(s=p[c++],s!=s)return!0}else for(;u>c;c++)if((t||c in p)&&p[c]===n)return t||c;return!t&&-1}}},{76:76,78:78,79:79}],8:[function(t,e,n){var a=t(17),r=t(34),i=t(80),o=t(79),s=t(9);e.exports=function(t){var e=1==t,n=2==t,p=3==t,u=4==t,c=6==t,l=5==t||c;return function(f,d,h){for(var m,v,g=i(f),b=r(g),y=a(d,h,3),_=o(b.length),x=0,w=e?s(f,_):n?s(f,0):void 0;_>x;x++)if((l||x in b)&&(m=b[x],v=y(m,x,g),t))if(e)w[x]=v;else if(v)switch(t){case 3:return!0;case 5:return m;case 6:return x;case 2:w.push(m)}else if(u)return!1;return c?-1:p||u?u:w}}},{17:17,34:34,79:79,80:80,9:9}],9:[function(t,e,n){var a=t(38),r=t(36),i=t(83)("species");e.exports=function(t,e){var n;return r(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!r(n.prototype)||(n=void 0),a(n)&&(n=n[i],null===n&&(n=void 0))),new(void 0===n?Array:n)(e)}},{36:36,38:38,83:83}],10:[function(t,e,n){var a=t(11),r=t(83)("toStringTag"),i="Arguments"==a(function(){return arguments}());e.exports=function(t){var e,n,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=(e=Object(t))[r])?n:i?a(e):"Object"==(o=a(e))&&"function"==typeof e.callee?"Arguments":o}},{11:11,83:83}],11:[function(t,e,n){var a={}.toString;e.exports=function(t){return a.call(t).slice(8,-1)}},{}],12:[function(t,e,n){"use strict";var a=t(46),r=t(31),i=t(60),o=t(17),s=t(69),p=t(18),u=t(27),c=t(42),l=t(44),f=t(82)("id"),d=t(30),h=t(38),m=t(65),v=t(19),g=Object.isExtensible||h,b=v?"_s":"size",y=0,_=function(t,e){if(!h(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!d(t,f)){if(!g(t))return"F";if(!e)return"E";r(t,f,++y)}return"O"+t[f]},x=function(t,e){var n,a=_(e);if("F"!==a)return t._i[a];for(n=t._f;n;n=n.n)if(n.k==e)return n};e.exports={getConstructor:function(t,e,n,r){var c=t(function(t,i){s(t,c,e),t._i=a.create(null),t._f=void 0,t._l=void 0,t[b]=0,void 0!=i&&u(i,n,t[r],t)});return i(c.prototype,{clear:function(){for(var t=this,e=t._i,n=t._f;n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete e[n.i];t._f=t._l=void 0,t[b]=0},"delete":function(t){var e=this,n=x(e,t);if(n){var a=n.n,r=n.p;delete e._i[n.i],n.r=!0,r&&(r.n=a),a&&(a.p=r),e._f==n&&(e._f=a),e._l==n&&(e._l=r),e[b]--}return!!n},forEach:function(t){for(var e,n=o(t,arguments.length>1?arguments[1]:void 0,3);e=e?e.n:this._f;)for(n(e.v,e.k,this);e&&e.r;)e=e.p},has:function(t){return!!x(this,t)}}),v&&a.setDesc(c.prototype,"size",{get:function(){return p(this[b])}}),c},def:function(t,e,n){var a,r,i=x(t,e);return i?i.v=n:(t._l=i={i:r=_(e,!0),k:e,v:n,p:a=t._l,n:void 0,r:!1},t._f||(t._f=i),a&&(a.n=i),t[b]++,"F"!==r&&(t._i[r]=i)),t},getEntry:x,setStrong:function(t,e,n){c(t,e,function(t,e){this._t=t,this._k=e,this._l=void 0},function(){for(var t=this,e=t._k,n=t._l;n&&n.r;)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?"keys"==e?l(0,n.k):"values"==e?l(0,n.v):l(0,[n.k,n.v]):(t._t=void 0,l(1))},n?"entries":"values",!n,!0),m(e)}}},{17:17,18:18,19:19,27:27,30:30,31:31,38:38,42:42,44:44,46:46,60:60,65:65,69:69,82:82}],13:[function(t,e,n){var a=t(27),r=t(10);e.exports=function(t){return function(){if(r(this)!=t)throw TypeError(t+"#toJSON isn't generic");var e=[];return a(this,!1,e.push,e),e}}},{10:10,27:27}],14:[function(t,e,n){"use strict";var a=t(31),r=t(60),i=t(4),o=t(38),s=t(69),p=t(27),u=t(8),c=t(30),l=t(82)("weak"),f=Object.isExtensible||o,d=u(5),h=u(6),m=0,v=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},b=function(t,e){return d(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=b(this,t);return e?e[1]:void 0},has:function(t){return!!b(this,t)},set:function(t,e){var n=b(this,t);n?n[1]=e:this.a.push([t,e])},"delete":function(t){var e=h(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},e.exports={getConstructor:function(t,e,n,a){var i=t(function(t,r){s(t,i,e),t._i=m++,t._l=void 0,void 0!=r&&p(r,n,t[a],t)});return r(i.prototype,{"delete":function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i)&&delete t[l][this._i]:v(this)["delete"](t):!1},has:function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i):v(this).has(t):!1}}),i},def:function(t,e,n){return f(i(e))?(c(e,l)||a(e,l,{}),e[l][t._i]=n):v(t).set(e,n),t},frozenStore:v,WEAK:l}},{27:27,30:30,31:31,38:38,4:4,60:60,69:69,8:8,82:82}],15:[function(t,e,n){"use strict";var a=t(29),r=t(22),i=t(61),o=t(60),s=t(27),p=t(69),u=t(38),c=t(24),l=t(43),f=t(66);e.exports=function(t,e,n,d,h,m){var v=a[t],g=v,b=h?"set":"add",y=g&&g.prototype,_={},x=function(t){var e=y[t];i(y,t,"delete"==t?function(t){return m&&!u(t)?!1:e.call(this,0===t?0:t)}:"has"==t?function(t){return m&&!u(t)?!1:e.call(this,0===t?0:t)}:"get"==t?function(t){return m&&!u(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof g&&(m||y.forEach&&!c(function(){(new g).entries().next()}))){var w,k=new g,C=k[b](m?{}:-0,1)!=k,P=c(function(){k.has(1)}),E=l(function(t){new g(t)});E||(g=e(function(e,n){p(e,g,t);var a=new v;return void 0!=n&&s(n,h,a[b],a),a}),g.prototype=y,y.constructor=g),m||k.forEach(function(t,e){w=1/e===-(1/0)}),(P||w)&&(x("delete"),x("has"),h&&x("get")),(w||C)&&x(b),m&&y.clear&&delete y.clear}else g=d.getConstructor(e,t,h,b),o(g.prototype,n);return f(g,t),_[t]=g,r(r.G+r.W+r.F*(g!=v),_),m||d.setStrong(g,t,h),g}},{22:22,24:24,27:27,29:29,38:38,43:43,60:60,61:61,66:66,69:69}],16:[function(t,e,n){var a=e.exports={version:"1.2.6"};"number"==typeof __e&&(__e=a)},{}],17:[function(t,e,n){var a=t(2);e.exports=function(t,e,n){if(a(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,a){return t.call(e,n,a)};case 3:return function(n,a,r){return t.call(e,n,a,r)}}return function(){return t.apply(e,arguments)}}},{2:2}],18:[function(t,e,n){e.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],19:[function(t,e,n){e.exports=!t(24)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{24:24}],20:[function(t,e,n){var a=t(38),r=t(29).document,i=a(r)&&a(r.createElement);e.exports=function(t){return i?r.createElement(t):{}}},{29:29,38:38}],21:[function(t,e,n){var a=t(46);e.exports=function(t){var e=a.getKeys(t),n=a.getSymbols;if(n)for(var r,i=n(t),o=a.isEnum,s=0;i.length>s;)o.call(t,r=i[s++])&&e.push(r);return e}},{46:46}],22:[function(t,e,n){var a=t(29),r=t(16),i=t(31),o=t(61),s=t(17),p="prototype",u=function(t,e,n){var c,l,f,d,h=t&u.F,m=t&u.G,v=t&u.S,g=t&u.P,b=t&u.B,y=m?a:v?a[e]||(a[e]={}):(a[e]||{})[p],_=m?r:r[e]||(r[e]={}),x=_[p]||(_[p]={});m&&(n=e);for(c in n)l=!h&&y&&c in y,f=(l?y:n)[c],d=b&&l?s(f,a):g&&"function"==typeof f?s(Function.call,f):f,y&&!l&&o(y,c,f),_[c]!=f&&i(_,c,d),g&&x[c]!=f&&(x[c]=f)};a.core=r,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,e.exports=u},{16:16,17:17,29:29,31:31,61:61}],23:[function(t,e,n){var a=t(83)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[a]=!1,!"/./"[t](e)}catch(r){}}return!0}},{83:83}],24:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],25:[function(t,e,n){"use strict";var a=t(31),r=t(61),i=t(24),o=t(18),s=t(83);e.exports=function(t,e,n){var p=s(t),u=""[t];i(function(){var e={};return e[p]=function(){return 7},7!=""[t](e)})&&(r(String.prototype,t,n(o,p,u)),a(RegExp.prototype,p,2==e?function(t,e){return u.call(t,this,e)}:function(t){return u.call(t,this)}))}},{18:18,24:24,31:31,61:61,83:83}],26:[function(t,e,n){"use strict";var a=t(4);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{4:4}],27:[function(t,e,n){var a=t(17),r=t(40),i=t(35),o=t(4),s=t(79),p=t(84);e.exports=function(t,e,n,u){var c,l,f,d=p(t),h=a(n,u,e?2:1),m=0;if("function"!=typeof d)throw TypeError(t+" is not iterable!");if(i(d))for(c=s(t.length);c>m;m++)e?h(o(l=t[m])[0],l[1]):h(t[m]);else for(f=d.call(t);!(l=f.next()).done;)r(f,h,l.value,e)}},{17:17,35:35,4:4,40:40,79:79,84:84}],28:[function(t,e,n){var a=t(78),r=t(46).getNames,i={}.toString,o="object"==typeof window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return r(t)}catch(e){return o.slice()}};e.exports.get=function(t){return o&&"[object Window]"==i.call(t)?s(t):r(a(t))}},{46:46,78:78}],29:[function(t,e,n){var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},{}],30:[function(t,e,n){var a={}.hasOwnProperty;e.exports=function(t,e){return a.call(t,e)}},{}],31:[function(t,e,n){var a=t(46),r=t(59);e.exports=t(19)?function(t,e,n){return a.setDesc(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},{19:19,46:46,59:59}],32:[function(t,e,n){e.exports=t(29).document&&document.documentElement},{29:29}],33:[function(t,e,n){e.exports=function(t,e,n){var a=void 0===n;switch(e.length){case 0:return a?t():t.call(n);case 1:return a?t(e[0]):t.call(n,e[0]);case 2:return a?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return a?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return a?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},{}],34:[function(t,e,n){var a=t(11);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==a(t)?t.split(""):Object(t)}},{11:11}],35:[function(t,e,n){var a=t(45),r=t(83)("iterator"),i=Array.prototype;e.exports=function(t){return void 0!==t&&(a.Array===t||i[r]===t)}},{45:45,83:83}],36:[function(t,e,n){var a=t(11);e.exports=Array.isArray||function(t){return"Array"==a(t)}},{11:11}],37:[function(t,e,n){var a=t(38),r=Math.floor;e.exports=function(t){return!a(t)&&isFinite(t)&&r(t)===t}},{38:38}],38:[function(t,e,n){e.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],39:[function(t,e,n){var a=t(38),r=t(11),i=t(83)("match");e.exports=function(t){var e;return a(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==r(t))}},{11:11,38:38,83:83}],40:[function(t,e,n){var a=t(4);e.exports=function(t,e,n,r){try{return r?e(a(n)[0],n[1]):e(n)}catch(i){var o=t["return"];throw void 0!==o&&a(o.call(t)),i}}},{4:4}],41:[function(t,e,n){"use strict";var a=t(46),r=t(59),i=t(66),o={};t(31)(o,t(83)("iterator"),function(){return this}),e.exports=function(t,e,n){t.prototype=a.create(o,{next:r(1,n)}),i(t,e+" Iterator")}},{31:31,46:46,59:59,66:66,83:83}],42:[function(t,e,n){"use strict";var a=t(48),r=t(22),i=t(61),o=t(31),s=t(30),p=t(45),u=t(41),c=t(66),l=t(46).getProto,f=t(83)("iterator"),d=!([].keys&&"next"in[].keys()),h="@@iterator",m="keys",v="values",g=function(){return this};e.exports=function(t,e,n,b,y,_,x){u(n,e,b);var w,k,C=function(t){if(!d&&t in A)return A[t];switch(t){case m:return function(){return new n(this,t)};case v:return function(){return new n(this,t)}}return function(){return new n(this,t)}},P=e+" Iterator",E=y==v,S=!1,A=t.prototype,O=A[f]||A[h]||y&&A[y],T=O||C(y);if(O){var M=l(T.call(new t));c(M,P,!0),!a&&s(A,h)&&o(M,f,g),E&&O.name!==v&&(S=!0,T=function(){return O.call(this)})}if(a&&!x||!d&&!S&&A[f]||o(A,f,T),p[e]=T,p[P]=g,y)if(w={values:E?T:C(v),keys:_?T:C(m),entries:E?C("entries"):T},x)for(k in w)k in A||i(A,k,w[k]);else r(r.P+r.F*(d||S),e,w);return w}},{22:22,30:30,31:31,41:41,45:45,46:46,48:48,61:61,66:66,83:83}],43:[function(t,e,n){var a=t(83)("iterator"),r=!1;try{var i=[7][a]();i["return"]=function(){r=!0},Array.from(i,function(){throw 2})}catch(o){}e.exports=function(t,e){if(!e&&!r)return!1;var n=!1;try{var i=[7],o=i[a]();o.next=function(){return{done:n=!0}},i[a]=function(){return o},t(i)}catch(s){}return n}},{83:83}],44:[function(t,e,n){e.exports=function(t,e){return{value:e,done:!!t}}},{}],45:[function(t,e,n){e.exports={}},{}],46:[function(t,e,n){var a=Object;e.exports={create:a.create,getProto:a.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:a.getOwnPropertyDescriptor,setDesc:a.defineProperty,setDescs:a.defineProperties,getKeys:a.keys,getNames:a.getOwnPropertyNames,getSymbols:a.getOwnPropertySymbols,each:[].forEach}},{}],47:[function(t,e,n){var a=t(46),r=t(78);e.exports=function(t,e){for(var n,i=r(t),o=a.getKeys(i),s=o.length,p=0;s>p;)if(i[n=o[p++]]===e)return n}},{46:46,78:78}],48:[function(t,e,n){e.exports=!1},{}],49:[function(t,e,n){e.exports=Math.expm1||function(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:Math.exp(t)-1}},{}],50:[function(t,e,n){e.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:Math.log(1+t)}},{}],51:[function(t,e,n){e.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1}},{}],52:[function(t,e,n){var a,r,i,o=t(29),s=t(75).set,p=o.MutationObserver||o.WebKitMutationObserver,u=o.process,c=o.Promise,l="process"==t(11)(u),f=function(){var t,e,n;for(l&&(t=u.domain)&&(u.domain=null,t.exit());a;)e=a.domain,n=a.fn,e&&e.enter(),n(),e&&e.exit(),a=a.next;r=void 0,t&&t.enter()};if(l)i=function(){u.nextTick(f)};else if(p){var d=1,h=document.createTextNode("");new p(f).observe(h,{characterData:!0}),i=function(){h.data=d=-d}}else i=c&&c.resolve?function(){c.resolve().then(f)}:function(){s.call(o,f)};e.exports=function(t){var e={fn:t,next:void 0,domain:l&&u.domain};r&&(r.next=e),a||(a=e,i()),r=e}},{11:11,29:29,75:75}],53:[function(t,e,n){var a=t(46),r=t(80),i=t(34);e.exports=t(24)(function(){var t=Object.assign,e={},n={},a=Symbol(),r="abcdefghijklmnopqrst";return e[a]=7,r.split("").forEach(function(t){n[t]=t}),7!=t({},e)[a]||Object.keys(t({},n)).join("")!=r})?function(t,e){for(var n=r(t),o=arguments,s=o.length,p=1,u=a.getKeys,c=a.getSymbols,l=a.isEnum;s>p;)for(var f,d=i(o[p++]),h=c?u(d).concat(c(d)):u(d),m=h.length,v=0;m>v;)l.call(d,f=h[v++])&&(n[f]=d[f]);return n}:Object.assign},{24:24,34:34,46:46,80:80}],54:[function(t,e,n){var a=t(22),r=t(16),i=t(24);e.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],o={};o[t]=e(n),a(a.S+a.F*i(function(){n(1)}),"Object",o)}},{16:16,22:22,24:24}],55:[function(t,e,n){var a=t(46),r=t(78),i=a.isEnum;e.exports=function(t){return function(e){for(var n,o=r(e),s=a.getKeys(o),p=s.length,u=0,c=[];p>u;)i.call(o,n=s[u++])&&c.push(t?[n,o[n]]:o[n]);return c}}},{46:46,78:78}],56:[function(t,e,n){var a=t(46),r=t(4),i=t(29).Reflect;e.exports=i&&i.ownKeys||function(t){var e=a.getNames(r(t)),n=a.getSymbols;return n?e.concat(n(t)):e}},{29:29,4:4,46:46}],57:[function(t,e,n){"use strict";var a=t(58),r=t(33),i=t(2);e.exports=function(){for(var t=i(this),e=arguments.length,n=Array(e),o=0,s=a._,p=!1;e>o;)(n[o]=arguments[o++])===s&&(p=!0);return function(){var a,i=this,o=arguments,u=o.length,c=0,l=0;if(!p&&!u)return r(t,n,i);if(a=n.slice(),p)for(;e>c;c++)a[c]===s&&(a[c]=o[l++]);for(;u>l;)a.push(o[l++]);return r(t,a,i)}}},{2:2,33:33,58:58}],58:[function(t,e,n){e.exports=t(29)},{29:29}],59:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],60:[function(t,e,n){var a=t(61);e.exports=function(t,e){for(var n in e)a(t,n,e[n]);return t}},{61:61}],61:[function(t,e,n){var a=t(29),r=t(31),i=t(82)("src"),o="toString",s=Function[o],p=(""+s).split(o);t(16).inspectSource=function(t){return s.call(t)},(e.exports=function(t,e,n,o){"function"==typeof n&&(n.hasOwnProperty(i)||r(n,i,t[e]?""+t[e]:p.join(e+"")),n.hasOwnProperty("name")||r(n,"name",e)),t===a?t[e]=n:(o||delete t[e],r(t,e,n))})(Function.prototype,o,function(){return"function"==typeof this&&this[i]||s.call(this)})},{16:16,29:29,31:31,82:82}],62:[function(t,e,n){e.exports=function(t,e){var n=e===Object(e)?function(t){return e[t]}:e;return function(e){return(e+"").replace(t,n)}}},{}],63:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}},{}],64:[function(t,e,n){var a=t(46).getDesc,r=t(38),i=t(4),o=function(t,e){if(i(t),!r(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,r){try{r=t(17)(Function.call,a(Object.prototype,"__proto__").set,2),r(e,[]),n=!(e instanceof Array)}catch(i){n=!0}return function(t,e){return o(t,e),n?t.__proto__=e:r(t,e),t}}({},!1):void 0),check:o}},{17:17,38:38,4:4,46:46}],65:[function(t,e,n){"use strict";var a=t(29),r=t(46),i=t(19),o=t(83)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.setDesc(e,o,{configurable:!0,get:function(){return this}})}},{19:19,29:29,46:46,83:83}],66:[function(t,e,n){var a=t(46).setDesc,r=t(30),i=t(83)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{30:30,46:46,83:83}],67:[function(t,e,n){var a=t(29),r="__core-js_shared__",i=a[r]||(a[r]={});e.exports=function(t){return i[t]||(i[t]={})}},{29:29}],68:[function(t,e,n){var a=t(4),r=t(2),i=t(83)("species");e.exports=function(t,e){var n,o=a(t).constructor;return void 0===o||void 0==(n=a(o)[i])?e:r(n)}},{2:2,4:4,83:83}],69:[function(t,e,n){e.exports=function(t,e,n){if(!(t instanceof e))throw TypeError(n+": use the 'new' operator!");return t}},{}],70:[function(t,e,n){var a=t(77),r=t(18);e.exports=function(t){return function(e,n){var i,o,s=r(e)+"",p=a(n),u=s.length;return 0>p||p>=u?t?"":void 0:(i=s.charCodeAt(p),55296>i||i>56319||p+1===u||(o=s.charCodeAt(p+1))<56320||o>57343?t?s.charAt(p):i:t?s.slice(p,p+2):(i-55296<<10)+(o-56320)+65536)}}},{18:18,77:77}],71:[function(t,e,n){var a=t(39),r=t(18);e.exports=function(t,e,n){if(a(e))throw TypeError("String#"+n+" doesn't accept regex!");return r(t)+""}},{18:18,39:39}],72:[function(t,e,n){var a=t(79),r=t(73),i=t(18);e.exports=function(t,e,n,o){var s=i(t)+"",p=s.length,u=void 0===n?" ":n+"",c=a(e);if(p>=c)return s;""==u&&(u=" ");var l=c-p,f=r.call(u,Math.ceil(l/u.length));return f.length>l&&(f=f.slice(0,l)),o?f+s:s+f}},{18:18,73:73,79:79}],73:[function(t,e,n){"use strict";var a=t(77),r=t(18);e.exports=function(t){var e=r(this)+"",n="",i=a(t);if(0>i||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},{18:18,77:77}],74:[function(t,e,n){var a=t(22),r=t(18),i=t(24),o=" \n\x0B\f\r   ᠎              \u2028\u2029\ufeff",s="["+o+"]",p="​…",u=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(t,e){var n={};n[t]=e(f),a(a.P+a.F*i(function(){return!!o[t]()||p[t]()!=p}),"String",n)},f=l.trim=function(t,e){return t=r(t)+"",1&e&&(t=t.replace(u,"")),2&e&&(t=t.replace(c,"")),t};e.exports=l},{18:18,22:22,24:24}],75:[function(t,e,n){var a,r,i,o=t(17),s=t(33),p=t(32),u=t(20),c=t(29),l=c.process,f=c.setImmediate,d=c.clearImmediate,h=c.MessageChannel,m=0,v={},g="onreadystatechange",b=function(){var t=+this;if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},y=function(t){b.call(t.data)};f&&d||(f=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return v[++m]=function(){s("function"==typeof t?t:Function(t),e)},a(m),m},d=function(t){delete v[t]},"process"==t(11)(l)?a=function(t){l.nextTick(o(b,t,1))}:h?(r=new h,i=r.port2,r.port1.onmessage=y,a=o(i.postMessage,i,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(a=function(t){c.postMessage(t+"","*")},c.addEventListener("message",y,!1)):a=g in u("script")?function(t){p.appendChild(u("script"))[g]=function(){p.removeChild(this),b.call(t)}}:function(t){setTimeout(o(b,t,1),0)}),e.exports={set:f,clear:d}},{11:11,17:17,20:20,29:29,32:32,33:33}],76:[function(t,e,n){var a=t(77),r=Math.max,i=Math.min;e.exports=function(t,e){return t=a(t),0>t?r(t+e,0):i(t,e)}},{77:77}],77:[function(t,e,n){var a=Math.ceil,r=Math.floor;e.exports=function(t){return isNaN(t=+t)?0:(t>0?r:a)(t)}},{}],78:[function(t,e,n){var a=t(34),r=t(18);e.exports=function(t){return a(r(t))}},{18:18,34:34}],79:[function(t,e,n){var a=t(77),r=Math.min;e.exports=function(t){return t>0?r(a(t),9007199254740991):0}},{77:77}],80:[function(t,e,n){var a=t(18);e.exports=function(t){return Object(a(t))}},{18:18}],81:[function(t,e,n){var a=t(38);e.exports=function(t,e){if(!a(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!a(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},{38:38}],82:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++a+r).toString(36))}},{}],83:[function(t,e,n){var a=t(67)("wks"),r=t(82),i=t(29).Symbol;e.exports=function(t){return a[t]||(a[t]=i&&i[t]||(i||r)("Symbol."+t))}},{29:29,67:67,82:82}],84:[function(t,e,n){var a=t(10),r=t(83)("iterator"),i=t(45);e.exports=t(16).getIteratorMethod=function(t){return void 0!=t?t[r]||t["@@iterator"]||i[a(t)]:void 0}},{10:10,16:16,45:45,83:83}],85:[function(t,e,n){"use strict";var a,r=t(46),i=t(22),o=t(19),s=t(59),p=t(32),u=t(20),c=t(30),l=t(11),f=t(33),d=t(24),h=t(4),m=t(2),v=t(38),g=t(80),b=t(78),y=t(77),_=t(76),x=t(79),w=t(34),k=t(82)("__proto__"),C=t(8),P=t(7)(!1),E=Object.prototype,S=Array.prototype,A=S.slice,O=S.join,T=r.setDesc,M=r.getDesc,R=r.setDescs,j={};o||(a=!d(function(){return 7!=T(u("div"),"a",{get:function(){return 7}}).a}),r.setDesc=function(t,e,n){if(a)try{return T(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(h(t)[e]=n.value),t},r.getDesc=function(t,e){if(a)try{return M(t,e)}catch(n){}return c(t,e)?s(!E.propertyIsEnumerable.call(t,e),t[e]):void 0},r.setDescs=R=function(t,e){h(t);for(var n,a=r.getKeys(e),i=a.length,o=0;i>o;)r.setDesc(t,n=a[o++],e[n]);return t}),i(i.S+i.F*!o,"Object",{getOwnPropertyDescriptor:r.getDesc,defineProperty:r.setDesc,defineProperties:R});var L="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),N=L.concat("length","prototype"),D=L.length,F=function(){var t,e=u("iframe"),n=D,a=">";for(e.style.display="none",p.appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write("