From 08eeda97f551c9b2f9538f012fd30113f254b5c9 Mon Sep 17 00:00:00 2001
From: Fermi <>
Date: Thu, 19 Sep 2019 01:45:21 +0100
Subject: [PATCH] Heck
---
_maps/map_files/PubbyStation/PubbyStation.dmm | 12 +-
_maps/map_files/generic/CentCom.dmm | 4 +-
code/__DEFINES/DNA.dm | 7 +
code/__DEFINES/admin.dm | 7 +
code/__DEFINES/citadel_defines.dm | 11 -
code/__DEFINES/is_helpers.dm | 2 +-
code/__DEFINES/jobs.dm | 38 +
code/__DEFINES/maths.dm | 6 +
code/__DEFINES/misc.dm | 3 +
code/__DEFINES/preferences.dm | 7 +-
code/__HELPERS/_cit_helpers.dm | 6 +
code/__HELPERS/cmp.dm | 3 +
code/__HELPERS/global_lists.dm | 13 +-
code/__HELPERS/mobs.dm | 49 +-
code/__HELPERS/roundend.dm | 7 +
code/__HELPERS/time.dm | 8 +
code/_globalvars/lists/flavor_misc.dm | 3 +-
code/controllers/subsystem/assets.dm | 12 +-
code/controllers/subsystem/job.dm | 180 +-
code/controllers/subsystem/ticker.dm | 2 +-
code/datums/outfit.dm | 8 +
code/game/gamemodes/brother/traitor_bro.dm | 2 +-
code/game/gamemodes/clock_cult/clock_cult.dm | 2 +-
code/game/gamemodes/cult/cult.dm | 4 +-
code/game/gamemodes/dynamic/dynamic.dm | 750 ++++++
.../gamemodes/dynamic/dynamic_rulesets.dm | 211 ++
.../dynamic/dynamic_rulesets_latejoin.dm | 110 +
.../dynamic/dynamic_rulesets_midround.dm | 460 ++++
.../dynamic/dynamic_rulesets_roundstart.dm | 732 ++++++
code/game/gamemodes/dynamic/readme.md | 57 +
code/game/gamemodes/game_mode.dm | 7 +-
code/game/gamemodes/overthrow/overthrow.dm | 3 +-
code/game/gamemodes/revolution/revolution.dm | 3 +-
code/game/gamemodes/traitor/traitor.dm | 2 +-
code/game/machinery/limbgrower.dm | 4 +-
code/game/objects/effects/spawners/bundle.dm | 2 +-
code/game/objects/items/holy_weapons.dm | 12 +-
code/game/objects/items/melee/misc.dm | 19 +-
.../crates_lockers/closets/job_closets.dm | 4 +-
code/game/objects/structures/dresser.dm | 2 +-
code/modules/admin/admin.dm | 57 +
code/modules/admin/create_mob.dm | 3 +-
code/modules/admin/topic.dm | 290 +++
.../antagonists/abductor/equipment/gland.dm | 2 +-
.../changeling/powers/strained_muscles.dm | 2 +
code/modules/client/client_defines.dm | 5 +
code/modules/client/preferences.dm | 286 +--
code/modules/client/preferences_savefile.dm | 280 ++-
code/modules/clothing/suits/jobs.dm | 30 +-
code/modules/clothing/suits/miscellaneous.dm | 17 -
code/modules/clothing/under/accessories.dm | 36 +-
.../food_and_drinks/food/snacks/meat.dm | 2 +-
.../food_and_drinks/recipes/drinks_recipes.dm | 7 +-
.../recipes/tablecraft/recipes_pastry.dm | 2 +-
code/modules/hydroponics/grown/tea_coffee.dm | 20 +-
code/modules/jobs/job_exp.dm | 2 +
.../jobs/job_types/{job.dm => _job.dm} | 485 ++--
.../jobs/job_types/{silicon.dm => ai.dm} | 159 +-
code/modules/jobs/job_types/assistant.dm | 2 +-
.../jobs/job_types/atmospheric_technician.dm | 44 +
code/modules/jobs/job_types/bartender.dm | 30 +
code/modules/jobs/job_types/botanist.dm | 32 +
code/modules/jobs/job_types/captain.dm | 62 +-
code/modules/jobs/job_types/cargo_service.dm | 293 ---
.../jobs/job_types/cargo_technician.dm | 27 +
.../{civilian_chaplain.dm => chaplain.dm} | 216 +-
code/modules/jobs/job_types/chemist.dm | 36 +
code/modules/jobs/job_types/chief_engineer.dm | 64 +
.../jobs/job_types/chief_medical_officer.dm | 59 +
code/modules/jobs/job_types/civilian.dm | 206 --
code/modules/jobs/job_types/clown.dm | 58 +
code/modules/jobs/job_types/cook.dm | 52 +
code/modules/jobs/job_types/curator.dm | 43 +
code/modules/jobs/job_types/cyborg.dm | 27 +
code/modules/jobs/job_types/detective.dm | 57 +
code/modules/jobs/job_types/engineering.dm | 169 --
code/modules/jobs/job_types/geneticist.dm | 35 +
.../jobs/job_types/head_of_personnel.dm | 51 +
.../jobs/job_types/head_of_security.dm | 68 +
code/modules/jobs/job_types/janitor.dm | 27 +
code/modules/jobs/job_types/lawyer.dm | 47 +
code/modules/jobs/job_types/medical.dm | 207 --
code/modules/jobs/job_types/medical_doctor.dm | 35 +
code/modules/jobs/job_types/mime.dm | 49 +
code/modules/jobs/job_types/quartermaster.dm | 41 +
.../jobs/job_types/research_director.dm | 61 +
code/modules/jobs/job_types/roboticist.dm | 34 +
code/modules/jobs/job_types/science.dm | 133 --
code/modules/jobs/job_types/scientist.dm | 33 +
code/modules/jobs/job_types/security.dm | 346 ---
.../jobs/job_types/security_officer.dm | 159 ++
code/modules/jobs/job_types/shaft_miner.dm | 77 +
.../jobs/job_types/station_engineer.dm | 54 +
code/modules/jobs/job_types/virologist.dm | 35 +
code/modules/jobs/job_types/warden.dm | 56 +
code/modules/keybindings/bindings_client.dm | 41 +-
code/modules/keybindings/setup.dm | 20 +-
.../modules/mob/dead/new_player/new_player.dm | 153 +-
.../mob/dead/new_player/preferences_setup.dm | 55 +-
.../sprite_accessories/Citadel_Snowflake.dm | 53 +
.../sprite_accessories/_sprite_accessories.dm | 11 +
.../sprite_accessories/alienpeople.dm | 53 +
.../sprite_accessories/body_markings.dm | 275 ++-
.../new_player/sprite_accessories/ears.dm | 289 ++-
.../sprite_accessories/hair_face.dm | 43 +-
.../sprite_accessories/hair_head.dm | 161 +-
.../new_player/sprite_accessories/horns.dm | 12 +-
.../sprite_accessories/ipc_synths.dm | 158 ++
.../new_player/sprite_accessories/legs.dm | 8 -
.../sprite_accessories/legs_and_taurs.dm | 124 +
.../sprite_accessories/moth_wings.dm | 68 -
.../new_player/sprite_accessories/snouts.dm | 357 ++-
.../new_player/sprite_accessories/tails.dm | 663 +++++-
.../new_player/sprite_accessories/wings.dm | 120 +-
.../mob/living/carbon/alien/larva/emote.dm | 113 -
code/modules/mob/living/carbon/human/human.dm | 9 +-
.../mob/living/carbon/human/human_defines.dm | 2 +
code/modules/mob/living/carbon/human/life.dm | 6 +-
code/modules/mob/living/carbon/human/login.dm | 9 -
.../mob/living/carbon/human/species.dm | 192 +-
.../carbon/human/species_types/bugmen.dm | 64 +
.../carbon/human/species_types/flypeople.dm | 2 +-
.../carbon/human/species_types/furrypeople.dm | 98 +
.../carbon/human/species_types/golems.dm | 2 +-
.../living/carbon/human/species_types/ipc.dm | 2 +-
.../carbon/human/species_types/jellypeople.dm | 262 ++-
.../human/species_types/lizardpeople.dm | 12 +-
.../carbon/human/species_types/mothmen.dm | 61 -
.../carbon/human/species_types/mushpeople.dm | 2 +-
.../carbon/human/species_types/plasmamen.dm | 2 +-
.../carbon/human/species_types/podpeople.dm | 3 +-
.../carbon/human/species_types/synths.dm | 2 +-
.../mob/living/carbon/human/whisper.dm | 91 -
code/modules/oracle_ui/README.md | 233 ++
code/modules/oracle_ui/assets.dm | 8 +
code/modules/oracle_ui/hookup_procs.dm | 44 +
code/modules/oracle_ui/oracle_ui.dm | 134 ++
code/modules/oracle_ui/themed.dm | 82 +
code/modules/paperwork/paper.dm | 56 +-
.../projectiles/guns/ballistic/shotgun.dm | 1 +
.../projectiles/projectile/bullets/shotgun.dm | 8 +-
.../chemistry/machinery/chem_master.dm | 41 +-
.../chemistry/reagents/alcohol_reagents.dm | 4 +-
.../chemistry/reagents/drink_reagents.dm | 20 +
.../chemistry/reagents/other_reagents.dm | 21 +-
.../reagents/chemistry/recipes/others.dm | 2 +-
code/modules/recycling/disposal/bin.dm | 50 +-
.../research/designs/limbgrower_designs.dm | 8 +-
code/modules/surgery/bodyparts/bodyparts.dm | 54 +-
code/modules/surgery/organs/eyes.dm | 4 +-
code/modules/vending/autodrobe.dm | 4 +-
code/modules/vending/clothesmate.dm | 10 +-
code/modules/vending/wardrobes.dm | 6 +-
config/game_options.txt | 2 +-
html/changelogs/AutoChangeLog-pr-9086.yml | 4 +
html/changelogs/AutoChangeLog-pr-9109.yml | 4 +
html/changelogs/AutoChangeLog-pr-9199.yml | 7 +
html/changelogs/AutoChangeLog-pr-9241.yml | 6 +
html/changelogs/AutoChangeLog-pr-9251.yml | 5 +
html/changelogs/AutoChangeLog-pr-9275.yml | 5 +
html/changelogs/AutoChangeLog-pr-9276.yml | 6 +
html/changelogs/AutoChangeLog-pr-9277.yml | 11 +
html/changelogs/AutoChangeLog-pr-9278.yml | 4 +
html/changelogs/AutoChangeLog-pr-9279.yml | 4 +
html/changelogs/AutoChangeLog-pr-9288.yml | 4 +
html/changelogs/AutoChangeLog-pr-9289.yml | 4 +
html/changelogs/AutoChangeLog-pr-9295.yml | 4 +
html/changelogs/AutoChangeLog-pr-9302.yml | 4 +
.../oracle_ui/content/disposal_bin/index.html | 27 +
html/oracle_ui/editor_tool.html | 103 +
html/oracle_ui/themes/nano/index.html | 19 +
.../oracle_ui/themes/nano/sui-nano-common.css | 353 +++
html/oracle_ui/themes/nano/sui-nano-common.js | 47 +
.../themes/nano/sui-nano-jquery.min.js | 4 +
icons/mob/accessories.dmi | Bin 8771 -> 9452 bytes
icons/mob/human_parts.dmi | Bin 38495 -> 41133 bytes
icons/mob/human_parts_greyscale.dmi | Bin 55820 -> 60456 bytes
icons/mob/mutant_bodyparts.dmi | Bin 33474 -> 34161 bytes
icons/mob/wings.dmi | Bin 79283 -> 95000 bytes
icons/obj/clothing/accessories.dmi | Bin 9764 -> 10692 bytes
icons/obj/hydroponics/growing_flowers.dmi | Bin 13230 -> 14070 bytes
icons/obj/hydroponics/harvest.dmi | Bin 51762 -> 52053 bytes
icons/obj/hydroponics/seeds.dmi | Bin 22779 -> 22917 bytes
.../code/game/gamemodes/gangs/gang_datums.dm | 4 +-
.../code/game/objects/items/meat.dm | 26 -
.../code/game/objects/items/melee/misc.dm | 57 -
modular_citadel/code/init.dm | 20 -
.../modules/food_and_drinks/snacks/meat.dm | 26 +
.../mob/dead/new_player/sprite_accessories.dm | 2083 -----------------
.../modules/mob/living/carbon/human/human.dm | 6 -
.../modules/mob/living/carbon/human/life.dm | 21 -
.../mob/living/carbon/human/species.dm | 166 --
.../carbon/human/species_types/furrypeople.dm | 237 --
.../carbon/human/species_types/jellypeople.dm | 257 --
.../reagents/chemistry/recipes/fermi.dm | 3 +
modular_citadel/icons/mob/mam_ears.dmi | Bin 10077 -> 10087 bytes
modular_citadel/icons/mob/mam_markings.dmi | Bin 93529 -> 106979 bytes
.../icons/mob/markings_notmammals.dmi | Bin 37510 -> 45688 bytes
.../icons/mob/mutant_bodyparts.dmi | Bin 8294 -> 6146 bytes
tgui/assets/tgui.js | 8 +-
tgui/src/interfaces/chem_master.ract | 4 +-
201 files changed, 9676 insertions(+), 5741 deletions(-)
create mode 100644 code/game/gamemodes/dynamic/dynamic.dm
create mode 100644 code/game/gamemodes/dynamic/dynamic_rulesets.dm
create mode 100644 code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
create mode 100644 code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
create mode 100644 code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
create mode 100644 code/game/gamemodes/dynamic/readme.md
rename code/modules/jobs/job_types/{job.dm => _job.dm} (88%)
rename code/modules/jobs/job_types/{silicon.dm => ai.dm} (71%)
create mode 100644 code/modules/jobs/job_types/atmospheric_technician.dm
create mode 100644 code/modules/jobs/job_types/bartender.dm
create mode 100644 code/modules/jobs/job_types/botanist.dm
delete mode 100644 code/modules/jobs/job_types/cargo_service.dm
create mode 100644 code/modules/jobs/job_types/cargo_technician.dm
rename code/modules/jobs/job_types/{civilian_chaplain.dm => chaplain.dm} (66%)
create mode 100644 code/modules/jobs/job_types/chemist.dm
create mode 100644 code/modules/jobs/job_types/chief_engineer.dm
create mode 100644 code/modules/jobs/job_types/chief_medical_officer.dm
delete mode 100644 code/modules/jobs/job_types/civilian.dm
create mode 100644 code/modules/jobs/job_types/clown.dm
create mode 100644 code/modules/jobs/job_types/cook.dm
create mode 100644 code/modules/jobs/job_types/curator.dm
create mode 100644 code/modules/jobs/job_types/cyborg.dm
create mode 100644 code/modules/jobs/job_types/detective.dm
delete mode 100644 code/modules/jobs/job_types/engineering.dm
create mode 100644 code/modules/jobs/job_types/geneticist.dm
create mode 100644 code/modules/jobs/job_types/head_of_personnel.dm
create mode 100644 code/modules/jobs/job_types/head_of_security.dm
create mode 100644 code/modules/jobs/job_types/janitor.dm
create mode 100644 code/modules/jobs/job_types/lawyer.dm
delete mode 100644 code/modules/jobs/job_types/medical.dm
create mode 100644 code/modules/jobs/job_types/medical_doctor.dm
create mode 100644 code/modules/jobs/job_types/mime.dm
create mode 100644 code/modules/jobs/job_types/quartermaster.dm
create mode 100644 code/modules/jobs/job_types/research_director.dm
create mode 100644 code/modules/jobs/job_types/roboticist.dm
delete mode 100644 code/modules/jobs/job_types/science.dm
create mode 100644 code/modules/jobs/job_types/scientist.dm
delete mode 100644 code/modules/jobs/job_types/security.dm
create mode 100644 code/modules/jobs/job_types/security_officer.dm
create mode 100644 code/modules/jobs/job_types/shaft_miner.dm
create mode 100644 code/modules/jobs/job_types/station_engineer.dm
create mode 100644 code/modules/jobs/job_types/virologist.dm
create mode 100644 code/modules/jobs/job_types/warden.dm
create mode 100644 code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm
create mode 100644 code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm
create mode 100644 code/modules/mob/dead/new_player/sprite_accessories/ipc_synths.dm
delete mode 100644 code/modules/mob/dead/new_player/sprite_accessories/legs.dm
create mode 100644 code/modules/mob/dead/new_player/sprite_accessories/legs_and_taurs.dm
delete mode 100644 code/modules/mob/dead/new_player/sprite_accessories/moth_wings.dm
delete mode 100644 code/modules/mob/living/carbon/alien/larva/emote.dm
delete mode 100644 code/modules/mob/living/carbon/human/login.dm
create mode 100644 code/modules/mob/living/carbon/human/species_types/bugmen.dm
create mode 100644 code/modules/mob/living/carbon/human/species_types/furrypeople.dm
rename {modular_citadel/code => code}/modules/mob/living/carbon/human/species_types/ipc.dm (98%)
delete mode 100644 code/modules/mob/living/carbon/human/species_types/mothmen.dm
delete mode 100644 code/modules/mob/living/carbon/human/whisper.dm
create mode 100644 code/modules/oracle_ui/README.md
create mode 100644 code/modules/oracle_ui/assets.dm
create mode 100644 code/modules/oracle_ui/hookup_procs.dm
create mode 100644 code/modules/oracle_ui/oracle_ui.dm
create mode 100644 code/modules/oracle_ui/themed.dm
create mode 100644 html/changelogs/AutoChangeLog-pr-9086.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9109.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9199.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9241.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9251.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9275.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9276.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9277.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9278.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9279.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9288.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9289.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9295.yml
create mode 100644 html/changelogs/AutoChangeLog-pr-9302.yml
create mode 100644 html/oracle_ui/content/disposal_bin/index.html
create mode 100644 html/oracle_ui/editor_tool.html
create mode 100644 html/oracle_ui/themes/nano/index.html
create mode 100644 html/oracle_ui/themes/nano/sui-nano-common.css
create mode 100644 html/oracle_ui/themes/nano/sui-nano-common.js
create mode 100644 html/oracle_ui/themes/nano/sui-nano-jquery.min.js
delete mode 100644 modular_citadel/code/game/objects/items/meat.dm
delete mode 100644 modular_citadel/code/game/objects/items/melee/misc.dm
delete mode 100644 modular_citadel/code/modules/mob/dead/new_player/sprite_accessories.dm
delete mode 100644 modular_citadel/code/modules/mob/living/carbon/human/life.dm
delete mode 100644 modular_citadel/code/modules/mob/living/carbon/human/species.dm
delete mode 100644 modular_citadel/code/modules/mob/living/carbon/human/species_types/furrypeople.dm
delete mode 100644 modular_citadel/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 2e8887c75f..7e4f54c8b4 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -47466,8 +47466,8 @@
/area/hydroponics/garden/monastery)
"cgL" = (
/obj/structure/closet/cabinet,
-/obj/item/clothing/suit/holidaypriest,
-/obj/item/clothing/suit/nun,
+/obj/item/clothing/suit/chaplain/holidaypriest,
+/obj/item/clothing/suit/chaplain/nun,
/obj/item/clothing/head/nun_hood,
/obj/machinery/button/door{
id = "Cell1";
@@ -47834,8 +47834,8 @@
/area/space/nearstation)
"cio" = (
/obj/structure/closet/cabinet,
-/obj/item/clothing/suit/holidaypriest,
-/obj/item/clothing/suit/nun,
+/obj/item/clothing/suit/chaplain/holidaypriest,
+/obj/item/clothing/suit/chaplain/nun,
/obj/item/clothing/head/nun_hood,
/obj/machinery/button/door{
id = "Cell2";
@@ -50476,8 +50476,8 @@
/obj/structure/closet,
/obj/item/storage/backpack/cultpack,
/obj/item/clothing/head/nun_hood,
-/obj/item/clothing/suit/nun,
-/obj/item/clothing/suit/holidaypriest,
+/obj/item/clothing/suit/chaplain/nun,
+/obj/item/clothing/suit/chaplain/holidaypriest,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index d04ee2fe49..80e80cd6a9 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -1264,9 +1264,9 @@
/area/holodeck/rec_center/chapelcourt)
"dw" = (
/obj/structure/table/wood/fancy,
-/obj/item/clothing/suit/nun,
+/obj/item/clothing/suit/chaplain/nun,
/obj/item/clothing/head/nun_hood,
-/obj/item/clothing/suit/holidaypriest,
+/obj/item/clothing/suit/chaplain/holidaypriest,
/turf/open/floor/holofloor{
dir = 8;
icon_state = "dark"
diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index 4ed099d9e2..4372c4ca24 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -98,6 +98,13 @@
#define DRINKSBLOOD 15
#define NOEYES 16
#define MARKINGS 17
+#define MUTCOLORS2 18
+#define MUTCOLORS3 19
+#define NOAROUSAL 20 //Stops all arousal effects
+#define NOGENITALS 21 //Cannot create, use, or otherwise have genitals
+#define MATRIXED 22 //if icon is color matrix'd
+#define SKINTONE 23 //uses skin tones
+#define HORNCOLOR 24
#define ORGAN_SLOT_BRAIN "brain"
#define ORGAN_SLOT_APPENDIX "appendix"
diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm
index fb42bc46c0..b875998f0a 100644
--- a/code/__DEFINES/admin.dm
+++ b/code/__DEFINES/admin.dm
@@ -81,3 +81,10 @@
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
+
+///Max length of a keypress command before it's considered to be a forged packet/bogus command
+#define MAX_KEYPRESS_COMMANDLENGTH 16
+///Max amount of keypress messages per second over two seconds before client is autokicked
+#define MAX_KEYPRESS_AUTOKICK 100
+///Length of held key rolling buffer
+#define HELD_KEY_BUFFER_LENGTH 15
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index da5981ff8a..d966c73d23 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -89,17 +89,6 @@
//Damage stuffs
#define AROUSAL "arousal"
-//DNA stuffs. Remember to change this if upstream adds more snowflake options
-
-
-//Species stuffs. Remember to change this if upstream updates species flags
-#define MUTCOLORS2 35
-#define MUTCOLORS3 36
-#define NOAROUSAL 37 //Stops all arousal effects
-#define NOGENITALS 38 //Cannot create, use, or otherwise have genitals
-#define MATRIXED 39 //if icon is color matrix'd
-#define SKINTONE 40 //uses skin tones
-
//Citadel istypes
#define isgenital(A) (istype(A, /obj/item/organ/genital))
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 8ff40c3ef9..ef9e6a044f 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -56,7 +56,7 @@
#define isslimeperson(A) (is_species(A, /datum/species/jelly/slime))
#define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent))
#define iszombie(A) (is_species(A, /datum/species/zombie))
-#define ismoth(A) (is_species(A, /datum/species/moth))
+#define ismoth(A) (is_species(A, /datum/species/insect))
#define ishumanbasic(A) (is_species(A, /datum/species/human))
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) )
diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm
index dc4080a789..e6eb9f313e 100644
--- a/code/__DEFINES/jobs.dm
+++ b/code/__DEFINES/jobs.dm
@@ -48,3 +48,41 @@
#define JOB_UNAVAILABLE_PLAYTIME 3
#define JOB_UNAVAILABLE_ACCOUNTAGE 4
#define JOB_UNAVAILABLE_SLOTFULL 5
+
+#define DEFAULT_RELIGION "Christianity"
+#define DEFAULT_DEITY "Space Jesus"
+
+#define JOB_DISPLAY_ORDER_DEFAULT 0
+
+#define JOB_DISPLAY_ORDER_ASSISTANT 1
+#define JOB_DISPLAY_ORDER_CAPTAIN 2
+#define JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL 3
+#define JOB_DISPLAY_ORDER_BARTENDER 4
+#define JOB_DISPLAY_ORDER_COOK 5
+#define JOB_DISPLAY_ORDER_BOTANIST 6
+#define JOB_DISPLAY_ORDER_JANITOR 7
+#define JOB_DISPLAY_ORDER_CLOWN 8
+#define JOB_DISPLAY_ORDER_MIME 9
+#define JOB_DISPLAY_ORDER_CURATOR 10
+#define JOB_DISPLAY_ORDER_LAWYER 11
+#define JOB_DISPLAY_ORDER_CHAPLAIN 12
+#define JOB_DISPLAY_ORDER_QUARTERMASTER 13
+#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 14
+#define JOB_DISPLAY_ORDER_SHAFT_MINER 15
+#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 16
+#define JOB_DISPLAY_ORDER_STATION_ENGINEER 17
+#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 18
+#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 19
+#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 20
+#define JOB_DISPLAY_ORDER_CHEMIST 21
+#define JOB_DISPLAY_ORDER_GENETICIST 22
+#define JOB_DISPLAY_ORDER_VIROLOGIST 23
+#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 24
+#define JOB_DISPLAY_ORDER_SCIENTIST 25
+#define JOB_DISPLAY_ORDER_ROBOTICIST 26
+#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 27
+#define JOB_DISPLAY_ORDER_WARDEN 28
+#define JOB_DISPLAY_ORDER_DETECTIVE 29
+#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 30
+#define JOB_DISPLAY_ORDER_AI 31
+#define JOB_DISPLAY_ORDER_CYBORG 32
diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm
index d344f7f010..5bce51293f 100644
--- a/code/__DEFINES/maths.dm
+++ b/code/__DEFINES/maths.dm
@@ -201,4 +201,10 @@
return list(region_x1 & region_x2, region_y1 & region_y2)
+#define EXP_DISTRIBUTION(desired_mean) ( -(1/(1/desired_mean)) * log(rand(1, 1000) * 0.001) )
+
+#define LORENTZ_DISTRIBUTION(x, s) ( s*TAN(TODEGREES(PI*(rand()-0.5))) + x )
+#define LORENTZ_CUMULATIVE_DISTRIBUTION(x, y, s) ( (1/PI)*TORADIANS(arctan((x-y)/s)) + 1/2 )
+
+#define RULE_OF_THREE(a, b, x) ((a*x)/b)
// )
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index c71780e7e9..b6115e93e9 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -472,6 +472,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
+// list of all null rod weapons
+#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/melee/baseball_bat/chaplain
+
// Used by PDA and cartridge code to reduce repetitiveness of spritesheets
#define PDAIMG(what) {""}
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 02f151dcd9..0992b2e586 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -69,4 +69,9 @@
//Flags in the players table in the db
#define DB_FLAG_EXEMPT 1
-#define DEFAULT_CYBORG_NAME "Default Cyborg Name"
\ No newline at end of file
+#define DEFAULT_CYBORG_NAME "Default Cyborg Name"
+
+//Job preferences levels
+#define JP_LOW 1
+#define JP_MEDIUM 2
+#define JP_HIGH 3
diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm
index 8683f75b08..86d0a34e3e 100644
--- a/code/__HELPERS/_cit_helpers.dm
+++ b/code/__HELPERS/_cit_helpers.dm
@@ -94,6 +94,12 @@ GLOBAL_LIST_INIT(dildo_colors, list(//mostly neon colors
"Purple" = "#e300ff"//purple
))
+GLOBAL_LIST_INIT(meat_types, list(
+ "Mammalian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/mammal,
+ "Aquatic" = /obj/item/reagent_containers/food/snacks/carpmeat/aquatic,
+ "Avian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/avian,
+ "Inesct" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect))
+
//Crew objective and miscreants stuff
GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm
index e09ebcb10c..37f36a7e0d 100644
--- a/code/__HELPERS/cmp.dm
+++ b/code/__HELPERS/cmp.dm
@@ -81,3 +81,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B)
return A.totalResistance() - B.totalResistance()
+
+/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
+ return A.display_order - B.display_order
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index ad2bedaa4e..b20122e653 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -30,7 +30,8 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/legs, GLOB.legs_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.r_wings_list,roundstart = TRUE)
init_sprite_accessory_subtypes(/datum/sprite_accessory/caps, GLOB.caps_list)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings, GLOB.moth_wings_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_wings, GLOB.insect_wings_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_fluff, GLOB.insect_fluffs_list)
//CIT CHANGES START HERE, ADDS SNOWFLAKE BODYPARTS AND MORE
//mammal bodyparts (fucking furries)
@@ -44,6 +45,9 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, GLOB.xeno_head_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_tail, GLOB.xeno_tail_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, GLOB.xeno_dorsal_list)
+ //ipcs
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/screen, GLOB.ipc_screens_list, roundstart = TRUE)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/antenna, GLOB.ipc_antennas_list, roundstart = TRUE)
//genitals
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
for(var/K in GLOB.cock_shapes_list)
@@ -53,7 +57,11 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
GLOB.breasts_size_list = list ("a", "b", "c", "d", "e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
- GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ", "cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret", "baloney pony", "schlanger")
+ GLOB.gentlemans_organ_names = list("phallus", "willy", "dick", "prick", "member", "tool", "gentleman's organ",
+ "cock", "wang", "knob", "dong", "joystick", "pecker", "johnson", "weenie", "tadger", "schlong", "thirsty ferret",
+ "baloney pony", "schlanger", "Mutton dagger", "old blind bob","Hanging Johnny", "fishing rod", "Tally whacker", "polly rocket",
+ "One eyed trouser trout", "Ding dong", "ankle spanker", "Pork sword", "engine cranker", "Harry hot dog", "Davy Crockett",
+ "Kidney cracker", "Heat seeking moisture missile", "Giggle stick", "love whistle", "Tube steak", "Uncle Dick", "Purple helmet warrior")
for(var/K in GLOB.breasts_shapes_list)
var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K]
GLOB.breasts_shapes_icons[K] = value.icon_state
@@ -62,6 +70,7 @@
for(var/K in GLOB.balls_shapes_list)
var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
GLOB.balls_shapes_icons[K] = value.icon_state
+
//END OF CIT CHANGES
//Species
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 7ec99fa885..8f3cd4f60d 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -59,7 +59,7 @@
if(!GLOB.horns_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, GLOB.horns_list)
if(!GLOB.ears_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.horns_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, GLOB.ears_list)
if(!GLOB.frills_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, GLOB.frills_list)
if(!GLOB.spines_list.len)
@@ -70,8 +70,10 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
if(!GLOB.wings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, GLOB.wings_list)
- if(!GLOB.moth_wings_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings, GLOB.moth_wings_list)
+ if(!GLOB.insect_wings_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_wings, GLOB.insect_wings_list)
+ if(!GLOB.insect_fluffs_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/insect_fluff, GLOB.insect_fluffs_list)
//CIT CHANGES - genitals and such
if(!GLOB.cock_shapes_list.len)
@@ -130,22 +132,23 @@
//CIT CHANGE - changes this entire return to support cit's snowflake parts
return(list(
- "mcolor" = color1,
- "mcolor2" = color2,
- "mcolor3" = color3,
- "tail_lizard" = pick(GLOB.tails_list_lizard),
- "tail_human" = "None",
- "wings" = "None",
- "snout" = pick(GLOB.snouts_list),
- "horns" = pick(GLOB.horns_list),
- "ears" = "None",
- "frills" = pick(GLOB.frills_list),
- "spines" = pick(GLOB.spines_list),
- "body_markings" = pick(GLOB.body_markings_list),
- "legs" = pick("Normal Legs","Digitigrade Legs"),
- "caps" = pick(GLOB.caps_list),
- "moth_wings" = pick(GLOB.moth_wings_list),
- "taur" = "None",
+ "mcolor" = color1,
+ "mcolor2" = color2,
+ "mcolor3" = color3,
+ "tail_lizard" = pick(GLOB.tails_list_lizard),
+ "tail_human" = "None",
+ "wings" = "None",
+ "snout" = pick(GLOB.snouts_list),
+ "horns" = pick(GLOB.horns_list),
+ "ears" = "None",
+ "frills" = pick(GLOB.frills_list),
+ "spines" = pick(GLOB.spines_list),
+ "body_markings" = pick(GLOB.body_markings_list),
+ "legs" = pick("Plantigrade","Digitigrade"),
+ "caps" = pick(GLOB.caps_list),
+ "insect_wings" = pick(GLOB.insect_wings_list),
+ "insect_fluff" = "None",
+ "taur" = "None",
"mam_body_markings" = pick(snowflake_markings_list),
"mam_ears" = pick(snowflake_ears_list),
"mam_snouts" = pick(snowflake_mam_snouts_list),
@@ -201,9 +204,11 @@
"womb_cum_mult" = CUM_RATE_MULT,
"womb_efficiency" = CUM_EFFICIENCY,
"womb_fluid" = "femcum",
- "ipc_screen" = "Sunburst",
- "ipc_antenna" = "None",
- "flavor_text" = ""))
+ "ipc_screen" = "Sunburst",
+ "ipc_antenna" = "None",
+ "flavor_text" = "",
+ "meat_type" = "Mammalian"
+ ))
/proc/random_hair_style(gender)
switch(gender)
diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index 55d9e7a6cd..0e9413520b 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -308,6 +308,13 @@
//ignore this comment, it fixes the broken sytax parsing caused by the " above
else
parts += "[GLOB.TAB]Nobody died this shift!"
+ if(istype(SSticker.mode, /datum/game_mode/dynamic))
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ parts += "[GLOB.TAB]Threat level: [mode.threat_level]"
+ parts += "[GLOB.TAB]Threat left: [mode.threat]"
+ parts += "[GLOB.TAB]Executed rules:"
+ for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
+ parts += "[GLOB.TAB][GLOB.TAB][rule.ruletype] - [rule.name]: -[rule.cost] threat"
return parts.Join("
")
/client/proc/roundend_report_file()
diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm
index b28e7b5807..f0d5a7b252 100644
--- a/code/__HELPERS/time.dm
+++ b/code/__HELPERS/time.dm
@@ -73,3 +73,11 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
/proc/daysSince(realtimev)
return round((world.realtime - realtimev) / (24 HOURS))
+
+/proc/worldtime2text()
+ return gameTimestamp("hh:mm:ss", world.time)
+
+/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
+ if(!wtime)
+ wtime = world.time
+ return time2text(wtime - GLOB.timezoneOffset, format)
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index d09368d7b7..c759658bd4 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -34,7 +34,8 @@ GLOBAL_LIST_EMPTY(ears_list)
GLOBAL_LIST_EMPTY(wings_list)
GLOBAL_LIST_EMPTY(wings_open_list)
GLOBAL_LIST_EMPTY(r_wings_list)
-GLOBAL_LIST_EMPTY(moth_wings_list)
+GLOBAL_LIST_EMPTY(insect_wings_list)
+GLOBAL_LIST_EMPTY(insect_fluffs_list)
GLOBAL_LIST_EMPTY(caps_list)
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm
index 7285298283..7b6554bd3f 100644
--- a/code/controllers/subsystem/assets.dm
+++ b/code/controllers/subsystem/assets.dm
@@ -6,7 +6,17 @@ SUBSYSTEM_DEF(assets)
var/list/preload = list()
/datum/controller/subsystem/assets/Initialize(timeofday)
- for(var/type in typesof(/datum/asset))
+
+ var/list/priority_assets = list(
+ /datum/asset/simple/oui_theme_nano,
+ /datum/asset/simple/goonchat
+ )
+
+ for(var/type in priority_assets)
+ var/datum/asset/A = new type()
+ A.register()
+
+ for(var/type in typesof(/datum/asset) - (priority_assets | list(/datum/asset, /datum/asset/simple)))
var/datum/asset/A = type
if (type != initial(A._abstract))
get_asset_datum(type)
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 4001c666ee..a0d9226e14 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -116,7 +116,7 @@ SUBSYSTEM_DEF(job)
if(player.mind && job.title in player.mind.restricted_roles)
JobDebug("FOC incompatible with antagonist role, Player: [player]")
continue
- if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
+ if(player.client.prefs.job_preferences["[job.title]"] == level)
JobDebug("FOC pass, Player: [player], Level:[level]")
candidates += player
return candidates
@@ -182,7 +182,7 @@ SUBSYSTEM_DEF(job)
if((job.current_positions >= job.total_positions) && job.total_positions != -1)
continue
var/list/candidates = FindOccupationCandidates(job, level)
- if(!candidates.len)
+ if(!candidates?.len)
continue
var/mob/dead/new_player/candidate = pick(candidates)
if(AssignRole(candidate, command_position))
@@ -200,7 +200,7 @@ SUBSYSTEM_DEF(job)
if((job.current_positions >= job.total_positions) && job.total_positions != -1)
continue
var/list/candidates = FindOccupationCandidates(job, level)
- if(!candidates.len)
+ if(!candidates?.len)
continue
var/mob/dead/new_player/candidate = pick(candidates)
AssignRole(candidate, command_position)
@@ -228,7 +228,7 @@ SUBSYSTEM_DEF(job)
* fills var "assigned_role" for all ready players.
* This proc must not have any side effect besides of modifying "assigned_role".
**/
-/datum/controller/subsystem/job/proc/DivideOccupations()
+/datum/controller/subsystem/job/proc/DivideOccupations(list/required_jobs)
//Setup new player list and get the jobs list
JobDebug("Running DO")
@@ -241,14 +241,14 @@ SUBSYSTEM_DEF(job)
//Get the players who are ready
for(var/mob/dead/new_player/player in GLOB.player_list)
- if(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role)
+ if(player.ready == PLAYER_READY_TO_PLAY && player.check_preferences() && player.mind && !player.mind.assigned_role)
unassigned += player
initial_players_to_assign = unassigned.len
- JobDebug("DO, Len: [unassigned.len]")
+ JobDebug("DO, Len: [unassigned?.len]")
if(unassigned.len == 0)
- return 0
+ return validate_required_jobs(required_jobs)
//Scale number of open security officer slots to population
setup_officer_positions()
@@ -269,8 +269,8 @@ SUBSYSTEM_DEF(job)
//People who wants to be the overflow role, sure, go on.
JobDebug("DO, Running Overflow Check 1")
var/datum/job/overflow = GetJob(SSjob.overflow_role)
- var/list/overflow_candidates = FindOccupationCandidates(overflow, 3)
- JobDebug("AC1, Candidates: [overflow_candidates.len]")
+ var/list/overflow_candidates = FindOccupationCandidates(overflow, JP_LOW)
+ JobDebug("AC1, Candidates: [overflow_candidates?.len]")
for(var/mob/dead/new_player/player in overflow_candidates)
JobDebug("AC1 pass, Player: [player]")
AssignRole(player, SSjob.overflow_role)
@@ -297,7 +297,8 @@ SUBSYSTEM_DEF(job)
// Loop through all levels from high to low
var/list/shuffledoccupations = shuffle(occupations)
- for(var/level = 1 to 3)
+ var/list/levels = list(JP_HIGH,JP_MEDIUM,JP_LOW)
+ for(var/level in levels)
//Check the head jobs first each level
CheckHeadPositions(level)
@@ -332,7 +333,7 @@ SUBSYSTEM_DEF(job)
continue
// If the player wants that job on this level, then try give it to him.
- if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
+ if(player.client.prefs.job_preferences["[job.title]"] == level)
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]")
@@ -351,9 +352,28 @@ SUBSYSTEM_DEF(job)
//Mop up people who can't leave.
for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
if(!GiveRandomJob(player))
- AssignRole(player, SSjob.overflow_role) //If everything is already filled, make them an assistant
+ if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them an assistant
+ return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
- return 1
+ return validate_required_jobs(required_jobs)
+
+/datum/controller/subsystem/job/proc/validate_required_jobs(list/required_jobs)
+ if(!required_jobs.len)
+ return TRUE
+ for(var/required_group in required_jobs)
+ var/group_ok = TRUE
+ for(var/rank in required_group)
+ var/datum/job/J = GetJob(rank)
+ if(!J)
+ SSticker.mode.setup_error = "Invalid job [rank] in gamemode required jobs."
+ return FALSE
+ if(J.current_positions < required_group[rank])
+ group_ok = FALSE
+ break
+ if(group_ok)
+ return TRUE
+ SSticker.mode.setup_error = "Required jobs not present."
+ return FALSE
//We couldn't find a job from prefs for this guy.
/datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player)
@@ -406,7 +426,7 @@ SUBSYSTEM_DEF(job)
if(length(GLOB.jobspawn_overrides[rank]))
S = pick(GLOB.jobspawn_overrides[rank])
if(S)
- SendToAtom(H, S, buckle = FALSE)
+ S.JoinPlayerHere(H, FALSE)
if(!S) //if there isn't a spawnpoint send them to latejoin, if there's no latejoin go yell at your mapper
log_world("Couldn't find a round start spawn point for [rank]")
SendToLateJoin(H)
@@ -418,7 +438,7 @@ SUBSYSTEM_DEF(job)
if(job)
if(!job.dresscodecompliant)// CIT CHANGE - dress code compliance
equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items
- var/new_mob = job.equip(H, null, null, joined_late)
+ var/new_mob = job.equip(H, null, null, joined_late , null, M.client)
if(ismob(new_mob))
H = new_mob
if(!joined_late)
@@ -428,12 +448,18 @@ SUBSYSTEM_DEF(job)
SSpersistence.antag_rep_change[M.client.ckey] += job.GetAntagRep()
+/* if(M.client.holder)
+ if(CONFIG_GET(flag/auto_deadmin_players) || (M.client.prefs?.toggles & DEADMIN_ALWAYS))
+ M.client.holder.auto_deadmin()
+ else
+ handle_auto_deadmin_roles(M.client, rank) */
+
to_chat(M, "You are the [rank].")
if(job)
to_chat(M, "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this.")
- to_chat(M, "To speak on your departments radio, use the :h button. To see others, look closely at your headset.")
+ job.radio_help_message(M)
if(job.req_admin_notify)
- to_chat(M, "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp.")
+ to_chat(M, "You are playing a job that is important for Game Progression. If you have to disconnect immediately, please notify the admins via adminhelp. Otherwise put your locker gear back into the locker and cryo out.")
if(job.custom_spawn_text)
to_chat(M, "[job.custom_spawn_text]")
if(CONFIG_GET(number/minimal_access_threshold))
@@ -446,12 +472,24 @@ SUBSYSTEM_DEF(job)
equip_loadout(N, H, TRUE)//CIT CHANGE - makes players spawn with in-backpack loadout items properly. A little hacky but it works
return H
-
+/*
+/datum/controller/subsystem/job/proc/handle_auto_deadmin_roles(client/C, rank)
+ if(!C?.holder)
+ return TRUE
+ var/datum/job/job = GetJob(rank)
+ if(!job)
+ return
+ if((job.auto_deadmin_role_flags & DEADMIN_POSITION_HEAD) && (CONFIG_GET(flag/auto_deadmin_heads) || (C.prefs?.toggles & DEADMIN_POSITION_HEAD)))
+ return C.holder.auto_deadmin()
+ else if((job.auto_deadmin_role_flags & DEADMIN_POSITION_SECURITY) && (CONFIG_GET(flag/auto_deadmin_security) || (C.prefs?.toggles & DEADMIN_POSITION_SECURITY)))
+ return C.holder.auto_deadmin()
+ else if((job.auto_deadmin_role_flags & DEADMIN_POSITION_SILICON) && (CONFIG_GET(flag/auto_deadmin_silicons) || (C.prefs?.toggles & DEADMIN_POSITION_SILICON))) //in the event there's ever psuedo-silicon roles added, ie synths.
+ return C.holder.auto_deadmin()*/
/datum/controller/subsystem/job/proc/setup_officer_positions()
var/datum/job/J = SSjob.GetJob("Security Officer")
if(!J)
- throw EXCEPTION("setup_officer_positions(): Security officer job is missing")
+ CRASH("setup_officer_positions(): Security officer job is missing")
var/ssc = CONFIG_GET(number/security_scaling_coeff)
if(ssc > 0)
@@ -502,13 +540,15 @@ SUBSYSTEM_DEF(job)
if(job.required_playtime_remaining(player.client))
young++
continue
- if(player.client.prefs.GetJobDepartment(job, 1) & job.flag)
- high++
- else if(player.client.prefs.GetJobDepartment(job, 2) & job.flag)
- medium++
- else if(player.client.prefs.GetJobDepartment(job, 3) & job.flag)
- low++
- else never++ //not selected
+ switch(player.client.prefs.job_preferences["[job.title]"])
+ if(JP_HIGH)
+ high++
+ if(JP_MEDIUM)
+ medium++
+ if(JP_LOW)
+ low++
+ else
+ never++
SSblackbox.record_feedback("nested tally", "job_preferences", high, list("[job.title]", "high"))
SSblackbox.record_feedback("nested tally", "job_preferences", medium, list("[job.title]", "medium"))
SSblackbox.record_feedback("nested tally", "job_preferences", low, list("[job.title]", "low"))
@@ -551,51 +591,61 @@ SUBSYSTEM_DEF(job)
newjob.spawn_positions = J.spawn_positions
newjob.current_positions = J.current_positions
-/datum/controller/subsystem/job/proc/SendToAtom(mob/M, atom/A, buckle)
- if(buckle && isliving(M) && istype(A, /obj/structure/chair))
- var/obj/structure/chair/C = A
- if(C.buckle_mob(M, FALSE, FALSE))
- return
- M.forceMove(get_turf(A))
+/atom/proc/JoinPlayerHere(mob/M, buckle)
+ // By default, just place the mob on the same turf as the marker or whatever.
+ M.forceMove(get_turf(src))
+
+/obj/structure/chair/JoinPlayerHere(mob/M, buckle)
+ // Placing a mob in a chair will attempt to buckle it, or else fall back to default.
+ if (buckle && isliving(M) && buckle_mob(M, FALSE, FALSE))
+ return
+ ..()
/datum/controller/subsystem/job/proc/SendToLateJoin(mob/M, buckle = TRUE)
+ var/atom/destination
if(M.mind && M.mind.assigned_role && length(GLOB.jobspawn_overrides[M.mind.assigned_role])) //We're doing something special today.
- SendToAtom(M,pick(GLOB.jobspawn_overrides[M.mind.assigned_role]),FALSE)
+ destination = pick(GLOB.jobspawn_overrides[M.mind.assigned_role])
+ destination.JoinPlayerHere(M, FALSE)
return
if(latejoin_trackers.len)
- SendToAtom(M, pick(latejoin_trackers), buckle)
- else
- //bad mojo
- var/area/shuttle/arrival/A = GLOB.areas_by_type[/area/shuttle/arrival]
- if(A)
- //first check if we can find a chair
- var/obj/structure/chair/C = locate() in A
- if(C)
- SendToAtom(M, C, buckle)
- return
- else //last hurrah
- var/list/avail = list()
- for(var/turf/T in A)
- if(!is_blocked_turf(T, TRUE))
- avail += T
- if(avail.len)
- SendToAtom(M, pick(avail), FALSE)
- return
+ destination = pick(latejoin_trackers)
+ destination.JoinPlayerHere(M, buckle)
+ return
- //pick an open spot on arrivals and dump em
- var/list/arrivals_turfs = shuffle(get_area_turfs(/area/shuttle/arrival))
- if(arrivals_turfs.len)
- for(var/turf/T in arrivals_turfs)
- if(!is_blocked_turf(T, TRUE))
- SendToAtom(M, T, FALSE)
- return
- //last chance, pick ANY spot on arrivals and dump em
- SendToAtom(M, arrivals_turfs[1], FALSE)
- else
- var/msg = "Unable to send mob [M] to late join!"
- message_admins(msg)
- CRASH(msg)
+ //bad mojo
+ var/area/shuttle/arrival/A = GLOB.areas_by_type[/area/shuttle/arrival]
+ if(A)
+ //first check if we can find a chair
+ var/obj/structure/chair/C = locate() in A
+ if(C)
+ C.JoinPlayerHere(M, buckle)
+ return
+
+ //last hurrah
+ var/list/avail = list()
+ for(var/turf/T in A)
+ if(!is_blocked_turf(T, TRUE))
+ avail += T
+ if(avail.len)
+ destination = pick(avail)
+ destination.JoinPlayerHere(M, FALSE)
+ return
+
+ //pick an open spot on arrivals and dump em
+ var/list/arrivals_turfs = shuffle(get_area_turfs(/area/shuttle/arrival))
+ if(arrivals_turfs.len)
+ for(var/turf/T in arrivals_turfs)
+ if(!is_blocked_turf(T, TRUE))
+ T.JoinPlayerHere(M, FALSE)
+ return
+ //last chance, pick ANY spot on arrivals and dump em
+ destination = arrivals_turfs[1]
+ destination.JoinPlayerHere(M, FALSE)
+ else
+ var/msg = "Unable to send mob [M] to late join!"
+ message_admins(msg)
+ CRASH(msg)
///////////////////////////////////
@@ -637,4 +687,4 @@ SUBSYSTEM_DEF(job)
. |= player.mind
/datum/controller/subsystem/job/proc/JobDebug(message)
- log_job_debug(message)
\ No newline at end of file
+ log_job_debug(message)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index f2469e8f7d..14e1e86f7d 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -255,7 +255,7 @@ SUBSYSTEM_DEF(ticker)
var/can_continue = 0
can_continue = src.mode.pre_setup() //Choose antagonists
CHECK_TICK
- SSjob.DivideOccupations() //Distribute jobs
+ can_continue = can_continue && SSjob.DivideOccupations(mode.required_jobs) //Distribute jobs
CHECK_TICK
if(!GLOB.Debug2)
diff --git a/code/datums/outfit.dm b/code/datums/outfit.dm
index 1f5c28d3c2..68165af956 100755
--- a/code/datums/outfit.dm
+++ b/code/datums/outfit.dm
@@ -21,6 +21,7 @@
var/l_hand = null
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = null // In the list(path=count,otherpath=count) format
+ var/box // Internals box. Will be inserted at the start of backpack_contents
var/list/implants = null
var/accessory = null
@@ -83,6 +84,13 @@
H.equip_to_slot_or_del(new l_pocket(H),SLOT_L_STORE)
if(r_pocket)
H.equip_to_slot_or_del(new r_pocket(H),SLOT_R_STORE)
+
+ if(box)
+ if(!backpack_contents)
+ backpack_contents = list()
+ backpack_contents.Insert(1, box)
+ backpack_contents[box] = 1
+
if(backpack_contents)
for(var/path in backpack_contents)
var/number = backpack_contents[path]
diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm
index 18611ebfcb..8bbe7f54ed 100644
--- a/code/game/gamemodes/brother/traitor_bro.dm
+++ b/code/game/gamemodes/brother/traitor_bro.dm
@@ -6,7 +6,7 @@
name = "traitor+brothers"
config_tag = "traitorbro"
restricted_jobs = list("AI", "Cyborg")
- protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Quartermaster", "Chief Engineer", "Research Director")
+ protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
announce_span = "danger"
announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 808022d25f..51a34f4194 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -135,7 +135,7 @@ Credit where due:
required_enemies = 3
recommended_enemies = 5
enemy_minimum_age = 7
- protected_jobs = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain") //Silicons can eventually be converted
+ protected_jobs = list("AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //Silicons can eventually be converted
restricted_jobs = list("Chaplain", "Captain")
announce_span = "brass"
announce_text = "Servants of Ratvar are trying to summon the Justiciar!\n\
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index e7cc3c53ae..497cc2f1c3 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -35,8 +35,8 @@
config_tag = "cult"
antag_flag = ROLE_CULTIST
false_report_weight = 10
- restricted_jobs = list("Chaplain","AI", "Cyborg", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel")
- protected_jobs = list()
+ restricted_jobs = list("AI", "Cyborg")
+ protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 30
required_enemies = 3
recommended_enemies = 5
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
new file mode 100644
index 0000000000..ab4ac4d5c6
--- /dev/null
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -0,0 +1,750 @@
+#define CURRENT_LIVING_PLAYERS 1
+#define CURRENT_LIVING_ANTAGS 2
+#define CURRENT_DEAD_PLAYERS 3
+#define CURRENT_OBSERVERS 4
+
+#define ONLY_RULESET 1
+#define HIGHLANDER_RULESET 2
+#define TRAITOR_RULESET 4
+#define MINOR_RULESET 8
+
+#define RULESET_STOP_PROCESSING 1
+
+// -- Injection delays
+GLOBAL_VAR_INIT(dynamic_latejoin_delay_min, (5 MINUTES))
+GLOBAL_VAR_INIT(dynamic_latejoin_delay_max, (25 MINUTES))
+
+GLOBAL_VAR_INIT(dynamic_midround_delay_min, (15 MINUTES))
+GLOBAL_VAR_INIT(dynamic_midround_delay_max, (35 MINUTES))
+
+// Are HIGHLANDER_RULESETs allowed to stack?
+GLOBAL_VAR_INIT(dynamic_no_stacking, TRUE)
+// A number between -5 and +5.
+// A negative value will give a more peaceful round and
+// a positive value will give a round with higher threat.
+GLOBAL_VAR_INIT(dynamic_curve_centre, 0)
+// A number between 0.5 and 4.
+// Higher value will favour extreme rounds and
+// lower value rounds closer to the average.
+GLOBAL_VAR_INIT(dynamic_curve_width, 1.8)
+// If enabled only picks a single starting rule and executes only autotraitor midround ruleset.
+GLOBAL_VAR_INIT(dynamic_classic_secret, FALSE)
+// How many roundstart players required for high population override to take effect.
+GLOBAL_VAR_INIT(dynamic_high_pop_limit, 55)
+// If enabled does not accept or execute any rulesets.
+GLOBAL_VAR_INIT(dynamic_forced_extended, FALSE)
+// How high threat is required for HIGHLANDER_RULESETs stacking.
+// This is independent of dynamic_no_stacking.
+GLOBAL_VAR_INIT(dynamic_stacking_limit, 90)
+// List of forced roundstart rulesets.
+GLOBAL_LIST_EMPTY(dynamic_forced_roundstart_ruleset)
+// Forced threat level, setting this to zero or higher forces the roundstart threat to the value.
+GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
+
+/datum/game_mode/dynamic
+ name = "dynamic mode"
+ config_tag = "dynamic"
+
+ announce_span = "danger"
+ announce_text = "Dynamic mode!" // This needs to be changed maybe
+
+ reroll_friendly = FALSE;
+
+ // Threat logging vars
+ /// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations
+ var/threat_level = 0
+ /// Set at the beginning of the round. Spent by the mode to "purchase" rules.
+ var/threat = 0
+ /// Running information about the threat. Can store text or datum entries.
+ var/list/threat_log = list()
+ /// List of roundstart rules used for selecting the rules.
+ var/list/roundstart_rules = list()
+ /// List of latejoin rules used for selecting the rules.
+ var/list/latejoin_rules = list()
+ /// List of midround rules used for selecting the rules.
+ var/list/midround_rules = list()
+ /** # Pop range per requirement.
+ * If the value is five the range is:
+ * 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+
+ * If it is six the range is:
+ * 0-5, 6-11, 12-17, 18-23, 24-29, 30-35, 36-41, 42-47, 48-53, 54+
+ * If it is seven the range is:
+ * 0-6, 7-13, 14-20, 21-27, 28-34, 35-41, 42-48, 49-55, 56-62, 63+
+ */
+ var/pop_per_requirement = 6
+ /// The requirement used for checking if a second rule should be selected.
+ var/list/second_rule_req = list(100, 100, 80, 70, 60, 50, 30, 20, 10, 0)
+ /// The requirement used for checking if a third rule should be selected.
+ var/list/third_rule_req = list(100, 100, 100, 90, 80, 70, 60, 50, 40, 30)
+ /// Threat requirement for a second ruleset when high pop override is in effect.
+ var/high_pop_second_rule_req = 40
+ /// Threat requirement for a third ruleset when high pop override is in effect.
+ var/high_pop_third_rule_req = 60
+ /// Number of players who were ready on roundstart.
+ var/roundstart_pop_ready = 0
+ /// List of candidates used on roundstart rulesets.
+ var/list/candidates = list()
+ /// Rules that are processed, rule_process is called on the rules in this list.
+ var/list/current_rules = list()
+ /// List of executed rulesets.
+ var/list/executed_rules = list()
+ /// Associative list of current players, in order: living players, living antagonists, dead players and observers.
+ var/list/list/current_players = list(CURRENT_LIVING_PLAYERS, CURRENT_LIVING_ANTAGS, CURRENT_DEAD_PLAYERS, CURRENT_OBSERVERS)
+ /// When world.time is over this number the mode tries to inject a latejoin ruleset.
+ var/latejoin_injection_cooldown = 0
+ /// When world.time is over this number the mode tries to inject a midround ruleset.
+ var/midround_injection_cooldown = 0
+ /// When TRUE GetInjectionChance returns 100.
+ var/forced_injection = FALSE
+ /// Forced ruleset to be executed for the next latejoin.
+ var/datum/dynamic_ruleset/latejoin/forced_latejoin_rule = null
+ /// When current_players was updated last time.
+ var/pop_last_updated = 0
+ /// How many percent of the rounds are more peaceful.
+ var/peaceful_percentage = 50
+ /// If a highlander executed.
+ var/highlander_executed = FALSE
+ /// If a only ruleset has been executed.
+ var/only_ruleset_executed = FALSE
+
+/datum/game_mode/dynamic/admin_panel()
+ var/list/dat = list("
Welcome, [client ? client.prefs.real_name : "Unknown User"]
" - output += "" + output += "| "
+ var/column_counter = 0
+ var/free_space = 0
+ for(var/list/category in list(GLOB.command_positions) + list(GLOB.supply_positions) + list(GLOB.engineering_positions) + list(GLOB.nonhuman_positions - "pAI") + list(GLOB.civilian_positions) + list(GLOB.medical_positions) + list(GLOB.science_positions) + list(GLOB.security_positions))
+ var/cat_color = "fff" //random default
+ if(SSjob.name_occupations && SSjob.name_occupations[category[1]])
+ cat_color = SSjob.name_occupations[category[1]].selection_color //use the color of the first job in the category (the department head) as the category color
+ else
+ cat_color = SSjob.occupations[category[1]].selection_color
+ dat += " " + column_counter++ + if(free_space <=4) + free_space++ + if(column_counter > 0 && (column_counter % 3 == 0)) + dat += " | " + if(free_space >= 5 && (free_space % 5 == 0) && (column_counter % 3 != 0)) + free_space = 0 + column_counter = 0 + dat += " | " + + dat += " |
"
+ dat += "
+
+```
+
+#### Step 3
+
+Now you need to implement the methods that provide data to oracle_ui. `oui_data` can be adapted from the `ui_data` proc that tgui uses.
+
+The `act` proc generates a hyperlink that will result in `oui_act` getting called on your object when clicked. The `class` argument defines a css class to be added to the hyperlink, and disabled determines whether the hyperlink will be disabled or not.
+
+Calling `soft_update_fields` will result in the UI being updated on all clients, which is useful when the object changes state.
+
+`code/modules/recycling/disposal-unit.dm`
+```dm
+/obj/machinery/disposal/bin/oui_data(mob/user)
+ var/list/data = list()
+ data["flush"] = flush ? ui.act("Disengage", user, "handle-0", class="active") : ui.act("Engage", user, "handle-1")
+ data["full_pressure"] = full_pressure ? "Ready" : (pressure_charging ? "Pressurizing" : "Off")
+ data["pressure_charging"] = pressure_charging ? ui.act("Turn Off", user, "pump-0", class="active", disabled=full_pressure) : ui.act("Turn On", user, "pump-1", disabled=full_pressure)
+ var/per = full_pressure ? 100 : Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 99)
+ data["per"] = "[round(per, 1)]%"
+ data["contents"] = ui.act("Eject Contents", user, "eject", disabled=contents.len < 1)
+ data["isai"] = isAI(user)
+ return data
+/obj/machinery/disposal/bin/oui_act(mob/user, action, list/params)
+ if(..())
+ return
+ switch(action)
+ if("handle-0")
+ flush = FALSE
+ update_icon()
+ . = TRUE
+ if("handle-1")
+ if(!panel_open)
+ flush = TRUE
+ update_icon()
+ . = TRUE
+ if("pump-0")
+ if(pressure_charging)
+ pressure_charging = FALSE
+ update_icon()
+ . = TRUE
+ if("pump-1")
+ if(!pressure_charging)
+ pressure_charging = TRUE
+ update_icon()
+ . = TRUE
+ if("eject")
+ eject()
+ . = TRUE
+ ui.soft_update_fields()
+```
+
+#### Step 4
+
+You now need to hook in and ensure oracle_ui is invoked upon clicking. `render` should be used to open the UI for a user, typically on click.
+
+`code/modules/recycling/disposal-unit.dm`
+```dm
+/obj/machinery/disposal/bin/ui_interact(mob/user, state)
+ if(stat & BROKEN)
+ return
+ if(user.loc == src)
+ to_chat(user, "You cannot reach the controls from inside!")
+ return
+ ui.render(user)
+```
+
+#### Done
+
+
+
+You should have a functional UI at this point. Some additional odds and ends can be discovered throughout `code/modules/recycling/disposal-unit.dm`. For a full diff of the changes made to it, refer to [the original pull request on GitHub](https://github.com/OracleStation/OracleStation/pull/702/files#diff-4b6c20ec7d37222630e7524d9577e230).
+
+### API Reference
+
+#### `/datum/oracle_ui`
+
+The main datum which handles the UI.
+
+##### `get_content(mob/target)`
+Returns the HTML that should be displayed for a specified target mob. Calls `oui_getcontent` on the datasource to get the return value. *This proc is not used in the themed subclass.*
+
+##### `can_view(mob/target)`
+Returns whether the specified target mob can view the UI. Calls `oui_canview` on the datasource to get the return value.
+
+##### `test_viewer(mob/target, updating)`
+Tests whether the client is valid and can view the UI. If updating is TRUE, checks to see if they still have the UI window open.
+
+##### `render(mob/target, updating = FALSE)`
+Opens the UI for a target mob, sending HTML. If updating is TRUE, will only do it to clients which still have the window open.
+
+##### `render_all()`
+Does the above, but for all viewers and with updating set to TRUE.
+
+##### `close(mob/target)`
+Closes the UI for the specified target mob.
+
+##### `close_all()`
+Does the above, but for all viewers.
+
+##### `check_view(mob/target)`
+Checks if the specified target mob can view the UI, and if they can't closes their UI
+
+##### `check_view_all()`
+Does the above, but for all viewers.
+
+##### `call_js(mob/target, js_func, list/parameters = list())`
+Invokes `js_func` in the UI of the specified target mob with the specified parameters.
+
+##### `call_js_all(js_func, list/parameters = list()))`
+Does the above, but for all viewers.
+
+##### `steal_focus(mob/target)`
+Causes the UI to steal focus for the specified target mob.
+
+##### `steal_focus_all()`
+Does the above, but for all viewers.
+
+##### `flash(mob/target, times = -1)`
+Causes the UI to flash for the specified target mob the specified number of times, the default keeps the element flashing until focused.
+
+##### `flash_all()`
+Does the above, but for all viewers.
+
+##### `href(mob/user, action, list/parameters = list())`
+Generates a href for the specified user which will invoke `oui_act` on the datasource with the specified action and parameters.
+
+#### `/datum/oracle_ui/themed`
+
+A subclass which supports templating and theming.
+
+##### `get_file(path)`
+Loads a file from disk and returns the contents. Caches files loaded from disk for you.
+
+##### `get_content_file(filename)`
+Loads a file from the current content folder and returns the contents.
+
+##### `get_themed_file(filename)`
+Loads a file from the current theme folder and returns the contents.
+
+##### `process_template(template, variables)`
+Processes a template and populates it with the provided variables.
+
+##### `get_inner_content(mob/target)`
+Returns the templated content to be inserted into the main template for the specified target mob.
+
+##### `soft_update_fields()`
+For all viewers, updates the fields in the template via the `updateFields` javaScript function.
+
+##### `soft_update_all()`
+For all viewers, updates the content body in the template via the `replaceContent` javaScript function.
+
+##### `change_page(var/newpage)`
+Changes the template to use to draw the page and forces an update to all viewers
+
+##### `act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE`
+Returns a fully formatted hyperlink for the specified user. `label` will be the hyperlink label, `action` and `parameters` are what will be passed to `oui_act`, `class` is any CSS classes to apply to the hyperlink and `disabled` will disable the hyperlink.
+
+#### `/datum`
+
+Functions built into all objects to support oracle_ui. There are default implementations for most major superclasses.
+
+##### `oui_canview(mob/user)`
+Returns whether the specified user view the UI at this time.
+
+##### `oui_getcontent(mob/user)`
+Returns the raw HTML to be sent to the specified user. *This proc is not used in the themed subclass of oracle_ui.*
+
+##### `oui_data(mob/user)`
+Returns templating data for the specified user. *This proc is only used in the themed subclass of oracle_ui.*
+
+##### `oui_data_debug(mob/user)`
+Returns the above, but JSON-encoded and escaped, for copy pasting into the web IDE. *This proc is only used for debugging purposes.*
+
+##### `oui_act(mob/user, action, list/params)`
+Called when a hyperlink is clicked in the UI.
diff --git a/code/modules/oracle_ui/assets.dm b/code/modules/oracle_ui/assets.dm
new file mode 100644
index 0000000000..5d26d80a81
--- /dev/null
+++ b/code/modules/oracle_ui/assets.dm
@@ -0,0 +1,8 @@
+/datum/asset/simple/oui_theme_nano
+ assets = list(
+ // JavaScript
+ "sui-nano-common.js" = 'html/oracle_ui/themes/nano/sui-nano-common.js',
+ "sui-nano-jquery.min.js" = 'html/oracle_ui/themes/nano/sui-nano-jquery.min.js',
+ // Stylesheets
+ "sui-nano-common.css" = 'html/oracle_ui/themes/nano/sui-nano-common.css',
+ )
diff --git a/code/modules/oracle_ui/hookup_procs.dm b/code/modules/oracle_ui/hookup_procs.dm
new file mode 100644
index 0000000000..e6038744c1
--- /dev/null
+++ b/code/modules/oracle_ui/hookup_procs.dm
@@ -0,0 +1,44 @@
+/datum/proc/oui_canview(mob/user)
+ return TRUE
+
+/datum/proc/oui_getcontent(mob/user)
+ return "Default Implementation"
+
+/datum/proc/oui_canuse(mob/user)
+ if(isobserver(user) && !user.has_unlimited_silicon_privilege)
+ return FALSE
+ return oui_canview(user)
+
+/datum/proc/oui_data(mob/user)
+ return list()
+
+/datum/proc/oui_data_debug(mob/user)
+ return html_encode(json_encode(oui_data(user)))
+
+/datum/proc/oui_act(mob/user, action, list/params)
+ // No Implementation
+
+/atom/oui_canview(mob/user)
+ if(isobserver(user))
+ return TRUE
+ if(user.incapacitated())
+ return FALSE
+ if(isturf(src.loc) && Adjacent(user))
+ return TRUE
+ return FALSE
+
+/obj/item/oui_canview(mob/user)
+ if(src.loc == user)
+ return src in user.held_items
+ return ..()
+
+/obj/machinery/oui_canview(mob/user)
+ if(user.has_unlimited_silicon_privilege)
+ return TRUE
+ if(!can_interact())
+ return FALSE
+ if(iscyborg(user))
+ return can_see(user, src, 7)
+ if(isAI(user))
+ return GLOB.cameranet.checkTurfVis(get_turf_pixel(src))
+ return ..()
diff --git a/code/modules/oracle_ui/oracle_ui.dm b/code/modules/oracle_ui/oracle_ui.dm
new file mode 100644
index 0000000000..5e8d6b9c7b
--- /dev/null
+++ b/code/modules/oracle_ui/oracle_ui.dm
@@ -0,0 +1,134 @@
+/datum/oracle_ui
+ var/width = 512
+ var/height = 512
+ var/can_close = TRUE
+ var/can_minimize = FALSE
+ var/can_resize = TRUE
+ var/titlebar = TRUE
+ var/window_id = null
+ var/viewers[0]
+ var/auto_check_view = TRUE
+ var/auto_refresh = FALSE
+ var/atom/datasource = null
+ var/datum/asset/assets = null
+
+/datum/oracle_ui/New(atom/n_datasource, n_width = 512, n_height = 512, n_assets = null)
+ datasource = n_datasource
+ window_id = REF(src)
+ width = n_width
+ height = n_height
+
+/datum/oracle_ui/Destroy()
+ close_all()
+ if(src.datum_flags & DF_ISPROCESSING)
+ STOP_PROCESSING(SSobj, src)
+ return ..()
+
+/datum/oracle_ui/process()
+ if(auto_check_view)
+ check_view_all()
+ if(auto_refresh)
+ render_all()
+
+/datum/oracle_ui/proc/get_content(mob/target)
+ return call(datasource, "oui_getcontent")(target)
+
+/datum/oracle_ui/proc/can_view(mob/target)
+ return call(datasource, "oui_canview")(target)
+
+/datum/oracle_ui/proc/test_viewer(mob/target, updating)
+ //If the target is null or does not have a client, remove from viewers and return
+ if(!target | !target.client | !can_view(target))
+ viewers -= target
+ if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING))
+ STOP_PROCESSING(SSobj, src) //No more viewers, stop polling
+ close(target)
+ return FALSE
+ //If this is an update, and they have closed the window, remove from viewers and return
+ if(updating && winget(target, window_id, "is-visible") != "true")
+ viewers -= target
+ if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING))
+ STOP_PROCESSING(SSobj, src) //No more viewers, stop polling
+ return FALSE
+ return TRUE
+
+/datum/oracle_ui/proc/render(mob/target, updating = FALSE)
+ set waitfor = FALSE //Makes this an async call
+ if(!can_view(target))
+ return
+ //Check to see if they have the window open still if updating
+ if(updating && !test_viewer(target, updating))
+ return
+ //Send assets
+ if(!updating && assets)
+ assets.send(target)
+ //Add them to the viewers if they aren't there already
+ viewers |= target
+ if(!(src.datum_flags & DF_ISPROCESSING) && (auto_refresh | auto_check_view))
+ START_PROCESSING(SSobj, src) //Start processing to poll for viewability
+ //Send the content
+ if(updating)
+ target << output(get_content(target), "[window_id].browser")
+ else
+ target << browse(get_content(target), "window=[window_id];size=[width]x[height];can_close=[can_close];can_minimize=[can_minimize];can_resize=[can_resize];titlebar=[titlebar];focus=false;")
+ steal_focus(target)
+
+/datum/oracle_ui/proc/render_all()
+ for(var/viewer in viewers)
+ render(viewer, TRUE)
+
+/datum/oracle_ui/proc/close(mob/target)
+ if(target && target.client)
+ target << browse(null, "window=[window_id]")
+
+/datum/oracle_ui/proc/close_all()
+ for(var/viewer in viewers)
+ close(viewer)
+ viewers = list()
+
+/datum/oracle_ui/proc/check_view_all()
+ for(var/viewer in viewers)
+ check_view(viewer)
+
+/datum/oracle_ui/proc/check_view(mob/target)
+ set waitfor = FALSE //Makes this an async call
+ if(!test_viewer(target, TRUE))
+ close(target)
+
+/datum/oracle_ui/proc/call_js(mob/target, js_func, list/parameters = list())
+ set waitfor = FALSE //Makes this an async call
+ if(!test_viewer(target, TRUE))
+ return
+ target << output(list2params(parameters),"[window_id].browser:[js_func]")
+
+/datum/oracle_ui/proc/call_js_all(js_func, list/parameters = list())
+ for(var/viewer in viewers)
+ call_js(viewer, js_func, parameters)
+
+/datum/oracle_ui/proc/steal_focus(mob/target)
+ set waitfor = FALSE //Makes this an async call
+ winset(target, "[window_id]","focus=true")
+
+/datum/oracle_ui/proc/steal_focus_all()
+ for(var/viewer in viewers)
+ steal_focus(viewer)
+
+/datum/oracle_ui/proc/flash(mob/target, times = -1)
+ set waitfor = FALSE //Makes this an async call
+ winset(target, "[window_id]","flash=[times]")
+
+/datum/oracle_ui/proc/flash_all(times = -1)
+ for(var/viewer in viewers)
+ flash(viewer, times)
+
+/datum/oracle_ui/proc/href(mob/user, action, list/parameters = list())
+ var/params_string = replacetext(list2params(parameters),"&",";")
+ return "?src=[REF(src)];sui_action=[action];sui_user=[REF(user)];[params_string]"
+
+/datum/oracle_ui/Topic(href, parameters)
+ var/action = parameters["sui_action"]
+ var/mob/current_user = locate(parameters["sui_user"])
+ if(!call(datasource, "oui_canuse")(current_user))
+ return
+ if(datasource)
+ call(datasource, "oui_act")(current_user, action, parameters);
diff --git a/code/modules/oracle_ui/themed.dm b/code/modules/oracle_ui/themed.dm
new file mode 100644
index 0000000000..56b82c2647
--- /dev/null
+++ b/code/modules/oracle_ui/themed.dm
@@ -0,0 +1,82 @@
+/datum/oracle_ui/themed
+ var/theme = ""
+ var/content_root = ""
+ var/current_page = "index.html"
+ var/root_template = ""
+
+/datum/oracle_ui/themed/New(atom/n_datasource, n_width = 512, n_height = 512, n_content_root = "")
+ root_template = get_themed_file("index.html")
+ content_root = n_content_root
+ return ..(n_datasource, n_width, n_height, get_asset_datum(/datum/asset/simple/oui_theme_nano))
+
+/datum/oracle_ui/themed/process()
+ if(auto_check_view)
+ check_view_all()
+ if(auto_refresh)
+ soft_update_fields()
+
+GLOBAL_LIST_EMPTY(oui_template_variables)
+GLOBAL_LIST_EMPTY(oui_file_cache)
+
+/datum/oracle_ui/themed/proc/get_file(path)
+ if(GLOB.oui_file_cache[path])
+ return GLOB.oui_file_cache[path]
+ else if(fexists(path))
+ var/data = file2text(path)
+ GLOB.oui_file_cache[path] = data
+ return data
+ else
+ var/errormsg = "MISSING PATH '[path]'"
+#ifndef UNIT_TESTS
+ log_world(errormsg) //Because Travis absolutely hates these procs
+#endif
+ return errormsg
+
+/datum/oracle_ui/themed/proc/get_content_file(filename)
+ return get_file("./html/oracle_ui/content/[content_root]/[filename]")
+
+/datum/oracle_ui/themed/proc/get_themed_file(filename)
+ return get_file("./html/oracle_ui/themes/[theme]/[filename]")
+
+/datum/oracle_ui/themed/proc/process_template(template, variables)
+ var/regex/pattern = regex("\\@\\{(\\w+)\\}","gi")
+ GLOB.oui_template_variables = variables
+ var/replaced = pattern.Replace(template, /proc/oui_process_template_replace)
+ GLOB.oui_template_variables = null
+ return replaced
+
+/proc/oui_process_template_replace(match, group1)
+ var/value = GLOB.oui_template_variables[group1]
+ return "[value]"
+
+/datum/oracle_ui/themed/proc/get_inner_content(mob/target)
+ var/list/data = call(datasource, "oui_data")(target)
+ return process_template(get_content_file(current_page), data)
+
+/datum/oracle_ui/themed/get_content(mob/target)
+ var/list/template_data = list("title" = datasource.name, "body" = get_inner_content(target))
+ return process_template(root_template, template_data)
+
+/datum/oracle_ui/themed/proc/soft_update_fields()
+ for(var/viewer in viewers)
+ var/json = json_encode(call(datasource, "oui_data")(viewer))
+ call_js(viewer, "updateFields", list(json))
+
+/datum/oracle_ui/themed/proc/soft_update_all()
+ for(var/viewer in viewers)
+ call_js(viewer, "replaceContent", list(get_inner_content(viewer)))
+
+/datum/oracle_ui/themed/proc/change_page(newpage)
+ if(newpage == current_page)
+ return
+ current_page = newpage
+ render_all()
+
+/datum/oracle_ui/themed/proc/act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE)
+ if(disabled)
+ return "[label]"
+ else
+ return "[label]"
+
+/datum/oracle_ui/themed/nano
+ theme = "nano"
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 37877ffb09..059a42bb36 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -31,6 +31,7 @@
var/spam_flag = 0
var/contact_poison // Reagent ID to transfer on contact
var/contact_poison_volume = 0
+ var/datum/oracle_ui/ui = null
/obj/item/paper/pickup(user)
@@ -40,16 +41,40 @@
if(!istype(G) || G.transfer_prints)
H.reagents.add_reagent(contact_poison,contact_poison_volume)
contact_poison = null
+ ui.check_view_all()
..()
+/obj/item/paper/dropped(mob/user)
+ ui.check_view(user)
+ return ..()
+
/obj/item/paper/Initialize()
. = ..()
pixel_y = rand(-8, 8)
pixel_x = rand(-9, 9)
+ ui = new /datum/oracle_ui(src, 420, 600, get_asset_datum(/datum/asset/spritesheet/simple/paper))
+ ui.can_resize = FALSE
update_icon()
updateinfolinks()
+/obj/item/paper/oui_getcontent(mob/target)
+ if(!target.is_literate())
+ return "@{full_pressure}
+
+
+
+
+
+ @{per}
+ @{flush}
+ @{contents}
+ @{pressure_charging}
+ [stamps]" + else if(istype(target.get_active_held_item(), /obj/item/pen) | istype(target.get_active_held_item(), /obj/item/toy/crayon)) + return " [stamps]" + else + return " [stamps]" + +/obj/item/paper/oui_canview(mob/target) + if(check_rights_for(target.client, R_FUN)) //Allows admins to view faxes + return TRUE + if(isAI(target)) + var/mob/living/silicon/ai/ai = target + return get_dist(src, ai.current) < 2 + if(iscyborg(target)) + return get_dist(src, target) < 2 + return ..() /obj/item/paper/update_icon() @@ -65,20 +90,13 @@ /obj/item/paper/examine(mob/user) ..() to_chat(user, "Alt-click to fold it.") - - var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper) - assets.send(user) - - if(in_range(user, src) || isobserver(user)) - if(user.is_literate()) - user << browse(" [stamps]", "window=[name]") - onclose(user, "[name]") - else - user << browse(" [stamps]", "window=[name]") - onclose(user, "[name]") + if(oui_canview(user)) + ui.render(user) else to_chat(user, "You're too far away to read it!") +/obj/item/paper/proc/show_content(mob/user) + user.examinate(src) /obj/item/paper/verb/rename() set name = "Rename paper" @@ -98,7 +116,7 @@ if((loc == usr && usr.stat == CONSCIOUS)) name = "paper[(n_name ? text("- '[n_name]'") : null)]" add_fingerprint(usr) - + ui.render_all() /obj/item/paper/suicide_act(mob/user) user.visible_message("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...") @@ -108,7 +126,7 @@ spam_flag = FALSE /obj/item/paper/attack_self(mob/user) - user.examinate(src) + show_content(user) if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS])) if(!spam_flag) spam_flag = TRUE @@ -123,11 +141,9 @@ else //cyborg or AI not seeing through a camera dist = get_dist(src, user) if(dist < 2) - usr << browse(" [stamps]", "window=[name]") - onclose(usr, "[name]") + show_content(user) else - usr << browse(" [stamps]", "window=[name]") - onclose(usr, "[name]") + to_chat(user, "You can't quite see it.") /obj/item/paper/proc/addtofield(id, text, links = 0) @@ -173,6 +189,7 @@ for(var/i in 1 to min(fields, 15)) addtofield(i, "write", 1) info_links = info_links + "write" + ui.render_all() /obj/item/paper/proc/clearpaper() @@ -274,7 +291,7 @@ else info += t // Oh, he wants to edit to the end of the file, let him. updateinfolinks() - usr << browse(" [stamps]", "window=[name]") // Update the window + show_content(usr) update_icon() @@ -289,7 +306,7 @@ if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) if(user.is_literate()) - user << browse(" [stamps]", "window=[name]") + show_content(user) return else to_chat(user, "You don't know how to read or write.") @@ -312,6 +329,7 @@ add_overlay(stampoverlay) to_chat(user, "You stamp the paper with your rubber stamp.") + ui.render_all() if(P.is_hot()) if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10)) diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 7d71a9acdd..d1b99c0e3c 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -207,6 +207,7 @@ name = "combat shotgun" desc = "A semi automatic shotgun with tactical furniture and a six-shell capacity underneath." icon_state = "cshotgun" + fire_delay = 3 mag_type = /obj/item/ammo_box/magazine/internal/shot/com w_class = WEIGHT_CLASS_HUGE unique_reskin = list("Tatical" = "cshotgun", diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index f9aa47c6a3..4a1c954b1b 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -5,7 +5,7 @@ /obj/item/projectile/bullet/shotgun_beanbag name = "beanbag slug" damage = 5 - stamina = 80 + stamina = 70 /obj/item/projectile/bullet/incendiary/shotgun name = "incendiary slug" @@ -61,12 +61,12 @@ /obj/item/projectile/bullet/pellet/shotgun_buckshot name = "buckshot pellet" - damage = 12.5 + damage = 10 /obj/item/projectile/bullet/pellet/shotgun_rubbershot name = "rubbershot pellet" - damage = 3 - stamina = 25 + damage = 2 + stamina = 15 /obj/item/projectile/bullet/pellet/Range() ..() diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 8416bb17f2..85cf5e5011 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -233,6 +233,12 @@ else reagents.remove_reagent(id, amount) . = TRUE + else if (amount == -1) // -1 means custom amount + useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null + if (useramount > 0) + end_fermi_reaction() + reagents.trans_id_to(beaker, id, useramount) + . = TRUE if("toggleMode") mode = !mode @@ -379,7 +385,7 @@ reagents.trans_to(P, vol_part) . = TRUE //END CITADEL ADDITIONS - if("analyze") + if("analyzeBeak") var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]] if(R) var/state = "Unknown" @@ -395,7 +401,38 @@ if(Rcr && Rcr.FermiChem) fermianalyze = TRUE var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2 - analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = initial(R.purity), "inverseRatioF" = initial(R.InverseChemVal), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) + var/datum/reagent/targetReagent = beaker.reagents.has_reagent("[R.id]") + + if(!targetReagent) + CRASH("Tried to find a reagent that doesn't exist in the chem_master!") + analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.InverseChemVal), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) + else + fermianalyze = FALSE + analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) + screen = "analyze" + return + + if("analyzeBuff") + var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]] + if(R) + var/state = "Unknown" + if(initial(R.reagent_state) == 1) + state = "Solid" + else if(initial(R.reagent_state) == 2) + state = "Liquid" + else if(initial(R.reagent_state) == 3) + state = "Gas" + var/const/P = 3 //The number of seconds between life ticks + var/T = initial(R.metabolization_rate) * (60 / P) + if(istype(R, /datum/reagent/fermi)) + fermianalyze = TRUE + var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.id) + var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2 + var/datum/reagent/targetReagent = reagents.has_reagent("[R.id]") + + if(!targetReagent) + CRASH("Tried to find a reagent that doesn't exist in the chem_master!") + analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.InverseChemVal), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) else fermianalyze = FALSE analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index a74d6216db..88073ca5f3 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1395,12 +1395,12 @@ All effects don't start immediately, but rather get worse over time; the rate is M.set_drugginess(50) M.dizziness +=2 M.adjustBrainLoss(1*REM, 150) - if(prob(20)) + if(prob(20) && !holder.has_reagent("neuroweak")) M.adjustStaminaLoss(10) M.drop_all_held_items() to_chat(M, "You cant feel your hands!") if(current_cycle > 5) - if(prob(20)) + if(prob(20) && !holder.has_reagent("neuroweak")) var/t = pickt() ADD_TRAIT(M, t, type) M.adjustStaminaLoss(10) diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 913a6b3ef7..dd51ce2bc7 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -886,3 +886,23 @@ to_chat(M, "[pick("Diamond skies where white deer fly.","Sipping strawberry tea.","Silver raindrops drift through timeless, Neverending June.","Crystal ... pearls free, with love!","Beaming love into me.")]") ..() . = 1 + +/datum/reagent/consumable/catnip_tea + name = "Catnip Tea" + id = "catnip_tea" + description = "A sleepy and tasty catnip tea!" + color = "#101000" // rgb: 16, 16, 0 + nutriment_factor = 0 + taste_description = "sugar and catnip" + glass_icon_state = "teaglass" + glass_name = "glass of catnip tea" + glass_desc = "A purrfect drink for a cat." + +/datum/reagent/consumable/catnip_tea/on_mob_life(mob/living/carbon/M) + M.adjustStaminaLoss(min(50 - M.getStaminaLoss(), 3)) + if(prob(20)) + M.emote("nya") + if(prob(20)) + to_chat(M, "[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]") + M.adjustArousalLoss(5) + ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 07c9b166ff..bc64d6636b 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -536,12 +536,12 @@ race = /datum/species/fly mutationtext = "The pain subsides. You feel... buzzy." -/datum/reagent/mutationtoxin/moth - name = "Moth Mutation Toxin" +/datum/reagent/mutationtoxin/insect + name = "Insect Mutation Toxin" id = "mothmutationtoxin" description = "A glowing toxin." color = "#5EFF3B" //RGB: 94, 255, 59 - race = /datum/species/moth + race = /datum/species/insect mutationtext = "The pain subsides. You feel... attracted to light." /datum/reagent/mutationtoxin/pod @@ -2031,3 +2031,18 @@ /datum/reagent/changeling_string/Destroy() qdel(original_dna) return ..() + +/datum/reagent/pax/catnip + name = "catnip" + id = "catnip" + taste_description = "grass" + description = "A colorless liquid that makes people more peaceful and felines more happy." + metabolization_rate = 1.75 * REAGENTS_METABOLISM + +/datum/reagent/pax/catnip/on_mob_life(mob/living/carbon/M) + if(prob(20)) + M.emote("nya") + if(prob(20)) + to_chat(M, "[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]") + M.adjustArousalLoss(2) + ..() diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index e34f34675c..fb2e4c396c 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -623,7 +623,7 @@ required_temp = 450 /datum/chemical_reaction/moff - name = "moth mutation toxic" + name = "insect mutation toxic" id = "moffs" results = list("mothmutationtoxin" = 1) required_reagents = list("liquid_dark_matter" = 2, "ammonia" = 5, "lithium" = 1, "stablemutationtoxin" = 1) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 871fd32b16..082b1a7d11 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -264,6 +264,13 @@ name = "disposal unit" desc = "A pneumatic waste disposal unit." icon_state = "disposal" + var/datum/oracle_ui/themed/nano/ui + +/obj/machinery/disposal/bin/Initialize(mapload, obj/structure/disposalconstruct/make_from) + . = ..() + ui = new /datum/oracle_ui/themed/nano(src, 330, 190, "disposal_bin") + ui.auto_refresh = TRUE + ui.can_resize = FALSE // attack by item places it in to disposal /obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params) @@ -275,32 +282,43 @@ STR.remove_from_storage(O,src) T.update_icon() update_icon() + ui.soft_update_fields() else + ui.soft_update_fields() return ..() // handle machine interaction -/obj/machinery/disposal/bin/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) +/obj/machinery/disposal/bin/ui_interact(mob/user, state) if(stat & BROKEN) return - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "disposal_unit", name, 300, 200, master_ui, state) - ui.open() + if(user.loc == src) + to_chat(user, "You cannot reach the controls from inside!") + return + ui.render(user) -/obj/machinery/disposal/bin/ui_data(mob/user) +/obj/machinery/disposal/bin/oui_canview(mob/user) + if(user.loc == src) + return FALSE + if(stat & BROKEN) + return FALSE + if(Adjacent(user)) + return TRUE + return ..() + + +/obj/machinery/disposal/bin/oui_data(mob/user) var/list/data = list() - data["flush"] = flush - data["full_pressure"] = full_pressure - data["pressure_charging"] = pressure_charging - data["panel_open"] = panel_open - var/per = CLAMP(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100) - data["per"] = round(per, 1) + data["flush"] = flush ? ui.act("Disengage", user, "handle-0", class="active") : ui.act("Engage", user, "handle-1") + data["full_pressure"] = full_pressure ? "Ready" : (pressure_charging ? "Pressurizing" : "Off") + data["pressure_charging"] = pressure_charging ? ui.act("Turn Off", user, "pump-0", class="active", disabled=full_pressure) : ui.act("Turn On", user, "pump-1", disabled=full_pressure) + var/per = full_pressure ? 100 : CLAMP(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 99) + data["per"] = "[round(per, 1)]%" + data["contents"] = ui.act("Eject Contents", user, "eject", disabled=contents.len < 1) data["isai"] = isAI(user) return data -/obj/machinery/disposal/bin/ui_act(action, params) +/obj/machinery/disposal/bin/oui_act(mob/user, action, list/params) if(..()) return @@ -327,6 +345,7 @@ if("eject") eject() . = TRUE + ui.soft_update_fields() /obj/machinery/disposal/bin/hitby(atom/movable/AM) @@ -346,6 +365,7 @@ full_pressure = FALSE pressure_charging = TRUE update_icon() + ui.soft_update_fields() /obj/machinery/disposal/bin/update_icon() cut_overlays() @@ -389,7 +409,7 @@ do_flush() flush_count = 0 - updateDialog() + ui.soft_update_fields() if(flush && air_contents.return_pressure() >= SEND_PRESSURE) // flush can happen even without power do_flush() diff --git a/code/modules/research/designs/limbgrower_designs.dm b/code/modules/research/designs/limbgrower_designs.dm index 71f7234e34..dae59408c8 100644 --- a/code/modules/research/designs/limbgrower_designs.dm +++ b/code/modules/research/designs/limbgrower_designs.dm @@ -8,7 +8,7 @@ build_type = LIMBGROWER reagents_list = list("synthflesh" = 25) build_path = /obj/item/bodypart/l_arm - category = list("initial","human","lizard","fly","moth","plasmaman") + category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno") /datum/design/rightarm name = "Right Arm" @@ -16,7 +16,7 @@ build_type = LIMBGROWER reagents_list = list("synthflesh" = 25) build_path = /obj/item/bodypart/r_arm - category = list("initial","human","lizard","fly","moth","plasmaman") + category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno") /datum/design/leftleg name = "Left Leg" @@ -24,7 +24,7 @@ build_type = LIMBGROWER reagents_list = list("synthflesh" = 25) build_path = /obj/item/bodypart/l_leg - category = list("initial","human","lizard","fly","moth","plasmaman") + category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno") /datum/design/rightleg name = "Right Leg" @@ -32,7 +32,7 @@ build_type = LIMBGROWER reagents_list = list("synthflesh" = 25) build_path = /obj/item/bodypart/r_leg - category = list("initial","human","lizard","fly","moth","plasmaman") + category = list("initial","human","lizard","fly","insect","plasmaman","mammal","xeno") /datum/design/armblade name = "Arm Blade" diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 81b491e6de..40c22189d9 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -40,6 +40,7 @@ var/skin_tone = "" var/body_gender = "" var/species_id = "" + var/should_draw_citadel = FALSE var/should_draw_gender = FALSE var/should_draw_greyscale = FALSE var/species_color = "" @@ -48,8 +49,8 @@ var/body_markings = "" //for bodypart markings var/body_markings_icon = 'modular_citadel/icons/mob/mam_markings.dmi' var/list/markings_color = list() - var/auxmarking = "" - var/list/auxmarking_color = list() + var/aux_marking + var/digitigrade_type var/animal_origin = null //for nonhuman bodypart (e.g. monkey) var/dismemberable = 1 //whether it can be dismembered with a weapon. @@ -309,7 +310,7 @@ should_draw_greyscale = FALSE no_update = TRUE body_markings = "husk" // reeee - auxmarking = "husk" + aux_marking = "husk" if(no_update) return @@ -351,6 +352,13 @@ else species_color = "" + if("legs" in S.default_features) + if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG) + if(DIGITIGRADE in S.species_traits) + digitigrade_type = lowertext(H.dna.features.["legs"]) + else + digitigrade_type = null + if("mam_body_markings" in S.default_features) var/datum/sprite_accessory/Smark Smark = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]] @@ -358,15 +366,15 @@ body_markings_icon = Smark.icon if(H.dna.features.["mam_body_markings"] != "None") body_markings = lowertext(H.dna.features.["mam_body_markings"]) - auxmarking = lowertext(H.dna.features.["mam_body_markings"]) + aux_marking = lowertext(H.dna.features.["mam_body_markings"]) else body_markings = "plain" - auxmarking = "plain" + aux_marking = "plain" markings_color = list(colorlist) else body_markings = null - auxmarking = null + aux_marking = null if(!dropping_limb && H.dna.check_mutation(HULK)) mutation_color = "00aa00" @@ -381,7 +389,7 @@ if(status == BODYPART_ROBOTIC) dmg_overlay_type = "robotic" body_markings = null - auxmarking = null + aux_marking = null if(dropping_limb) no_update = TRUE //when attached, the limb won't be affected by the appearance changes of its mob owner. @@ -423,7 +431,7 @@ else . += image(body_markings_icon, "[body_markings]_[body_zone]", -MARKING_LAYER, image_dir) else - . += image(body_markings_icon, "[body_markings]_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) + . += image(body_markings_icon, "[body_markings]_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) var/image/limb = image(layer = -BODYPARTS_LAYER, dir = image_dir) var/image/aux @@ -453,21 +461,25 @@ if(should_draw_gender) limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" else if(use_digitigrade) - limb.icon_state = "digitigrade_[use_digitigrade]_[body_zone]" + limb.icon_state = "[digitigrade_type]_[use_digitigrade]_[body_zone]" else limb.icon_state = "[species_id]_[body_zone]" else limb.icon = 'icons/mob/human_parts.dmi' if(should_draw_gender) limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" + else if(use_digitigrade) + limb.icon_state = "[species_id]_[digitigrade_type]_[use_digitigrade]_[body_zone]" else limb.icon_state = "[species_id]_[body_zone]" // Citadel Start - if(should_draw_citadel && !use_digitigrade) + if(should_draw_citadel) limb.icon = 'modular_citadel/icons/mob/mutant_bodyparts.dmi' if(should_draw_gender) limb.icon_state = "[species_id]_[body_zone]_[icon_gender]" + else if(use_digitigrade) + limb.icon_state = "[species_id]_[digitigrade_type]_[use_digitigrade]_[body_zone]" else limb.icon_state = "[species_id]_[body_zone]" @@ -476,7 +488,7 @@ if(species_id == "husk") marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[body_zone]", -MARKING_LAYER, image_dir) else if(species_id == "husk" && use_digitigrade) - marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) + marking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) else if(!use_digitigrade) if(body_zone == BODY_ZONE_CHEST) @@ -484,20 +496,21 @@ else marking = image(body_markings_icon, "[body_markings]_[body_zone]", -MARKING_LAYER, image_dir) else - marking = image(body_markings_icon, "[body_markings]_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) + marking = image(body_markings_icon, "[body_markings]_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) + . += marking // Citadel End if(aux_zone) aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir) - . += aux - if(!isnull(auxmarking)) + if(!isnull(aux_marking)) if(species_id == "husk") auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir) else auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir) - . += auxmarking + . += aux + . += auxmarking else limb.icon = icon @@ -509,7 +522,7 @@ if(aux_zone) aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir) . += aux - if(!isnull(auxmarking)) + if(!isnull(aux_marking)) if(species_id == "husk") auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir) else @@ -528,7 +541,7 @@ else marking = image(body_markings_icon, "[body_markings]_[body_zone]", -MARKING_LAYER, image_dir) else - marking = image(body_markings_icon, "[body_markings]_digitigrade_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) + marking = image(body_markings_icon, "[body_markings]_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir) . += marking return @@ -538,8 +551,11 @@ limb.color = "#[draw_color]" if(aux_zone) aux.color = "#[draw_color]" - if(!isnull(auxmarking)) - auxmarking.color = list(markings_color) + if(!isnull(aux_marking)) + if(species_id == "husk") + auxmarking.color = "#141414" + else + auxmarking.color = list(markings_color) if(!isnull(body_markings)) if(species_id == "husk") diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index eeaaaf2a03..40d11ca2a4 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -321,7 +321,7 @@ if(!istype(parent)) return INITIALIZE_HINT_QDEL -/obj/item/organ/eyes/moth - name = "moth eyes" +/obj/item/organ/eyes/insect + name = "insect eyes" desc = "These eyes seem to have increased sensitivity to bright light, with no improvement to low light vision." flash_protect = -1 diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index a265a4e907..c577643df3 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -54,7 +54,7 @@ /obj/item/clothing/head/ushanka = 1, /obj/item/clothing/suit/imperium_monk = 1, /obj/item/clothing/mask/gas/cyborg = 1, - /obj/item/clothing/suit/holidaypriest = 1, + /obj/item/clothing/suit/chaplain/holidaypriest = 1, /obj/item/clothing/head/wizard/marisa/fake = 1, /obj/item/clothing/suit/wizrobe/marisa/fake = 1, /obj/item/clothing/under/sundress = 1, @@ -122,7 +122,7 @@ /obj/item/clothing/shoes/roman = 1, /obj/item/shield/riot/roman/fake = 1, /obj/item/skub = 1, - /obj/item/clothing/under/lobster = 1, // CIT CHANGES + /obj/item/clothing/under/lobster = 1, // CIT CHANGES /obj/item/clothing/head/lobsterhat = 1, /obj/item/clothing/head/drfreezehat = 1, /obj/item/clothing/suit/dracula = 1, diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 1497992fe8..b232184975 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -99,7 +99,9 @@ /obj/item/clothing/suit/jacket/letterman_red = 3, /obj/item/clothing/ears/headphones = 10, /obj/item/clothing/suit/apron/purple_bartender = 4, - /obj/item/clothing/under/rank/bartender/purple = 4) + /obj/item/clothing/under/rank/bartender/purple = 4, + /obj/item/clothing/accessory/attrocious_pokadots = 8, + /obj/item/clothing/accessory/black_white_pokadots = 8) contraband = list(/obj/item/clothing/under/syndicate/tacticool = 3, /obj/item/clothing/under/syndicate/tacticool/skirt = 3, /obj/item/clothing/mask/balaclava = 3, @@ -109,7 +111,8 @@ /obj/item/clothing/suit/jacket/letterman_syndie = 5, /obj/item/clothing/under/jabroni = 2, /obj/item/clothing/suit/vapeshirt = 2, - /obj/item/clothing/under/geisha = 4) + /obj/item/clothing/under/geisha = 4, + /obj/item/clothing/accessory/syndi_pokadots = 4) premium = list(/obj/item/clothing/under/suit_jacket/checkered = 4, /obj/item/clothing/head/mailman = 2, /obj/item/clothing/under/rank/mailman = 2, @@ -117,7 +120,8 @@ /obj/item/clothing/suit/jacket/leather/overcoat = 4, /obj/item/clothing/under/pants/mustangjeans = 3, /obj/item/clothing/neck/necklace/dope = 5, - /obj/item/clothing/suit/jacket/letterman_nanotrasen = 5) + /obj/item/clothing/suit/jacket/letterman_nanotrasen = 5, + /obj/item/clothing/accessory/nt_pokadots = 5) refill_canister = /obj/item/vending_refill/clothing /obj/item/vending_refill/clothing diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 015890419d..0cf0069436 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -317,10 +317,10 @@ /obj/item/clothing/under/rank/chaplain = 2, /obj/item/clothing/under/rank/chaplain/skirt = 2, /obj/item/clothing/shoes/sneakers/black = 2, - /obj/item/clothing/suit/nun = 2, + /obj/item/clothing/suit/chaplain/nun = 2, /obj/item/clothing/head/nun_hood = 2, - /obj/item/clothing/suit/holidaypriest = 2, - /obj/item/clothing/suit/pharaoh = 2, + /obj/item/clothing/suit/chaplain/holidaypriest = 2, + /obj/item/clothing/suit/chaplain/pharaoh = 2, /obj/item/clothing/head/nemes = 1, /obj/item/clothing/head/pharaoh = 1, /obj/item/storage/fancy/candle_box = 3) diff --git a/config/game_options.txt b/config/game_options.txt index 6d59f10807..2e346ce0ac 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -410,7 +410,7 @@ ROUNDSTART_RACES human ## Races that are strictly worse than humans that could probably be turned on without balance concerns ROUNDSTART_RACES lizard #ROUNDSTART_RACES fly -#ROUNDSTART_RACES moth +#ROUNDSTART_RACES insect ROUNDSTART_RACES plasmaman #ROUNDSTART_RACES shadow ROUNDSTART_RACES felinid diff --git a/html/changelogs/AutoChangeLog-pr-9086.yml b/html/changelogs/AutoChangeLog-pr-9086.yml new file mode 100644 index 0000000000..4dea682d47 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9086.yml @@ -0,0 +1,4 @@ +author: "original by TheChosenEvilOne, port by sishen1542" +delete-after: True +changes: + - rscadd: "Ported dynamic mode from /vg/, originally made by @DeityLink, @Kurfursten and @ShiftyRail" diff --git a/html/changelogs/AutoChangeLog-pr-9109.yml b/html/changelogs/AutoChangeLog-pr-9109.yml new file mode 100644 index 0000000000..137ca7f325 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9109.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "amazing things like tea of catnip, catnip and plant" diff --git a/html/changelogs/AutoChangeLog-pr-9199.yml b/html/changelogs/AutoChangeLog-pr-9199.yml new file mode 100644 index 0000000000..bf0219c7d9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9199.yml @@ -0,0 +1,7 @@ +author: "Tupinambis" +delete-after: True +changes: + - balance: "added a small fire delay (3 ticks) to automatic shotguns" + - balance: "Reduced buckshot brute damage by 20%. (12.5 -> 10 brute per pellet) (75 -> 60 brute at close range)" + - balance: "Reduced rubbershot stamina damage by 40% (25 -> 15 stamina per pellet) (150 -> 90 stamina at close range)" + - balance: "Reduced beanbag stamina damage by 12.5% (80 -> 70 stamina per shot)" diff --git a/html/changelogs/AutoChangeLog-pr-9241.yml b/html/changelogs/AutoChangeLog-pr-9241.yml new file mode 100644 index 0000000000..1cb08cd8d0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9241.yml @@ -0,0 +1,6 @@ +author: "Alonefromhell" +delete-after: True +changes: + - rscadd: "Ported Oracle UI, a framework for self-updating and neat UI's" + - refactor: "Paper now uses OUI" + - refactor: "Bins now use OUI" diff --git a/html/changelogs/AutoChangeLog-pr-9251.yml b/html/changelogs/AutoChangeLog-pr-9251.yml new file mode 100644 index 0000000000..c40c2e05fc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9251.yml @@ -0,0 +1,5 @@ +author: "Linzolle" +delete-after: True +changes: + - tweak: "all chaplain suits can hold the same items in suit storage" + - code_imp: "improvement to organisation for chaplain suits" diff --git a/html/changelogs/AutoChangeLog-pr-9275.yml b/html/changelogs/AutoChangeLog-pr-9275.yml new file mode 100644 index 0000000000..cd74273366 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9275.yml @@ -0,0 +1,5 @@ +author: "Fermis" +delete-after: True +changes: + - bugfix: "Fixes analyse function on ChemMasters to correctly display purity." + - bugfix: "Fixes the custom transfer for buffer to beaker button." diff --git a/html/changelogs/AutoChangeLog-pr-9276.yml b/html/changelogs/AutoChangeLog-pr-9276.yml new file mode 100644 index 0000000000..f778c26c13 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9276.yml @@ -0,0 +1,6 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - rscadd: "trash" + - imageadd: "eye bleed +:add: misstakes" diff --git a/html/changelogs/AutoChangeLog-pr-9277.yml b/html/changelogs/AutoChangeLog-pr-9277.yml new file mode 100644 index 0000000000..4bf92cd32e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9277.yml @@ -0,0 +1,11 @@ +author: "Poojawa" +delete-after: True +changes: + - rscadd: "Added new wings to Insects and separated fluff from old ones, they're Insect's new body markings now without being per-limb (for now)." + - rscadd: "Horns are now available to mammals, and they have their own color." + - rscadd: "Legs are no longer a binary hack code, but actually something that can be changed. Framework for tauric adaptations." + - rscdel: "Purged Modular Citadel's sprite_accessories." + - bugfix: "improved the quality of a number of sprites." + - tweak: "Moths are now all insects. Avians and Aquatics are all anthromorphics. Just as planned." + - rscadd: "Anthromorphs can choose their preferred gibbing meat. I guess. Snowflakes are weird." + - bugfix: "Additional Gentlemen names." diff --git a/html/changelogs/AutoChangeLog-pr-9278.yml b/html/changelogs/AutoChangeLog-pr-9278.yml new file mode 100644 index 0000000000..3ec1eb839a --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9278.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - bugfix: "Spamming forged packets no longer crashes the server." diff --git a/html/changelogs/AutoChangeLog-pr-9279.yml b/html/changelogs/AutoChangeLog-pr-9279.yml new file mode 100644 index 0000000000..572f40e643 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9279.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed undergarments color preferences resetting each round." diff --git a/html/changelogs/AutoChangeLog-pr-9288.yml b/html/changelogs/AutoChangeLog-pr-9288.yml new file mode 100644 index 0000000000..8a684431bf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9288.yml @@ -0,0 +1,4 @@ +author: "Trilbyspaceclone" +delete-after: True +changes: + - bugfix: "UI memes" diff --git a/html/changelogs/AutoChangeLog-pr-9289.yml b/html/changelogs/AutoChangeLog-pr-9289.yml new file mode 100644 index 0000000000..7abf947bfc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9289.yml @@ -0,0 +1,4 @@ +author: "Sishen1542" +delete-after: True +changes: + - bugfix: "fixing chems for strained muscles" diff --git a/html/changelogs/AutoChangeLog-pr-9295.yml b/html/changelogs/AutoChangeLog-pr-9295.yml new file mode 100644 index 0000000000..a96540c11b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9295.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - balance: "Slowed down police baton and tele baton speed by 75%, should be still be faster than the legacy speed (2 seconds) by 0.6 seconds. Telescopic batons' stamina cost per swing is now on par with police batons, ergo more expensive." diff --git a/html/changelogs/AutoChangeLog-pr-9302.yml b/html/changelogs/AutoChangeLog-pr-9302.yml new file mode 100644 index 0000000000..4f6ed4d336 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9302.yml @@ -0,0 +1,4 @@ +author: "deathride58" +delete-after: True +changes: + - bugfix: "Things that access job_preferences now explicitly access keys, which means it no longer attempts to access invalid indices and runtimes as a result." diff --git a/html/oracle_ui/content/disposal_bin/index.html b/html/oracle_ui/content/disposal_bin/index.html new file mode 100644 index 0000000000..8f7713b53c --- /dev/null +++ b/html/oracle_ui/content/disposal_bin/index.html @@ -0,0 +1,27 @@ +
+
\ No newline at end of file
diff --git a/html/oracle_ui/editor_tool.html b/html/oracle_ui/editor_tool.html
new file mode 100644
index 0000000000..e0ce75bb29
--- /dev/null
+++ b/html/oracle_ui/editor_tool.html
@@ -0,0 +1,103 @@
+
+
+
+
+
+ @{full_pressure}
+
+
+
+
+
+ @{per}
+ @{flush}
+ @{contents}
+ @{pressure_charging}
+
+
+ Content Template:+ +
+
+ Data:+ +
+
+
+
+
diff --git a/html/oracle_ui/themes/nano/index.html b/html/oracle_ui/themes/nano/index.html
new file mode 100644
index 0000000000..388f6e4ce4
--- /dev/null
+++ b/html/oracle_ui/themes/nano/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Output:+ +
+
+
+
diff --git a/html/oracle_ui/themes/nano/sui-nano-common.css b/html/oracle_ui/themes/nano/sui-nano-common.css
new file mode 100644
index 0000000000..481b81c3e3
--- /dev/null
+++ b/html/oracle_ui/themes/nano/sui-nano-common.css
@@ -0,0 +1,353 @@
+body
+{
+ padding: 0;
+ margin: 0;
+ background-color: #272727;
+ font-size: 12px;
+ color: #ffffff;
+ line-height: 170%;
+ cursor: default;
+ -moz-user-select: none;
+ -ms-user-select: none;
+}
+
+hr
+{
+ background-color: #40628a;
+ height: 1px;
+}
+
+a, a:link, a:visited, a:active, .linkOn, .linkOff
+{
+ color: #ffffff;
+ text-decoration: none;
+ background: #40628a;
+ border: 1px solid #161616;
+ padding: 1px 4px 1px 4px;
+ margin: 0 2px 0 0;
+ cursor:default;
+}
+
+a:hover
+{
+ color: #40628a;
+ background: #ffffff;
+}
+
+a.white, a.white:link, a.white:visited, a.white:active
+{
+ color: #40628a;
+ text-decoration: none;
+ background: #ffffff;
+ border: 1px solid #161616;
+ padding: 1px 4px 1px 4px;
+ margin: 0 2px 0 0;
+ cursor:default;
+}
+
+a.white:hover
+{
+ color: #ffffff;
+ background: #40628a;
+}
+
+.active, a.active:link, a.active:visited, a.active:active, a.active:hover
+{
+ color: #ffffff;
+ background: #2f943c;
+ border-color: #24722e;
+}
+
+.disabled, a.disabled:link, a.disabled:visited, a.disabled:active, a.disabled:hover
+{
+ color: #ffffff;
+ background: #999999;
+ border-color: #666666;
+}
+
+a.icon, .linkOn.icon, .linkOff.icon
+{
+ position: relative;
+ padding: 1px 4px 2px 20px;
+}
+
+a.icon img, .linkOn.icon img
+{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 18px;
+ height: 18px;
+}
+
+ul
+{
+ padding: 4px 0 0 10px;
+ margin: 0;
+ list-style-type: none;
+}
+
+li
+{
+ padding: 0 0 2px 0;
+}
+
+img, a img
+{
+ border-style:none;
+}
+
+h1, h2, h3, h4, h5, h6
+{
+ margin: 0;
+ padding: 16px 0 8px 0;
+ color: #517087;
+}
+
+h1
+{
+ font-size: 15px;
+}
+
+h2
+{
+ font-size: 14px;
+}
+
+h3
+{
+ font-size: 13px;
+}
+
+h4
+{
+ font-size: 12px;
+}
+
+.uiWrapper
+{
+
+ width: 100%;
+ height: 100%;
+}
+
+.uiTitle
+{
+ clear: both;
+ padding: 6px 8px 6px 8px;
+ border-bottom: 2px solid #161616;
+ background: #383838;
+ color: #98B0C3;
+ font-size: 16px;
+}
+
+.uiTitle.icon
+{
+ padding: 6px 8px 6px 42px;
+ background-position: 2px 50%;
+ background-repeat: no-repeat;
+}
+
+.uiContent
+{
+ clear: both;
+ padding: 8px;
+ font-family: Verdana, Geneva, sans-serif;
+}
+
+.good
+{
+ color: #00ff00;
+}
+
+.average
+{
+ color: #d09000;
+}
+
+.bad
+{
+ color: #ff0000;
+}
+
+.highlight
+{
+ color: #8BA5C4;
+}
+
+.dark
+{
+ color: #272727;
+}
+
+.notice
+{
+ position: relative;
+ background: #E9C183;
+ color: #15345A;
+ font-size: 10px;
+ font-style: italic;
+ padding: 2px 4px 0 4px;
+ margin: 4px;
+}
+
+.notice.icon
+{
+ padding: 2px 4px 0 20px;
+}
+
+.notice img
+{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 16px;
+ height: 16px;
+}
+
+div.notice
+{
+ clear: both;
+}
+
+.statusDisplay
+{
+ background: #000000;
+ color: #ffffff;
+ border: 1px solid #40628a;
+ padding: 4px;
+ margin: 3px 0;
+}
+
+.statusLabel
+{
+ width: 138px;
+ float: left;
+ overflow: hidden;
+ color: #98B0C3;
+}
+
+.statusValue
+{
+ float: left;
+}
+
+.block
+{
+ padding: 8px;
+ margin: 10px 4px 4px 4px;
+ border: 1px solid #40628a;
+ background-color: #202020;
+}
+
+.block h3
+{
+ padding: 0;
+}
+
+.progressBar
+{
+ position: relative;
+ width: 185px;
+ height: 14px;
+ border: 1px solid #666666;
+ float: left;
+ overflow: hidden;
+ padding: 1px;
+}
+
+.progressLabel
+{
+ top: -2px;
+ height: 100%;
+ position: absolute;
+ right: 4px;
+ text-align: right;
+}
+
+.progressFill
+{
+ width: 100%;
+ height: 100%;
+ background: #40628a;
+ overflow: hidden;
+ transition: width 2.2s linear;
+}
+
+.progressFill.good
+{
+ color: #ffffff;
+ background: #00ff00;
+}
+
+.progressFill.average
+{
+ color: #ffffff;
+ background: #d09000;
+}
+
+.progressFill.bad
+{
+ color: #ffffff;
+ background: #ff0000;
+}
+
+.progressFill.highlight
+{
+ color: #ffffff;
+ background: #8BA5C4;
+}
+
+.clearBoth
+{
+ clear: both;
+}
+
+.clearLeft
+{
+ clear: left;
+}
+
+.clearRight
+{
+ clear: right;
+}
+
+.line
+{
+ width: 100%;
+ clear: both;
+}
+
+section .label, section .content
+{
+ display: table-cell;
+ margin: 0;
+ text-align: left;
+ vertical-align: middle;
+ padding: 3px 2px
+}
+
+section .label
+{
+ width: 1%;
+ padding-right: 32px;
+ white-space: nowrap;
+ color: #8ba5c4;
+}
+
+section
+{
+ display: table-row;
+ width: 100%
+}
+
+.display {
+ width: calc(100% - 8px);
+ padding: 4px;
+ background-color: #000;
+ background-color: rgba(0, 0, 0, .33);
+ box-shadow: inset 0 0 5px rgba(0, 0, 0, .5);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";
+ filter: progid: DXImageTransform.Microsoft.gradient(startColorStr=#54000000, endColorStr=#54000000);
+}
\ No newline at end of file
diff --git a/html/oracle_ui/themes/nano/sui-nano-common.js b/html/oracle_ui/themes/nano/sui-nano-common.js
new file mode 100644
index 0000000000..716891a53f
--- /dev/null
+++ b/html/oracle_ui/themes/nano/sui-nano-common.js
@@ -0,0 +1,47 @@
+function replaceContent(body) {
+ var maincontent = document.getElementById('maincontent');
+ if(maincontent) {
+ maincontent.innerHTML = body;
+ }
+}
+
+function updateProgressLabels() {
+ var progressBars = document.getElementsByClassName("progressBar");
+ for(var i = 0; i < progressBars.length; i++) {
+ var progressBar = progressBars[i];
+ if(!progressBar)
+ continue;
+ var progressFill = progressBar.getElementsByClassName("progressFill")[0];
+ if(!progressFill)
+ continue;
+ var width = parseInt(getComputedStyle(progressFill).width);
+ var maxWidth = parseInt(getComputedStyle(progressBar).width);
+ var progressLabel = progressBar.getElementsByClassName("progressLabel")[0];
+ if(progressLabel)
+ progressLabel.innerHTML = Math.round((width / maxWidth) * 100) + '%';
+ }
+}
+
+if(getComputedStyle) { setInterval(updateProgressLabels, 50); } //Fallback
+
+function updateFields(json) {
+ var fields = JSON.parse(json);
+ for (var key in fields) {
+ let value = fields[key];
+ var element = document.getElementById(key);
+ if(element == null) {
+ continue;
+ } else if(element.classList.contains('progressBar')) {
+ var progressFill = element.getElementsByClassName("progressFill")[0];
+ if(progressFill)
+ progressFill.style["width"] = value;
+ if(!getComputedStyle) { //Fallback
+ var progressLabel = element.getElementsByClassName("progressLabel")[0];
+ if(progressLabel)
+ progressLabel.innerHTML = value;
+ }
+ } else {
+ element.innerHTML = value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/html/oracle_ui/themes/nano/sui-nano-jquery.min.js b/html/oracle_ui/themes/nano/sui-nano-jquery.min.js
new file mode 100644
index 0000000000..645c5adc18
--- /dev/null
+++ b/html/oracle_ui/themes/nano/sui-nano-jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;
+ if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length@{title}
+ @{body}
+
+ "," "]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"
").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m});
\ No newline at end of file
diff --git a/icons/mob/accessories.dmi b/icons/mob/accessories.dmi
index 68f13c887568e3a6335655aaa82e66e558c21f5c..33964645ee192faadb0ce7db9dc4a2b412c7bdfd 100644
GIT binary patch
literal 9452
zcmc(Fg +9T}>J={QO}abj#=54av4Hkt>i*@hv9Wd3JI?$G(RdS}&^BG~ z$kyH6ttf{sJC-<}Ew1=%{_2W{i+?f_(YrB?sfQH5T=3+&$-CW~dR&ISctx{*<3|6` zQJI^AuQbwdALd526RPtNp |