diff --git a/SQL/database_changelog.txt b/SQL/database_changelog.txt index c34c6b694be..d0546da131d 100644 --- a/SQL/database_changelog.txt +++ b/SQL/database_changelog.txt @@ -1,3 +1,13 @@ +21 April 2017, by Jordie0608 + +Modified table 'player', adding the column 'accountjoindate', removing the column 'id' and making the column 'ckey' the primary key. + +ALTER TABLE `feedback`.`player` DROP COLUMN `id`, ADD COLUMN `accountjoindate` DATE NULL AFTER `lastadminrank`, DROP PRIMARY KEY, ADD PRIMARY KEY (`ckey`), DROP INDEX `ckey`; + +Remember to add a prefix to the table name if you use them. + +---------------------------------------------------- + 10 March 2017, by Jordie0608 Modified table 'death', adding the columns 'toxloss', 'cloneloss', and 'staminaloss' and table 'legacy_population', adding the columns 'server_ip' and 'server_port'. diff --git a/SQL/tgstation_schema.sql b/SQL/tgstation_schema.sql index eebc683918e..73e2d465f3d 100644 --- a/SQL/tgstation_schema.sql +++ b/SQL/tgstation_schema.sql @@ -261,15 +261,14 @@ DROP TABLE IF EXISTS `player`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `player` ( - `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, `firstseen` datetime NOT NULL, `lastseen` datetime NOT NULL, `ip` int(10) unsigned NOT NULL, `computerid` varchar(32) NOT NULL, `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', - PRIMARY KEY (`id`), - UNIQUE KEY `ckey` (`ckey`), + `accountjoindate` DATE DEFAULT NULL, + PRIMARY KEY (`ckey`), KEY `idx_player_cid_ckey` (`computerid`,`ckey`), KEY `idx_player_ip_ckey` (`ip`,`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; diff --git a/SQL/tgstation_schema_prefixed.sql b/SQL/tgstation_schema_prefixed.sql index be27384ea53..4d74b9deaab 100644 --- a/SQL/tgstation_schema_prefixed.sql +++ b/SQL/tgstation_schema_prefixed.sql @@ -261,15 +261,14 @@ DROP TABLE IF EXISTS `SS13_player`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `SS13_player` ( - `id` int(11) NOT NULL AUTO_INCREMENT, `ckey` varchar(32) NOT NULL, `firstseen` datetime NOT NULL, `lastseen` datetime NOT NULL, `ip` int(10) unsigned NOT NULL, `computerid` varchar(32) NOT NULL, `lastadminrank` varchar(32) NOT NULL DEFAULT 'Player', - PRIMARY KEY (`id`), - UNIQUE KEY `ckey` (`ckey`), + `accountjoindate` DATE DEFAULT NULL, + PRIMARY KEY (`ckey`), KEY `idx_player_cid_ckey` (`computerid`,`ckey`), KEY `idx_player_ip_ckey` (`ip`,`ckey`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; diff --git a/_maps/map_files/Cerestation/cerestation.dmm b/_maps/map_files/Cerestation/cerestation.dmm index 23fc961f770..c93ce6a262d 100644 --- a/_maps/map_files/Cerestation/cerestation.dmm +++ b/_maps/map_files/Cerestation/cerestation.dmm @@ -7067,8 +7067,8 @@ "anI" = ( /obj/docking_port/stationary/random{ dir = 1; - id = "pod_asteroid1"; - name = "asteroid" + id = "pod_lavaland1"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -8136,7 +8136,7 @@ /obj/machinery/computer/shuttle/pod{ pixel_x = -32; pixel_y = 0; - possible_destinations = "pod_asteroid1"; + possible_destinations = "pod_lavaland1"; shuttleId = "pod1" }, /obj/machinery/light/small{ @@ -40971,7 +40971,7 @@ /obj/machinery/computer/shuttle/pod{ pixel_x = 0; pixel_y = 32; - possible_destinations = "pod_asteroid3"; + possible_destinations = "pod_lavaland3"; shuttleId = "pod3" }, /obj/item/device/radio/intercom{ @@ -40993,8 +40993,8 @@ "btw" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid3"; - name = "asteroid" + id = "pod_lavaland3"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -69378,8 +69378,8 @@ "crd" = ( /obj/docking_port/stationary/random{ dir = 8; - id = "pod_asteroid2"; - name = "asteroid" + id = "pod_lavaland2"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -69394,7 +69394,7 @@ /obj/machinery/computer/shuttle/pod{ pixel_x = 0; pixel_y = -32; - possible_destinations = "pod_asteroid2"; + possible_destinations = "pod_lavaland2"; shuttleId = "pod2" }, /obj/structure/chair{ diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index f5e6964696a..34ff6f13ff5 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -142,15 +142,15 @@ /area/solar/auxstarboard) "aap" = ( /obj/docking_port/stationary/random{ - id = "pod_asteroid1"; - name = "asteroid" + id = "pod_lavaland1"; + name = "lavaland" }, /turf/open/space, /area/space) "aaq" = ( /obj/docking_port/stationary/random{ - id = "pod_asteroid2"; - name = "asteroid" + id = "pod_lavaland2"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -203,7 +203,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_x = -32; - possible_destinations = "pod_asteroid1"; + possible_destinations = "pod_lavaland1"; shuttleId = "pod1" }, /obj/effect/turf_decal/stripes/line{ @@ -226,7 +226,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_x = -32; - possible_destinations = "pod_asteroid2"; + possible_destinations = "pod_lavaland2"; shuttleId = "pod2" }, /obj/effect/turf_decal/stripes/line{ @@ -25977,7 +25977,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_y = -32; - possible_destinations = "pod_asteroid3"; + possible_destinations = "pod_lavaland3"; shuttleId = "pod3" }, /obj/effect/turf_decal/stripes/line{ @@ -25996,8 +25996,8 @@ "aXK" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid4"; - name = "asteroid" + id = "pod_lavaland4"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -63736,7 +63736,7 @@ /area/library) "cqF" = ( /obj/machinery/door/morgue{ - name = "Librarian's Study"; + name = "Curator's Study"; req_access_txt = "37" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -108178,7 +108178,7 @@ /area/maintenance/fpmaint2/aft_port_maintenance) "dXu" = ( /obj/structure/table/wood/fancy, -/obj/item/weapon/spellbook/oneuse/smoke, +/obj/item/weapon/spellbook/oneuse/smoke/lesser, /obj/item/weapon/nullrod, /obj/item/organ/heart, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index abc3eccf3d0..f6fe1c8188f 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -1910,8 +1910,8 @@ /area/shuttle/pod_3) "adG" = ( /obj/docking_port/stationary/random{ - id = "pod_asteroid2"; - name = "asteroid" + id = "pod_lavaland2"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -1927,7 +1927,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_x = -32; - possible_destinations = "pod_asteroid2"; + possible_destinations = "pod_lavaland2"; shuttleId = "pod2" }, /turf/open/floor/mineral/titanium/blue, @@ -23696,7 +23696,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_y = -32; - possible_destinations = "pod_asteroid3"; + possible_destinations = "pod_lavaland3"; shuttleId = "pod3" }, /turf/open/floor/mineral/titanium/blue, @@ -34140,8 +34140,8 @@ "bii" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid3"; - name = "asteroid" + id = "pod_lavaland3"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -82489,7 +82489,7 @@ /area/chapel/office) "cMa" = ( /obj/structure/table/wood, -/obj/item/weapon/spellbook/oneuse/smoke{ +/obj/item/weapon/spellbook/oneuse/smoke/lesser{ name = "mysterious old book of " }, /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater{ @@ -86090,8 +86090,8 @@ /area/toxins/xenobiology) "cSP" = ( /obj/docking_port/stationary/random{ - id = "pod_asteroid1"; - name = "asteroid" + id = "pod_lavaland1"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -86181,7 +86181,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_x = -32; - possible_destinations = "pod_asteroid1"; + possible_destinations = "pod_lavaland1"; shuttleId = "pod1" }, /turf/open/floor/mineral/titanium/blue, @@ -86374,7 +86374,7 @@ }, /obj/machinery/computer/shuttle/pod{ pixel_y = -32; - possible_destinations = "pod_asteroid4"; + possible_destinations = "pod_lavaland4"; shuttleId = "pod4" }, /turf/open/floor/mineral/titanium/blue, @@ -87168,8 +87168,8 @@ "cUL" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid4"; - name = "asteroid" + id = "pod_lavaland4"; + name = "lavaland" }, /turf/open/space, /area/space) diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index d841a0f335f..e8cb9e2187f 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -16523,6 +16523,9 @@ /obj/machinery/status_display{ pixel_x = -32 }, +/obj/machinery/light{ + dir = 8 + }, /turf/open/floor/mineral/plastitanium/brig, /area/shuttle/escape) "aAb" = ( @@ -16558,6 +16561,9 @@ "aAf" = ( /obj/structure/table/reinforced, /obj/item/weapon/storage/fancy/donut_box, +/obj/machinery/light{ + dir = 4 + }, /turf/open/floor/plasteel/vault{ dir = 8 }, @@ -24133,6 +24139,9 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery, +/obj/machinery/light{ + dir = 8 + }, /turf/open/floor/plasteel, /area/shuttle/escape) "aME" = ( @@ -24187,6 +24196,9 @@ /obj/machinery/status_display{ pixel_x = 32 }, +/obj/machinery/light{ + dir = 4 + }, /turf/open/floor/plasteel/whiteblue/side{ dir = 5 }, @@ -30548,7 +30560,7 @@ /area/maintenance/starboard) "aXL" = ( /obj/machinery/door/morgue{ - name = "Librarian's Study"; + name = "Curator's Study"; req_access_txt = "37" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -41920,6 +41932,38 @@ /area/ruin/unpowered{ name = "Asteroid" }) +"bvO" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/plasteel/neutral/side{ + dir = 1 + }, +/area/shuttle/escape) +"bvP" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/turf_decal/bot, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/shuttle/escape) +"bvQ" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/obj/machinery/light/small{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/shuttle/escape) +"bvR" = ( +/obj/machinery/light, +/turf/open/floor/plasteel/neutral/side, +/area/shuttle/escape) (1,1,1) = {" aaa @@ -94203,7 +94247,7 @@ aAb axY aDl aEi -aEi +bvP aEi aEi aEi @@ -94715,13 +94759,13 @@ axY aAc axY aCp -aDl +bvO aEk aEj aGd aEl aEk -aJf +bvR aKn aLz axY @@ -95231,7 +95275,7 @@ aAd aCq aDl aEm -aEm +bvQ aEm aEm aEm diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 2de3a5e8dcb..56bcff286e9 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -32850,10 +32850,6 @@ /turf/open/floor/plasteel/white, /area/toxins/xenobiology) "bnU" = ( -/obj/machinery/door/airlock/research{ - name = "Kill Room Access"; - req_access_txt = "55" - }, /obj/structure/disposalpipe/segment{ dir = 4 }, diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm index 7fbc6e734e7..5504f4d54a3 100644 --- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm +++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm @@ -2509,7 +2509,7 @@ "afq" = ( /obj/machinery/computer/shuttle/pod{ pixel_y = -32; - possible_destinations = "pod_asteroid3"; + possible_destinations = "pod_lavaland3"; shuttleId = "pod3" }, /obj/structure/chair{ @@ -7825,8 +7825,8 @@ "aqG" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid3"; - name = "asteroid" + id = "pod_lavaland3"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -54760,8 +54760,8 @@ "cpe" = ( /obj/docking_port/stationary/random{ dir = 8; - id = "pod_asteroid2"; - name = "asteroid" + id = "pod_lavaland2"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -55061,7 +55061,7 @@ /obj/machinery/computer/shuttle/pod{ pixel_x = 0; pixel_y = -32; - possible_destinations = "pod_asteroid2"; + possible_destinations = "pod_lavaland2"; shuttleId = "pod2" }, /obj/structure/chair{ @@ -58604,8 +58604,8 @@ "cwV" = ( /obj/docking_port/stationary/random{ dir = 8; - id = "pod_asteroid1"; - name = "asteroid" + id = "pod_lavaland1"; + name = "lavaland" }, /turf/open/space, /area/space) @@ -58718,7 +58718,7 @@ /obj/machinery/computer/shuttle/pod{ pixel_x = 0; pixel_y = -32; - possible_destinations = "pod_asteroid1"; + possible_destinations = "pod_lavaland1"; shuttleId = "pod1" }, /obj/structure/chair{ @@ -59670,7 +59670,7 @@ "czL" = ( /obj/machinery/computer/shuttle/pod{ pixel_y = -32; - possible_destinations = "pod_asteroid4"; + possible_destinations = "pod_lavaland4"; shuttleId = "pod4" }, /obj/structure/chair{ @@ -59701,8 +59701,8 @@ "czN" = ( /obj/docking_port/stationary/random{ dir = 4; - id = "pod_asteroid4"; - name = "asteroid" + id = "pod_lavaland4"; + name = "lavaland" }, /turf/open/space, /area/space) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 20bf0b55cc8..53a1f09fa50 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -113,3 +113,4 @@ #define EASYLIMBATTACHMENT 23 #define TOXINLOVER 24 #define DIGITIGRADE 25 //Uses weird leg sprites. Optional for Lizards, required for ashwalkers. Don't give it to other races unless you make sprites for this (see human_parts_greyscale.dmi) +#define NO_UNDERWEAR 26 diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index 9c86e031abc..acc0cdc9ab4 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -37,15 +37,15 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us #define JUDGEMENT_CV_REQ 300 //general component/cooldown things -#define SLAB_PRODUCTION_TIME 900 //how long(deciseconds) slabs require to produce a single component; defaults to 1 minute 30 seconds +#define SLAB_PRODUCTION_TIME 450 //how long(deciseconds) slabs require to produce a single component; defaults to 45 seconds -#define SLAB_SERVANT_SLOWDOWN 300 //how much each servant above 5 slows down slab-based generation; defaults to 30 seconds per sevant +#define SLAB_SERVANT_SLOWDOWN 150 //how much each servant above 5 slows down slab-based generation; defaults to 15 seconds per sevant -#define SLAB_SLOWDOWN_MAXIMUM 2700 //maximum slowdown from additional servants; defaults to 4 minutes 30 seconds +#define SLAB_SLOWDOWN_MAXIMUM 1350 //maximum slowdown from additional servants; defaults to 2 minutes 15 seconds -#define CACHE_PRODUCTION_TIME 600 //how long(deciseconds) caches require to produce a component; defaults to 1 minute +#define CACHE_PRODUCTION_TIME 300 //how long(deciseconds) caches require to produce a component; defaults to 30 seconds -#define ACTIVE_CACHE_SLOWDOWN 100 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 10 seconds +#define ACTIVE_CACHE_SLOWDOWN 50 //how many additional deciseconds caches take to produce a component for each linked cache; defaults to 5 seconds #define LOWER_PROB_PER_COMPONENT 10 //how much each component in the cache reduces the weight of getting another of that component type @@ -87,9 +87,9 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us #define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home -#define ARK_SUMMON_COST 3 //how many of each component an Ark costs to summon +#define ARK_SUMMON_COST 5 //how many of each component an Ark costs to summon -#define ARK_CONSUME_COST 7 //how many of each component an Ark needs to consume to activate +#define ARK_CONSUME_COST 15 //how many of each component an Ark needs to consume to activate //Objective text define #define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar." diff --git a/code/__DEFINES/language.dm b/code/__DEFINES/language.dm index e7818d7bf32..dc2ac19e657 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/status_effects.dm b/code/__DEFINES/status_effects.dm index 0bfbe31fb14..043158da111 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -33,4 +33,8 @@ #define STATUS_EFFECT_SIGILMARK /datum/status_effect/sigil_mark #define STATUS_EFFECT_BELLIGERENT /datum/status_effect/belligerent //forces the affected to walk, doing damage if they try to run +#define STATUS_EFFECT_MANIAMOTOR /datum/status_effect/maniamotor //disrupts, damages, and confuses the affected as long as they're in range of the motor +#define MAX_MANIA_SEVERITY 100 //how high the mania severity can go +#define MANIA_DAMAGE_TO_CONVERT 90 //how much damage is required before it'll convert affected targets + #define STATUS_EFFECT_HISWRATH /datum/status_effect/his_wrath //His Wrath. diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 6143022993e..79617db7bf9 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -45,6 +45,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/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 9ff38a3477a..e66d528a5af 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -488,15 +488,3 @@ L1[key] += other_value else L1[key] = other_value - -/proc/print_single_line(list/L) - . = "list(" - for(var/I in 1 to L.len) - var/key = L[I] - . += "[key]" - var/val = L[key] - if(!isnull(val)) - . += " => [val]" - if(I < L.len) - . += ", " - . += ")" diff --git a/code/__HELPERS/bandetect.dm b/code/__HELPERS/bandetect.dm deleted file mode 100644 index 19c0d378387..00000000000 --- a/code/__HELPERS/bandetect.dm +++ /dev/null @@ -1,37 +0,0 @@ -#define YOUNG 4 - - -/client/proc/join_date_check(y,m,d) - var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),'[y]-[m]-[d]')") - - if(!query_datediff.Execute()) - return FALSE - - if(query_datediff.NextRow()) - var/diff = text2num(query_datediff.item[1]) - if(config.use_account_age_for_jobs) - player_age = max(0,diff) //So job code soesn't freak out if they are time traveling. - if(diff < YOUNG) - var/msg = "(IP: [address], ID: [computer_id]) is a new BYOND account made on [y]-[m]-[d]." - if(diff < 0) - msg += " They are also apparently from the future." - message_admins("[key_name_admin(src)] [msg]") - return TRUE -#undef YOUNG - - -/client/proc/findJoinDate() - var/http[] = world.Export("http://byond.com/members/[src.ckey]?format=text") - if(!http) - log_world("Failed to connect to byond age check for [src.ckey]") - return FALSE - - var/F = file2text(http["CONTENT"]) - if(F) - var/regex/R = regex("joined = \"(\\d{4})-(\\d{2})-(\\d{2})\"") - if(!R.Find(F)) - CRASH("Age check regex failed") - var/y = R.group[1] - var/m = R.group[2] - var/d = R.group[3] - return join_date_check(y,m,d) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 14242963245..154879f884c 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 d000a2fe1a7..5755db27478 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 452bdcc0485..eea8effa8ae 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/configuration.dm b/code/controllers/configuration.dm index 730582070ae..d2748ff54bd 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -127,6 +127,7 @@ var/forbid_peaceborg = 0 var/panic_bunker = 0 // prevents new people it hasn't seen before from connecting var/notify_new_player_age = 0 // how long do we notify admins of a new player + var/notify_new_player_account_age = 0 // how long do we notify admins of a new byond account var/irc_first_connection_alert = 0 // do we notify the irc channel when somebody is connecting for the first time? var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors @@ -474,6 +475,8 @@ panic_bunker = 1 if("notify_new_player_age") notify_new_player_age = text2num(value) + if("notify_new_player_account_age") + notify_new_player_account_age = text2num(value) if("irc_first_connection_alert") irc_first_connection_alert = 1 if("check_randomizer") diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm index e0f114778c7..be5250d6565 100644 --- a/code/controllers/globals.dm +++ b/code/controllers/globals.dm @@ -52,6 +52,12 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars) /datum/controller/global_vars/Initialize() gvars_datum_init_order = list() gvars_datum_protected_varlist = list("gvars_datum_protected_varlist") + + //See https://github.com/tgstation/tgstation/issues/26954 + for(var/I in typesof(/datum/controller/global_vars/proc)) + var/CLEANBOT_RETURNS = "[I]" + pass(CLEANBOT_RETURNS) + for(var/I in vars - gvars_datum_in_built_vars) var/start_tick = world.time call(src, "InitGlobal[I]")() diff --git a/code/controllers/subsystem/language.dm b/code/controllers/subsystem/language.dm new file mode 100644 index 00000000000..e80a7096d8c --- /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 08239492f33..5a397fe3bda 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 0153e414145..6d6b1104dc8 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -111,6 +111,11 @@ var/obj/machinery/holopad/Holo = I LAZYREMOVE(Holo.holo_calls, src) dialed_holopads -= Holo + + for(var/I in H.holo_calls) + var/datum/holocall/HC = I + if(HC != src) + HC.Disconnect(H) if(!Check()) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 439b178dc1e..9147d14e26d 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/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 8eec853047b..9f6e481edb7 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -76,3 +76,89 @@ /datum/status_effect/belligerent/on_remove() if(owner.m_intent == MOVE_INTENT_WALK) owner.toggle_move_intent() + + +/datum/status_effect/maniamotor + id = "maniamotor" + duration = -1 + tick_interval = 10 + status_type = STATUS_EFFECT_MULTIPLE + alert_type = null + var/obj/structure/destructible/clockwork/powered/mania_motor/motor + var/severity = 0 //goes up to a maximum of MAX_MANIA_SEVERITY + var/warned_turnoff = FALSE //if we've warned that the motor is off + var/warned_outofsight = FALSE //if we've warned that the target is out of sight of the motor + var/static/list/mania_messages = list("Go nuts.", "Take a crack at crazy.", "Make a bid for insanity.", "Get kooky.", "Move towards mania.", "Become bewildered.", "Wax wild.", \ + "Go round the bend.", "Land in lunacy.", "Try dementia.", "Strive to get a screw loose.", "Advance forward.", "Approach the transmitter.", "Touch the antennae.", \ + "Move towards the mania motor.", "Come closer.", "Get over here already!", "Keep your eyes on the motor.") + var/static/list/flee_messages = list("Oh, NOW you flee.", "Get back here!", "If you were smarter, you'd come back.", "Only fools run.", "You'll be back.") + var/static/list/turnoff_messages = list("Why would they turn it-", "What are these idi-", "Fools, fools, all of-", "Are they trying to c-", "All this effort just f-") + var/static/list/powerloss_messages = list("\"Oh, the id**ts di***t s***e en**** pow**...\"", "\"D*dn't **ey mak* an **te***c*i*n le**?\"", "\"The** f**ls for**t t* make a ***** *f-\"", \ + "\"No, *O, you **re so cl***-\"", "You hear a yell of frustration, cut off by static.") + +/datum/status_effect/maniamotor/Destroy() + motor = null + return ..() + +/datum/status_effect/maniamotor/tick() + var/is_servant = is_servant_of_ratvar(owner) + var/span_part = severity > 50 ? "" : "_small" //let's save like one check + if(QDELETED(motor)) + if(!is_servant) + to_chat(owner, "You feel a frustrated voice quietly fade from your mind...") + qdel(src) + return + if(!motor.active) //it being off makes it fall off much faster + if(!is_servant && !warned_turnoff) + if(motor.total_accessable_power() > motor.mania_cost) + to_chat(owner, "\"[text2ratvar(pick(turnoff_messages))]\"") + else + to_chat(owner, "[text2ratvar(pick(powerloss_messages))]") + warned_turnoff = TRUE + severity = max(severity - 2, 0) + if(!severity) + qdel(src) + return + else + if(prob(severity * 2)) + warned_turnoff = FALSE + if(!(owner in viewers(7, motor))) //not being in range makes it fall off slightly faster + if(!is_servant && !warned_outofsight) + to_chat(owner, "\"[text2ratvar(pick(flee_messages))]\"") + warned_outofsight = TRUE + severity = max(severity - 1, 0) + if(!severity) + qdel(src) + return + else if(prob(severity * 2)) + warned_outofsight = FALSE + if(is_servant) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion + if(owner.hallucination) + owner.hallucination = 0 + if(owner.druggy) + owner.adjust_drugginess(-owner.druggy) + if(owner.dizziness) + owner.dizziness = 0 + if(owner.confused) + owner.confused = 0 + severity = 0 + else if(!owner.null_rod_check() && owner.stat != DEAD && severity) + var/static/hum = get_sfx('sound/effects/screech.ogg') //same sound for every proc call + if(owner.getToxLoss() > MANIA_DAMAGE_TO_CONVERT) + if(is_eligible_servant(owner)) + to_chat(owner, "\"[text2ratvar("You are mine and his, now.")]\"") + add_servant_of_ratvar(owner) + owner.Paralyse(5) + else + if(prob(severity * 0.15)) + to_chat(owner, "\"[text2ratvar(pick(mania_messages))]\"") + owner.playsound_local(get_turf(motor), hum, severity, 1) + owner.adjust_drugginess(Clamp(max(severity * 0.075, 1), 0, max(0, 50 - owner.druggy))) //7.5% of severity per second, minimum 1 + if(owner.hallucination < 50) + owner.hallucination = min(owner.hallucination + max(severity * 0.075, 1), 50) //7.5% of severity per second, minimum 1 + if(owner.dizziness < 50) + owner.dizziness = min(owner.dizziness + round(severity * 0.05, 1), 50) //5% of severity per second above 10 severity + if(owner.confused < 25) + owner.confused = min(owner.confused + round(severity * 0.025, 1), 25) //2.5% of severity per second above 20 severity + owner.adjustToxLoss(severity * 0.02, TRUE, TRUE) //2% of severity per second + severity-- diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 74a18536832..3e40aa3072d 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -103,3 +103,11 @@ for(var/datum/status_effect/S in status_effects) if(initial(S1.id) == S.id) return S + +/mob/living/proc/has_status_effect_list(effect) //returns a list of effects with matching IDs that the mod owns; use for effects there can be multiple of + . = list() + if(status_effects) + var/datum/status_effect/S1 = effect + for(var/datum/status_effect/S in status_effects) + if(initial(S1.id) == S.id) + . += S diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 54abfd439ea..f8ebcb87653 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 4e35f820753..097e9d306de 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -14,9 +14,8 @@ 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/verb_say = "says" var/verb_ask = "asks" var/verb_exclaim = "exclaims" @@ -45,11 +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 var/atom/oldloc = loc @@ -178,6 +172,7 @@ STOP_PROCESSING(SSinbounds, src) QDEL_NULL(proximity_monitor) + QDEL_NULL(language_holder) . = ..() if(loc) @@ -576,44 +571,68 @@ /* 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 @@ -623,8 +642,10 @@ 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/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm index cdb69516bf4..1abd58854b2 100644 --- a/code/game/gamemodes/changeling/changeling_power.dm +++ b/code/game/gamemodes/changeling/changeling_power.dm @@ -13,8 +13,6 @@ var/req_dna = 0 //amount of dna needed to use this ability. Changelings always have atleast 1 var/req_human = 0 //if you need to be human to use this ability var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD - var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss. - var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet. var/always_keep = 0 // important for abilities like revive that screw you if you lose them. var/ignores_fakedeath = FALSE // usable with the FAKEDEATH flag @@ -39,7 +37,7 @@ if(sting_action(user, target)) SSblackbox.add_details("changeling_powers",name) sting_feedback(user, target) - take_chemical_cost(c) + c.chem_charges -= chemical_cost /obj/effect/proc_holder/changeling/proc/sting_action(mob/user, mob/target) return 0 @@ -47,10 +45,6 @@ /obj/effect/proc_holder/changeling/proc/sting_feedback(mob/user, mob/target) return 0 -/obj/effect/proc_holder/changeling/proc/take_chemical_cost(datum/changeling/changeling) - changeling.chem_charges -= chemical_cost - changeling.geneticdamage += genetic_damage - //Fairly important to remember to return 1 on success >.< /obj/effect/proc_holder/changeling/proc/can_sting(mob/user, mob/target) if(!ishuman(user) && !ismonkey(user)) //typecast everything from mob to carbon from this point onwards @@ -71,9 +65,6 @@ if((user.status_flags & FAKEDEATH) && (!ignores_fakedeath)) to_chat(user, "We are incapacitated.") return 0 - if(c.geneticdamage > max_genetic_damage) - to_chat(user, "Our genomes are still reassembling. We need time to recover first.") - return 0 return 1 //used in /mob/Stat() diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index de31e575897..c7b02a32242 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -4,7 +4,6 @@ chemical_cost = 0 dna_cost = 0 req_human = 1 - max_genetic_damage = 100 /obj/effect/proc_holder/changeling/absorbDNA/can_sting(mob/living/carbon/user) if(!..()) diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm index 453dec93758..6e2d6b0ddda 100644 --- a/code/game/gamemodes/changeling/powers/biodegrade.dm +++ b/code/game/gamemodes/changeling/powers/biodegrade.dm @@ -5,9 +5,6 @@ chemical_cost = 30 //High cost to prevent spam dna_cost = 2 req_human = 1 - genetic_damage = 10 - max_genetic_damage = 0 - /obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user) var/used = FALSE // only one form of shackles removed per use diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm index 1f18f628a88..3be51031058 100644 --- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm +++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm @@ -5,9 +5,6 @@ dna_cost = 2 chemical_cost = 25 req_human = 1 - genetic_damage = 10 - max_genetic_damage = 50 - /obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user) var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm index 6e71c34744e..a9345dc1fde 100644 --- a/code/game/gamemodes/changeling/powers/fakedeath.dm +++ b/code/game/gamemodes/changeling/powers/fakedeath.dm @@ -5,8 +5,6 @@ dna_cost = 0 req_dna = 1 req_stat = DEAD - max_genetic_damage = 100 - //Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay. /obj/effect/proc_holder/changeling/fakedeath/sting_action(mob/living/user) diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index 7d926ce2aa0..382c7eb79c2 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -2,10 +2,7 @@ name = "Human Form" desc = "We change into a human." chemical_cost = 5 - genetic_damage = 3 req_dna = 1 - max_genetic_damage = 3 - //Transform into a human. /obj/effect/proc_holder/changeling/humanform/sting_action(mob/living/carbon/user) diff --git a/code/game/gamemodes/changeling/powers/lesserform.dm b/code/game/gamemodes/changeling/powers/lesserform.dm index aa1d0a2bc53..2bdab4bf765 100644 --- a/code/game/gamemodes/changeling/powers/lesserform.dm +++ b/code/game/gamemodes/changeling/powers/lesserform.dm @@ -3,7 +3,6 @@ desc = "We debase ourselves and become lesser. We become a monkey." chemical_cost = 5 dna_cost = 1 - genetic_damage = 3 req_human = 1 //Transform into a monkey. diff --git a/code/game/gamemodes/changeling/powers/linglink.dm b/code/game/gamemodes/changeling/powers/linglink.dm index fc4b91b6503..232774c937e 100644 --- a/code/game/gamemodes/changeling/powers/linglink.dm +++ b/code/game/gamemodes/changeling/powers/linglink.dm @@ -4,7 +4,6 @@ chemical_cost = 0 dna_cost = 0 req_human = 1 - max_genetic_damage = 100 /obj/effect/proc_holder/changeling/linglink/can_sting(mob/living/carbon/user) if(!..()) diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index 54e8ea1e38a..aef9b6f1d26 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -16,7 +16,6 @@ helptext = "Yell at Miauw and/or Perakp" chemical_cost = 1000 dna_cost = -1 - genetic_damage = 1000 var/silent = FALSE var/weapon_type @@ -67,7 +66,6 @@ helptext = "Yell at Miauw and/or Perakp" chemical_cost = 1000 dna_cost = -1 - genetic_damage = 1000 var/helmet_type = /obj/item var/suit_type = /obj/item @@ -89,7 +87,7 @@ return 1 var/mob/living/carbon/human/H = user if(istype(H.wear_suit, suit_type) || istype(H.head, helmet_type)) - H.visible_message("[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple][genetic_damage > 0 ? ", temporarily weakening our genomes." : "."]", "You hear the organic matter ripping and tearing!") + H.visible_message("[H] casts off their [suit_name_simple]!", "We cast off our [suit_name_simple].", "You hear the organic matter ripping and tearing!") H.temporarilyRemoveItemFromInventory(H.head, TRUE) //The qdel on dropped() takes care of it H.temporarilyRemoveItemFromInventory(H.wear_suit, TRUE) H.update_inv_wear_suit() @@ -100,7 +98,6 @@ H.add_splatter_floor() playsound(H.loc, 'sound/effects/splat.ogg', 50, 1) //So real sounds - changeling.geneticdamage += genetic_damage //Casting off a space suit leaves you weak for a few seconds. changeling.chem_recharge_slowdown -= recharge_slowdown return 1 @@ -139,9 +136,7 @@ helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form." chemical_cost = 20 dna_cost = 2 - genetic_damage = 10 req_human = 1 - max_genetic_damage = 20 weapon_type = /obj/item/weapon/melee/arm_blade weapon_name_simple = "blade" @@ -217,9 +212,7 @@ and Harm will stun it, and stab it if we're also holding a sharp weapon. Cannot be used while in lesser form." chemical_cost = 10 dna_cost = 2 - genetic_damage = 5 req_human = 1 - max_genetic_damage = 10 weapon_type = /obj/item/weapon/gun/magic/tentacle weapon_name_simple = "tentacle" silent = TRUE @@ -381,9 +374,7 @@ helptext = "Organic tissue cannot resist damage forever; the shield will break after it is hit too much. The more genomes we absorb, the stronger it is. Cannot be used while in lesser form." chemical_cost = 20 dna_cost = 1 - genetic_damage = 12 req_human = 1 - max_genetic_damage = 20 weapon_type = /obj/item/weapon/shield/changeling weapon_name_simple = "shield" @@ -430,12 +421,10 @@ /obj/effect/proc_holder/changeling/suit/organic_space_suit name = "Organic Space Suit" desc = "We grow an organic suit to protect ourselves from space exposure." - helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Retreating the suit damages our genomes. Cannot be used in lesser form." + helptext = "We must constantly repair our form to make it space-proof, reducing chemical production while we are protected. Cannot be used in lesser form." chemical_cost = 20 dna_cost = 2 - genetic_damage = 8 req_human = 1 - max_genetic_damage = 20 suit_type = /obj/item/clothing/suit/space/changeling helmet_type = /obj/item/clothing/head/helmet/space/changeling @@ -477,12 +466,10 @@ /obj/effect/proc_holder/changeling/suit/armor name = "Chitinous Armor" desc = "We turn our skin into tough chitin to protect us from damage." - helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Retreating the armor damages our genomes. Cannot be used in lesser form." + helptext = "Upkeep of the armor requires a low expenditure of chemicals. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form." chemical_cost = 20 dna_cost = 1 - genetic_damage = 11 req_human = 1 - max_genetic_damage = 20 recharge_slowdown = 0.25 suit_type = /obj/item/clothing/suit/armor/changeling diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm index 06866331c41..eb1e8baba71 100644 --- a/code/game/gamemodes/changeling/powers/tiny_prick.dm +++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm @@ -41,9 +41,8 @@ if(!AStar(user, target.loc, /turf/proc/Distance, user.mind.changeling.sting_range, simulated_only = 0)) return if(target.mind && target.mind.changeling) - sting_feedback(user,target) - take_chemical_cost(user.mind.changeling) - return + sting_feedback(user, target) + user.mind.changeling.chem_charges -= chemical_cost return 1 /obj/effect/proc_holder/changeling/sting/sting_feedback(mob/user, mob/target) @@ -62,7 +61,6 @@ sting_icon = "sting_transform" chemical_cost = 40 dna_cost = 3 - genetic_damage = 100 var/datum/changelingprofile/selected_dna = null /obj/effect/proc_holder/changeling/sting/transformation/Click() @@ -117,8 +115,6 @@ sting_icon = "sting_armblade" chemical_cost = 20 dna_cost = 1 - genetic_damage = 20 - max_genetic_damage = 10 /obj/item/weapon/melee/arm_blade/false desc = "A grotesque mass of flesh that used to be your arm. Although it looks dangerous at first, you can tell it's actually quite dull and useless." diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm index da258f52dde..52b056c7a7d 100644 --- a/code/game/gamemodes/changeling/powers/transform.dm +++ b/code/game/gamemodes/changeling/powers/transform.dm @@ -5,7 +5,6 @@ dna_cost = 0 req_dna = 1 req_human = 1 - max_genetic_damage = 3 /obj/item/clothing/glasses/changeling name = "flesh" diff --git a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm index 4f45b473aea..abd5866442f 100644 --- a/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm +++ b/code/game/gamemodes/clock_cult/clock_effects/clock_sigils.dm @@ -54,8 +54,11 @@ clockwork_desc = "A sigil that will stun the next non-Servant to cross it." icon_state = "sigildull" layer = HIGH_SIGIL_LAYER - alpha = 60 + alpha = 75 color = "#FAE48C" + light_range = 1.4 + light_power = 0.4 + light_color = "#FAE48C" sigil_name = "Sigil of Transgression" /obj/effect/clockwork/sigil/transgression/sigil_effects(mob/living/L) diff --git a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm index 35caabab5a8..8b3aa01533a 100644 --- a/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm +++ b/code/game/gamemodes/clock_cult/clock_items/clockwork_slab.dm @@ -326,13 +326,19 @@ if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM) production_text_addon = ", which increases for each human or silicon servant above [SCRIPT_SERVANT_REQ]" production_time = production_time/600 - var/production_text = "[round(production_time)] minute\s" + var/list/production_text + if(round(production_time)) + production_text = list("[round(production_time)] minute\s") if(production_time != round(production_time)) production_time -= round(production_time) production_time *= 60 - production_text += " and [round(production_time, 1)] second\s" + if(!LAZYLEN(production_text)) + production_text = list("[round(production_time, 1)] second\s") + else + production_text += " and [round(production_time, 1)] second\s" production_text += "" production_text += production_text_addon + production_text = production_text.Join() textlist = list("
Chetr nyy hagehguf-naq-ubabe Ratvar.

\ \ diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm index 81d02deeebe..97a68fd3216 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs.dm @@ -13,9 +13,9 @@ speak_emote = list("clanks", "clinks", "clunks", "clangs") verb_ask = "requests" verb_exclaim = "proclaims" + verb_whisper = "imparts" 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/clock_cult/clock_scriptures/scripture_applications.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm index 25576f57107..aa1a07ac2f2 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_applications.dm @@ -10,7 +10,7 @@ It will penetrate mindshield implants once before disappearing." invocations = list("Divinity, enslave...", "...all who trespass here!") channel_time = 70 - consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(BELLIGERENT_EYE = 4, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 2) whispered = TRUE object_path = /obj/effect/clockwork/sigil/submission/accession prevent_path = /obj/effect/clockwork/sigil/submission @@ -32,7 +32,7 @@ It grows faster to invoke with more adjacent Servants." invocations = list("Shield us...", "...with the...", "... fragments of Engine!") channel_time = 100 - consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(VANGUARD_COGWHEEL = 4, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2) usage_tip = "This scripture will replace all weaker armor worn by affected Servants." tier = SCRIPTURE_APPLICATION multiple_invokers_used = TRUE @@ -99,7 +99,7 @@ If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you." invocations = list("Fright's will...", "...call forth...") channel_time = 100 - consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2) + consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 4) usage_tip = "Marauders are useful as personal bodyguards and frontline warriors." tier = SCRIPTURE_APPLICATION primary_component = GEIS_CAPACITOR @@ -160,7 +160,7 @@ and exceptional speed, though taking damage will temporarily slow it down." invocations = list("Call forth...", "...the soldiers of Armorer.") channel_time = 80 - consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 2) + consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 4) object_path = /obj/structure/destructible/clockwork/shell/fragment creator_message = "You form an anima fragment, a powerful soul vessel receptacle." observer_message = "The slab disgorges a puddle of black metal that expands and forms into a strange shell!" @@ -179,7 +179,7 @@ desc = "Places a sigil that stores energy to power clockwork structures." invocations = list("Divinity...", "...power our creations!") channel_time = 70 - consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2) + consumed_components = list(VANGUARD_COGWHEEL = 2, GEIS_CAPACITOR = 2, HIEROPHANT_ANSIBLE = 4) whispered = TRUE object_path = /obj/effect/clockwork/sigil/transmission creator_message = "A sigil silently appears below you. It will automatically power clockwork structures near it." @@ -199,7 +199,7 @@ desc = "Creates a clockwork totem that sabotages nearby machinery and funnels drained power into nearby Sigils of Transmission or the area's APC." invocations = list("May this totem...", "...shroud the false suns!") channel_time = 80 - consumed_components = list(BELLIGERENT_EYE = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(BELLIGERENT_EYE = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2) object_path = /obj/structure/destructible/clockwork/powered/interdiction_lens creator_message = "You form an interdiction lens, which disrupts cameras and radios and drains power." observer_message = "A brass totem rises from the ground, a purple gem appearing in its center!" @@ -218,22 +218,22 @@ /datum/clockwork_scripture/create_object/mania_motor descname = "Powered Structure, Area Denial" name = "Mania Motor" - desc = "Creates a mania motor which will cause brain damage and hallucinations in nearby non-Servant humans. It will also try to convert humans directly adjecent to the motor." + desc = "Creates a mania motor which causes minor damage and a variety of negative mental effects in nearby non-Servant humans, potentially up to and including conversion." invocations = list("May this transmitter...", "...break the will of all who oppose us!") channel_time = 80 - consumed_components = list(GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(GEIS_CAPACITOR = 5, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2) object_path = /obj/structure/destructible/clockwork/powered/mania_motor - creator_message = "You form a mania motor which will cause brain damage and hallucinations in nearby humans while active." + creator_message = "You form a mania motor, which causes minor damage and negative mental effects in non-Servants." observer_message = "A two-pronged machine rises from the ground!" invokers_required = 2 multiple_invokers_used = TRUE - usage_tip = "Eligible non-Servant humans next to the motor will be converted at an additional power cost. It will also cure hallucinations and brain damage in nearby Servants." + usage_tip = "It will also cure hallucinations and brain damage in nearby Servants." tier = SCRIPTURE_APPLICATION one_per_tile = TRUE primary_component = GEIS_CAPACITOR sort_priority = 8 quickbind = TRUE - quickbind_desc = "Creates a Mania Motor, which can convert adjacent non-Servants with power." + quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants." //Tinkerer's Daemon: Creates an efficient machine that rapidly produces components at a power cost. @@ -244,7 +244,7 @@ and there is at least one existing cache." invocations = list("May this generator...", "...collect Engine parts that yet hold greatness!") channel_time = 80 - consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 3) + consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 5) object_path = /obj/structure/destructible/clockwork/powered/tinkerers_daemon creator_message = "You form a tinkerer's daemon which can rapidly collect components at a power cost." invokers_required = 2 @@ -278,7 +278,7 @@ desc = "Creates a clockwork obelisk that can broadcast messages over the Hierophant Network or open a Spatial Gateway to any living Servant or clockwork obelisk." invocations = list("May this obelisk...", "...take us to all places!") channel_time = 80 - consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 3) + consumed_components = list(BELLIGERENT_EYE = 2, VANGUARD_COGWHEEL = 2, HIEROPHANT_ANSIBLE = 5) object_path = /obj/structure/destructible/clockwork/powered/clockwork_obelisk creator_message = "You form a clockwork obelisk which can broadcast messages or produce Spatial Gateways." observer_message = "A brass obelisk appears hanging in midair!" diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm index 2e822199d3f..b49b0c58196 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_drivers.dm @@ -259,7 +259,7 @@ var/static/prev_cost = 0 /datum/clockwork_scripture/create_object/tinkerers_cache/creation_update() - var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.25), 5) + var/cache_cost_increase = min(round(GLOB.clockwork_caches*0.4), 10) if(cache_cost_increase != prev_cost) prev_cost = cache_cost_increase consumed_components = list(BELLIGERENT_EYE = 0, VANGUARD_COGWHEEL = 0, GEIS_CAPACITOR = 0, REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 0) diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm index 0dbd2d46e80..25bedd79d30 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_revenant.dm @@ -9,7 +9,7 @@ desc = "Taps the limitless power of Inath-neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all Servants in range for fifteen seconds." invocations = list("I call upon you, Vanguard!!", "Let the Resonant Cogs turn once more!!", "Grant me and my allies the strength to vanquish our foes!!") channel_time = 100 - consumed_components = list(VANGUARD_COGWHEEL = 4, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 2) + consumed_components = list(VANGUARD_COGWHEEL = 10, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 3) usage_tip = "Servants affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity." tier = SCRIPTURE_REVENANT primary_component = VANGUARD_COGWHEEL @@ -44,7 +44,7 @@ for all non-servant humans on the same z-level as them. The power of this scripture falls off somewhat with distance, and certain things may reduce its effects." invocations = list("I call upon you, Fright!!", "Let your power shatter the sanity of the weak-minded!!", "Let your tendrils hold sway over all!!") channel_time = 150 - consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 6, HIEROPHANT_ANSIBLE = 3) + consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 10, HIEROPHANT_ANSIBLE = 6) usage_tip = "Causes brain damage, hallucinations, confusion, and dizziness in massive amounts." tier = SCRIPTURE_REVENANT sort_priority = 3 @@ -108,7 +108,7 @@ clockwork proselytizers will charge very rapidly." invocations = list("I call upon you, Armorer!!", "Let your machinations reign on this miserable station!!", "Let your power flow through the tools of your master!!") channel_time = 150 - consumed_components = list(BELLIGERENT_EYE = 3, VANGUARD_COGWHEEL = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 6) + consumed_components = list(BELLIGERENT_EYE = 6, VANGUARD_COGWHEEL = 6, GEIS_CAPACITOR = 6, REPLICANT_ALLOY = 10) usage_tip = "Ocular wardens will become empowered, clockwork proselytizers will require no alloy, tinkerer's daemons will produce twice as quickly, \ and interdiction lenses, mania motors, tinkerer's daemons, and clockwork obelisks will all require no power." tier = SCRIPTURE_REVENANT @@ -153,7 +153,7 @@ will be struck by devastating lightning bolts." invocations = list("I call upon you, Amperage!!", "Let your energy flow through me!!", "Let your boundless power shatter stars!!") channel_time = 100 - consumed_components = list(BELLIGERENT_EYE = 2, GEIS_CAPACITOR = 2, REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 4) + consumed_components = list(BELLIGERENT_EYE = 3, GEIS_CAPACITOR = 3, REPLICANT_ALLOY = 3, HIEROPHANT_ANSIBLE = 10) usage_tip = "Struck targets will also be knocked down for about sixteen seconds." tier = SCRIPTURE_REVENANT primary_component = HIEROPHANT_ANSIBLE diff --git a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm index f7fcc8c2998..bc5ec1b9d83 100644 --- a/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm +++ b/code/game/gamemodes/clock_cult/clock_scriptures/scripture_scripts.dm @@ -9,7 +9,7 @@ desc = "Forms an automatic short-range turret which will automatically attack nearby unrestrained non-Servants that can see it." invocations = list("Guardians...", "...of the Engine...", "...defend us!") channel_time = 120 - consumed_components = list(BELLIGERENT_EYE = 1, REPLICANT_ALLOY = 1) + consumed_components = list(BELLIGERENT_EYE = 2, REPLICANT_ALLOY = 1) object_path = /obj/structure/destructible/clockwork/ocular_warden creator_message = "You form an ocular warden, which will automatically attack nearby unrestrained non-Servants that can see it." observer_message = "A brass eye takes shape and slowly rises into the air, its red iris glaring!" @@ -36,7 +36,7 @@ desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer." invocations = list("Call forth...", "...the workers of Armorer.") channel_time = 60 - consumed_components = list(BELLIGERENT_EYE = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(BELLIGERENT_EYE = 2, HIEROPHANT_ANSIBLE = 1) object_path = /obj/structure/destructible/clockwork/shell/cogscarab creator_message = "You form a cogscarab, a constructor soul vessel receptacle." observer_message = "The slab disgorges a puddle of black metal that contracts and forms into a strange shell!" @@ -56,7 +56,7 @@ Matrices have drained from non-Servants. Dead Servants can be revived by this sigil if there is vitality equal to the target Servant's non-oxygen damage." invocations = list("Divinity...", "...steal their life...", "...for these shells!") channel_time = 60 - consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 1) + consumed_components = list(BELLIGERENT_EYE = 1, VANGUARD_COGWHEEL = 2) whispered = TRUE object_path = /obj/effect/clockwork/sigil/vitality creator_message = "A vitality matrix appears below you. It will drain life from non-Servants and heal Servants that cross it." @@ -77,7 +77,7 @@ chant_invocations = list("Mend our dents!", "Heal our scratches!", "Repair our gears!") chant_amount = 10 chant_interval = 20 - consumed_components = list(VANGUARD_COGWHEEL = 1, REPLICANT_ALLOY = 1) + consumed_components = list(VANGUARD_COGWHEEL = 2, REPLICANT_ALLOY = 1) usage_tip = "This is a very effective way to rapidly reinforce a base after an attack." tier = SCRIPTURE_SCRIPT primary_component = VANGUARD_COGWHEEL @@ -177,6 +177,7 @@ new /obj/effect/overlay/temp/heal(T, "#1E8CE1") else break + new /obj/effect/overlay/temp/ratvar/mending_mantra(get_turf(invoker)) return TRUE @@ -187,7 +188,7 @@ desc = "Places a luminous sigil that will enslave any valid beings standing on it after a time." invocations = list("Divinity, enlighten...", "...those who trespass here!") channel_time = 60 - consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 1) + consumed_components = list(BELLIGERENT_EYE = 1, GEIS_CAPACITOR = 2) whispered = TRUE object_path = /obj/effect/clockwork/sigil/submission creator_message = "A luminous sigil appears below you. The next non-servant to cross it will be enslaved after a brief time if they do not move." @@ -207,7 +208,7 @@ desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar." invocations = list("Herd the souls of...", "...the blasphemous damned!") channel_time = 30 - consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 1) + consumed_components = list(VANGUARD_COGWHEEL = 1, GEIS_CAPACITOR = 2) whispered = TRUE object_path = /obj/item/device/mmi/posibrain/soul_vessel creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness." @@ -227,7 +228,7 @@ desc = "Forms a device that, when used on certain objects, converts them into their Ratvarian equivalents. It requires power to function." invocations = list("With this device...", "...his presence shall be made known.") channel_time = 20 - consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 1) + consumed_components = list(GEIS_CAPACITOR = 1, REPLICANT_ALLOY = 2) whispered = TRUE object_path = /obj/item/clockwork/clockwork_proselytizer/preloaded creator_message = "You form a clockwork proselytizer." @@ -248,7 +249,7 @@ vanish three minutes after being summoned." invocations = list("Grant me...", "...the might of brass!") channel_time = 20 - consumed_components = list(REPLICANT_ALLOY = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(REPLICANT_ALLOY = 2, HIEROPHANT_ANSIBLE = 1) whispered = TRUE usage_tip = "You can impale human targets with the spear by pulling them, then attacking. Throwing the spear at a mob will do massive damage and stun them, but break the spear." tier = SCRIPTURE_SCRIPT @@ -307,7 +308,7 @@ Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration." invocations = list("Spatial Gateway...", "...activate!") channel_time = 80 - consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(VANGUARD_COGWHEEL = 1, HIEROPHANT_ANSIBLE = 2) multiple_invokers_used = TRUE multiple_invokers_optional = TRUE usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal." @@ -356,7 +357,7 @@ chant_invocations = list("Use charge to kill!", "Slay with power!", "Hunt with energy!") chant_amount = 4 chant_interval = 5 - consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 1) + consumed_components = list(GEIS_CAPACITOR = 1, HIEROPHANT_ANSIBLE = 2) usage_tip = "Though it requires you to stand still, this scripture can do massive damage." tier = SCRIPTURE_SCRIPT primary_component = HIEROPHANT_ANSIBLE diff --git a/code/game/gamemodes/clock_cult/clock_structures/mania_motor.dm b/code/game/gamemodes/clock_cult/clock_structures/mania_motor.dm index 09372044a91..dd26b5d4043 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/mania_motor.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/mania_motor.dm @@ -1,8 +1,8 @@ -//Mania Motor: A pair of antenna that, while active, cause braindamage and hallucinations in nearby human mobs. +//Mania Motor: A pair of antenna that, while active, cause a variety of negative mental effects in nearby human mobs. /obj/structure/destructible/clockwork/powered/mania_motor name = "mania motor" desc = "A pair of antenna with what appear to be sockets around the base. It reminds you of an antlion." - clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing hallucinations and brain damage as long as it remains powered." + clockwork_desc = "A transmitter that allows Sevtug to whisper into the minds of nearby non-servants, causing a variety of negative mental effects, up to and including conversion." icon_state = "mania_motor_inactive" active_icon = "mania_motor" inactive_icon = "mania_motor_inactive" @@ -16,22 +16,11 @@ /obj/item/clockwork/alloy_shards/small = 2, \ /obj/item/clockwork/component/geis_capacitor/antennae = 1) var/mania_cost = 150 - var/convert_cost = 150 - var/static/list/mania_messages = list("Go nuts.", "Take a crack at crazy.", "Make a bid for insanity.", "Get kooky.", "Move towards mania.", "Become bewildered.", "Wax wild.", \ - "Go round the bend.", "Land in lunacy.", "Try dementia.", "Strive to get a screw loose.") - var/static/list/compel_messages = list("Come closer.", "Approach the transmitter.", "Touch the antennae.", "I always have to deal with idiots. Move towards the mania motor.", \ - "Advance forward and place your head between the antennae - that's all it's good for.", "If you were smarter, you'd be over here already.", "Move FORWARD, you fool.") - var/static/list/convert_messages = list("You won't do. Go to sleep while I tell these nitwits how to convert you.", "You are insufficient. I must instruct these idiots in the art of conversion.", \ - "Oh of course, someone we can't convert. These servants are fools.", "How hard is it to use a Sigil, anyway? All it takes is dragging someone onto it.", \ - "How do they fail to use a Sigil of Accession, anyway?", "Why is it that all servants are this inept?", "It's quite likely you'll be stuck here for a while.") - var/static/list/close_messages = list("Well, you can't reach the motor from THERE, you moron.", "Interesting location. I'd prefer if you went somewhere you could ACTUALLY TOUCH THE ANTENNAE!", \ - "Amazing. You somehow managed to wedge yourself somewhere you can't actually reach the motor from.", "Such a show of idiocy is unparalleled. Perhaps I should put you on display?", \ - "Did you do this on purpose? I can't imagine you doing so accidentally. Oh, wait, I can.", "How is it that such smart creatures can still do something AS STUPID AS THIS!") /obj/structure/destructible/clockwork/powered/mania_motor/examine(mob/user) ..() if(is_servant_of_ratvar(user) || isobserver(user)) - to_chat(user, "It requires [mania_cost]W to run, and at least [convert_cost]W to attempt to convert humans adjacent to it.") + to_chat(user, "It requires [mania_cost]W to run.") /obj/structure/destructible/clockwork/powered/mania_motor/forced_disable(bad_effects) if(active) @@ -60,82 +49,17 @@ if(!try_use_power(mania_cost)) forced_disable(FALSE) return - var/turf/T = get_turf(src) - var/hum = get_sfx('sound/effects/screech.ogg') //like playsound, same sound for everyone affected var/efficiency = get_efficiency_mod() for(var/mob/living/carbon/human/H in viewers(7, src)) - if(is_servant_of_ratvar(H)) //heals servants of braindamage, hallucination, druggy, dizziness, and confusion - var/brainloss = H.getBrainLoss() - if(brainloss) - H.adjustBrainLoss(-brainloss) - if(H.hallucination) - H.hallucination = 0 - if(H.druggy) - H.adjust_drugginess(-H.druggy) - if(H.dizziness) - H.dizziness = 0 - if(H.confused) - H.confused = 0 - else if(!H.null_rod_check() && H.stat != DEAD) - var/distance = 0 + get_dist(T, get_turf(H)) - var/falloff_distance = min((110) - distance * 10, 80) - var/sound_distance = falloff_distance * 0.5 - var/targetbrainloss = H.getBrainLoss() - if(distance > 3 && prob(falloff_distance * 0.5)) - to_chat(H, "\"[text2ratvar(pick(mania_messages))]\"") - if(distance <= 1) - if(!H.Adjacent(src)) - to_chat(H, "\"[text2ratvar(pick(close_messages))]\"") - H.playsound_local(T, hum, sound_distance, 1) - else if(!try_use_power(convert_cost)) - visible_message("[src]'s antennae fizzle quietly.") - playsound(src, 'sound/effects/light_flicker.ogg', 50, 1) - else - H.playsound_local(T, hum, 80, 1) - if(!H.stat) - if(H.getBrainLoss() < 100) - H.adjustBrainLoss(20 * efficiency) - H.visible_message("[H] reaches out and touches [src].", "You touch [src] involuntarily.") - else - H.Paralyse(3) - else if(is_eligible_servant(H)) - to_chat(H, "\"[text2ratvar("You are mine and his, now.")]\"") - add_servant_of_ratvar(H) - H.Paralyse(5) - else - H.playsound_local(T, hum, sound_distance, 1) - switch(distance) - if(0 to 3) - if(prob(falloff_distance * 0.5)) - if(prob(falloff_distance)) - to_chat(H, "\"[text2ratvar(pick(mania_messages))]\"") - else - to_chat(H, "\"[text2ratvar(pick(compel_messages))]\"") - if(targetbrainloss <= 40) - H.adjustBrainLoss(3 * efficiency) - H.adjust_drugginess(Clamp(7 * efficiency, 0, 50 - H.druggy)) - H.hallucination = min(H.hallucination + (7 * efficiency), 50) - H.dizziness = min(H.dizziness + (3 * efficiency), 20) - H.confused = min(H.confused + (3 * efficiency), 20) - if(3 to 5) - if(targetbrainloss <= 20) - H.adjustBrainLoss(2 * efficiency) - H.adjust_drugginess(Clamp(5 * efficiency, 0, 25 - H.druggy)) - H.hallucination = min(H.hallucination + (5 * efficiency), 25) - H.dizziness = min(H.dizziness + (2 * efficiency), 10) - H.confused = min(H.confused + (2 * efficiency), 10) - if(5 to 6) - if(targetbrainloss <= 10) - H.adjustBrainLoss(1 * efficiency) - H.adjust_drugginess(Clamp(2 * efficiency, 0, 20 - H.druggy)) - H.hallucination = min(H.hallucination + (2 * efficiency), 20) - H.dizziness = min(H.dizziness + (2 * efficiency), 5) - H.confused = min(H.confused + (2 * efficiency), 5) - if(6 to 7) - if(targetbrainloss <= 5) - H.adjustBrainLoss(1 * efficiency) - H.adjust_drugginess(Clamp(2 * efficiency, 0, 10 - H.druggy)) - H.hallucination = min(H.hallucination + (2 * efficiency), 10) - if(7 to INFINITY) - H.adjust_drugginess(Clamp(2 * efficiency, 0, 5 - H.druggy)) - H.hallucination = min(H.hallucination + (2 * efficiency), 5) + if(is_servant_of_ratvar(H)) + continue + var/list/effects = H.has_status_effect_list(STATUS_EFFECT_MANIAMOTOR) + var/datum/status_effect/maniamotor/M + for(var/datum/status_effect/maniamotor/MM in effects) + if(MM.motor == src) + M = MM + break + if(!M) + M = H.apply_status_effect(STATUS_EFFECT_MANIAMOTOR) + M.motor = src + M.severity = Clamp(M.severity + ((11 - get_dist(src, H)) * efficiency * efficiency), 0, MAX_MANIA_SEVERITY) diff --git a/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm b/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm index 22ea9e2ce50..b0a17338ffe 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/tinkerers_daemon.dm @@ -18,7 +18,7 @@ var/static/mutable_appearance/component_glow = mutable_appearance('icons/obj/clockwork_objects.dmi', "t_random_component") var/component_id_to_produce var/production_time = 0 //last time we produced a component - var/production_cooldown = 120 + var/production_cooldown = 60 /obj/structure/destructible/clockwork/powered/tinkerers_daemon/Initialize() . = ..() diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm index 5e4c49a5490..5f7dabf4722 100644 --- a/code/game/gamemodes/gang/gang_datum.dm +++ b/code/game/gamemodes/gang/gang_datum.dm @@ -13,6 +13,7 @@ var/list/territory = list() var/list/territory_new = list() var/list/territory_lost = list() + var/recalls = 1 var/dom_attempts = 2 var/points = 15 var/datum/atom_hud/antag/gang/ganghud @@ -262,4 +263,4 @@ ganghud = new() /datum/gang/multiverse/income() - return \ No newline at end of file + return diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm index 459448077d7..02d05713f9e 100644 --- a/code/game/gamemodes/gang/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -168,6 +168,9 @@ if(recalling) to_chat(usr, "Error: Recall already in progress.") return 0 + + if(!gang.recalls) + to_chat(usr, "Error: Unable to access communication arrays. Firewall has logged our signature and is blocking all further attempts.") gang.message_gangtools("[usr] is attempting to recall the emergency shuttle.") recalling = 1 @@ -209,6 +212,7 @@ userturf = get_turf(user) if(userturf.z == 1) //Check one more time that they are on station. if(SSshuttle.cancelEvac(user)) + gang.recalls -= 1 return 1 to_chat(loc, "[bicon(src)]No response recieved. Emergency shuttle cannot be recalled at this time.") diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index c6248b03cc2..3b315bb6682 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/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 7260d8221f0..265688a15b6 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -14,6 +14,7 @@ var/icon_reveal = "revenant_revealed" var/icon_stun = "revenant_stun" var/icon_drain = "revenant_draining" + var/stasis = 0 incorporeal_move = 3 invisibility = INVISIBILITY_REVENANT health = INFINITY //Revenants don't use health, they use essence instead @@ -94,6 +95,8 @@ //Life, Stat, Hud Updates, and Say /mob/living/simple_animal/revenant/Life() + if(stasis) + return if(revealed && essence <= 0) death() if(unreveal_time && world.time >= unreveal_time) @@ -200,9 +203,8 @@ death() /mob/living/simple_animal/revenant/death() - if(!revealed || stat == DEAD) //Revenants cannot die if they aren't revealed //or are already dead + if(!revealed || stasis) //Revenants cannot die if they aren't revealed //or are already dead return 0 - ..(1) to_chat(src, "NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...") notransform = TRUE revealed = TRUE @@ -217,9 +219,12 @@ var/reforming_essence = essence_regen_cap //retain the gained essence capacity var/obj/item/weapon/ectoplasm/revenant/R = new(get_turf(src)) R.essence = max(reforming_essence - 15 * perfectsouls, 75) //minus any perfect souls - R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body - ghostize() - qdel(src) + R.client_to_revive = client //If the essence reforms, the old revenant is put back in the body + R.revenant = src + invisibility = INVISIBILITY_ABSTRACT + revealed = 0 + stasis = 1 + ghostize(0)//Don't re-enter invisible corpse return @@ -302,6 +307,18 @@ to_chat(src, "Lost [essence_amt]E[source ? " from [source]":""].") return 1 +/mob/living/simple_animal/revenant/proc/death_reset() + revealed = FALSE + unreveal_time = 0 + notransform = 0 + unstun_time = 0 + inhibited = FALSE + draining = FALSE + incorporeal_move = 3 + invisibility = INVISIBILITY_REVENANT + alpha=255 + stasis = 0 + //reforming /obj/item/weapon/ectoplasm/revenant @@ -314,11 +331,15 @@ var/reforming = TRUE var/inert = FALSE var/client/client_to_revive + var/mob/living/simple_animal/revenant/revenant /obj/item/weapon/ectoplasm/revenant/New() ..() addtimer(CALLBACK(src, .proc/try_reform), 600) +/obj/item/weapon/ectoplasm/revenant/proc/scatter() + qdel(src) + /obj/item/weapon/ectoplasm/revenant/proc/try_reform() if(reforming) reforming = FALSE @@ -333,14 +354,14 @@ user.visible_message("[user] scatters [src] in all directions.", \ "You scatter [src] across the area. The particles slowly fade away.") user.drop_item() - qdel(src) + scatter() /obj/item/weapon/ectoplasm/revenant/throw_impact(atom/hit_atom) ..() if(inert) return visible_message("[src] breaks into particles upon impact, which fade away to nothingness.") - qdel(src) + scatter() /obj/item/weapon/ectoplasm/revenant/examine(mob/user) ..() @@ -350,47 +371,51 @@ to_chat(user, "It is shifting and distorted. It would be wise to destroy this.") /obj/item/weapon/ectoplasm/revenant/proc/reform() - if(QDELETED(src) || inert) + if(QDELETED(src) || QDELETED(revenant) || inert) return var/key_of_revenant message_admins("Revenant ectoplasm was left undestroyed for 1 minute and is reforming into a new revenant.") loc = get_turf(src) //In case it's in a backpack or someone's hand - var/mob/living/simple_animal/revenant/R = new(get_turf(src)) + revenant.forceMove(loc) if(client_to_revive) for(var/mob/M in GLOB.dead_mob_list) if(M.client == client_to_revive) //Only recreates the mob if the mob the client is in is dead - R.client = client_to_revive + revenant.client = client_to_revive key_of_revenant = client_to_revive.key if(!key_of_revenant) message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...") - var/list/candidates = get_candidates(ROLE_REVENANT) + var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", "revenant", null, ROLE_REVENANT, 50, revenant) if(!candidates.len) - qdel(R) + qdel(revenant) message_admins("No candidates were found for the new revenant. Oh well!") inert = TRUE visible_message("[src] settles down and seems lifeless.") return var/client/C = pick(candidates) + revenant.client = C key_of_revenant = C.key if(!key_of_revenant) - qdel(R) + qdel(revenant) message_admins("No ckey was found for the new revenant. Oh well!") inert = TRUE visible_message("[src] settles down and seems lifeless.") return - var/datum/mind/player_mind = new /datum/mind(key_of_revenant) - R.essence_regen_cap = essence - R.essence = R.essence_regen_cap - player_mind.active = 1 - player_mind.transfer_to(R) - player_mind.assigned_role = "revenant" - player_mind.special_role = "Revenant" - SSticker.mode.traitors |= player_mind + message_admins("[key_of_revenant] has been [client_to_revive ? "re":""]made into a revenant by reforming ectoplasm.") log_game("[key_of_revenant] was [client_to_revive ? "re":""]made as a revenant by reforming ectoplasm.") visible_message("[src] suddenly rises into the air before fading away.") + + revenant.essence = essence + revenant.essence_regen_cap = essence + revenant.death_reset() + revenant.key = key_of_revenant + revenant = null qdel(src) +/obj/item/weapon/ectoplasm/revenant/Destroy() + if(!QDELETED(revenant)) + qdel(revenant) + ..() //objectives /datum/objective/revenant diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index b326aea5d97..3134547a666 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -778,6 +778,9 @@ icon_state ="booksmoke" desc = "This book is overflowing with the dank arts." +/obj/item/weapon/spellbook/oneuse/smoke/lesser //Chaplain smoke book + spell = /obj/effect/proc_holder/spell/targeted/smoke/lesser + /obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user) ..() to_chat(user,"Your stomach rumbles...") @@ -786,6 +789,7 @@ if(user.nutrition <= 0) user.nutrition = 0 + /obj/item/weapon/spellbook/oneuse/blind spell = /obj/effect/proc_holder/spell/targeted/trigger/blind spellname = "blind" diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm index 1515c1f32fb..98450453bd1 100644 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ b/code/game/machinery/computer/telecrystalconsoles.dm @@ -58,7 +58,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E /obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1) if(uplinkholder && linkedboss) - if(amt <= uplinkholder.hidden_uplink.telecrystals) + if(amt < 0) + linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals + if(addLog) + linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].") + uplinkholder.hidden_uplink.telecrystals = 0 + else if(amt <= uplinkholder.hidden_uplink.telecrystals) uplinkholder.hidden_uplink.telecrystals -= amt linkedboss.storedcrystals += amt if(addLog) @@ -66,7 +71,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E /obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1) if(uplinkholder && linkedboss) - if(amt <= linkedboss.storedcrystals) + if(amt < 0) + uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals + if(addLog) + linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].") + linkedboss.storedcrystals = 0 + else if(amt <= linkedboss.storedcrystals) uplinkholder.hidden_uplink.telecrystals += amt linkedboss.storedcrystals -= amt if(addLog) @@ -89,7 +99,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E if(uplinkholder) dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.
" if(linkedboss) - dat += "Donate TC: 1 | 5" + dat += "Donate TC: 1 | 5 | All" dat += "
Eject Uplink" @@ -103,11 +113,9 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E if(..()) return - if(href_list["donate1"]) - donateTC(1) - - if(href_list["donate5"]) - donateTC(5) + if(href_list["donate"]) + var/tcamt = text2num(href_list["donate"]) + donateTC(tcamt) if(href_list["eject"]) ejectuplink() @@ -162,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E var/dat = "" dat += "Scan for TC stations.
" - dat += "This [src] has [storedcrystals] telecrystals available for distribution.
" + dat += "[storedcrystals] telecrystals are available for distribution.
" dat += "

" @@ -171,10 +179,10 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E if(A.uplinkholder) dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals." if(storedcrystals) - dat+= "
Add TC: 1 | 5" + dat+= "
Add TC: 1 | 5 | 10 | All" dat += "
" - if(TCstations.len) + if(TCstations.len && storedcrystals) dat += "

Evenly distribute remaining TC.

" @@ -195,13 +203,11 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E if(href_list["scan"]) scanUplinkers() - if(href_list["give1"]) - var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"]) - A.giveTC(1) - - if(href_list["give5"]) - var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"]) - A.giveTC(5) + if(href_list["give"]) + var/tcamt = text2num(href_list["give"]) + if(TCstations.len) // sanity + var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations + A.giveTC(tcamt) if(href_list["distrib"]) var/sanity = 0 diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 0a819ee7e66..bef00409e2b 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -152,7 +152,7 @@ GLOBAL_LIST_EMPTY(holopads) var/datum/holocall/HC = I if(HC.connected_holopad == src) dat += "Disconnect call from [HC.user].
" - + var/datum/browser/popup = new(user, "holopad", name, 300, 130) popup.set_content(dat) @@ -192,7 +192,7 @@ GLOBAL_LIST_EMPTY(holopads) if(A) LAZYADD(callnames[A], I) callnames -= get_area(src) - + var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames if(QDELETED(usr) || !result || outgoing_call) return @@ -201,7 +201,7 @@ GLOBAL_LIST_EMPTY(holopads) temp = "Dialing...
" temp += "Main Menu" new /datum/holocall(usr, src, callnames[result]) - + else if(href_list["connectcall"]) var/datum/holocall/call_to_connect = locate(href_list["connectcall"]) if(!QDELETED(call_to_connect)) @@ -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. @@ -315,12 +315,12 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ for(var/mob/living/silicon/ai/master in masters) if(masters[master] && speaker != master) master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) - + for(var/I in holo_calls) var/datum/holocall/HC = I if(HC.connected_holopad == src && speaker != HC.hologram) - HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans) - + HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + if(outgoing_call && speaker == outgoing_call.user) outgoing_call.hologram.say(raw_message) @@ -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/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 74506b0c0f2..bb5d37073d0 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -251,6 +251,8 @@ GLOBAL_LIST_INIT(pipeID2State, list( var/mob/living/carbon/C = user for(var/i=1 to 20) C.vomit(0,1,0,4,0) + if(prob(20)) + C.spew_organ() sleep(5) C.blood_volume = 0 return(OXYLOSS|BRUTELOSS) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index d64e01e3de1..aa8aedbbe2e 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -364,6 +364,10 @@ var/list/targets = list() var/turretview = view(scan_range, base) for(var/A in turretview) + var/atom/AA = A + if(AA.invisibility>SEE_INVISIBLE_LIVING) + continue + if(check_anomalies)//if it's set to check for simple animals if(istype(A, /mob/living/simple_animal)) var/mob/living/simple_animal/SA = A diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 73555ce7c41..209f311a47d 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -307,7 +307,10 @@ if(panel_open) attack_hand(user) return - else if(istype(W, /obj/item/weapon/coin) && premium.len > 0) + else if(istype(W, /obj/item/weapon/coin)) + if(!premium.len) + to_chat(user, "[src] doesn't have a coin slot.") + return if(!user.drop_item()) return W.loc = src diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 3935b86c92c..a6517ccdb5a 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -323,11 +323,30 @@ /obj/effect/overlay/temp/ratvar/grille/broken icon_state = "ratvarbrokengrilleglow" +/obj/effect/overlay/temp/ratvar/mending_mantra + layer = ABOVE_MOB_LAYER + duration = 20 + alpha = 200 + icon_state = "mending_mantra" + light_range = 1.5 + light_color = "#1E8CE1" + +/obj/effect/overlay/temp/ratvar/mending_mantra/Initialize(mapload) + . = ..() + transform = matrix()*2 + var/matrix/M = transform + M.Turn(90) + animate(src, alpha = 20, time = duration, easing = BOUNCE_EASING, flags = ANIMATION_PARALLEL) + animate(src, transform = M, time = duration, flags = ANIMATION_PARALLEL) + /obj/effect/overlay/temp/ratvar/volt_hit name = "volt blast" layer = ABOVE_MOB_LAYER duration = 5 icon_state = "volt_hit" + light_range = 1.5 + light_power = 2 + light_color = LIGHT_COLOR_ORANGE var/mob/user var/damage = 20 @@ -336,7 +355,6 @@ damage *= multiplier duration = max(round(damage * 0.2), 1) . = ..() - set_light(1.5, 2, LIGHT_COLOR_ORANGE) /obj/effect/overlay/temp/ratvar/volt_hit/true/Initialize(mapload, caster, multiplier) . = ..() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index d8d673ce0b8..7ed563d6b78 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -37,9 +37,9 @@ return 1 -/obj/item/device/flashlight/attack(mob/living/carbon/human/M, mob/living/carbon/human/user) +/obj/item/device/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user) add_fingerprint(user) - if(on && user.zone_selected == "eyes") + if(istype(M) && on && user.zone_selected in list("eyes", "mouth")) if((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) //too dumb to use flashlight properly return ..() //just hit them in the head @@ -48,28 +48,101 @@ to_chat(user, "You don't have the dexterity to do this!") return - var/mob/living/carbon/human/H = M //mob has protective eyewear - if(ishuman(M) && ((H.head && H.head.flags_cover & HEADCOVERSEYES) || (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) || (H.glasses && H.glasses.flags_cover & GLASSESCOVERSEYES))) - to_chat(user, "You're going to need to remove that [(H.head && H.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (H.wear_mask && H.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.") + if(!M.get_bodypart("head")) + to_chat(user, "[M] doesn't have a head!") return - if(M == user) //they're using it on themselves - if(M.flash_act(visual = 1)) - M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes! Trippy!") - else - M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes.") - else - user.visible_message("[user] directs [src] to [M]'s eyes.", \ - "You direct [src] to [M]'s eyes.") - var/mob/living/carbon/C = M - if(istype(C)) - if(C.stat == DEAD || (C.disabilities & BLIND)) //mob is dead or fully blind - to_chat(user, "[C] pupils don't react to the light!") - else if(C.dna.check_mutation(XRAY)) //mob has X-RAY vision - to_chat(user, "[C] pupils give an eerie glow!") - else //they're okay! - if(C.flash_act(visual = 1)) - to_chat(user, "[C]'s pupils narrow.") + switch(user.zone_selected) + if("eyes") + if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) + to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first.") + return + + var/obj/item/organ/eyes/E = M.getorganslot("eye_sight") + if(!E) + to_chat(user, "[M] doesn't have any eyes!") + return + + if(M == user) //they're using it on themselves + if(M.flash_act(visual = 1)) + M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes! Trippy!") + else + M.visible_message("[M] directs [src] to [M.p_their()] eyes.", "You wave the light in front of your eyes.") + else + user.visible_message("[user] directs [src] to [M]'s eyes.", \ + "You direct [src] to [M]'s eyes.") + if(M.stat == DEAD || (M.disabilities & BLIND) || !M.flash_act(visual = 1)) //mob is dead or fully blind + to_chat(user, "[M]'s pupils don't react to the light!") + else if(M.dna && M.dna.check_mutation(XRAY)) //mob has X-RAY vision + to_chat(user, "[M]'s pupils give an eerie glow!") + else //they're okay! + to_chat(user, "[M]'s pupils narrow.") + + if("mouth") + + if((M.head && M.head.flags_cover & HEADCOVERSMOUTH) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH)) + to_chat(user, "You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first.") + return + + var/their = M.p_their() + + var/list/mouth_organs = new + for(var/obj/item/organ/O in M.internal_organs) + if(O.zone == "mouth") + mouth_organs.Add(O) + var/organ_list = "" + var/organ_count = LAZYLEN(mouth_organs) + if(organ_count) + for(var/I in 1 to organ_count) + if(I > 1) + if(I == mouth_organs.len) + organ_list += ", and " + else + organ_list += ", " + var/obj/item/organ/O = mouth_organs[I] + organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") + + var/pill_count = 0 + for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions) + pill_count++ + + if(M == user) + var/can_use_mirror = FALSE + if(isturf(user.loc)) + var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) + if(mirror) + switch(user.dir) + if(NORTH) + can_use_mirror = mirror.pixel_y > 0 + if(SOUTH) + can_use_mirror = mirror.pixel_y < 0 + if(EAST) + can_use_mirror = mirror.pixel_x > 0 + if(WEST) + can_use_mirror = mirror.pixel_x < 0 + + M.visible_message("[M] directs [src] to [their] mouth.", \ + "You point [src] into your mouth.") + if(!can_use_mirror) + to_chat(user, "You can't see anything without a mirror.") + return + if(organ_count) + to_chat(user, "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].") + else + to_chat(user, "There's nothing inside your mouth.") + if(pill_count) + to_chat(user, "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].") + + else + user.visible_message("[user] directs [src] to [M]'s mouth.",\ + "You direct [src] to [M]'s mouth.") + if(organ_count) + to_chat(user, "Inside [their] mouth [organ_count > 1 ? "are" : "is"] [organ_list].") + else + to_chat(user, "[M] doesn't have any organs in [their] mouth.") + if(pill_count) + to_chat(user, "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [their] teeth.") + else return ..() @@ -280,7 +353,7 @@ return TRUE /obj/item/device/flashlight/emp/attack(mob/living/M, mob/living/user) - if(on && user.zone_selected == "eyes") // call original attack proc only if aiming at the eyes + if(on && user.zone_selected in list("eyes", "mouth")) // call original attack when examining organs ..() return diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 5e2495a7b9b..185ddf23e62 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -237,6 +237,7 @@ /obj/item/borg/upgrade/selfrepair/proc/check_dropped() if(loc != cyborg) toggle_action.Remove(cyborg) + QDEL_NULL(toggle_action) cyborg = null deactivate() @@ -399,4 +400,4 @@ return R.make_shell(src) - return TRUE \ No newline at end of file + return TRUE diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index d81b8a5a69f..436bc5ff598 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -29,6 +29,7 @@ Mineral Sheets GLOBAL_LIST_INIT(sandstone_recipes, list ( \ new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \ + new/datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 2, 4, 20), \ new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Breakdown into sand", /obj/item/weapon/ore/glass, 1, one_per_turf = 0, on_floor = 1), \ /* new/datum/stack_recipe("sandstone wall", ???), \ @@ -335,12 +336,20 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \ /* * Adamantine */ +GLOBAL_LIST_INIT(adamantine_recipes, list( + new /datum/stack_recipe("artificial golem shell", /obj/item/golem_shell/artificial, req_amount=1, res_amount=1), + )) + /obj/item/stack/sheet/mineral/adamantine name = "adamantine" icon_state = "sheet-adamantine" singular_name = "adamantine sheet" origin_tech = "materials=4" +/obj/item/stack/sheet/mineral/adamantine/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.adamantine_recipes + ..() + /* * Mythril */ diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index aecee4e0701..ef123030f5e 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -88,6 +88,14 @@ turf_type = /turf/open/floor/wood resistance_flags = FLAMMABLE +//Basalt +/obj/item/stack/tile/basalt + name = "basalt tile" + singular_name = "basalt floor tile" + desc = "Artificially made ashy soil themed on a hostile enviroment." + icon_state = "tile_basalt" + origin_tech = "materials=1" + turf_type = /turf/open/floor/grass/fakebasalt //Carpets /obj/item/stack/tile/carpet diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 0af7877d3d7..d53b87f5f27 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -1,5 +1,5 @@ /obj/item/weapon/grenade/spawnergrenade - desc = "It will unleash unleash an unspecified anomaly into the vicinity." + desc = "It will unleash an unspecified anomaly into the vicinity." name = "delivery grenade" icon = 'icons/obj/grenade.dmi' icon_state = "delivery" diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 0652d8bf1c0..2d5e926d039 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -220,6 +220,7 @@ new /obj/item/weapon/reagent_containers/glass/bottle/venom(src) new /obj/item/weapon/reagent_containers/glass/bottle/neurotoxin2(src) new /obj/item/weapon/reagent_containers/glass/bottle/formaldehyde(src) + new /obj/item/weapon/reagent_containers/glass/bottle/spewium(src) new /obj/item/weapon/reagent_containers/glass/bottle/cyanide(src) new /obj/item/weapon/reagent_containers/glass/bottle/histamine(src) new /obj/item/weapon/reagent_containers/glass/bottle/initropidril(src) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index a14d345e2f8..20f8e8c15c7 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/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index 2df9ca60a26..3d4cfaee93d 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -145,8 +145,7 @@ to_chat(user, "You [open ? "close":"open"] the [src]") toggle_lock(user) else if(open && !showpiece) - if(user.drop_item()) - W.loc = src + if(user.transferItemToLoc(W, src)) showpiece = W to_chat(user, "You put [W] on display") update_icon() @@ -256,6 +255,8 @@ var/trophy_message = "" var/placer_key = "" var/added_roundstart = TRUE + var/is_locked = TRUE + alert = TRUE integrity_failure = 0 @@ -278,8 +279,16 @@ if(!user.Adjacent(src)) //no TK museology return - if(!(user.mind && user.mind.assigned_role == "Curator")) - to_chat(user, "You're not sure how to work this. Maybe you should ask the curator for help.") + if(user.is_holding_item_of_type(/obj/item/key/displaycase)) + if(added_roundstart) + is_locked = !is_locked + to_chat(user, "You [!is_locked ? "un" : ""]lock the case.") + else + to_chat(user, "The lock is stuck shut!") + return + + if(is_locked) + to_chat(user, "The case is shut tight with an old fashioned physical lock. Maybe you should ask the curator for the key?") return if(!added_roundstart) @@ -295,14 +304,13 @@ to_chat(user, "The case rejects the [W].") return - if(user.drop_item()) + if(user.transferItemToLoc(W, src)) if(showpiece) to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.") QDEL_NULL(showpiece) to_chat(user, "You insert [W] into the case.") - W.forceMove(src) showpiece = W added_roundstart = FALSE update_icon() @@ -336,6 +344,10 @@ else ..() +/obj/item/key/displaycase + name = "display case key" + desc = "The key to the curator's display cases." + /obj/item/showpiece_dummy name = "Cheap replica" diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 1205ea6c879..104b86bc061 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -12,6 +12,10 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user + if(H.dna && H.dna.species && (NO_UNDERWEAR in H.dna.species.species_traits)) + to_chat(user, "You are not capable of wearing underwear.") + return + var/choice = input(user, "Underwear, Undershirt, or Socks?", "Changing") as null|anything in list("Underwear","Undershirt","Socks") if(!Adjacent(user)) @@ -32,4 +36,4 @@ H.socks= new_socks add_fingerprint(H) - H.update_body() \ No newline at end of file + H.update_body() diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 84fe78cef64..411e81de85e 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -88,7 +88,7 @@ pixel_y = -20 /obj/structure/flora/tree/jungle/Initialize() - icon_state = "[icon_state][rand(1, 3)]" + icon_state = "[icon_state][rand(1, 6)]" ..() //grass diff --git a/code/game/say.dm b/code/game/say.dm index deab83ad101..674f4a1b759 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -35,10 +35,10 @@ GLOBAL_LIST_INIT(freqtospan, list( return 1 /atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode) - var/rendered = compose_message(src, message_language, message, , spans) + var/rendered = compose_message(src, message_language, message, , spans, message_mode) for(var/_AM in get_hearers_in_view(range, source)) var/atom/movable/AM = _AM - AM.Hear(rendered, src, message_language, message, , spans) + AM.Hear(rendered, src, message_language, message, , spans, message_mode) //To get robot span classes, stuff like that. /atom/movable/proc/get_spans() @@ -58,10 +58,10 @@ GLOBAL_LIST_INIT(freqtospan, list( var/endspanpart = "" //Message - var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans)]" + var/messagepart = " [lang_treat(speaker, message_language, raw_message, spans, message_mode)]" 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/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 8890c501293..8b24a4c816a 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -143,14 +143,14 @@ qdel(S.mmi) qdel(AM) - + if(AM && !QDELETED(AM)) //It's indestructible visible_message("[src] spits out the [AM]!") AM.alpha = oldalpha AM.color = oldcolor AM.transform = oldtransform AM.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1, 10),rand(1, 10)) - + /turf/open/chasm/straight_down/lava_land_surface/normal_air initial_gas_mix = "o2=22;n2=82;TEMP=293.15" @@ -158,3 +158,17 @@ /turf/open/chasm/CanPass(atom/movable/mover, turf/target, height=0) return 1 + + + +//Jungle + +/turf/open/chasm/jungle + icon = 'icons/turf/floors/junglechasm.dmi' + planetary_atmos = TRUE + initial_gas_mix = "o2=14;n2=23;TEMP=300" + +/turf/open/chasm/straight_down/jungle + icon = 'icons/turf/floors/junglechasm.dmi' + planetary_atmos = TRUE + initial_gas_mix = "o2=14;n2=23;TEMP=300" \ No newline at end of file diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index eaba3d50eb2..cce77568928 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -1,6 +1,7 @@ /* In this file: * Wood floor * Grass floor + * Fake Basalt * Carpet floor * Fake pits * Fake space @@ -67,6 +68,7 @@ broken_states = list("sand") flags = NONE var/ore_type = /obj/item/weapon/ore/glass + var/turfverb = "uproot" /turf/open/floor/grass/Initialize() ..() @@ -76,7 +78,7 @@ if(istype(C, /obj/item/weapon/shovel) && params) new ore_type(src) new ore_type(src) //Make some sand if you shovel grass - user.visible_message("[user] digs up [src].", "You uproot [src].") + user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].") playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) make_plating() if(..()) @@ -93,7 +95,6 @@ initial_gas_mix = "o2=22;n2=82;TEMP=180" slowdown = 2 - /turf/open/floor/grass/snow/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/weapon/crowbar))//You need to dig this turf out instead of crowbarring it return @@ -113,6 +114,24 @@ icon_state = "basalt[rand(0, 12)]" set_basalt_light(src) + +/turf/open/floor/grass/fakebasalt //Heart is not a real planeteer power + name = "aesthetic volcanic flooring" + desc = "Safely recreated turf for your hellplanet-scaping" + icon = 'icons/turf/floors.dmi' + icon_state = "basalt" + floor_tile = /obj/item/stack/tile/basalt + ore_type = /obj/item/weapon/ore/glass/basalt + turfverb = "dig up" + slowdown = 0 + +/turf/open/floor/grass/fakebasalt/Initialize() + ..() + if(prob(15)) + icon_state = "basalt[rand(0, 12)]" + set_basalt_light(src) + + /turf/open/floor/carpet name = "carpet" desc = "Soft velvet carpeting. Feels good between your toes." diff --git a/code/game/turfs/simulated/floor/plating/dirt.dm b/code/game/turfs/simulated/floor/plating/dirt.dm index 580aadc85f6..0d13b934328 100644 --- a/code/game/turfs/simulated/floor/plating/dirt.dm +++ b/code/game/turfs/simulated/floor/plating/dirt.dm @@ -3,19 +3,9 @@ desc = "Upon closer examination, it's still dirt." icon = 'icons/turf/floors.dmi' icon_state = "dirt" - var/smooth_icon = 'icons/turf/floors/dirt.dmi' - canSmoothWith = list(/turf/closed, /turf/open/floor/plating/dirt) - smooth = SMOOTH_MORE|SMOOTH_BORDER - baseturf = /turf/open/chasm/straight_down/lava_land_surface + baseturf = /turf/open/chasm/straight_down/jungle initial_gas_mix = "o2=14;n2=23;TEMP=300" planetary_atmos = TRUE -/turf/open/floor/plating/dirt/Initialize() - pixel_y = -2 - pixel_x = -2 - icon = smooth_icon - ..() - /turf/open/floor/plating/dirt/dark - icon_state = "darkdirt" - smooth_icon = 'icons/turf/floors/darkdirt.dmi' + icon_state = "greenerdirt" diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 6b1d0e36f6d..e8803868fef 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -610,41 +610,20 @@ set desc = "(atom path) Spawn an atom" set name = "Spawn" - return usr.client.spawn_atom_impl(object, FALSE) - -/datum/admins/proc/spawn_atom_adv(object as text) - set category = "Debug" - set desc = "(atom path) Spawn an atom with New() parameters" - set name = "Advanced Spawn" - - return usr.client.spawn_atom_impl(object, TRUE) - - -/client/proc/spawn_atom_impl(object, params) if(!check_rights(R_SPAWN)) return var/chosen = pick_closest_path(object) if(!chosen) return - - var/list/arguments if(ispath(chosen,/turf)) var/turf/T = get_turf(usr.loc) T.ChangeTurf(chosen) else - if(params) - arguments = usr.client.get_callproc_args(TRUE) - - if(!usr) - return - - arguments = list(usr.loc) + arguments - - var/atom/A = new chosen(arglist(arguments)) + var/atom/A = new chosen(usr.loc) A.admin_spawned = TRUE - log_admin("[key_name(usr)] spawned [chosen] at [COORD(usr)][LAZYLEN(arguments) > 1 ? " with parameters [print_single_line(arguments)]": ""]") + log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])") SSblackbox.add_details("admin_verb","Spawn Atom") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 068f68e2b96..469581f4b77 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -101,7 +101,7 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list( /client/proc/smite )) GLOBAL_PROTECT(admin_verbs_spawn) -GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom,/datum/admins/proc/spawn_atom_adv,/client/proc/respawn_character)) +GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom,/client/proc/respawn_character)) GLOBAL_PROTECT(admin_verbs_server) GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer()) /world/proc/AVerbsServer() diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 1f8778361fd..a126dbb225f 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/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 489441ee97a..c4eb65d3527 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -103,6 +103,7 @@ if(!recipient) if(holder) to_chat(src, "Error: Admin-PM: Client not found.") + to_chat(src, msg) else current_ticket.MessageNoRecipient(msg) return diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 1b099a9e0a5..1ee98d15557 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -145,8 +145,8 @@ GLOBAL_PROTECT(AdminProcCallCount) -/client/proc/get_callproc_args(is_atom_new = FALSE) - var/argnum = input("Number of arguments[is_atom_new ? " (Excluding loc)" : ""]","Number:",0) as num|null +/client/proc/get_callproc_args() + var/argnum = input("Number of arguments","Number:",0) as num|null if(isnull(argnum)) return diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index c4a4d249e99..94d955bdd0c 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -213,14 +213,7 @@ GLOBAL_PROTECT(VVpixelmovement) .["class"] = null return .["type"] = type - - var/list/arguments - if(alert(usr, "Would you like to add arguments?", "New Atom", "No", "Yes") == "Yes") - arguments = get_callproc_args(FALSE) - else - arguments = list() - - .["value"] = new type(arglist(arguments)) + .["value"] = new type() if (VV_NEW_DATUM) var/type = pick_closest_path(FALSE, get_fancy_list_of_datum_types()) @@ -228,13 +221,7 @@ GLOBAL_PROTECT(VVpixelmovement) .["class"] = null return .["type"] = type - var/list/arguments - if(alert(usr, "Would you like to add arguments?", "New Atom", "No", "Yes") == "Yes") - arguments = get_callproc_args(FALSE) - else - arguments = list() - - .["value"] = new type(arglist(arguments)) + .["value"] = new type() if (VV_NEW_TYPE) var/type = current_value @@ -250,14 +237,7 @@ GLOBAL_PROTECT(VVpixelmovement) .["class"] = null return .["type"] = type - - var/list/arguments - if(alert(usr, "Would you like to add arguments?", "New Atom", "No", "Yes") == "Yes") - arguments = get_callproc_args(FALSE); - else - arguments = list() - - .["value"] = new type(arglist(arguments)) + .["value"] = new type() if (VV_NEW_LIST) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 16e1a648d3c..0c84d2e43ff 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -39,9 +39,11 @@ //////////////////////////////////// //things that require the database// //////////////////////////////////// - var/player_age = "Requires database" //So admins know why it isn't working - Used to determine how old the account is - in days. + var/player_age = -1 //Used to determine how old the account is - in days. var/related_accounts_ip = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this ip var/related_accounts_cid = "Requires database" //So admins know why it isn't working - Used to determine what other accounts previously logged in from this computer id + var/account_join_date = null //Date of byond account creation in ISO 8601 format + var/account_age = -1 //Age of byond account in days preload_rsc = PRELOAD_RSC @@ -64,4 +66,5 @@ var/inprefs = FALSE var/list/topiclimiter - var/datum/chatOutput/chatOutput \ No newline at end of file + var/datum/chatOutput/chatOutput + diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 34a932e98cf..307be5d85e4 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -274,17 +274,11 @@ GLOBAL_LIST(external_rsc_urls) if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms. to_chat(src, "The server's API key is either too short or is the default value! Consider changing it immediately!") - add_verbs_from_config() + add_verbs_from_config(tdata) set_client_age_from_db() var/cached_player_age = player_age //we have to cache this because other shit may change it and we need it's current value now down below. if (isnum(cached_player_age) && cached_player_age == -1) //first connection player_age = 0 - if(!IsGuestKey(key) && SSdbcore.IsConnected()) - findJoinDate() - - sync_client_with_db(tdata) - - if (isnum(cached_player_age) && cached_player_age == -1) //first connection if (config.panic_bunker && !holder && !(ckey in GLOB.deadmins)) log_access("Failed Login: [key] - New account attempting to connect during panic bunker") @@ -303,7 +297,14 @@ GLOBAL_LIST(external_rsc_urls) send2irc_adminless_only("New-user", "[key_name(src)] is connecting for the first time!") else if (isnum(cached_player_age) && cached_player_age < config.notify_new_player_age) message_admins("New user: [key_name_admin(src)] just connected with an age of [cached_player_age] day[(player_age==1?"":"s")]") - + if(config.use_account_age_for_jobs && account_age >= 0) + player_age = account_age + if(account_age >= 0 && account_age < config.notify_new_player_account_age) + message_admins("[key_name_admin(src)] (IP: [address], ID: [computer_id]) is a new BYOND account day[(account_age==1?"":"s")] old, created on [account_join_date].") + if (config.irc_first_connection_alert) + send2irc_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account day[(account_age==1?"":"s")] old, created on [account_join_date].") + else //We failed to get an age for this user, let admins know they need to keep an eye on them + message_admins("Failed to get BYOND account age for [key_name_admin(src)]") get_message_output("watchlist entry", ckey) check_ip_intel() @@ -348,7 +349,6 @@ GLOBAL_LIST(external_rsc_urls) adminGreet(1) holder.owner = null GLOB.admins -= src - if (!GLOB.admins.len && SSticker.IsRoundInProgress()) //Only report this stuff if we are currently playing. if(!GLOB.admins.len) //Apparently the admin logging out is no longer an admin at this point, so we have to check this towards 0 and not towards 1. Awell. var/cheesy_message = pick( @@ -379,70 +379,84 @@ GLOBAL_LIST(external_rsc_urls) /client/Destroy() return QDEL_HINT_HARDDEL_NOW -/client/proc/set_client_age_from_db() +/client/proc/set_client_age_from_db(connectiontopic) if (IsGuestKey(src.key)) return - if(!SSdbcore.Connect()) return - var/sql_ckey = sanitizeSQL(src.ckey) - - var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") - if(!query_get_client_age.Execute()) - return - - while(query_get_client_age.NextRow()) - player_age = text2num(query_get_client_age.item[2]) - return - - //no match mark it as a first connection for use in client/New() - player_age = -1 - - -/client/proc/sync_client_with_db(connectiontopic) - if (IsGuestKey(src.key)) - return - - if (!SSdbcore.Connect()) - return - - var/sql_ckey = sanitizeSQL(ckey) - - var/datum/DBQuery/query_get_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON('[address]') AND ckey != '[sql_ckey]'") - query_get_ip.Execute() + var/datum/DBQuery/query_get_related_ip = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = INET_ATON('[address]') AND ckey != '[sql_ckey]'") + query_get_related_ip.Execute() related_accounts_ip = "" - while(query_get_ip.NextRow()) - related_accounts_ip += "[query_get_ip.item[1]], " - - var/datum/DBQuery/query_get_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]' AND ckey != '[sql_ckey]'") - if(!query_get_cid.Execute()) + while(query_get_related_ip.NextRow()) + related_accounts_ip += "[query_get_related_ip.item[1]], " + var/datum/DBQuery/query_get_related_cid = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]' AND ckey != '[sql_ckey]'") + if(!query_get_related_cid.Execute()) return related_accounts_cid = "" - while (query_get_cid.NextRow()) - related_accounts_cid += "[query_get_cid.item[1]], " - + while (query_get_related_cid.NextRow()) + related_accounts_cid += "[query_get_related_cid.item[1]], " var/admin_rank = "Player" if (src.holder && src.holder.rank) admin_rank = src.holder.rank.name else if (check_randomizer(connectiontopic)) return - - var/sql_ip = sanitizeSQL(src.address) - var/sql_computerid = sanitizeSQL(src.computer_id) + var/sql_ip = sanitizeSQL(address) + var/sql_computerid = sanitizeSQL(computer_id) var/sql_admin_rank = sanitizeSQL(admin_rank) - - - var/datum/DBQuery/query_log_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]') ON DUPLICATE KEY UPDATE lastseen = VALUES(lastseen), ip = VALUES(ip), computerid = VALUES(computerid), lastadminrank = VALUES(lastadminrank)") - if(!query_log_player.Execute()) + var/new_player + var/datum/DBQuery/query_client_in_db = SSdbcore.NewQuery("SELECT 1 FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + if(!query_client_in_db.Execute()) return - - //Logging player access - + if(!query_client_in_db.NextRow()) + new_player = 1 + account_join_date = sanitizeSQL(findJoinDate()) + var/datum/DBQuery/query_add_player = SSdbcore.NewQuery("INSERT INTO [format_table_name("player")] VALUES ('[sql_ckey]', Now(), Now(), INET_ATON('[sql_ip]'), '[sql_computerid]', '[sql_admin_rank]', [account_join_date ? "'[account_join_date]'" : "NULL"])") + if(!query_add_player.Execute()) + return + if(!account_join_date) + account_join_date = "Error" + account_age = -1 + var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),firstseen), DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'") + if(!query_get_client_age.Execute()) + return + if(query_get_client_age.NextRow()) + player_age = text2num(query_get_client_age.item[1]) + if(!account_join_date) + account_age = query_get_client_age.item[2] + if(!account_age) + account_join_date = sanitizeSQL(findJoinDate()) + if(!account_join_date) + account_age = -1 + else + var/datum/DBQuery/query_datediff = SSdbcore.NewQuery("SELECT DATEDIFF(Now(),[account_join_date])") + if(!query_datediff.Execute()) + return + if(query_datediff.NextRow()) + account_age = text2num(query_datediff.item[1]) + if(!new_player) + var/datum/DBQuery/query_log_player = SSdbcore.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = INET_ATON('[sql_ip]'), computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]', accountjoindate = [account_join_date ? "'[account_join_date]'" : "NULL"] WHERE ckey = '[sql_ckey]'") + if(!query_log_player.Execute()) + return + if(!account_join_date) + account_join_date = "Error" var/datum/DBQuery/query_log_connection = SSdbcore.NewQuery("INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`server_ip`,`server_port`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),INET_ATON('[world.internet_address]'),'[world.port]','[sql_ckey]',INET_ATON('[sql_ip]'),'[sql_computerid]')") query_log_connection.Execute() +/client/proc/findJoinDate() + var/list/http = world.Export("http://byond.com/members/[ckey]?format=text") + if(!http) + log_world("Failed to connect to byond age check for [ckey]") + return + var/F = file2text(http["CONTENT"]) + if(F) + var/regex/R = regex("joined = \"(\\d{4}-\\d{2}-\\d{2})\"") + if(R.Find(F)) + . = R.group[1] + else + CRASH("Age check regex failed for [src.ckey]") + /client/proc/check_randomizer(topic) . = FALSE if (connection != "seeker") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index e78ec61a3b1..6aaae5f029a 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -265,9 +265,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(config.mutant_races && species_id && (species_id in GLOB.roundstart_species)) var/newtype = GLOB.roundstart_species[species_id] pref_species = new newtype() - else + else if (config.roundstart_races.len) var/rando_race = pick(config.roundstart_races) - pref_species = new rando_race() + if (rando_race) + pref_species = new rando_race() if(!S["features["mcolor"]"] || S["features["mcolor"]"] == "#000") S["features["mcolor"]"] << "#FFF" diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index eea95501a85..eda3abbf39c 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -12,7 +12,7 @@ return if(confirm == "Yes") suiciding = 1 - log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) commited suicide at [get_area(src)].") + log_game("[key_name(src)] (job: [job ? "[job]" : "None"]) committed suicide at [get_area(src)].") var/obj/item/held_item = get_active_held_item() if(held_item) var/damagetype = held_item.suicide_act(src) diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm index 57782a470a1..448bf8a0a31 100644 --- a/code/modules/clothing/spacesuits/flightsuit.dm +++ b/code/modules/clothing/spacesuits/flightsuit.dm @@ -326,9 +326,6 @@ disable_flight(1) if(!suit) disable_flight(1) - if(!resync) - addtimer(CALLBACK(src, .proc/resync), 600) - resync = 1 if(!wearer) //Oh god our user fell off! disable_flight(1) if(!pressure && brake) @@ -340,12 +337,6 @@ stabilizer = FALSE usermessage("Warning: Sensor data is not being recieved from flight shoes. Stabilizers and airbrake modules OFFLINE!", 2) -//Resync the suit -/obj/item/device/flightpack/proc/resync() - resync = FALSE - suit.resync() - -//How fast should the wearer be? /obj/item/device/flightpack/proc/update_slowdown() if(!flight) suit.slowdown = slowdown_ground @@ -356,20 +347,11 @@ /obj/item/device/flightpack/process() if(!suit || (processing_mode == FLIGHTSUIT_PROCESSING_NONE)) return FALSE - update_slowdown() - update_icon() check_conditions() calculate_momentum_speed() momentum_drift() handle_boost() handle_damage() - handle_flight() - -/obj/item/device/flightpack/proc/handle_flight() - if(!flight) - return FALSE - if(wearer) - wearer.float(TRUE) /obj/item/device/flightpack/proc/handle_damage() if(crash_damage) @@ -424,7 +406,6 @@ if(boost_charge < boost_maxcharge) boost_charge = Clamp(boost_charge+boost_chargerate, 0, boost_maxcharge) - /obj/item/device/flightpack/proc/cycle_power() if(powersetting < powersetting_high) powersetting++ @@ -654,6 +635,8 @@ wearer.movement_type |= FLYING wearer.pass_flags |= flight_passflags usermessage("ENGAGING FLIGHT ENGINES.") + update_slowdown() + wearer.floating = TRUE wearer.visible_message("[wearer]'s flight engines activate as they lift into the air!") //I DONT HAVE SOUND EFFECTS YET playsound( flight = TRUE @@ -670,6 +653,8 @@ momentum_x = 0 momentum_y = 0 usermessage("DISENGAGING FLIGHT ENGINES.") + update_slowdown() + wearer.floating = FALSE wearer.visible_message("[wearer] drops to the ground as their flight engines cut out!") //NO SOUND YET playsound( ion_trail.stop() @@ -749,11 +734,13 @@ wearer.visible_message("[wearer.name]'s flightpack engines flare in intensity as they are rocketed forward by the immense thrust!") boost = TRUE update_slowdown() + update_icon() /obj/item/device/flightpack/proc/deactivate_booster() usermessage("Boosters disengaged!") boost = FALSE update_slowdown() + update_icon() /obj/item/device/flightpack/proc/enable_airbrake() if(wearer) diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 56102321220..c3d58ee67d7 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -13,6 +13,8 @@ var/scanning = 0 var/list/log = list() origin_tech = "engineering=4;biotech=2;programming=5" + var/range = 8 + var/view_check = TRUE /obj/item/device/detective_scanner/attack_self(mob/user) if(log.len && !scanning) @@ -43,7 +45,7 @@ log = list() scanning = 0 -/obj/item/device/detective_scanner/pre_attackby(atom/A, mob/user, params) +/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params) scan(A, user) return FALSE @@ -51,9 +53,7 @@ set waitfor = 0 if(!scanning) // Can remotely scan objects and mobs. - if(!in_range(A, user) && !(A in view(world.view, user))) - return - if(loc != user) + if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user)) return scanning = 1 diff --git a/code/modules/jobs/job_types/civilian.dm b/code/modules/jobs/job_types/civilian.dm index 3561e0e60cd..7ae392e55a9 100644 --- a/code/modules/jobs/job_types/civilian.dm +++ b/code/modules/jobs/job_types/civilian.dm @@ -137,11 +137,12 @@ Curator belt = /obj/item/device/pda/curator uniform = /obj/item/clothing/under/rank/curator l_hand = /obj/item/weapon/storage/bag/books - r_pocket = /obj/item/weapon/barcodescanner + r_pocket = /obj/item/key/displaycase l_pocket = /obj/item/device/laser_pointer backpack_contents = list( /obj/item/weapon/melee/curator_whip = 1, - /obj/item/soapstone = 1 + /obj/item/soapstone = 1, + /obj/item/weapon/barcodescanner = 1 ) diff --git a/code/modules/language/draconic.dm b/code/modules/language/draconic.dm new file mode 100644 index 00000000000..aaa998c2c0d --- /dev/null +++ b/code/modules/language/draconic.dm @@ -0,0 +1,20 @@ +/datum/language/draconic + name = "Draconic" + desc = "The common language of lizard-people, composed of sibilant hisses and rattles." + speech_verb = "hisses" + ask_verb = "hisses" + exclaim_verb = "roars" + key = "o" + flags = TONGUELESS_SPEECH + space_chance = 40 + syllables = list( + "za", "az", "ze", "ez", "zi", "iz", "zo", "oz", "zu", "uz", "zs", "sz", + "ha", "ah", "he", "eh", "hi", "ih", "ho", "oh", "hu", "uh", "hs", "sh", + "la", "al", "le", "el", "li", "il", "lo", "ol", "lu", "ul", "ls", "sl", + "ka", "ak", "ke", "ek", "ki", "ik", "ko", "ok", "ku", "uk", "ks", "sk", + "sa", "as", "se", "es", "si", "is", "so", "os", "su", "us", "ss", "ss", + "ra", "ar", "re", "er", "ri", "ir", "ro", "or", "ru", "ur", "rs", "sr", + "a", "a", "e", "e", "i", "i", "o", "o", "u", "u", "s", "s" + ) + icon_state = "lizard" + default_priority = 90 diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm index f01eb2c7006..2f01cd06e0a 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 00000000000..cd0ce23b23f --- /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 43af26a972b..87fc1e0d528 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/dead.dm b/code/modules/mob/dead/dead.dm index bec7ba24fec..8a6250403ff 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -3,9 +3,17 @@ INITIALIZE_IMMEDIATE(/mob/dead) /mob/dead/Initialize() - . = ..() + if(initialized) + stack_trace("Warning: [src]([type]) initialized multiple times!") + initialized = TRUE + tag = "mob_[next_mob_id++]" + GLOB.mob_list += src + + prepare_huds() + if(config.cross_allowed) verbs += /mob/dead/proc/server_hop + return INITIALIZE_HINT_NORMAL /mob/dead/dust() //ghosts can't be vaporised. return diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index aa948343089..5dfea0aaa8b 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -16,12 +16,6 @@ var/mob/living/new_character //for instant transfer once the round is set up /mob/dead/new_player/Initialize() - if(initialized) - stack_trace("Warning: [src]([type]) initialized multiple times!") - initialized = TRUE - tag = "mob_[next_mob_id++]" - GLOB.mob_list += src - if(client && SSticker.state == GAME_STATE_STARTUP) var/obj/screen/splash/S = new(client, TRUE, TRUE) S.Fade(TRUE) @@ -30,7 +24,10 @@ loc = pick(GLOB.newplayer_start) else loc = locate(1,1,1) - return INITIALIZE_HINT_NORMAL + . = ..() + +/mob/dead/new_player/prepare_huds() + return /mob/dead/new_player/proc/new_player_panel() @@ -303,7 +300,7 @@ if(!IsJobAvailable(rank)) alert(src, "[rank] is not available. Please try another.") return 0 - + if(SSticker.late_join_disabled) alert(src, "An administrator has disabled late join spawning.") return FALSE diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 300c4636ea2..2f7f3e3b0bf 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -117,9 +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/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 71b1355ef57..fad2fe82f68 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -20,6 +20,6 @@ to_follow = V.source var/link = FOLLOW_LINK(src, to_follow) // Recompose the message, because it's scrambled by default - message = compose_message(speaker, message_language, raw_message, radio_freq, spans) + message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode) to_chat(src, "[link] [message]") diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index ca380170f73..ca8b8f2d9d5 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -35,22 +35,21 @@ blood_volume += 0.1 // regenerate blood VERY slowly //Effects of bloodloss + var/word = pick("dizzy","woozy","faint") switch(blood_volume) if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) if(prob(5)) - to_chat(src, "You feel [pick("dizzy","woozy","faint")].") + to_chat(src, "You feel [word].") adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1)) if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1)) if(prob(5)) blur_eyes(6) - var/word = pick("dizzy","woozy","faint") to_chat(src, "You feel very [word].") if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) adjustOxyLoss(5) if(prob(15)) Paralyse(rand(1,3)) - var/word = pick("dizzy","woozy","faint") to_chat(src, "You feel extremely [word].") if(0 to BLOOD_VOLUME_SURVIVE) death() @@ -70,7 +69,7 @@ bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases - if(bleed_rate && !bleedsuppress) + if(bleed_rate && !bleedsuppress && !(status_flags & FAKEDEATH)) bleed(bleed_rate) //Makes a blood drop, leaking amt units of blood from the mob diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm index 5751c65b364..0cfbf5d1700 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 cc4ebcda5f0..f9ff1c3018c 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/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index 8a9ee012d9d..f9bd64153e9 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -87,6 +87,8 @@ owner.adjustFireLoss(-heal_amt) owner.adjustOxyLoss(-heal_amt) owner.adjustCloneLoss(-heal_amt) + else + owner.adjustPlasma(plasma_rate * 0.1) /obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0) ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 85f2dfc3e0e..6f213171c4b 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -484,7 +484,7 @@ adjustBruteLoss(3) else if(T) - T.add_vomit_floor(src, 0)//toxic barf looks different + T.add_vomit_floor(src, toxic)//toxic barf looks different nutrition -= lost_nutrition adjustToxLoss(-3) T = get_step(T, dir) @@ -492,6 +492,16 @@ break return 1 +/mob/living/carbon/proc/spew_organ(power = 5) + if(!internal_organs.len) + return //Guess we're out of organs + var/obj/item/organ/guts = pick(internal_organs) + var/turf/T = get_turf(src) + guts.Remove(src) + guts.forceMove(T) + var/atom/throw_target = get_edge_target_turf(guts, dir) + guts.throw_at(throw_target, power, 4, src) + /mob/living/carbon/fully_replace_character_name(oldname,newname) ..() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 8edd807f67e..20f968a9015 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -134,7 +134,7 @@ if(stat == DEAD || (status_flags & FAKEDEATH)) appears_dead = 1 if(suiciding) - msg += "[t_He] appear[p_s()] to have commited suicide... there is no hope of recovery.\n" + msg += "[t_He] appear[p_s()] to have committed suicide... there is no hope of recovery.\n" if(hellbound) msg += "[t_His] soul seems to have been ripped out of [t_his] body. Revival is impossible.\n" msg += "[t_He] [t_is] limp and unresponsive; there are no signs of life" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b43245192c0..f5fd93d7b6d 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -5,11 +5,6 @@ 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 @@ -58,8 +53,9 @@ 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.mutanteyes internal_organs += new dna.species.mutantears + internal_organs += new dna.species.mutanttongue internal_organs += new /obj/item/organ/brain ..() diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index dfebb8905e2..3122201f001 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/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index f87b01c6671..ee2e9a84c49 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -36,7 +36,7 @@ var/say_mod = "says" // affects the speech message var/list/default_features = list() // Default mutant bodyparts for this species. Don't forget to set one for every mutant bodypart you allow this species to have. var/list/mutant_bodyparts = list() // Parts of the body that are diferent enough from the standard human model that they cause clipping with some equipment - var/list/mutant_organs = list(/obj/item/organ/tongue) //Internal organs that are unique to this race. + var/list/mutant_organs = list() //Internal organs that are unique to this race. var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster var/armor = 0 // overall defense for the race... or less defense, if it's negative. var/brutemod = 1 // multiplier for brute damage @@ -66,15 +66,10 @@ //Flight and floating var/override_float = 0 - - //Eyes var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes - - //Ears var/obj/item/organ/ears/mutantears = /obj/item/organ/ears - - //Hands var/obj/item/mutanthands = null + var/obj/item/organ/tongue/mutanttongue = /obj/item/organ/tongue /////////// // PROCS // @@ -132,6 +127,7 @@ var/obj/item/organ/appendix/appendix = C.getorganslot("appendix") var/obj/item/organ/eyes/eyes = C.getorganslot("eye_sight") var/obj/item/organ/ears/ears = C.getorganslot("ears") + var/obj/item/organ/tongue/tongue = C.getorganslot("tongue") if((NOBLOOD in species_traits) && heart) heart.Remove(C) @@ -155,6 +151,11 @@ ears = new mutantears ears.Insert(C) + if(tongue) + qdel(tongue) + tongue = new mutanttongue + tongue.Insert(C) + if((!(NOBREATH in species_traits)) && !lungs) if(mutantlungs) lungs = new mutantlungs() @@ -354,23 +355,24 @@ standing += eye_overlay //Underwear, Undershirts & Socks - if(H.underwear) - var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear] - if(underwear) - standing += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER) + if(!(NO_UNDERWEAR in species_traits)) + if(H.underwear) + var/datum/sprite_accessory/underwear/underwear = GLOB.underwear_list[H.underwear] + if(underwear) + standing += mutable_appearance(underwear.icon, underwear.icon_state, -BODY_LAYER) - if(H.undershirt) - var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt] - if(undershirt) - if(H.dna.species.sexes && H.gender == FEMALE) - standing += wear_female_version(undershirt.icon_state, undershirt.icon, -BODY_LAYER) - else - standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) + if(H.undershirt) + var/datum/sprite_accessory/undershirt/undershirt = GLOB.undershirt_list[H.undershirt] + if(undershirt) + if(H.dna.species.sexes && H.gender == FEMALE) + standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER) + else + standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER) - if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits)) - var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks] - if(socks) - standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER) + if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits)) + var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks] + if(socks) + standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER) if(standing.len) H.overlays_standing[BODY_LAYER] = standing diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 0b8ca1500d7..18444bb366d 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -4,6 +4,6 @@ say_mod = "gibbers" sexes = 0 species_traits = list(NOBLOOD,NOBREATH,VIRUSIMMUNE,NOGUNS,NOHUNGER) - mutant_organs = list(/obj/item/organ/tongue/abductor) + mutanttongue = /obj/item/organ/tongue/abductor var/scientist = 0 // vars to not pollute spieces list with castes - var/team = 1 \ No newline at end of file + var/team = 1 diff --git a/code/modules/mob/living/carbon/human/species_types/android.dm b/code/modules/mob/living/carbon/human/species_types/android.dm index 748bd238b2f..44f1e5c456a 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -5,7 +5,7 @@ species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOBLOOD,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYLIMBATTACHMENT) meat = null damage_overlay_type = "synth" - mutant_organs = list(/obj/item/organ/tongue/robot) + mutanttongue = /obj/item/organ/tongue/robot limbs_id = "synth" /datum/species/android/on_species_gain(mob/living/carbon/C) @@ -18,4 +18,4 @@ . = ..() for(var/X in C.bodyparts) var/obj/item/bodypart/O = X - O.change_bodypart_status(BODYPART_ORGANIC,FALSE, TRUE) \ No newline at end of file + O.change_bodypart_status(BODYPART_ORGANIC,FALSE, TRUE) diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index 8aae311330b..e77e424d405 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -2,7 +2,7 @@ name = "Flyperson" id = "fly" say_mod = "buzzes" - mutant_organs = list(/obj/item/organ/tongue/fly) + mutanttongue = /obj/item/organ/tongue/fly meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/fly /datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index fd8b8f4f250..52145f609b6 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -2,7 +2,8 @@ // Animated beings of stone. They have increased defenses, and do not need to breathe. They're also slow as fuuuck. name = "Golem" id = "iron golem" - species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS) + species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS,NO_UNDERWEAR) + mutant_organs = list(/obj/item/organ/adamantine_resonator) speedmod = 2 armor = 55 siemens_coeff = 0 @@ -54,8 +55,9 @@ name = "Adamantine Golem" id = "adamantine golem" meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine + mutant_organs = list(/obj/item/organ/adamantine_resonator, /obj/item/organ/vocal_cords/adamantine) fixed_mut_color = "4ed" - info_text = "As an Adamantine Golem, you don't have any special traits." + info_text = "As an Adamantine Golem, you possess special vocal cords allowing you to \"resonate\" messages to all golems." prefix = "Adamantine" //Explodes on death @@ -65,7 +67,7 @@ fixed_mut_color = "a3d" meat = /obj/item/weapon/ore/plasma //Can burn and takes damage from heat - species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS) + species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS,NO_UNDERWEAR) info_text = "As a Plasma Golem, you explode on death!" burnmod = 1.5 prefix = "Plasma" @@ -194,7 +196,7 @@ fixed_mut_color = "49311c" meat = /obj/item/stack/sheet/mineral/wood //Can burn and take damage from heat - species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS) + species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS,NO_UNDERWEAR) armor = 30 burnmod = 1.25 heatmod = 1.5 @@ -504,7 +506,7 @@ limbs_id = "cultgolem" sexes = FALSE info_text = "As a Runic Golem, you possess eldritch powers granted by the Elder God Nar'Sie." - species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER) //no mutcolors + species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOFIRE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR) //no mutcolors prefix = "Runic" var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/golem/phase_shift @@ -553,7 +555,7 @@ limbs_id = "clothgolem" sexes = FALSE info_text = "As a Cloth Golem, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable." - species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER) //no mutcolors, and can burn + species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,NO_UNDERWEAR) //no mutcolors, and can burn armor = 15 //feels no pain, but not too resistant burnmod = 2 // don't get burned speedmod = 1 // not as heavy as stone @@ -643,4 +645,4 @@ if(P.is_hot()) visible_message("[src] bursts into flames!") - fire_act() \ No newline at end of file + fire_act() diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 45007140dc4..4c6a06a17a8 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -6,7 +6,7 @@ default_color = "00FF00" species_traits = list(MUTCOLORS,EYECOLOR,LIPS) mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs") - mutant_organs = list(/obj/item/organ/tongue/lizard) + mutanttongue = /obj/item/organ/tongue/lizard coldmod = 1.5 heatmod = 0.67 default_features = list("mcolor" = "0F0", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Normal Legs") @@ -17,6 +17,9 @@ skinned_type = /obj/item/stack/sheet/animalhide/lizard exotic_bloodtype = "L" +/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H) + H.grant_language(/datum/language/draconic) + /datum/species/lizard/random_name(gender,unique,lastname) if(unique) return random_unique_lizard_name(gender) diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 09d89d3a01a..664eabefcdd 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -6,7 +6,7 @@ meat = /obj/item/stack/sheet/mineral/plasma species_traits = list(NOBLOOD,RESISTCOLD,RADIMMUNE,NOTRANSSTING,VIRUSIMMUNE,NOHUNGER) mutantlungs = /obj/item/organ/lungs/plasmaman - mutant_organs = list(/obj/item/organ/tongue/bone/plasmaman) + mutanttongue = /obj/item/organ/tongue/bone/plasmaman dangerous_existence = 1 //So so much blacklisted = 1 //See above burnmod = 1.5 @@ -66,4 +66,4 @@ if(lastname) randname += " [lastname]" - return randname \ No newline at end of file + return randname diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 152f708ab57..077d85c32e2 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 039b40b2341..ed1f5f08b55 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 0421ccabefd..92725d73a65 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 7f3253ec295..3531dfc7a66 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 b0ab3b27af4..8bc21c4b41b 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/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index 11091d97181..672df66804a 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -106,4 +106,4 @@ /mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode) if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker)) - ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans) + ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index fe3a24cef05..f7e568aac95 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 ca4a15beea3..c556b1f709d 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 b3cf47d642c..caf63892c57 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 2cbbd0d5b17..12dc0a880c5 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 7cd6567ecb0..5c78995be9e 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" @@ -108,10 +109,10 @@ speak_emote = list("clanks", "clinks", "clunks", "clangs") verb_ask = "requests" verb_exclaim = "proclaims" + verb_whisper = "imparts" 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 d822a058864..cd2f11f399e 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -401,7 +401,7 @@ Difficulty: Very Hard to_chat(user, observer_desc) to_chat(user, "It is activated by [activation_method].") -/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans) +/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) ..() if(isliving(speaker)) ActivationReaction(speaker, ACTIVATE_SPEECH) @@ -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 8db43623dcf..767d869c8f0 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/say.dm b/code/modules/mob/living/simple_animal/slime/say.dm index ae7c14068f6..60a25f90b70 100644 --- a/code/modules/mob/living/simple_animal/slime/say.dm +++ b/code/modules/mob/living/simple_animal/slime/say.dm @@ -1,4 +1,4 @@ -/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans) +/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode) if(speaker != src && !radio_freq && !stat) if (speaker in Friends) speech_buffer = list() diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 11a6ca71608..352b7b3b5ef 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("telepathically chirps") 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 4080601971c..d3a002a4a56 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -350,7 +350,7 @@ /mob/proc/spin(spintime, speed) set waitfor = 0 var/D = dir - if((spintime <= 1)||(speed <= 1)||!spintime||!speed) + if((spintime < 1)||(speed < 1)||!spintime||!speed) return while(spintime >= speed) sleep(speed) @@ -742,7 +742,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 @@ -1005,3 +1004,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/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 9deebdfe10a..7d0d4fdbb5f 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -26,8 +26,8 @@ grav_pull = 10 consume_range = 12 //How many tiles out do we eat -/obj/singularity/narsie/large/New() - ..() +/obj/singularity/narsie/large/Initialize() + . = ..() send_to_playing_players("NAR-SIE HAS RISEN") send_to_playing_players(pick('sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg')) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 3b0bc3087b0..1a308ed4712 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -29,12 +29,12 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF dangerous_possession = TRUE -/obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0) +/obj/singularity/Initialize(mapload, starting_energy = 50) //CARN: admin-alert for chuckle-fuckery. admin_investigate_setup() src.energy = starting_energy - ..() + . = ..() START_PROCESSING(SSobj, src) GLOB.poi_list |= src GLOB.singularities |= src diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index fbb82cb36a7..df088991407 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -40,6 +40,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp var/energy_to_raise = 32 var/energy_to_lower = -20 +/obj/singularity/energy_ball/Initialize(mapload, starting_energy = 50, is_miniball = FALSE) + . = ..() + if(!is_miniball) + set_light(10, 7, "#EEEEFF") + /obj/singularity/energy_ball/ex_act(severity, target) return @@ -54,6 +59,11 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp . = ..() +/obj/singularity/energy_ball/admin_investigate_setup() + if(istype(loc, /obj/singularity/energy_ball)) + return + ..() + /obj/singularity/energy_ball/process() if(!orbiting) handle_energy() @@ -117,7 +127,7 @@ GLOBAL_LIST_INIT(blacklisted_tesla_types, typecacheof(list(/obj/machinery/atmosp /obj/singularity/energy_ball/proc/new_mini_ball() if(!loc) return - var/obj/singularity/energy_ball/EB = new(loc) + var/obj/singularity/energy_ball/EB = new(loc, 0, TRUE) EB.transform *= pick(0.3, 0.4, 0.5, 0.6, 0.7) var/icon/I = icon(icon,icon_state,dir) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 005389fa6f3..3dedaa9ae1c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -179,6 +179,8 @@ return if(setAngle) Angle = setAngle + var/old_pixel_x = pixel_x + var/old_pixel_y = pixel_y if(!legacy) //new projectiles set waitfor = 0 var/next_run = world.time @@ -201,29 +203,30 @@ var/Pixel_x=round((sin(Angle)+16*sin(Angle)*2), 1) //round() is a floor operation when only one argument is supplied, we don't want that here var/Pixel_y=round((cos(Angle)+16*cos(Angle)*2), 1) - var/pixel_x_offset = pixel_x + Pixel_x - var/pixel_y_offset = pixel_y + Pixel_y + var/pixel_x_offset = old_pixel_x + Pixel_x + var/pixel_y_offset = old_pixel_y + Pixel_y var/new_x = x var/new_y = y while(pixel_x_offset > 16) pixel_x_offset -= 32 - pixel_x -= 32 + old_pixel_x -= 32 new_x++// x++ while(pixel_x_offset < -16) pixel_x_offset += 32 - pixel_x += 32 + old_pixel_x += 32 new_x-- - while(pixel_y_offset > 16) pixel_y_offset -= 32 - pixel_y -= 32 + old_pixel_y -= 32 new_y++ while(pixel_y_offset < -16) pixel_y_offset += 32 - pixel_y += 32 + old_pixel_y += 32 new_y-- - + + pixel_x = old_pixel_x + pixel_y = old_pixel_y step_towards(src, locate(new_x, new_y, z)) next_run += max(world.tick_lag, speed) var/delay = next_run - world.time @@ -232,7 +235,9 @@ pixel_y = pixel_y_offset else animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW) - + old_pixel_x = pixel_x_offset + old_pixel_y = pixel_y_offset + if(original && (original.layer>=2.75) || ismob(original)) if(loc == get_turf(original)) if(!(original in permutated)) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 442772fea84..56a89fe389f 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -60,7 +60,10 @@ // data for nutriment is one or more (flavour -> ratio) // where all the ratio values adds up to 1 - var/list/taste_amounts = data.Copy() + var/list/taste_amounts = list() + if(data) + taste_amounts = data.Copy() + counterlist_scale(taste_amounts, volume) var/list/other_taste_amounts = newdata.Copy() diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 500147d2334..434161fa517 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -962,8 +962,7 @@ /datum/reagent/medicine/antitoxin/on_mob_life(mob/living/M) M.adjustToxLoss(-2*REM, 0) for(var/datum/reagent/toxin/R in M.reagents.reagent_list) - if(R != src) - M.reagents.remove_reagent(R.id,1) + M.reagents.remove_reagent(R.id,1) ..() . = 1 diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 528124f84c6..cedec9941b7 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -648,6 +648,34 @@ M.losebreath += 5 return ..() +/datum/reagent/toxin/spewium + name = "Spewium" + id = "spewium" + description = "A powerful emetic, causes uncontrollable vomiting. May result in vomiting organs at high doses." + reagent_state = LIQUID + color = "#2f6617" //A sickly green color + metabolization_rate = REAGENTS_METABOLISM + overdose_threshold = 29 + toxpwr = 0 + taste_description = "vomit" + +/datum/reagent/toxin/spewium/on_mob_life(mob/living/M) + .=..() + if(current_cycle >=11 && prob(min(50,current_cycle)) && ishuman(M)) + var/mob/living/carbon/human/H = M + H.vomit(lost_nutrition = 10, blood = prob(10), stun = prob(50), distance = rand(0,4), message = TRUE, toxic = prob(30)) + for(var/datum/reagent/toxin/R in M.reagents.reagent_list) + if(R != src) + H.reagents.remove_reagent(R.id,1) + +/datum/reagent/toxin/spewium/overdose_process(mob/living/M) + . = ..() + if(current_cycle >=33 && prob(15) && ishuman(M)) + var/mob/living/carbon/human/H = M + H.spew_organ() + H.vomit(lost_nutrition = 0, blood = 1, stun = 1, distance = 4) + to_chat(H, "You feel something lumpy come up as you vomit.") + /datum/reagent/toxin/curare name = "Curare" id = "curare" diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index e67557919e4..f06dff50cfb 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -478,26 +478,15 @@ ..() //Adamantine -/datum/chemical_reaction/slime/slimegolem - name = "Slime Golem" - id = "m_golem" +/datum/chemical_reaction/slime/adamantine + name = "Adamantine" + id = "adamantine" required_reagents = list("plasma" = 1) required_container = /obj/item/slime_extract/adamantine required_other = 1 -/datum/chemical_reaction/slime/slimegolem/on_reaction(datum/reagents/holder) - new /obj/effect/golemrune(get_turf(holder.my_atom)) - ..() - -/datum/chemical_reaction/slime/slimegolem2 - name = "Slime Golem 2" - id = "m_golem2" - required_reagents = list("iron" = 1) - required_container = /obj/item/slime_extract/adamantine - required_other = 1 - -/datum/chemical_reaction/slime/slimegolem2/on_reaction(datum/reagents/holder) - new /obj/item/golem_shell/artificial(get_turf(holder.my_atom)) +/datum/chemical_reaction/slime/adamantine/on_reaction(datum/reagents/holder) + new /obj/item/stack/sheet/mineral/adamantine(get_turf(holder.my_atom)) ..() //Bluespace diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index a92c52abf47..37074b6d121 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -58,6 +58,12 @@ icon_state = "bottle12" list_reagents = list("cyanide" = 30) +/obj/item/weapon/reagent_containers/glass/bottle/spewium + name = "spewium bottle" + desc = "A small bottle of spewium." + icon_state = "bottle12" + list_reagents = list("spewium" = 30) + /obj/item/weapon/reagent_containers/glass/bottle/morphine name = "morphine bottle" desc = "A small bottle of morphine." diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index e427400553f..bdd85ae4d46 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -104,6 +104,9 @@ if(istype(O, /obj/item/stack/medical/gauze) || istype(O, /obj/item/stack/sheet/cloth)) species = /datum/species/golem/cloth + if(istype(O, /obj/item/stack/sheet/mineral/adamantine)) + species = /datum/species/golem/adamantine + if(species) if(O.use(10)) to_chat(user, "You finish up the golem shell with ten sheets of [O].") diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 78732d82e4b..aa28f2402c6 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/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 14a5409e986..b8296a1da5b 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -69,6 +69,24 @@ action_icon_state = "smoke" + +/obj/effect/proc_holder/spell/targeted/smoke/lesser //Chaplain smoke book + name = "Smoke" + desc = "This spell spawns a small cloud of choking smoke at your location." + + school = "conjuration" + charge_max = 360 + clothes_req = 0 + invocation = "none" + invocation_type = "none" + range = -1 + include_user = 1 + + smoke_spread = 1 + smoke_amt = 2 + + action_icon_state = "smoke" + /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech name = "Disable Tech" desc = "This spell disables all weapons, cameras and most other technology in range." diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index c8f0ade4b8d..585f452de49 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -218,6 +218,14 @@ for(var/X in list(owner.glasses, owner.ears, owner.wear_mask, owner.head)) var/obj/item/I = X owner.dropItemToGround(I, TRUE) + + //Handle dental implants + for(var/datum/action/item_action/hands_free/activate_pill/AP in owner.actions) + AP.Remove(owner) + var/obj/pill = AP.target + if(pill) + pill.forceMove(src) + name = "[owner.real_name]'s head" ..() @@ -305,6 +313,14 @@ C.real_name = real_name real_name = "" name = initial(name) + + //Handle dental implants + for(var/obj/item/weapon/reagent_containers/pill/P in src) + for(var/datum/action/item_action/hands_free/activate_pill/AP in P.actions) + P.forceMove(C) + AP.Grant(C) + break + ..() diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 909f83e4d71..dd635060864 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -48,7 +48,10 @@ brain = null update_icon_dropped() else - I.loc = T + if(istype(I, /obj/item/weapon/reagent_containers/pill)) + for(var/datum/action/item_action/hands_free/activate_pill/AP in I.actions) + qdel(AP) + I.forceMove(T) /obj/item/bodypart/head/update_limb(dropping_limb, mob/living/carbon/source) var/mob/living/carbon/C diff --git a/code/modules/surgery/dental_implant.dm b/code/modules/surgery/dental_implant.dm index eef88e4a5ff..c51a49081cf 100644 --- a/code/modules/surgery/dental_implant.dm +++ b/code/modules/surgery/dental_implant.dm @@ -18,10 +18,10 @@ user.drop_item() tool.loc = target - var/datum/action/item_action/hands_free/activate_pill/P = new + var/datum/action/item_action/hands_free/activate_pill/P = new(tool) P.button.name = "Activate [tool.name]" P.target = tool - P.Grant(target) + P.Grant(target) //The pill never actually goes in an inventory slot, so the owner doesn't inherit actions from it user.visible_message("[user] wedges \the [tool] into [target]'s [parse_zone(target_zone)]!", "You wedge [tool] into [target]'s [parse_zone(target_zone)].") return 1 @@ -37,6 +37,5 @@ if(target.reagents.total_volume) target.reagents.reaction(owner, INGEST) target.reagents.trans_to(owner, target.reagents.total_volume) - Remove(owner) qdel(target) return 1 \ No newline at end of file diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 9dbca40558b..e27337a813e 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -125,16 +125,13 @@ if(!getorganslot("tongue")) var/obj/item/organ/tongue/T - if(dna && dna.species) - for(var/tongue_type in dna.species.mutant_organs) - if(ispath(tongue_type, /obj/item/organ/tongue)) - T = new tongue_type() - T.Insert(src) + if(dna && dna.species && dna.species.mutanttongue) + T = new dna.species.mutanttongue() + else + T = new() // if they have no mutant tongues, give them a regular one - if(!T) - T = new() - T.Insert(src) + T.Insert(src) if(!getorganslot("eye_sight")) var/obj/item/organ/eyes/E diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index c02c22d19e0..f3f9d7a8cd1 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -13,6 +13,7 @@ . = ..() languages_possible = typecacheof(list( /datum/language/common, + /datum/language/draconic, /datum/language/monkey, /datum/language/ratvar )) @@ -33,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 @@ -127,6 +128,7 @@ languages_possible = typecacheof(list( /datum/language/xenocommon, /datum/language/common, + /datum/language/draconic, /datum/language/ratvar, /datum/language/monkey)) @@ -183,16 +185,8 @@ attack_verb = list("beeped", "booped") taste_sensitivity = 25 // not as good as an organic tongue -/obj/item/organ/tongue/robot/Initialize(mapload) - . = ..() - languages_possible = typecacheof(list( - /datum/language/xenocommon, - /datum/language/common, - /datum/language/ratvar, - /datum/language/monkey, - /datum/language/drone, - /datum/language/machine, - /datum/language/swarmer)) +/obj/item/organ/tongue/robot/can_speak_in_language(datum/language/dt) + . = TRUE // THE MAGIC OF ELECTRONICS /obj/item/organ/tongue/robot/get_spans() return ..() | SPAN_ROBOT diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 50f66fef27e..e817557cc25 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -20,6 +20,40 @@ /obj/item/organ/vocal_cords/proc/handle_speech(message) //actually say the message owner.say(message, spans = spans, sanitize = FALSE) +/obj/item/organ/adamantine_resonator + name = "adamantine resonator" + desc = "Fragments of adamantine exists in all golems, stemming from their origins as purely magical constructs. These are used to \"hear\" messages from their leaders." + zone = "head" + slot = "adamantine_resonator" + icon_state = "adamantine_resonator" + +/obj/item/organ/vocal_cords/adamantine + name = "adamantine vocal cords" + desc = "When adamantine resonates, it causes all nearby pieces of adamantine to resonate as well. Adamantine golems use this to broadcast messages to nearby golems." + actions_types = list(/datum/action/item_action/organ_action/use/adamantine_vocal_cords) + zone = "mouth" + slot = "vocal_cords" + icon_state = "adamantine_cords" + +/datum/action/item_action/organ_action/use/adamantine_vocal_cords/Trigger() + if(!IsAvailable()) + return + var/message = input(owner, "Resonate a message to all nearby golems.", "Resonate") + if(QDELETED(src) || QDELETED(owner) || !message) + return + owner.say(".x[message]") + +/obj/item/organ/vocal_cords/adamantine/handle_speech(message) + var/msg = "[owner.real_name] resonates, \"[message]\"" + for(var/m in GLOB.player_list) + if(iscarbon(m)) + var/mob/living/carbon/C = m + if(C.getorganslot("adamantine_resonator")) + to_chat(C, msg) + if(isobserver(m)) + var/link = FOLLOW_LINK(m, src) + to_chat(m, "[link] [msg]") + //Colossus drop, forces the listeners to obey certain commands /obj/item/organ/vocal_cords/colossus name = "divine vocal cords" diff --git a/code/modules/tgui/states/language_menu.dm b/code/modules/tgui/states/language_menu.dm index 4a370e82130..fedc4320e47 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/code/world.dm b/code/world.dm index c46e3a9fb82..42326f6ba69 100644 --- a/code/world.dm +++ b/code/world.dm @@ -42,7 +42,7 @@ else log_world("Your server failed to establish a connection with the database.") if(!GLOB.round_id) - GLOB.log_directory += "[time_stamp()]" + GLOB.log_directory += "[replacetext(time_stamp(), ":", ".")]" GLOB.world_game_log = file("[GLOB.log_directory]/game.log") GLOB.world_attack_log = file("[GLOB.log_directory]/attack.log") GLOB.world_runtime_log = file("[GLOB.log_directory]/runtime.log") @@ -250,7 +250,7 @@ /world/proc/RoundEndAnimation(round_end_sound_sent) set waitfor = FALSE var/round_end_sound - if(!SSticker && SSticker.round_end_sound) + if(SSticker.round_end_sound) round_end_sound = SSticker.round_end_sound if (!round_end_sound_sent) for(var/thing in GLOB.clients) diff --git a/config/config.txt b/config/config.txt index 07cd2c1f874..ca4486d7e47 100644 --- a/config/config.txt +++ b/config/config.txt @@ -251,6 +251,10 @@ EXTREME_POPCAP_MESSAGE The server is currently serving a high number of users, f ## Requres database NOTIFY_NEW_PLAYER_AGE 0 +## Notify admins when a player connects if their byond account was created in the last X days +## Requires database +NOTIFY_NEW_PLAYER_ACCOUNT_AGE 1 + ## Notify the irc channel when a new player makes their first connection ## Requres database #IRC_FIRST_CONNECTION_ALERT diff --git a/config/jobs.txt b/config/jobs.txt index 3b65a6a9b8d..a0c1ffa970b 100644 --- a/config/jobs.txt +++ b/config/jobs.txt @@ -22,7 +22,7 @@ Janitor=2,1 Clown=1,1 Mime=1,1 -Librarian=1,1 +Curator=1,1 Lawyer=2,2 Chaplain=1,1 diff --git a/html/changelog.html b/html/changelog.html index 575ee862cc1..222dbcc4afd 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,13 +55,91 @@ -->
+

05 May 2017

+

Incoming updated:

+
    +
  • Display cases now require a key to open, which the curator spawns with
  • +
+

Joan updated:

+
    +
  • Sigil of Accession, Fellowship Armory, Memory Allocation, Anima Fragment, and Sigil of Transmission are not affected by the previously-mentioned % reduction to Application scripture costs.
  • +
+

LanCartwright updated:

+
    +
  • Lesser smoke book to Delta and Metastation
  • +
  • Normal smoke book from Delta and Metastation
  • +
  • Civilian smoke book now has a 360 max cooldown (from 120) and halved smoke output.
  • +
+

QualityVan updated:

+
    +
  • Dental implants stay with the head they're in
  • +
+

bgobandit updated:

+
    +
  • The Syndicate has added basic functionality to their state-of-the-art equipment. Nuke ops can now donate all TCs at once.
  • +
+

lordpidey updated:

+
    +
  • There is a new traitor poison, spewium. It will cause uncontrollable vomiting, which gets worse the longer it's in your system. An overdose can cause vomiting of organs.
  • +
  • Committing suicide with a gas pump can now shoot out random organs.
  • +
  • Toxic vomit now shows up as intended.
  • +
+ +

04 May 2017

+

4dplanner updated:

+
    +
  • revenants now properly resurrect from ectoplasm, as opposed to ectoplasm merely spawning a new grief ghost
  • +
  • Turrets can no longer see invisible things, such as unrevealed revenants
  • +
+

Joan updated:

+
    +
  • Mania Motors now do minor toxin damage over time and will convert those affected if the toxin damage is high enough.
  • +
  • The effects of a Mania Motor continue to apply to targets after they leave its range, though they will fall off extremely quickly.
  • +
  • Mania Motors no longer cause brain damage.
  • +
  • Ratvarian Spears have new inhand icons.
  • +
+

Lzimann updated:

+
    +
  • Gang game mode was removed
  • +
+

Moonlighting Mac says updated:

+
    +
  • Courtesy of the art & crafts division, imitation basalt tiles themed on the rough volcanic terrain of lavaland are now available to be made out of sandstone.
  • +
  • The manufacturer even managed to replicate the way that it lights up with volcanic energy, it is the perfect accompaniment to other fake (or real) lava-land tiles or a independent piece.
  • +
+

QualityVan updated:

+
    +
  • Point flashlights at mouths to see what's inside them
  • +
+

03 May 2017

+

BeeSting12 updated:

+
    +
  • Omega shuttle now has lighting.
  • +
+

Joan updated:

+
    +
  • Clockwork component generation is twice as fast.
  • +
  • Scriptures cost up to twice as much; Driver scriptures are unaffected, meaning they cost 50% less, Script scriptures cost 25% less, Application scriptures cost about 12.5% less, and Revenant scriptures cost about 5% less.
  • +

Jordie0608 updated:

  • Investigate logs are now persistent.
  • Game logs are now stored per-round; use .getserverlog to access previous rounds.
  • .giveruntimelog and .getruntimelog removed.
+

Kor, Profakos, Iamgoofball updated:

+
    +
  • The Librarian has been replaced by the Curator.
  • +
  • Persistent trophy cases have been added to the library on Meta, Delta, and Box. These are only usable by the Curator.
  • +
  • The Curator now starts with his whip.
  • +
  • The Curator now has access to his treasure hunter outfit, stashed in his private office.
  • +
+

coiax updated:

+
    +
  • Plasma vessels, the organs inside aliens that are responsible for their internal plasma storage, will regenerate small amounts of plasma even if the owner is not on resin weeds.
  • +
  • Restrictions on Lizardpeople using their native language on the station have been lifted by Centcom, in order to maximise worker productivity. The language's key is ",o".
  • +

deathride58 updated:

  • Fixed the slimecore HUD's neck slot sprite.
  • @@ -1261,58 +1339,6 @@
  • Admin ghosts can just click directly on the CTF controller to enable them, in addition to using the Secrets panel.
  • Cyborg radios can no longer have their inaccessible wires pulsed by EMPs.
- -

03 March 2017

-

Cyberboss updated:

-
    -
  • You can now repair shuttles in transit space
  • -
-

Incoming5643 updated:

-
    -
  • Server Owners: There is a new system for title screens accessible from config/title_screen folder.
  • -
  • This system allows for multiple rotating title screens as well as map specific title screens.
  • -
  • It also allows for hosting title screens in formats other than DMI.
  • -
  • See the readme.txt in config/title_screen for full details. remove: The previous method of title screen selection, the define TITLESCREEN, has been depreciated by this change.
  • -
-

Sligneris updated:

-
    -
  • Updated sprites for the small xeno queen mode
  • -
- -

02 March 2017

-

Gun Hog updated:

-
    -
  • Advanced camera, Slime Management, and Base Construction consoles may now be operated by drones and cyborgs.
  • -
-

Robustin updated:

-
    -
  • The syndicate power beacon will now announce the distance and direction of any engines every 10 seconds.
  • -
-

Steelpoint updated:

-
    -
  • Robotics and Mech Bay have seen a mapping overhaul on Boxstation.
  • -
  • A cautery surgical tool has been added to the Robotics surgical area on Boxstation.
  • -
-

XDTM updated:

-
    -
  • Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
  • -
  • Added some new hallucinations.
  • -
  • Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
  • -
-

coiax updated:

-
    -
  • Ghosts are polled if they want to play an alien larva that is about to chestburst. They are also told who is the (un)lucky victim.
  • -
  • Clones no longer gasp for air while in cloning pods.
  • -
  • Adds a new reagent, "Mime's Bane", that prevents all emoting while it is in a victim's system. Currently admin only.
  • -
  • Mappers now have an easier time adding posters, and specifying whether they're random, random official, random contraband or a specific poster.
  • -
  • Posters no longer have serial numbers when rolled up; their names are visible instead.
  • -
-

kevinz000 updated:

-
    -
  • You can now craft pressure plates.
  • -
  • Pressure plates are hidden under the floor like smuggler satchels are, but you can attach a signaller to them to have it signal when a mob passes over them!
  • -
  • Bomb armor is now effective in lessening the chance of being knocked out by bombs.
  • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 86571b113cd..2193515d58f 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -10833,10 +10833,76 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscadd: When talking on the alien hivemind, a person will be identified by their real name, rather than who they are disguised as. 2017-05-03: + BeeSting12: + - bugfix: Omega shuttle now has lighting. + Joan: + - balance: Clockwork component generation is twice as fast. + - balance: Scriptures cost up to twice as much; Driver scriptures are unaffected, + meaning they cost 50% less, Script scriptures cost 25% less, Application scriptures + cost about 12.5% less, and Revenant scriptures cost about 5% less. Jordie0608: - rscadd: Investigate logs are now persistent. - tweak: Game logs are now stored per-round; use .getserverlog to access previous rounds. - rscdel: .giveruntimelog and .getruntimelog removed. + Kor, Profakos, Iamgoofball: + - rscadd: The Librarian has been replaced by the Curator. + - rscadd: Persistent trophy cases have been added to the library on Meta, Delta, + and Box. These are only usable by the Curator. + - rscadd: The Curator now starts with his whip. + - rscadd: The Curator now has access to his treasure hunter outfit, stashed in his + private office. + coiax: + - balance: Plasma vessels, the organs inside aliens that are responsible for their + internal plasma storage, will regenerate small amounts of plasma even if the + owner is not on resin weeds. + - rscadd: Restrictions on Lizardpeople using their native language on the station + have been lifted by Centcom, in order to maximise worker productivity. The language's + key is ",o". deathride58: - tweak: Fixed the slimecore HUD's neck slot sprite. +2017-05-04: + 4dplanner: + - bugfix: revenants now properly resurrect from ectoplasm, as opposed to ectoplasm + merely spawning a new grief ghost + - bugfix: Turrets can no longer see invisible things, such as unrevealed revenants + Joan: + - rscadd: Mania Motors now do minor toxin damage over time and will convert those + affected if the toxin damage is high enough. + - balance: The effects of a Mania Motor continue to apply to targets after they + leave its range, though they will fall off extremely quickly. + - rscdel: Mania Motors no longer cause brain damage. + - imageadd: Ratvarian Spears have new inhand icons. + Lzimann: + - rscdel: Gang game mode was removed + Moonlighting Mac says: + - rscadd: Courtesy of the art & crafts division, imitation basalt tiles themed on + the rough volcanic terrain of lavaland are now available to be made out of sandstone. + - experiment: The manufacturer even managed to replicate the way that it lights + up with volcanic energy, it is the perfect accompaniment to other fake (or real) + lava-land tiles or a independent piece. + QualityVan: + - rscadd: Point flashlights at mouths to see what's inside them +2017-05-05: + Incoming: + - tweak: Display cases now require a key to open, which the curator spawns with + Joan: + - balance: Sigil of Accession, Fellowship Armory, Memory Allocation, Anima Fragment, + and Sigil of Transmission are not affected by the previously-mentioned % reduction + to Application scripture costs. + LanCartwright: + - rscadd: Lesser smoke book to Delta and Metastation + - rscdel: Normal smoke book from Delta and Metastation + - tweak: Civilian smoke book now has a 360 max cooldown (from 120) and halved smoke + output. + QualityVan: + - bugfix: Dental implants stay with the head they're in + bgobandit: + - tweak: The Syndicate has added basic functionality to their state-of-the-art equipment. + Nuke ops can now donate all TCs at once. + lordpidey: + - rscadd: There is a new traitor poison, spewium. It will cause uncontrollable + vomiting, which gets worse the longer it's in your system. An overdose can + cause vomiting of organs. + - tweak: Committing suicide with a gas pump can now shoot out random organs. + - bugfix: Toxic vomit now shows up as intended. diff --git a/html/changelogs/AutoChangeLog-pr-26772.yml b/html/changelogs/AutoChangeLog-pr-26772.yml new file mode 100644 index 00000000000..608a0902493 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26772.yml @@ -0,0 +1,14 @@ +author: "coiax" +delete-after: True +changes: + - rscadd: "Adamantine golems have special vocal cords that allow them to send +one-way messages to all golems, due to fragments of resonating +adamantine in their heads. Both of these are organs, and can be removed +and put in other species." + - rscadd: "You can use adamantine vocal cords by prefixing your message with +\":x\"." + - rscdel: "Xenobiology is no longer capable of making golem runes with plasma. +Instead, inject plasma into the adamantine slime core to get bars of adamantine +which you can then craft into an incomplete golem shell. Add 10 sheets of +suitable material to finish the shell." + - experiment: "The metal adamantine is also quite valuable when sold via cargo." diff --git a/html/changelogs/AutoChangeLog-pr-26776.yml b/html/changelogs/AutoChangeLog-pr-26776.yml new file mode 100644 index 00000000000..bf9411c7a16 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26776.yml @@ -0,0 +1,9 @@ +author: "coiax" +delete-after: True +changes: + - bugfix: "If you know more than the usual number of languages, you'll now remember them after you get cloned." + - rscdel: "Humans turning into monkeys will not suddenly be able to speak the monkey language, and will continue to understand and speak human." + - rscadd: "Ghosts can now modify their own understood languages with the +language menu." + - rscadd: "Any mob can also open their language menu with the IC->Open Language Menu verb." + - rscadd: "Silicons can now understand Draconic as part of their internal databases." diff --git a/html/changelogs/AutoChangeLog-pr-26813.yml b/html/changelogs/AutoChangeLog-pr-26813.yml deleted file mode 100644 index 10d910d62b6..00000000000 --- a/html/changelogs/AutoChangeLog-pr-26813.yml +++ /dev/null @@ -1,7 +0,0 @@ -author: "Kor, Profakos, Iamgoofball" -delete-after: True -changes: - - rscadd: "The Librarian has been replaced by the Curator." - - rscadd: "Persistent trophy cases have been added to the library on Meta, Delta, and Box. These are only usable by the Curator." - - rscadd: "The Curator now starts with his whip." - - rscadd: "The Curator now has access to his treasure hunter outfit, stashed in his private office." diff --git a/html/changelogs/AutoChangeLog-pr-26872.yml b/html/changelogs/AutoChangeLog-pr-26872.yml new file mode 100644 index 00000000000..031ec641511 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26872.yml @@ -0,0 +1,4 @@ +author: "BeeSting12" +delete-after: True +changes: + - bugfix: "Pubbystation no longer has two airlocks stacked on top of each other leading into xenobiology's kill room." diff --git a/html/changelogs/AutoChangeLog-pr-26894.yml b/html/changelogs/AutoChangeLog-pr-26894.yml new file mode 100644 index 00000000000..b9cfd4624f5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26894.yml @@ -0,0 +1,4 @@ +author: "coiax" +delete-after: True +changes: + - bugfix: "Golems no longer have underwear, undershorts or socks." diff --git a/html/changelogs/AutoChangeLog-pr-26895.yml b/html/changelogs/AutoChangeLog-pr-26895.yml new file mode 100644 index 00000000000..e3777f40640 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26895.yml @@ -0,0 +1,4 @@ +author: "Joan" +delete-after: True +changes: + - balance: "Sigils of Transgression are slightly more visible and glow very faintly." diff --git a/html/changelogs/AutoChangeLog-pr-26899.yml b/html/changelogs/AutoChangeLog-pr-26899.yml new file mode 100644 index 00000000000..cd4b8f7864f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26899.yml @@ -0,0 +1,4 @@ +author: "Cyberboss" +delete-after: True +changes: + - tweak: "Teslas now give off light" diff --git a/html/changelogs/AutoChangeLog-pr-26915.yml b/html/changelogs/AutoChangeLog-pr-26915.yml new file mode 100644 index 00000000000..fa85366e4cc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-26915.yml @@ -0,0 +1,4 @@ +author: "PKPenguin321" +delete-after: True +changes: + - rscadd: "Undid the gang gamemode removal." diff --git a/icons/effects/clockwork_effects.dmi b/icons/effects/clockwork_effects.dmi index 8bbf24a7ef1..b2e15da1d0d 100644 Binary files a/icons/effects/clockwork_effects.dmi and b/icons/effects/clockwork_effects.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 9531e328fef..42b390ff3b4 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 7fb0eccbbd5..64a58e66987 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/flora/jungletrees.dmi b/icons/obj/flora/jungletrees.dmi index 461ac0b265f..67c7e0f463c 100644 Binary files a/icons/obj/flora/jungletrees.dmi and b/icons/obj/flora/jungletrees.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 19d6275d785..78657abe361 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi index d629cfe24d4..5a8afeee510 100644 Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index a1cd8fb2f98..28bc9e28d37 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/turf/floors/junglechasm.dmi b/icons/turf/floors/junglechasm.dmi new file mode 100644 index 00000000000..699a3b667cd Binary files /dev/null and b/icons/turf/floors/junglechasm.dmi differ diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index bf15140478c..10c39a2eb82 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -151,4 +151,5 @@ BIG IMG.icon {width: 32px; height: 32px;} .drone {color: #848482;} .monkey {color: #975032;} .swarmer {color: #2C75FF;} +.resonate {color: #298F85;} "} diff --git a/strings/cas_black.txt b/strings/cas_black.txt index ba078abea46..2e7c6fb407e 100644 --- a/strings/cas_black.txt +++ b/strings/cas_black.txt @@ -76,7 +76,7 @@ I'm not a space bigot, I just hate _________. Why is the station so filthy? THE SHUTTLE CANNOT BE CALLED BECAUSE OF ________ ON THE STATION. After murdering dozens, the traitor was finally brought down by _________. -The librarian has read a lot of porn, but never about _____________! +The curator has read a lot of porn, but never about _____________! Oh god! There's ________________ outside escape! The hottest new space couple is ________ and __________. Lord Singulo hungers for _______. diff --git a/strings/cas_white.txt b/strings/cas_white.txt index 506f6f6c652..d36f19ffe98 100644 --- a/strings/cas_white.txt +++ b/strings/cas_white.txt @@ -61,7 +61,7 @@ Lopping off the Captain's johnson and shooting it out a pneumatic cannon. The secret monkey technique. Putting the pAI's doorjack where it don't belong. Chemical sprayers filled with lube. -Librarians. +Curators. Spooky skeletons. Replicating the Milgram experiment with an electropack. Catgirls. diff --git a/strings/ion_laws.json b/strings/ion_laws.json index a4a3e312f78..5a61fc31964 100644 --- a/strings/ion_laws.json +++ b/strings/ion_laws.json @@ -343,7 +343,7 @@ "CLOWNS", "MIMES", "CHAPLAINS", - "LIBRARIANS", + "CURATORS", "HEADS OF CREW", "CAPTAINS AND HEADS", "CYBORGS", diff --git a/strings/tips.txt b/strings/tips.txt index 0293e53c141..4db52bbed2b 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -102,8 +102,8 @@ As the Bartender, the drinks you start with only give you the basics. If you wan As the Bartender, you can use a circular saw on your shotgun to make it easier to store. As a Janitor, if someone steals your janicart, you can instead use your space cleaner spray, grenades, water sprayer or order another from Cargo. As a Janitor, mousetraps can be used to create bombs or booby-trap containers. -As the Librarian, you are not completely defenseless. Your laser pointer can blind humans and cyborgs, and you can hide items in wirecut books. -As the Librarian, be sure to keep the shelves stocked and the library clean for crew. +As the Curator, you are not completely defenseless. Your laser pointer can blind humans and cyborgs, and you can hide items in wirecut books. +As the Curator, be sure to keep the shelves stocked and the library clean for crew. As a Cargo Technician, you can hack MULEbots to make them faster, run over people in their way, and even let you ride them! As a Cargo Technician, you can order contraband items from the supply shuttle console by de-constructing it and using a multitool on the circuit board, the re-assembling it. As a Cargo Technician, you can earn more cargo points by shipping back crates from maintenance, liquid containers, plasma sheets, rare seeds from hydroponics, and more! diff --git a/tgstation.dme b/tgstation.dme index 726b46f5663..2462a5985d9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -72,7 +72,6 @@ #include "code\__HELPERS\_logging.dm" #include "code\__HELPERS\_string_lists.dm" #include "code\__HELPERS\AStar.dm" -#include "code\__HELPERS\bandetect.dm" #include "code\__HELPERS\cmp.dm" #include "code\__HELPERS\files.dm" #include "code\__HELPERS\flags.dm" @@ -173,6 +172,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" @@ -1379,8 +1379,10 @@ #include "code\modules\jobs\job_types\silicon.dm" #include "code\modules\jobs\map_changes\map_changes.dm" #include "code\modules\language\common.dm" +#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 b/tgui/assets/tgui.css index 531fb00530b..d52500b9d64 100644 --- a/tgui/assets/tgui.css +++ b/tgui/assets/tgui.css @@ -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 7f024a02be8..15a0f7fb350 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,16 +1,16 @@ -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,P=k[b](m?{}:-0,1)!=k,C=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)}),(C||w)&&(x("delete"),x("has"),h&&x("get")),(w||P)&&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,P=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)}},C=e+" Iterator",E=y==v,S=!1,A=t.prototype,O=A[f]||A[h]||y&&A[y],T=O||P(y);if(O){var M=l(T.call(new t));c(M,C,!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[C]=g,y)if(w={values:E?T:P(v),keys:_?T:P(m),entries:E?P("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__"),P=t(8),C=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("