diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9099488143..19a0ceb7de 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,14 @@ { "recommendations": [ - "gbasood.byond-dm-language-support", - "platymuus.dm-langclient" - ] + "gbasood.byond-dm-language-support", + "platymuus.dm-langclient", + "stylemistake.auto-comment-blocks", + "eamodio.gitlens", + "oderwat.indent-rainbow", + "rexebin.darkpurple-black", + "dbaeumer.vscode-eslint", + "editorconfig.editorconfig", + "donkie.vscode-tgstation-test-adapter", + "icrawl.discord-vscode" + ] } diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm index 0a98818683..ed22966cbe 100644 --- a/code/__defines/chemistry.dm +++ b/code/__defines/chemistry.dm @@ -37,6 +37,7 @@ #define CE_SPEEDBOOST "gofast" // Hyperzine #define CE_SLOWDOWN "goslow" // Slowdown #define CE_ANTACID "nopuke" // Don't puke. +#define CE_ALLERGEN "allergyreaction" // Self explanatory #define REAGENTS_PER_SHEET 20 @@ -47,7 +48,7 @@ // Chemistry lists. var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglycerin", "thirteenloko", "nicotine") // Increase heart rate. -var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate. +var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "bliss", "stoxin", "ambrosia_extract") // Decrease heart rate. var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart. var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional diff --git a/code/__defines/holomap.dm b/code/__defines/holomap.dm index 53584a5648..2cb576c0ef 100644 --- a/code/__defines/holomap.dm +++ b/code/__defines/holomap.dm @@ -62,6 +62,7 @@ #define HOLOMAP_AREACOLOR_ARRIVALS "#0000FFCC" #define HOLOMAP_AREACOLOR_ESCAPE "#FF0000CC" #define HOLOMAP_AREACOLOR_DORMS "#CCCC0099" +#define HOLOMAP_AREACOLOR_CIV "#3ea800" //VOREStation Addition #define LIST_NUMERIC_SET(L, I, V) if(!L) { L = list(); } if (L.len < I) { L.len = I; } L[I] = V diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm index 2e1ff795d6..8689580b04 100644 --- a/code/__defines/is_helpers.dm +++ b/code/__defines/is_helpers.dm @@ -13,7 +13,7 @@ #define isitem(D) istype(D, /obj/item) -#define isradio(A) istype(A, /obj/item/device/radio) +#define isradio(A) istype(A, /obj/item/device/radio) #define isairlock(A) istype(A, /obj/machinery/door/airlock) @@ -23,6 +23,8 @@ #define ismecha(A) istype(A, /obj/mecha) +#define isstructure(A) istype(A, /obj/structure) + //--------------- //#define isarea(D) istype(D, /area) //Built in diff --git a/code/__defines/misc_vr.dm b/code/__defines/misc_vr.dm index 986029d0a1..9a9d7ba3f4 100644 --- a/code/__defines/misc_vr.dm +++ b/code/__defines/misc_vr.dm @@ -20,7 +20,7 @@ //For custom species #define STARTING_SPECIES_POINTS 1 //CHOMPEdit -#define MAX_SPECIES_TRAITS 8 //CHOMPEdit +#define MAX_SPECIES_TRAITS 6 //CHOMPEdit - Cap positive traits at 6, given negatives are unlimited. // Xenochimera thing mostly #define REVIVING_NOW -1 diff --git a/code/__defines/span_vr.dm b/code/__defines/span_vr.dm new file mode 100644 index 0000000000..85e9672dae --- /dev/null +++ b/code/__defines/span_vr.dm @@ -0,0 +1,121 @@ +// Sorted alphabetically +// Shamelessly yoinked from TGCode, luv u folks +#define span_abductor(str) ("" + str + "") +#define span_admin(str) ("" + str + "") +#define span_adminhelp(str) ("" + str + "") +#define span_adminnotice(str) ("" + str + "") +#define span_adminobserverooc(str) ("" + str + "") +#define span_adminooc(str) ("" + str + "") +#define span_adminsay(str) ("" + str + "") +#define span_aiprivradio(str) ("" + str + "") +#define span_alert(str) ("" + str + "") +#define span_alertalien(str) ("" + str + "") +#define span_alertsyndie(str) ("" + str + "") +#define span_alertwarning(str) ("" + str + "") +#define span_alien(str) ("" + str + "") +#define span_announce(str) ("" + str + "") +#define span_big(str) ("" + str + "") +#define span_bigicon(str) ("" + str + "") +#define span_binarysay(str) ("" + str + "") +#define span_blue(str) ("" + str + "") +#define span_blueteamradio(str) ("" + str + "") +#define span_bold(str) ("" + str + "") +#define span_boldannounce(str) ("" + str + "") +#define span_boldnotice(str) ("" + str + "") +#define span_boldwarning(str) ("" + str + "") +#define span_centcomradio(str) ("" + str + "") +#define span_changeling(str) ("" + str + "") +#define span_clown(str) ("" + str + "") +#define span_colossus(str) ("" + str + "") +#define span_command_headset(str) ("" + str + "") +#define span_comradio(str) ("" + str + "") +#define span_cult(str) ("" + str + "") +#define span_cultbold(str) ("" + str + "") +#define span_cultboldtalic(str) ("" + str + "") +#define span_cultitalic(str) ("" + str + "") +#define span_cultlarge(str) ("" + str + "") +#define span_danger(str) ("" + str + "") +#define span_deadsay(str) ("" + str + "") +#define span_deconversion_message(str) ("" + str + "") +#define span_drone(str) ("" + str + "") +#define span_engradio(str) ("" + str + "") +#define span_extremelybig(str) ("" + str + "") +#define span_ghostalert(str) ("" + str + "") +#define span_green(str) ("" + str + "") +#define span_greenannounce(str) ("" + str + "") +#define span_greenteamradio(str) ("" + str + "") +#define span_greentext(str) ("" + str + "") +#define span_hear(str) ("" + str + "") +#define span_hidden(str) ("") +#define span_hierophant(str) ("" + str + "") +#define span_hierophant_warning(str) ("" + str + "") +#define span_highlight(str) ("" + str + "") +#define span_his_grace(str) ("" + str + "") +#define span_holoparasite(str) ("" + str + "") +#define span_hypnophrase(str) ("" + str + "") +#define span_icon(str) ("" + str + "") +#define span_info(str) ("" + str + "") +#define span_interface(str) ("" + str + "") +#define span_looc(str) ("" + str + "") +#define span_medal(str) ("" + str + "") +#define span_medradio(str) ("" + str + "") +#define span_memo(str) ("" + str + "") +#define span_memoedit(str) ("" + str + "") +#define span_mind_control(str) ("" + str + "") +#define span_minorannounce(str) ("" + str + "") +#define span_monkey(str) ("" + str + "") +#define span_monkeyhive(str) ("" + str + "") +#define span_monkeylead(str) ("" + str + "") +#define span_name(str) ("" + str + "") +#define span_narsie(str) ("" + str + "") +#define span_narsiesmall(str) ("" + str + "") +#define span_nicegreen(str) ("" + str + "") +#define span_notice(str) ("" + str + "") +#define span_noticealien(str) ("" + str + "") +#define span_ooc(str) ("" + str + "") +#define span_papyrus(str) ("" + str + "") +#define span_phobia(str) ("" + str + "") +#define span_prefix(str) ("" + str + "") +#define span_purple(str) ("" + str + "") +#define span_radio(str) ("" + str + "") +#define span_reallybig(str) ("" + str + "") +#define span_red(str) ("" + str + "") +#define span_redteamradio(str) ("" + str + "") +#define span_redtext(str) ("" + str + "") +#define span_resonate(str) ("" + str + "") +#define span_revenbignotice(str) ("" + str + "") +#define span_revenboldnotice(str) ("" + str + "") +#define span_revendanger(str) ("" + str + "") +#define span_revenminor(str) ("" + str + "") +#define span_revennotice(str) ("" + str + "") +#define span_revenwarning(str) ("" + str + "") +#define span_robot(str) ("" + str + "") +#define span_rose(str) ("" + str + "") +#define span_sans(str) ("" + str + "") +#define span_sciradio(str) ("" + str + "") +#define span_secradio(str) ("" + str + "") +#define span_servradio(str) ("" + str + "") +#define span_singing(str) ("" + str + "") +#define span_slime(str) ("" + str + "") +#define span_small(str) ("" + str + "") +#define span_smallnotice(str) ("" + str + "") +#define span_smallnoticeital(str) ("" + str + "") +#define span_spider(str) ("" + str + "") +#define span_suicide(str) ("" + str + "") +#define span_suppradio(str) ("" + str + "") +#define span_swarmer(str) ("" + str + "") +#define span_syndradio(str) ("" + str + "") +#define span_tape_recorder(str) ("" + str + "") +#define span_tinynotice(str) ("" + str + "") +#define span_tinynoticeital(str) ("" + str + "") +#define span_unconscious(str) ("" + str + "") +#define span_userdanger(str) ("" + str + "") +#define span_warning(str) ("" + str + "") +#define span_yell(str) ("" + str + "") +#define span_yellowteamradio(str) ("" + str + "" + +// VORE Specific stuff after this point +// Sorted by however I felt like it +#define span_game_say(str) ("" + str + "" +#define span_emote_subtle(str) ("" + str + "" +#define span_emote(str) ("" + str + "" \ No newline at end of file diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm index 46cff510cb..67d6b6e7d6 100644 --- a/code/__defines/species_languages.dm +++ b/code/__defines/species_languages.dm @@ -40,14 +40,16 @@ #define ALLERGEN_STIMULANT 0x1000 // Stimulants are what makes the Tajaran heart go ruh roh - not just coffee! // Allergen reactions -#define AG_TOX_DMG 0x1 // the classic -#define AG_OXY_DMG 0x2 // intense airway reactions -#define AG_EMOTE 0x4 // general emote reactions based on affect type -#define AG_PAIN 0x8 // short-lived hurt -#define AG_WEAKEN 0x10 // too weak to move, oof -#define AG_BLURRY 0x20 // blurred vision! -#define AG_SLEEPY 0x40 // fatigue/exhaustion -#define AG_CONFUSE 0x80 // disorientation - VOREStation addition +#define AG_PHYS_DMG 0x1 // brute +#define AG_BURN_DMG 0x2 // burns +#define AG_TOX_DMG 0x4 // the classic +#define AG_OXY_DMG 0x8 // intense airway reactions +#define AG_EMOTE 0x10 // general emote reactions based on affect type +#define AG_PAIN 0x20 // short-lived hurt +#define AG_WEAKEN 0x40 // too weak to move, oof +#define AG_BLURRY 0x80 // blurred vision! +#define AG_SLEEPY 0x100 // fatigue/exhaustion +#define AG_CONFUSE 0x200 // disorientation // Species spawn flags #define SPECIES_IS_WHITELISTED 0x1 // Must be whitelisted to play. diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index 850ec24c38..8088eaa5e1 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -590,3 +590,252 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN, var/global/list/weavable_structures = list() var/global/list/weavable_items = list() + + +var/global/list/xenobio_metal_materials_normal = list( + /obj/item/stack/material/steel = 20, + /obj/item/stack/material/glass = 15, + /obj/item/stack/material/plastic = 12, + /obj/item/stack/material/wood = 12, + /obj/item/stack/material/cardboard = 6, + /obj/item/stack/material/sandstone = 5, + /obj/item/stack/material/log = 5, + /obj/item/stack/material/lead = 5, + /obj/item/stack/material/iron = 5, + /obj/item/stack/material/graphite = 5, + /obj/item/stack/material/copper = 4, + /obj/item/stack/material/tin = 4, + /obj/item/stack/material/bronze = 4, + /obj/item/stack/material/aluminium = 4) + +var/global/list/xenobio_metal_materials_adv = list( + /obj/item/stack/material/glass/reinforced = 15, + /obj/item/stack/material/marble = 10, + /obj/item/stack/material/plasteel = 10, + /obj/item/stack/material/glass/phoronglass = 10, + /obj/item/stack/material/wood/sif = 5, + /obj/item/stack/material/wood/hard = 5, + /obj/item/stack/material/log/sif = 5, + /obj/item/stack/material/log/hard = 5, + /obj/item/stack/material/glass/phoronrglass = 5, + /obj/item/stack/material/glass/titanium = 3, + /obj/item/stack/material/glass/plastitanium = 3, + /obj/item/stack/material/durasteel = 2, + /obj/item/stack/material/painite = 1, + /obj/item/stack/material/void_opal = 1, + /obj/item/stack/material/quartz = 1) + +var/global/list/xenobio_metal_materials_weird = list( + /obj/item/stack/material/cloth = 10, + /obj/item/stack/material/leather = 5, + /obj/item/stack/material/fiber = 5, + /obj/item/stack/material/fur/wool = 7, + /obj/item/stack/material/snow = 3, + /obj/item/stack/material/snowbrick = 3, + /obj/item/stack/material/flint = 3, + /obj/item/stack/material/stick = 3, + /obj/item/stack/material/chitin = 1) + +var/global/list/xenobio_silver_materials_basic = list( + /obj/item/stack/material/silver = 10, + /obj/item/stack/material/uranium = 8, + /obj/item/stack/material/gold = 6, + /obj/item/stack/material/titanium = 4, + /obj/item/stack/material/phoron = 1) + +var/global/list/xenobio_silver_materials_adv = list( + /obj/item/stack/material/deuterium = 5, + /obj/item/stack/material/tritium = 5, + /obj/item/stack/material/osmium = 5, + /obj/item/stack/material/mhydrogen = 3, + /obj/item/stack/material/diamond = 2, + /obj/item/stack/material/verdantium = 1) + +var/global/list/xenobio_silver_materials_special = list( + /obj/item/stack/material/valhollide = 1, + /obj/item/stack/material/morphium = 1, + /obj/item/stack/material/supermatter = 1) + +var/global/list/xenobio_gold_mobs_hostile = list( + /mob/living/simple_mob/vore/alienanimals/space_jellyfish, + /mob/living/simple_mob/vore/alienanimals/skeleton, + /mob/living/simple_mob/vore/alienanimals/space_ghost, + /mob/living/simple_mob/vore/alienanimals/startreader, + /mob/living/simple_mob/animal/passive/mouse/operative, + /mob/living/simple_mob/animal/giant_spider, + /mob/living/simple_mob/animal/giant_spider/frost, + /mob/living/simple_mob/animal/giant_spider/electric, + /mob/living/simple_mob/animal/giant_spider/hunter, + /mob/living/simple_mob/animal/giant_spider/lurker, + /mob/living/simple_mob/animal/giant_spider/pepper, + /mob/living/simple_mob/animal/giant_spider/thermic, + /mob/living/simple_mob/animal/giant_spider/tunneler, + /mob/living/simple_mob/animal/giant_spider/webslinger, + /mob/living/simple_mob/animal/giant_spider/phorogenic, + /mob/living/simple_mob/animal/giant_spider/carrier, + /mob/living/simple_mob/animal/giant_spider/nurse, + /mob/living/simple_mob/animal/giant_spider/ion, + /mob/living/simple_mob/animal/giant_spider/nurse/queen, + /mob/living/simple_mob/animal/sif/diyaab, + /mob/living/simple_mob/animal/sif/duck, + /mob/living/simple_mob/animal/sif/frostfly, + /mob/living/simple_mob/animal/sif/glitterfly, + /mob/living/simple_mob/animal/sif/hooligan_crab, + /mob/living/simple_mob/animal/sif/kururak, + /mob/living/simple_mob/animal/sif/leech, + /mob/living/simple_mob/animal/sif/tymisian, + /mob/living/simple_mob/animal/sif/sakimm, + /mob/living/simple_mob/animal/sif/savik, + /mob/living/simple_mob/animal/sif/shantak, + /mob/living/simple_mob/animal/sif/siffet, + /mob/living/simple_mob/animal/space/alien, + /mob/living/simple_mob/animal/space/alien/drone, + /mob/living/simple_mob/animal/space/alien/sentinel, + /mob/living/simple_mob/animal/space/alien/sentinel/praetorian, + /mob/living/simple_mob/animal/space/alien/queen, + /mob/living/simple_mob/animal/space/alien/queen/empress, + /mob/living/simple_mob/animal/space/alien/queen/empress/mother, + /mob/living/simple_mob/animal/space/bats, + /mob/living/simple_mob/animal/space/bear, + /mob/living/simple_mob/animal/space/carp, + /mob/living/simple_mob/animal/space/carp/large, + /mob/living/simple_mob/animal/space/carp/large/huge, + /mob/living/simple_mob/animal/space/goose, + /mob/living/simple_mob/creature, + /mob/living/simple_mob/faithless, + /mob/living/simple_mob/tomato, + /mob/living/simple_mob/animal/space/tree, + /mob/living/simple_mob/vore/aggressive/corrupthound, + /mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi, + /mob/living/simple_mob/vore/aggressive/deathclaw, + /mob/living/simple_mob/vore/aggressive/dino, + /mob/living/simple_mob/vore/aggressive/dragon, + /mob/living/simple_mob/vore/aggressive/frog, + /mob/living/simple_mob/otie, + /mob/living/simple_mob/otie/red, + /mob/living/simple_mob/vore/aggressive/panther, + /mob/living/simple_mob/vore/aggressive/rat, + /mob/living/simple_mob/vore/aggressive/giant_snake, + /mob/living/simple_mob/vore/sect_drone, + /mob/living/simple_mob/vore/sect_queen, + /mob/living/simple_mob/vore/weretiger, + /mob/living/simple_mob/animal/wolf, + /mob/living/simple_mob/vore/xeno_defanged) + +var/global/list/xenobio_gold_mobs_bosses = list( + /mob/living/simple_mob/animal/giant_spider/broodmother, + /mob/living/simple_mob/vore/leopardmander, + /mob/living/simple_mob/vore/leopardmander/blue, + /mob/living/simple_mob/vore/leopardmander/exotic, + /mob/living/simple_mob/vore/greatwolf, + /mob/living/simple_mob/vore/greatwolf/black, + /mob/living/simple_mob/vore/greatwolf/grey, + /mob/living/simple_mob/vore/bigdragon) + +var/global/list/xenobio_gold_mobs_safe = list( + /mob/living/simple_mob/vore/alienanimals/dustjumper, + /mob/living/simple_mob/vore/alienanimals/teppi, + /mob/living/simple_mob/animal/passive/chicken, + /mob/living/simple_mob/animal/passive/cow, + /mob/living/simple_mob/animal/goat, + /mob/living/simple_mob/animal/passive/crab, + /mob/living/simple_mob/animal/passive/mouse/jerboa, + /mob/living/simple_mob/animal/passive/lizard, + /mob/living/simple_mob/animal/passive/lizard/large, + /mob/living/simple_mob/animal/passive/yithian, + /mob/living/simple_mob/animal/passive/tindalos, + /mob/living/simple_mob/animal/passive/mouse, + /mob/living/simple_mob/animal/passive/penguin, + /mob/living/simple_mob/animal/passive/opossum, + /mob/living/simple_mob/animal/passive/cat, + /mob/living/simple_mob/animal/passive/dog/corgi, + /mob/living/simple_mob/animal/passive/dog/void_puppy, + /mob/living/simple_mob/animal/passive/dog/bullterrier, + /mob/living/simple_mob/animal/passive/dog/tamaskan, + /mob/living/simple_mob/animal/passive/dog/brittany, + /mob/living/simple_mob/animal/passive/fox, + /mob/living/simple_mob/animal/passive/fox/syndicate, + /mob/living/simple_mob/animal/passive/hare, + /mob/living/simple_mob/animal/passive/pillbug, + /mob/living/simple_mob/animal/passive/gaslamp, + /mob/living/simple_mob/animal/passive/snake, + /mob/living/simple_mob/animal/passive/snake/red, + /mob/living/simple_mob/animal/passive/snake/python, + /mob/living/simple_mob/vore/bee, + /mob/living/simple_mob/vore/fennec, + /mob/living/simple_mob/vore/fennix, + /mob/living/simple_mob/vore/hippo, + /mob/living/simple_mob/vore/horse, + /mob/living/simple_mob/animal/space/jelly, + /mob/living/simple_mob/vore/oregrub, + /mob/living/simple_mob/vore/oregrub/lava, + /mob/living/simple_mob/vore/rabbit, + /mob/living/simple_mob/vore/redpanda, + /mob/living/simple_mob/vore/sheep, + /mob/living/simple_mob/vore/solargrub) + +var/global/list/xenobio_gold_mobs_birds = list(/mob/living/simple_mob/animal/passive/bird/black_bird, + /mob/living/simple_mob/animal/passive/bird/azure_tit, + /mob/living/simple_mob/animal/passive/bird/european_robin, + /mob/living/simple_mob/animal/passive/bird/goldcrest, + /mob/living/simple_mob/animal/passive/bird/ringneck_dove, + /mob/living/simple_mob/animal/passive/bird/parrot, + /mob/living/simple_mob/animal/passive/bird/parrot/kea, + /mob/living/simple_mob/animal/passive/bird/parrot/eclectus, + /mob/living/simple_mob/animal/passive/bird/parrot/grey_parrot, + /mob/living/simple_mob/animal/passive/bird/parrot/black_headed_caique, + /mob/living/simple_mob/animal/passive/bird/parrot/white_caique, + /mob/living/simple_mob/animal/passive/bird/parrot/budgerigar, + /mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/blue, + /mob/living/simple_mob/animal/passive/bird/parrot/budgerigar/bluegreen, + /mob/living/simple_mob/animal/passive/bird/parrot/cockatiel, + /mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/white, + /mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/yellowish, + /mob/living/simple_mob/animal/passive/bird/parrot/cockatiel/grey, + /mob/living/simple_mob/animal/passive/bird/parrot/sulphur_cockatoo, + /mob/living/simple_mob/animal/passive/bird/parrot/white_cockatoo, + /mob/living/simple_mob/animal/passive/bird/parrot/pink_cockatoo) //There's too dang many + +var/global/list/xenobio_cerulean_potions = list( + /obj/item/slimepotion/enhancer, + /obj/item/slimepotion/stabilizer, + /obj/item/slimepotion/mutator, + /obj/item/slimepotion/docility, + /obj/item/slimepotion/steroid, + /obj/item/slimepotion/unity, + /obj/item/slimepotion/loyalty, + /obj/item/slimepotion/friendship, + /obj/item/slimepotion/feeding, + /obj/item/slimepotion/infertility, + /obj/item/slimepotion/fertility, + /obj/item/slimepotion/shrink, + /obj/item/slimepotion/death, + /obj/item/slimepotion/ferality, + /obj/item/slimepotion/reinvigoration, + /obj/item/slimepotion/mimic, + /obj/item/slimepotion/sapience, + /obj/item/slimepotion/obedience) + +var/global/list/xenobio_rainbow_extracts = list( + /obj/item/slime_extract/grey = 2, + /obj/item/slime_extract/metal = 3, + /obj/item/slime_extract/blue = 3, + /obj/item/slime_extract/purple = 1, + /obj/item/slime_extract/orange = 3, + /obj/item/slime_extract/yellow = 3, + /obj/item/slime_extract/gold = 3, + /obj/item/slime_extract/silver = 3, + /obj/item/slime_extract/dark_purple = 2, + /obj/item/slime_extract/dark_blue = 3, + /obj/item/slime_extract/red = 3, + /obj/item/slime_extract/green = 3, + /obj/item/slime_extract/pink = 3, + /obj/item/slime_extract/oil = 3, + /obj/item/slime_extract/bluespace = 3, + /obj/item/slime_extract/cerulean = 1, + /obj/item/slime_extract/amber = 3, + /obj/item/slime_extract/sapphire = 3, + /obj/item/slime_extract/ruby = 3, + /obj/item/slime_extract/emerald = 3, + /obj/item/slime_extract/light_pink = 1, + /obj/item/slime_extract/rainbow = 1) \ No newline at end of file diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm index cdca430fb6..690e4f1833 100644 --- a/code/_helpers/turfs.dm +++ b/code/_helpers/turfs.dm @@ -1,10 +1,20 @@ -// Returns the atom sitting on the turf. -// For example, using this on a disk, which is in a bag, on a mob, will return the mob because it's on the turf. -/proc/get_atom_on_turf(var/atom/movable/M) - var/atom/mloc = M - while(mloc && mloc.loc && !istype(mloc.loc, /turf/)) - mloc = mloc.loc - return mloc +/** +* Returns a best attempt at the least-nested containing movable of subject, or subject. +* eg, if subject is an item in a bag on a mob in a locker in the world, returns the locker. +*/ +/proc/get_atom_on_turf(atom/movable/subject) + var/atom/parent = subject?.loc + if (!parent || !ismovable(subject) || isarea(parent)) + return subject + var/atom/current = subject + do + parent = current.loc + if (isturf(parent)) + return current + current = parent + while (current) + return subject + /proc/iswall(turf/T) return (istype(T, /turf/simulated/wall) || istype(T, /turf/unsimulated/wall) || istype(T, /turf/simulated/shuttle/wall)) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 44037305dd..14feaf1b5f 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -103,6 +103,12 @@ #define ui_alien_fire "EAST-1:28,NORTH-3:25" #define ui_alien_oxygen "EAST-1:28,NORTH-4:25" +// Goes above HUD, mid-right +#define ui_ammo_hud1 "EAST-1:28,CENTER+1:25" +#define ui_ammo_hud2 "EAST-1:28,CENTER+2:27" +#define ui_ammo_hud3 "EAST-1:28,CENTER+3:29" +#define ui_ammo_hud4 "EAST-1:28,CENTER+4:31" + //Middle right (status indicators) #define ui_temp "EAST-1:28,CENTER-2:13" #define ui_health "EAST-1:28,CENTER-1:15" diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 6cb86b152f..988c11df10 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -39,6 +39,7 @@ alert.icon_state = "itembased" var/image/I = image(icon = new_master.icon, icon_state = new_master.icon_state, dir = SOUTH) I.plane = PLANE_PLAYER_HUD_ABOVE + I.color = new_master.color alert.add_overlay(I) alert.master = new_master else @@ -471,6 +472,7 @@ so as to remain in compliance with the most up-to-date laws." return if(master) return usr.client.Click(master, location, control, params) + ..() // VOREStation Edit: Pass through to click_vr /obj/screen/alert/Destroy() ..() diff --git a/code/_onclick/hud/alert_vr.dm b/code/_onclick/hud/alert_vr.dm index 19310ad315..e4168c3971 100644 --- a/code/_onclick/hud/alert_vr.dm +++ b/code/_onclick/hud/alert_vr.dm @@ -23,3 +23,31 @@ /obj/screen/alert/starving/synth name = "Low Power" desc = "Your battery is very low! Low power mode makes all movements slower." + +/obj/screen/alert/xenochimera/reconstitution + name = "Reconstructing Form" + desc = "You're still rebuilding your body! Click the alert to find out how long you have left." + icon_state = "regenerating" + +/* // Commenting this out for now, will revisit later once I can figure out how to override Click() appropriately. +/obj/screen/alert/xenochimera/reconstitution/Click(mob/usr) + var/mob/living/carbon/human/H = usr + if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert. + if(H.revive_ready == REVIVING_NOW) + to_chat(usr, "We are currently reviving, and will be done in [(H.revive_finished - world.time) / 10] seconds.") + else if(H.revive_ready == REVIVING_DONE) + to_chat(usr, "You should have a notification + alert for this! Bug report that this is still here!") +*/ + +/obj/screen/alert/xenochimera/readytohatch + name = "Ready to Hatch" + desc = "You're done reconstructing your cells! Click me to Hatch!" + icon_state = "hatch_ready" + +/* // Commenting this out for now, will revisit later once I can figure out how to override Click() appropriately. +/obj/screen/alert/xenochimera/readytohatch/Click(mob/usr) + var/mob/living/carbon/human/H = usr + if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert. + if(H.revive_ready == REVIVING_DONE) // Sanity check. + H.hatch() // Hatch. +*/ diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 98c187fc97..6298747901 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -1,3 +1,4 @@ +#define MAX_AMMO_HUD_POSSIBLE 4 // Cap the amount of HUDs at 4. /* The global hud: Uses the same visual objects for all players. @@ -40,9 +41,9 @@ var/list/global_huds = list( /datum/global_hud/proc/setup_overlay(var/icon_state) var/obj/screen/screen = new /obj/screen() - screen.alpha = 40 // Adjut this if you want goggle overlays to be thinner or thicker. + screen.alpha = 30 // Adjut this if you want goggle overlays to be thinner or thicker. //VOREStation Edit screen.screen_loc = "SOUTHWEST to NORTHEAST" // Will tile up to the whole screen, scaling beyond 15x15 if needed. - screen.icon = 'icons/obj/hud_tiled.dmi' + screen.icon = 'icons/obj/hud_tiled_vr.dmi' //VOREStation Edit screen.icon_state = icon_state screen.layer = SCREEN_LAYER screen.plane = PLANE_FULLSCREEN @@ -191,6 +192,9 @@ var/list/global_huds = list( var/icon/ui_style var/ui_color var/ui_alpha + + // TGMC Ammo HUD Port + var/list/obj/screen/ammo_hud_list = list() var/list/minihuds = list() @@ -220,6 +224,7 @@ var/list/global_huds = list( other_important = null hotkeybuttons = null // item_action_list = null // ? + QDEL_LIST(ammo_hud_list) mymob = null /datum/hud/proc/hidden_inventory_update() @@ -460,4 +465,37 @@ var/list/global_huds = list( client.screen += client.void /mob/new_player/add_click_catcher() - return \ No newline at end of file + return + +/* TGMC Ammo HUD Port + * These procs call to screen_objects.dm's respective procs. + * All these do is manage the amount of huds on screen and set the HUD. +*/ +///Add an ammo hud to the user informing of the ammo count of G +/datum/hud/proc/add_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + if(length(ammo_hud_list) >= MAX_AMMO_HUD_POSSIBLE) + return + var/obj/screen/ammo/ammo_hud = new + ammo_hud_list[G] = ammo_hud + ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[length(ammo_hud_list)] + ammo_hud.add_hud(user, G) + ammo_hud.update_hud(user, G) + +///Remove the ammo hud related to the gun G from the user +/datum/hud/proc/remove_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + var/obj/screen/ammo/ammo_hud = ammo_hud_list[G] + if(isnull(ammo_hud)) + return + ammo_hud.remove_hud(user, G) + qdel(ammo_hud) + ammo_hud_list -= G + var/i = 1 + for(var/key in ammo_hud_list) + ammo_hud = ammo_hud_list[key] + ammo_hud.screen_loc = ammo_hud.ammo_screen_loc_list[i] + i++ + +///Update the ammo hud related to the gun G +/datum/hud/proc/update_ammo_hud(mob/living/user, obj/item/weapon/gun/G) + var/obj/screen/ammo/ammo_hud = ammo_hud_list[G] + ammo_hud?.update_hud(user, G) \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 00446add6d..a06df0c082 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -898,3 +898,80 @@ icon_state = null plane = PLANE_HOLOMAP_ICONS appearance_flags = KEEP_TOGETHER + +// Begin TGMC Ammo HUD Port +/obj/screen/ammo + name = "ammo" + icon = 'icons/mob/screen_ammo.dmi' + icon_state = "ammo" + screen_loc = ui_ammo_hud1 + var/warned = FALSE + var/static/list/ammo_screen_loc_list = list(ui_ammo_hud1, ui_ammo_hud2, ui_ammo_hud3 ,ui_ammo_hud4) + +/obj/screen/ammo/proc/add_hud(var/mob/living/user, var/obj/item/weapon/gun/G) + + if(!user?.client) + return + + if(!G) + CRASH("/obj/screen/ammo/proc/add_hud() has been called from [src] without the required param of G") + + if(!G.has_ammo_counter()) + return + + user.client.screen += src + +/obj/screen/ammo/proc/remove_hud(var/mob/living/user) + user?.client?.screen -= src + +/obj/screen/ammo/proc/update_hud(var/mob/living/user, var/obj/item/weapon/gun/G) + if(!user?.client?.screen.Find(src)) + return + + if(!G || !istype(G) || !G.has_ammo_counter() || !G.get_ammo_type() || isnull(G.get_ammo_count())) + remove_hud() + return + + var/list/ammo_type = G.get_ammo_type() + var/rounds = G.get_ammo_count() + + var/hud_state = ammo_type[1] + var/hud_state_empty = ammo_type[2] + + overlays.Cut() + + var/empty = image('icons/mob/screen_ammo.dmi', src, "[hud_state_empty]") + + if(rounds == 0) + if(warned) + overlays += empty + else + warned = TRUE + var/obj/screen/ammo/F = new /obj/screen/ammo(src) + F.icon_state = "frame" + user.client.screen += F + flick("[hud_state_empty]_flash", F) + spawn(20) + user.client.screen -= F + qdel(F) + overlays += empty + else + warned = FALSE + overlays += image('icons/mob/screen_ammo.dmi', src, "[hud_state]") + + rounds = num2text(rounds) + //Handle the amount of rounds + switch(length(rounds)) + if(1) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[1]]") + if(2) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[2]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[1]]") + if(3) + overlays += image('icons/mob/screen_ammo.dmi', src, "o[rounds[3]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "t[rounds[2]]") + overlays += image('icons/mob/screen_ammo.dmi', src, "h[rounds[1]]") + else //"0" is still length 1 so this means it's over 999 + overlays += image('icons/mob/screen_ammo.dmi', src, "o9") + overlays += image('icons/mob/screen_ammo.dmi', src, "t9") + overlays += image('icons/mob/screen_ammo.dmi', src, "h9") \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects_zz_ch.dm b/code/_onclick/hud/screen_objects_ch.dm similarity index 97% rename from code/_onclick/hud/screen_objects_zz_ch.dm rename to code/_onclick/hud/screen_objects_ch.dm index f0fbd912fe..c229c3c57c 100644 --- a/code/_onclick/hud/screen_objects_zz_ch.dm +++ b/code/_onclick/hud/screen_objects_ch.dm @@ -27,4 +27,5 @@ item_overlay.color = "#00ff00" object_overlays += item_overlay - add_overlay(object_overlays) \ No newline at end of file + add_overlay(object_overlays) + \ No newline at end of file diff --git a/code/_onclick/hud/screen_objects_vr.dm b/code/_onclick/hud/screen_objects_vr.dm index ac38f2cf43..65b6df5c3b 100644 --- a/code/_onclick/hud/screen_objects_vr.dm +++ b/code/_onclick/hud/screen_objects_vr.dm @@ -45,15 +45,29 @@ var/turf/T = get_turf(H) if(T.get_lumcount() <= 0.1) to_chat(usr, "You are slowly calming down in darkness' safety...") - else if(isbelly(H.loc)) // CHOMPEdit: Safety message for if inside a belly. + + else if(isbelly(H.loc)) // Safety message for if inside a belly. to_chat(usr, "You are slowly calming down within the darkness of something's belly, listening to their body as it moves around you. ...safe...") else to_chat(usr, "You are slowly calming down... But safety of darkness is much preferred.") else if(H.nutrition < 150) to_chat(usr, "Your hunger is slowly making you unstable.") + if("Reconstructing Form") // Allow Viewing Reconstruction Timer + Hatching for 'chimera + var/mob/living/carbon/human/H = usr + if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert. + if(H.revive_ready == REVIVING_NOW) + to_chat(usr, "We are currently reviving, and will be done in [round((H.revive_finished - world.time) / 10)] seconds, or [round(((H.revive_finished - world.time) * 0.1) / 60)] minutes.") + else if(H.revive_ready == REVIVING_DONE) + to_chat(usr, "You should have a notification + alert for this! Bug report that this is still here!") + + if("Ready to Hatch") // Allow Viewing Reconstruction Timer + Hatching for 'chimera + var/mob/living/carbon/human/H = usr + if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert. + if(H.revive_ready == REVIVING_DONE) // Sanity check. + H.hatch() // Hatch. else return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm index 6b0815999b..6bffac865d 100644 --- a/code/controllers/subsystems/transcore_vr.dm +++ b/code/controllers/subsystems/transcore_vr.dm @@ -112,10 +112,11 @@ SUBSYSTEM_DEF(transcore) if(since_backup < overdue_time) curr_MR.dead_state = MR_NORMAL else - if(curr_MR.dead_state != MR_DEAD) //First time switching to dead + if(curr_MR.dead_state != MR_DEAD) //First time switching to dead //Remove auto notification! Ghosts have a button to notify, so no more false flags. CHOMPEdit: Revert removal if(curr_MR.do_notify) db.notify(curr_MR) curr_MR.last_notification = world.time + curr_MR.dead_state = MR_DEAD if(MC_TICK_CHECK) diff --git a/code/datums/autolathe/devices_ch.dm b/code/datums/autolathe/devices_ch.dm new file mode 100644 index 0000000000..e17ae6bcca --- /dev/null +++ b/code/datums/autolathe/devices_ch.dm @@ -0,0 +1,3 @@ +/datum/category_item/autolathe/devices/lightpainter + name = "Light Painter" + path =/obj/item/device/lightpainter diff --git a/code/datums/autolathe/engineering_vr.dm b/code/datums/autolathe/engineering_vr.dm index 90970c6e48..577d9febd2 100644 --- a/code/datums/autolathe/engineering_vr.dm +++ b/code/datums/autolathe/engineering_vr.dm @@ -24,4 +24,52 @@ /datum/category_item/autolathe/engineering/candymachine name = "candy machine electronics" - path =/obj/item/weapon/circuitboard/candymachine \ No newline at end of file + path =/obj/item/weapon/circuitboard/candymachine + +/datum/category_item/autolathe/engineering/battle_arcade + name = "battle arcade machine electronics" + path =/obj/item/weapon/circuitboard/arcade/battle + +/datum/category_item/autolathe/engineering/orion_trail + name = "orion trail aracade machine electronics" + path =/obj/item/weapon/circuitboard/arcade/orion_trail + +/datum/category_item/autolathe/engineering/clawmachine + name = "claw machine electronics" + path =/obj/item/weapon/circuitboard/arcade/clawmachine + +/datum/category_item/autolathe/engineering/jukebox + name = "jukebox electronics" + path =/obj/item/weapon/circuitboard/jukebox + +/datum/category_item/autolathe/engineering/mech_recharger + name = "mech recharging station electronics" + path =/obj/item/weapon/circuitboard/mech_recharger + +/datum/category_item/autolathe/engineering/recharge_station + name = "cyborg recharging station electronics" + path =/obj/item/weapon/circuitboard/recharge_station + +/datum/category_item/autolathe/engineering/batteryrack + name = "battery rack electronics" + path =/obj/item/weapon/circuitboard/batteryrack + +/datum/category_item/autolathe/engineering/grid_checker + name = "grid checker electronics" + path =/obj/item/weapon/circuitboard/grid_checker + +/datum/category_item/autolathe/engineering/breakerbox + name = "breaker box electronics" + path =/obj/item/weapon/circuitboard/breakerbox + +/datum/category_item/autolathe/engineering/gas_heater + name = "gas heater electronics" + path =/obj/item/weapon/circuitboard/unary_atmos/heater + +/datum/category_item/autolathe/engineering/gas_cooler + name = "gas cooler electronics" + path =/obj/item/weapon/circuitboard/unary_atmos/cooler + +/datum/category_item/autolathe/engineering/arf_generator + name = "atmospheric field generator electronics" + path =/obj/item/weapon/circuitboard/arf_generator \ No newline at end of file diff --git a/code/datums/components/crafting/recipes/primitive.dm b/code/datums/components/crafting/recipes/primitive.dm index 97f6be5e39..ce268e893a 100644 --- a/code/datums/components/crafting/recipes/primitive.dm +++ b/code/datums/components/crafting/recipes/primitive.dm @@ -1,3 +1,6 @@ +/* + * Misc + */ /datum/crafting_recipe/cloth name = "Cloth bolt" result = /obj/item/stack/material/cloth @@ -13,9 +16,8 @@ category = CAT_PRIMAL /* - * Clothing + * Primitive Clothing */ - /datum/crafting_recipe/primitive_clothes name = "primitive clothes" result = /obj/item/clothing/under/primitive diff --git a/code/datums/components/crafting/recipes/weapons.dm b/code/datums/components/crafting/recipes/weapons.dm index b8fe974e05..68f01b54e9 100644 --- a/code/datums/components/crafting/recipes/weapons.dm +++ b/code/datums/components/crafting/recipes/weapons.dm @@ -56,3 +56,12 @@ time = 120 category = CAT_WEAPONRY subcategory = CAT_WEAPON + +/datum/crafting_recipe/scopedrifle + name = "Bolt scope to bolt-action (cannot be removed)" + result = /obj/item/weapon/gun/projectile/shotgun/pump/rifle/scoped + reqs = list(list(/obj/item/device/binoculars/scope = 1), + list(/obj/item/weapon/gun/projectile/shotgun/pump/rifle = 1)) + time = 180 + category = CAT_WEAPONRY + subcategory = CAT_WEAPON diff --git a/code/datums/mind_vr.dm b/code/datums/mind_vr.dm index a98607e2c9..89b522469c 100644 --- a/code/datums/mind_vr.dm +++ b/code/datums/mind_vr.dm @@ -1,3 +1,2 @@ -//CHOMPStation EDIT: This file has been disabled in the .dme. /datum/mind var/vore_death = FALSE // Was our last gasp a gurgle? diff --git a/code/datums/supplypacks/atmospherics.dm b/code/datums/supplypacks/atmospherics.dm index 3630b9bea0..a18b630892 100644 --- a/code/datums/supplypacks/atmospherics.dm +++ b/code/datums/supplypacks/atmospherics.dm @@ -106,3 +106,16 @@ cost = 35 containertype = /obj/structure/closet/crate/aether containername = "Emergency crate" + +/datum/supply_pack/atmos/firefighting + name = "Firefighting equipment" + contains = list( + /obj/item/clothing/suit/fire/heavy = 2, + /obj/item/weapon/tank/oxygen/red = 2, + /obj/item/weapon/watertank/atmos = 2, + /obj/item/device/flashlight = 2, + /obj/item/clothing/head/hardhat/firefighter/atmos = 2 + ) + cost = 35 + containertype = /obj/structure/closet/crate/aether + containername = "Firefighting crate" \ No newline at end of file diff --git a/code/datums/supplypacks/munitions.dm b/code/datums/supplypacks/munitions.dm index 4de4c30f7a..73d150fd03 100644 --- a/code/datums/supplypacks/munitions.dm +++ b/code/datums/supplypacks/munitions.dm @@ -129,6 +129,17 @@ containername = "Ballistic weapon crate" access = access_armory +/datum/supply_pack/munitions/bolt_rifles_lethal + name = "Weapons - Bolt-Action Rifles" + contains = list( + /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 2, + /obj/item/ammo_magazine/ammo_box/b762 = 4, + ) + cost = 60 + containertype = /obj/structure/closet/crate/secure/weapon + containername = "Ballistic Weapons crate" + access = access_armory + /datum/supply_pack/munitions/bolt_rifles_competitive name = "Weapons - Competitive shooting rifles" contains = list( diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm index c19c4b0097..18cc82af76 100644 --- a/code/datums/supplypacks/security.dm +++ b/code/datums/supplypacks/security.dm @@ -288,6 +288,16 @@ containername = "Riot armor crate" access = access_armory +/datum/supply_pack/security/riot_sprayer + name = "Gear - Riot sprayer" + contains = list( + /obj/item/weapon/watertank/pepperspray + ) + cost = 40 + containertype = /obj/structure/closet/crate/secure/lawson + containername = "Riot sprayer crate" + access = access_armory + /datum/supply_pack/security/ablative_armor name = "Armor - Ablative" contains = list( diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm index 6b2cc3d10f..11c4f1f6b3 100644 --- a/code/datums/underwear/undershirts.dm +++ b/code/datums/underwear/undershirts.dm @@ -196,4 +196,14 @@ /datum/category_item/underwear/undershirt/sleevelessturtle name = "Turtleneck, Sleeveless" icon_state = "sleevelessturtle" + has_color = TRUE + +/datum/category_item/underwear/undershirt/dress_shirt_fem + name = "Dress shirt, feminine" + icon_state = "undershirt_dress_fem" + has_color = TRUE + +/datum/category_item/underwear/undershirt/dress_shirt + name = "Dress shirt, masculine" + icon_state = "undershirt_dress" has_color = TRUE \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 21f8c0fbfe..99fc8efcf1 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -703,7 +703,7 @@ desc = "Spooky!" gender = PLURAL icon = 'icons/obj/wizard.dmi' - icon_state = "ectoplasm" + icon_state = "ectoplasm2" /obj/item/weapon/research name = "research debugging device" diff --git a/code/game/area/Space Station 13 areas_ch.dm b/code/game/area/Space Station 13 areas_ch.dm index b72cfc07c9..473b7fb02d 100644 --- a/code/game/area/Space Station 13 areas_ch.dm +++ b/code/game/area/Space Station 13 areas_ch.dm @@ -108,3 +108,6 @@ /area/crew_quarters/sleep/vistor_room_12 limit_mob_size = FALSE + +/area/medical/cryo/autoresleeve + name = "\improper Medical Autoresleeving" \ No newline at end of file diff --git a/code/game/area/Space Station 13 areas_vr.dm b/code/game/area/Space Station 13 areas_vr.dm index dc89132971..37887dcb16 100644 --- a/code/game/area/Space Station 13 areas_vr.dm +++ b/code/game/area/Space Station 13 areas_vr.dm @@ -188,3 +188,6 @@ /area/holodeck/source_patient_ward name = "\improper Holodeck - Patient Ward" + +/area/holodeck/the_uwu_zone + name = "\improper Holodeck - Inside" diff --git a/code/game/area/areas_vr.dm b/code/game/area/areas_vr.dm index 371701e5b6..e356063e2a 100644 --- a/code/game/area/areas_vr.dm +++ b/code/game/area/areas_vr.dm @@ -3,6 +3,7 @@ var/exit_message var/limit_mob_size = TRUE //If mob size is limited in the area. var/block_suit_sensors = FALSE //If mob size is limited in the area. + var/turf/ceiling_type /area/Entered(var/atom/movable/AM, oldLoc) . = ..() @@ -13,3 +14,18 @@ . = ..() if(exit_message && isliving(AM)) to_chat(AM, exit_message) + +/area/Initialize(mapload) + apply_ceiling() + . = ..() + +/area/proc/apply_ceiling() + if(!ceiling_type) + return + for(var/turf/T in contents) + if(T.outdoors >= 0) + continue + if(HasAbove(T.z)) + var/turf/TA = GetAbove(T) + if(isopenspace(TA)) + TA.ChangeTurf(ceiling_type, TRUE, TRUE, TRUE) diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index 4639f57138..c52e51d5b5 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -1081,8 +1081,8 @@ datum return 0 drugs - steal_target = /datum/reagent/space_drugs - explanation_text = "Steal some space drugs." + steal_target = /datum/reagent/drugs/bliss + explanation_text = "Steal some bliss." weight = 40 get_points(var/job) diff --git a/code/game/jobs/job/assistant_vr.dm b/code/game/jobs/job/assistant_vr.dm index f2ab8378f4..bfcf3037b4 100644 --- a/code/game/jobs/job/assistant_vr.dm +++ b/code/game/jobs/job/assistant_vr.dm @@ -21,7 +21,9 @@ "Lab Assistant" = /datum/alt_title/intern_sci, //CHOMPEdit "Security Cadet" = /datum/alt_title/intern_sec, "Jr. Cargo Tech" = /datum/alt_title/intern_crg, - "Server" = /datum/alt_title/server) + "Jr. Explorer" = /datum/alt_title/intern_exp, + "Server" = /datum/alt_title/server, + "Assistant" = /datum/alt_title/assistant) job_description = "An Intern does whatever is requested of them, often doing so in process of learning \ another job. Though they are part of the crew, they have no real authority." timeoff_factor = 0 // Interns, noh @@ -56,11 +58,22 @@ often in training to become a Cargo Technician. A Jr. Cargo Tech has no real authority." title_outfit = /decl/hierarchy/outfit/job/assistant/cargo +/datum/alt_title/intern_exp + title = "Jr. Explorer" + title_blurb = "A Jr. Explorer attempts to provide whatever the Exploration department needs. They are not proper Explorers, and are \ + often in training to become an Explorer. A Jr. Explorer has no real authority." + title_outfit = /decl/hierarchy/outfit/job/assistant/explorer + /datum/alt_title/server title = "Server" title_blurb = "A Server helps out kitchen and diner staff with various tasks, primarily food delivery. A Server has no real authority." title_outfit = /decl/hierarchy/outfit/job/service/server +/datum/alt_title/assistant + title = "Assistant" + title_blurb = "An assistant helps out wherever they might be needed. They have no authority, but can volunteer to help if help is needed." + title_outfit = /decl/hierarchy/outfit/job/service/server + /datum/job/intern/New() ..() if(config) diff --git a/code/game/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm index e98e687af4..227e36948c 100644 --- a/code/game/machinery/biogenerator.dm +++ b/code/game/machinery/biogenerator.dm @@ -101,8 +101,9 @@ BIOGEN_ITEM("Winter Coat", /obj/item/clothing/suit/storage/hooded/wintercoat, 1, 500), //VOREStation Edit - Algae for oxygen generator BIOGEN_ITEM("4 Algae Sheets", /obj/item/stack/material/algae, 4, 400), + BIOGEN_ITEM("50 Algae Sheets", /obj/item/stack/material/algae, 50, 5000), ) - + /obj/machinery/biogenerator/tgui_static_data(mob/user) var/list/static_data[0] @@ -155,7 +156,7 @@ if(!(category in item_list) || !(name in item_list[category])) // Not trying something that's not in the list, are you? return - + var/datum/data/biogenerator_item/bi = item_list[category][name] if(!istype(bi)) var/datum/data/biogenerator_reagent/br = item_list[category][name] @@ -175,7 +176,7 @@ beaker.reagents.add_reagent(br.reagent_id, amt_to_actually_dispense) playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1) return - + var/cost = round(bi.cost / build_eff) if(cost > points) to_chat(usr, "Insufficient biomass.") diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 1980079098..d36a9be13d 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -1,85 +1,41 @@ -#define CHARGER_EMPTY 0 -#define CHARGER_WORKING 1 -#define CHARGER_DONE 2 - /obj/machinery/cell_charger name = "heavy-duty cell charger" desc = "A much more powerful version of the standard recharger that is specially designed for charging power cells." icon = 'icons/obj/power.dmi' - icon_state = "recharger" - anchored = TRUE + icon_state = "ccharger0" + anchored = 1 use_power = USE_POWER_IDLE - power_channel = EQUIP idle_power_usage = 5 active_power_usage = 60000 //60 kW. (this the power drawn when charging) - circuit = /obj/item/weapon/circuitboard/cell_charger - var/efficiency = 60000 //will provide the modified power rate when upgraded + power_channel = EQUIP var/obj/item/weapon/cell/charging = null - var/charging_vis_flags = NONE - var/charge_state = CHARGER_EMPTY + var/chargelevel = -1 + circuit = /obj/item/weapon/circuitboard/cell_charger /obj/machinery/cell_charger/Initialize() . = ..() default_apply_parts() /obj/machinery/cell_charger/update_icon() - var/new_state + icon_state = "ccharger[charging ? 1 : 0]" + if(!anchored) - new_state = "[initial(icon_state)]4" - return + icon_state = "ccharger2" - if(stat & (BROKEN|NOPOWER)) - new_state = "[initial(icon_state)]3" - return + if(charging && !(stat & (BROKEN|NOPOWER))) - switch(charge_state) - if(CHARGER_EMPTY) - new_state = "[initial(icon_state)]0" - if(CHARGER_WORKING) - new_state = "[initial(icon_state)]1" - if(CHARGER_DONE) - new_state = "[initial(icon_state)]2" - - if(icon_state != new_state) - icon_state = new_state + var/newlevel = round(charging.percent() * 4.0 / 99) + //to_world("nl: [newlevel]") -/obj/machinery/cell_charger/proc/insert_item(obj/item/W, mob/user) - if(!W || !user) - return + if(chargelevel != newlevel) - user.drop_item() - charging = W - charging.loc = src - charging_vis_flags = charging.vis_flags - charging.vis_flags = VIS_INHERIT_ID - vis_contents += charging - - charge_state = CHARGER_WORKING - update_icon() + cut_overlays() + add_overlay("ccharger-o[newlevel]") - if((stat & (BROKEN|NOPOWER)) || !anchored) - update_use_power(USE_POWER_OFF) + chargelevel = newlevel else - update_use_power(USE_POWER_ACTIVE) - -/obj/machinery/cell_charger/proc/remove_item(mob/user) - if(!charging || !user) - return - - vis_contents -= charging - charging.vis_flags = charging_vis_flags - user.put_in_hands(charging) - charging = null - - charge_state = CHARGER_EMPTY - - if((stat & (BROKEN|NOPOWER)) || !anchored) - update_use_power(USE_POWER_OFF) - else - update_use_power(USE_POWER_IDLE) - - update_icon() + cut_overlays() /obj/machinery/cell_charger/examine(mob/user) . = ..() @@ -107,8 +63,11 @@ to_chat(user, "\The [src] blinks red as you try to insert [W]!") return - insert_item(W, user) + user.drop_item() + W.loc = src + charging = W user.visible_message("[user] inserts [charging] into [src].", "You insert [charging] into [src].") + chargelevel = -1 update_icon() else if(W.is_wrench()) if(charging) @@ -129,15 +88,22 @@ add_fingerprint(user) if(charging) - remove_item(user) + user.put_in_hands(charging) + charging.update_icon() user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") + charging = null + chargelevel = -1 + update_icon() + /obj/machinery/cell_charger/attack_ai(mob/user) if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) // Borgs can remove the cell if they are near enough if(charging) - remove_item(user) - user.visible_message("[user] disconnects [charging] from [src].", "You disconnect [charging] from [src].") - + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") + charging.loc = src.loc + charging.update_icon() + charging = null + update_icon() /obj/machinery/cell_charger/emp_act(severity) if(stat & (BROKEN|NOPOWER)) @@ -146,9 +112,6 @@ charging.emp_act(severity) ..(severity) -/obj/machinery/cell_charger/power_change() - . = ..() - update_icon() /obj/machinery/cell_charger/process() //to_world("ccpt [charging] [stat]") @@ -156,22 +119,16 @@ update_use_power(USE_POWER_OFF) return - if(charging) - if(!charging.fully_charged()) - charge_state = CHARGER_WORKING - charging.give(efficiency*CELLRATE) - update_use_power(USE_POWER_ACTIVE) - else - charge_state = CHARGER_DONE - update_use_power(USE_POWER_IDLE) + if(charging && !charging.fully_charged()) + charging.give(efficiency*CELLRATE) + update_use_power(USE_POWER_ACTIVE) + update_icon() + else + update_use_power(USE_POWER_IDLE) /obj/machinery/cell_charger/RefreshParts() var/E = 0 for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) E += C.rating - efficiency = active_power_usage * (1+ (E - 1)*0.5) - -#undef CHARGER_EMPTY -#undef CHARGER_WORKING -#undef CHARGER_DONE \ No newline at end of file + efficiency = active_power_usage * (1+ (E - 1)*0.5) \ No newline at end of file diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index b39e8513bf..5962f9aa8f 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -69,11 +69,15 @@ ..() /obj/machinery/computer/message_monitor/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/message_monitor/LateInitialize() + . = ..() //Is the server isn't linked to a server, and there's a server available, default it to the first one in the list. if(!linkedServer) if(message_servers && message_servers.len > 0) linkedServer = message_servers[1] - return ..() /obj/machinery/computer/message_monitor/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index f948459970..38ac815cff 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -185,6 +185,7 @@ icon_state = "cryo_rear" anchored = TRUE dir = WEST + density = TRUE //Cryopods themselves. /obj/machinery/cryopod @@ -210,7 +211,7 @@ var/disallow_occupant_types = list() var/mob/occupant = null // Person waiting to be despawned. - var/time_till_despawn = 599 // Down to 1 minute to reflect Vorestation respawn times. + var/time_till_despawn = 60 // Down to 1 minute to reflect Vorestation respawn times. //CHOMP Edit: Now 6 seconds. Mind the deciseconds. var/time_entered = 0 // Used to keep track of the safe period. var/obj/item/device/radio/intercom/announce // @@ -522,13 +523,13 @@ control_computer.frozen_crew += "[to_despawn.real_name], [to_despawn.mind.role_alt_title] - [stationtime2text()]" control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]" log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.") - + //VOREStation Edit Start var/depart_announce = TRUE if(istype(to_despawn, /mob/living/dominated_brain)) depart_announce = FALSE - + if(depart_announce) announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE)) visible_message("\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]", 3) diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 84f228c6ab..e68ce7aa4e 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -128,3 +128,17 @@ icon = 'icons/effects/blood.dmi' icon_state = "mfloor1" random_icon_states = list("mfloor1", "mfloor2", "mfloor3", "mfloor4", "mfloor5", "mfloor6", "mfloor7") + +/obj/effect/decal/cleanable/confetti + name = "confetti" + desc = "Tiny bits of colored paper thrown about for the janitor to enjoy!" + gender = PLURAL + density = FALSE + anchored = TRUE + icon = 'icons/effects/effects.dmi' + icon_state = "confetti" + +/obj/effect/decal/cleanable/confetti/attack_hand(mob/user) + to_chat(user, "You start to meticulously pick up the confetti.") + if(do_after(user, 60)) + qdel(src) diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 0746161919..8545ca174e 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -57,9 +57,12 @@ health -= Proj.get_structure_damage() healthcheck() +/obj/effect/spider/proc/die() + qdel(src) + /obj/effect/spider/proc/healthcheck() if(health <= 0) - qdel(src) + die() /obj/effect/spider/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature > 300 + T0C) @@ -148,7 +151,7 @@ layer = HIDING_LAYER health = 3 var/last_itch = 0 - var/amount_grown = -1 + var/amount_grown = 0 var/obj/machinery/atmospherics/unary/vent_pump/entry_vent var/travelling_in_vent = 0 var/list/grow_as = list(/mob/living/simple_mob/animal/giant_spider, /mob/living/simple_mob/animal/giant_spider/nurse, /mob/living/simple_mob/animal/giant_spider/hunter) @@ -187,16 +190,17 @@ else ..() -/obj/effect/spider/spiderling/proc/die() +/obj/effect/spider/spiderling/die() visible_message("[src] dies!") new /obj/effect/decal/cleanable/spiderling_remains(src.loc) - qdel(src) + ..() /obj/effect/spider/spiderling/healthcheck() if(health <= 0) die() /obj/effect/spider/spiderling/process() + healthcheck() if(travelling_in_vent) if(istype(src.loc, /turf)) travelling_in_vent = 0 diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 9ae9fa782d..22c6eea30c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -230,6 +230,9 @@ if(!temp) to_chat(user, "You try to use your hand, but realize it is no longer attached!") return + if(istype(src, /obj/item/weapon/holder)) + var/obj/item/weapon/holder/D = src + if(D.held_mob == user) return // No picking your own micro self up var/old_loc = src.loc if (istype(src.loc, /obj/item/weapon/storage)) diff --git a/code/game/objects/items/contraband.dm b/code/game/objects/items/contraband.dm index a6e1ef3c2d..b9895428b7 100644 --- a/code/game/objects/items/contraband.dm +++ b/code/game/objects/items/contraband.dm @@ -1,6 +1,8 @@ -//Let's get some REAL contraband stuff in here. Because come on, getting brigged for LIPSTICK is no fun. - -//Illicit drugs~ +// Let's get some REAL contraband stuff in here. Because come on, getting brigged for LIPSTICK is no fun. +// +// Includes drug powder. +// +// Illicit drugs~ /obj/item/weapon/storage/pill_bottle/happy name = "bottle of Happy pills" desc = "Highly illegal drug. When you want to see the rainbow." @@ -19,7 +21,7 @@ /obj/item/weapon/reagent_containers/glass/beaker/vial/random/toxin random_reagent_list = list( - list("mindbreaker" = 10, "space_drugs" = 20) = 3, + list("mindbreaker" = 10, "bliss" = 20) = 3, list("carpotoxin" = 15) = 2, list("impedrezene" = 15) = 2, list("zombiepowder" = 10) = 1) @@ -39,3 +41,56 @@ desc = "Contains [english_list(names)]." update_icon() + +// +// Drug Powder +// +/obj/item/weapon/reagent_containers/powder + name = "powder" + desc = "A powdered form of... something." + icon = 'icons/obj/chemical.dmi' + icon_state = "powder" + item_state = "powder" + amount_per_transfer_from_this = 2 + possible_transfer_amounts = 2 + w_class = ITEMSIZE_TINY + volume = 50 + +/obj/item/weapon/reagent_containers/powder/examine(mob/user) + if(reagents) + var/datum/reagent/R = reagents.get_master_reagent() + desc = "A powdered form of what appears to be [R.name]. There's about [reagents.total_volume] units here." + return ..() + +/obj/item/weapon/reagent_containers/powder/Initialize() + ..() + get_appearance() + +/obj/item/weapon/reagent_containers/powder/proc/get_appearance() + /// Names and colors based on dominant reagent. + if (reagents.reagent_list.len > 0) + color = reagents.get_color() + var/datum/reagent/R = reagents.get_master_reagent() + var/new_name = lowertext(R) + name = "powdered [new_name]" + +/// Snorting. + +/obj/item/weapon/reagent_containers/powder/attackby(var/obj/item/weapon/W, var/mob/living/user) + + if(!ishuman(user)) /// You gotta be fleshy to snort the naughty drugs. + return ..() + + if(!istype(W, /obj/item/weapon/glass_extra/straw) && !istype(W, /obj/item/weapon/reagent_containers/rollingpaper)) + return ..() + + user.visible_message("[user] snorts [src] with [W]!") + playsound(loc, 'sound/effects/snort.ogg', 50, 1) + + if(reagents) + reagents.trans_to_mob(user, amount_per_transfer_from_this, CHEM_BLOOD) + + if(!reagents.total_volume) /// Did we use all of it? + qdel(src) + +////// End powder. ///////// \ No newline at end of file diff --git a/code/game/objects/items/devices/binoculars.dm b/code/game/objects/items/devices/binoculars.dm index 1bb63fab38..90b7af0a60 100644 --- a/code/game/objects/items/devices/binoculars.dm +++ b/code/game/objects/items/devices/binoculars.dm @@ -18,4 +18,9 @@ name = "spyglass" desc = "It's a hand-held telescope, useful for star-gazing, peeping, and recon." icon_state = "spyglass" - slot_flags = SLOT_BELT \ No newline at end of file + slot_flags = SLOT_BELT + +/obj/item/device/binoculars/scope + name = "rifle scope" + desc = "It's a rifle scope. Would be better if it were actually attached to a rifle." + icon_state = "rifle_scope" \ No newline at end of file diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index e40db08278..f672cbcf1b 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -501,6 +501,12 @@ M.Weaken(rand(10,25)) M.updatehealth() apply_brain_damage(M) + M.adjustHalLoss(40) // CHOMPEdit: Moderate amount of halloss for EVERYONE being defibbed. Defibs feel like being kicked in the chest by a mule. Shit hurts if you're awake. + // VOREStation Edits Start: Defib pain + if(istype(M.species, /datum/species/xenochimera)) // Only do the following to Xenochimera. Handwave this however you want, this is to balance defibs on an alien race. + M.adjustHalLoss(220) // This hurts a LOT, stacks on top of the previous halloss. + M.feral += 100 // If they somehow weren't already feral, force them feral by increasing ferality var directly, to avoid any messy checks. handle_feralness() will immediately set our feral properly according to halloss anyhow. + // VOREStation Edits End // SSgame_master.adjust_danger(-20) // VOREStation Edit - We don't use SSgame_master yet. /obj/item/weapon/shockpaddles/proc/apply_brain_damage(mob/living/carbon/human/H) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 3b20ccbb5c..4a800e9292 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -144,7 +144,7 @@ to_chat(user, "There's visible lag between left and right pupils' reactions.") var/list/pinpoint = list("oxycodone"=1,"tramadol"=5) - var/list/dilating = list("space_drugs"=5,"mindbreaker"=1) + var/list/dilating = list("bliss"=5,"ambrosia_extract"=5,"mindbreaker"=1) if(M.reagents.has_any_reagent(pinpoint) || H.ingested.has_any_reagent(pinpoint)) to_chat(user, "\The [M]'s pupils are already pinpoint and cannot narrow any more.") else if(M.reagents.has_any_reagent(dilating) || H.ingested.has_any_reagent(dilating)) @@ -486,30 +486,3 @@ light_range = 8 light_power = 0.1 light_color = "#49F37C" - -/* - * Slime Extract - */ - -/obj/item/device/flashlight/slime - gender = PLURAL - name = "glowing slime extract" - desc = "A slimy ball that appears to be glowing from bioluminesence." - icon = 'icons/obj/lighting.dmi' - icon_state = "floor1" //not a slime extract sprite but... something close enough! - item_state = "slime" - light_color = "#FFF423" - w_class = ITEMSIZE_TINY - light_range = 6 - on = 1 //Bio-luminesence has one setting, on. - power_use = 0 - -/obj/item/device/flashlight/slime/New() - ..() - set_light(light_range, light_power, light_color) - -/obj/item/device/flashlight/slime/update_brightness() - return - -/obj/item/device/flashlight/slime/attack_self(mob/user) - return //Bio-luminescence does not toggle. diff --git a/code/game/objects/items/devices/lightpainter_ch.dm b/code/game/objects/items/devices/lightpainter_ch.dm new file mode 100644 index 0000000000..ab166bccc6 --- /dev/null +++ b/code/game/objects/items/devices/lightpainter_ch.dm @@ -0,0 +1,73 @@ +// Light Painter. + + +/obj/item/device/lightpainter + name = "light painter" + desc = "A device to configure the emission color of lighting fixtures. Use this device in-hand to set/reset the color. Use the device on a light fixture to assign the color." + icon = 'icons/obj/janitor.dmi' + icon_state = "lightreplacer0" + color = "#bbbbff" + slot_flags = SLOT_BELT + + matter = list(MAT_STEEL = 5000,MAT_GLASS = 1500) + + var/static/dcolor = "#e0eff0" + var/static/dnightcolor = "#efcc86" + //set color values. + var/setcolor = "#e0eff0" + var/setnightcolor = "#efcc86" + var/resetmode = 1 + + var/dimming = 0.7 // multiply value to dim lights from setcolor to nightcolor + + +/obj/item/device/lightpainter/New() + . = ..() + +/obj/item/device/lightpainter/examine(mob/user) + . = ..() + if(get_dist(user, src) <= 2) + if(resetmode) + . += "It is currently resetting light colors." + else + . += "It is currently coloring lights." + +/obj/item/device/lightpainter/attack_self(mob/user) + + if(!resetmode) + resetmode = 1 + to_chat(usr, "Painter reset.") + else + var/color_input = input(usr,"","Choose Light Color",setcolor) as color|null + if(color_input) + setcolor = sanitize_hexcolor(color_input) + var/list/setcolorRGB = hex2rgb(setcolor) + var/setcolorR = num2hex(setcolorRGB[1] * dimming, 2) + var/setcolorG = num2hex(setcolorRGB[2] * dimming, 2) + var/setcolorB = num2hex(setcolorRGB[3] * dimming, 2) + setnightcolor = addtext("#", setcolorR, setcolorG, setcolorB) + resetmode = 0 + to_chat(usr, "Painter color set.") + + +/obj/item/device/lightpainter/proc/ColorLight(var/obj/machinery/light/target, var/mob/living/U) + + src.add_fingerprint(U) + + if(resetmode) + to_chat(U, "You reset the color of the [target.get_fitting_name()].") + target.brightness_color = dcolor + target.brightness_color_ns = dnightcolor + else + to_chat(U, "You set the color of the [target.get_fitting_name()].") + + target.brightness_color = setcolor + target.brightness_color_ns = setnightcolor + + if(target.nightshift_enabled) + target.light_color = target.brightness_color_ns + else + target.light_color = target.brightness_color + + target.set_light(0) + target.update() \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 5adca5dffb..b7304fa8a1 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -298,7 +298,8 @@ var/global/list/default_medbay_channels = list( GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) -/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels) +/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels, var/states) //VOREStation Edit + if(!GLOB.autospeaker) return var/datum/radio_frequency/connection = null @@ -314,12 +315,15 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer) if(!LAZYLEN(zlevels)) zlevels = list(0) - + //VOREStation Edit Start + if(!states) + states = "states" + //VOREStation Edit End GLOB.autospeaker.SetName(from) Broadcast_Message(connection, GLOB.autospeaker, 0, "*garbled automated announcement*", src, message_to_multilingual(message), from, "Automated Announcement", from, "synthesized voice", - DATA_FAKE, 0, zlevels, connection.frequency, "states") + DATA_FAKE, 0, zlevels, connection.frequency, states) //VOREStation Edit // Interprets the message mode when talking into a radio, possibly returning a connection datum /obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 1fac4f3226..6b4d7fe373 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -277,7 +277,19 @@ HALOGEN COUNTER - Radcount on mobs dat += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" else dat += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" - dat += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm." + dat += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.
" // CHOMP/VORE Edit: Missed a linebreak here. + if(istype(H.species, /datum/species/xenochimera)) // VOREStation Edit Start: Visible feedback for medmains on Xenochimera. + if(H.stat == DEAD && H.revive_ready == REVIVING_READY && !H.hasnutriment()) + dat += "WARNING: Protein levels low. Subject incapable of reconstitution." + else if(H.revive_ready == REVIVING_NOW) + dat += "Subject is undergoing form reconstruction. Estimated time to finish is in: [round((H.revive_finished - world.time) / 10)] seconds." + else if(H.revive_ready == REVIVING_DONE) + dat += "Subject is ready to hatch. Transfer to dark room for holding with food available." + else if(H.stat == DEAD) + dat+= "WARNING: Defib will cause extreme pain and set subject feral. Sedation recommended prior to defibrillation." + else // If they bop them and they're not dead or reviving, give 'em a little notice. + dat += "Subject is a Xenochimera. Treat accordingly." + // VOREStation Edit End user.show_message(dat, 1) /obj/item/device/healthanalyzer/verb/toggle_mode() @@ -533,4 +545,4 @@ HALOGEN COUNTER - Radcount on mobs to_chat(user, "No radiation detected.") return -#undef DEFIB_TIME_LIMIT //VOREStation addition \ No newline at end of file +#undef DEFIB_TIME_LIMIT //VOREStation addition diff --git a/code/game/objects/items/gunbox.dm b/code/game/objects/items/gunbox.dm index d97aa51ba0..249daf1b4e 100644 --- a/code/game/objects/items/gunbox.dm +++ b/code/game/objects/items/gunbox.dm @@ -33,6 +33,27 @@ options["Stun Revolver"] = list(/obj/item/weapon/gun/energy/stunrevolver/detective, /obj/item/weapon/cell/device/weapon, /obj/item/weapon/cell/device/weapon) options["Taser"] = list(/obj/item/weapon/gun/energy/taser, /obj/item/weapon/cell/device/weapon, /obj/item/weapon/cell/device/weapon) var/choice = tgui_input_list(user,"Please, select an option.", "Stun Gun!", options) + if(src && choice) + var/list/things_to_spawn = options[choice] + for(var/new_type in things_to_spawn) // Spawn all the things, the gun and the ammo. + var/atom/movable/AM = new new_type(get_turf(src)) + if(istype(AM, /obj/item/weapon/gun)) + to_chat(user, "You have chosen \the [AM]. Say hello to your new friend.") + qdel(src) + +/* + * CentCom Pistol + */ +/obj/item/gunbox/centcom + name = "centcom sidearm box" + desc = "A secure box containing a lethal sidearm used by Central Command." + w_class = ITEMSIZE_HUGE +/obj/item/gunbox/centcom/attack_self(mob/living/user) + var/list/options = list() + options["Écureuil (10mm)"] = list(/obj/item/weapon/gun/projectile/ecureuil, /obj/item/ammo_magazine/m10mm/pistol, /obj/item/ammo_magazine/m10mm/pistol) + options["Écureuil Olive (10mm)"] = list(/obj/item/weapon/gun/projectile/ecureuil/tac, /obj/item/ammo_magazine/m10mm/pistol, /obj/item/ammo_magazine/m10mm/pistol) + options["Écureuil Tan (10mm)"] = list(/obj/item/weapon/gun/projectile/ecureuil/tac2, /obj/item/ammo_magazine/m10mm/pistol, /obj/item/ammo_magazine/m10mm/pistol) + var/choice = tgui_input_list(user,"Please, select an option.", "Gun!", options) if(src && choice) var/list/things_to_spawn = options[choice] for(var/new_type in things_to_spawn) // Spawn all the things, the gun and the ammo. diff --git a/code/game/objects/items/stacks/stack_vr.dm b/code/game/objects/items/stacks/stack_vr.dm new file mode 100644 index 0000000000..eb00a7ee9a --- /dev/null +++ b/code/game/objects/items/stacks/stack_vr.dm @@ -0,0 +1,24 @@ +// Porting stack dragging/auto stacking from TG. + +/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible + if(uses_charge || S.uses_charge) // This should realistically never happen, but in case it does lets avoid breaking things. + return + if(S.stacktype != stacktype) + return + if(S.amount >= S.max_amount) + return + + var/transfer = get_amount() + transfer = min(transfer, S.max_amount - S.amount) + if(pulledby) + pulledby.start_pulling(S) + transfer_fingerprints_to(S) + if(blood_DNA) + S.blood_DNA |= blood_DNA + use(transfer) + S.add(transfer) + +/obj/item/stack/Crossed(var/atom/movable/AM) + if(isturf(AM.loc) && AM != src && istype(AM, src.type) && !AM.throwing) + merge(AM) + return ..() \ No newline at end of file diff --git a/code/game/objects/items/toys/toys_vr.dm b/code/game/objects/items/toys/toys_vr.dm index db7dc423a3..2fca91a496 100644 --- a/code/game/objects/items/toys/toys_vr.dm +++ b/code/game/objects/items/toys/toys_vr.dm @@ -22,6 +22,7 @@ * Professor Who universal ID * Professor Who sonic driver * Action figures + * Desk toys */ @@ -969,3 +970,114 @@ icon = 'icons/obj/toy_vr.dmi' icon_state = "prisoner" toysay = "I did not hit her! I did not!" + +/obj/item/toy/figure/error + name = "completely glitched action figure" + desc = "A \"Space Life\" brand... wait, what the hell is this thing? It seems to be requesting the sweet release of death." + icon = 'icons/obj/toy_vr.dmi' + icon_state = "glitched" + toysay = "AaAAaAAAaAaaaAAA!!!!!" + +/* + * Desk toys + */ +/obj/item/weapon/toy/desk + icon = 'icons/obj/toy_vr.dmi' + var/on = FALSE + var/activation_sound = 'sound/machines/click.ogg' + +/obj/item/weapon/toy/desk/update_icon() + if(on) + icon_state = "[initial(icon_state)]-on" + else + icon_state = "[initial(icon_state)]" + +/obj/item/weapon/toy/desk/proc/activate(mob/user as mob) + on = !on + playsound(src.loc, activation_sound, 75, 1) + update_icon() + return 1 + +/obj/item/weapon/toy/desk/attack_self(mob/user) + activate(user) + +/obj/item/weapon/toy/desk/AltClick(mob/user) + activate(user) + +/obj/item/weapon/toy/desk/MouseDrop(mob/user as mob) // Code from Paper bin, so you can still pick up the deck + if((user == usr && (!( usr.restrained() ) && (!( usr.stat ) && (usr.contents.Find(src) || in_range(src, usr)))))) + if(!istype(usr, /mob/living/simple_mob)) + if( !usr.get_active_hand() ) //if active hand is empty + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/temp = H.organs_by_name["r_hand"] + + if (H.hand) + temp = H.organs_by_name["l_hand"] + if(temp && !temp.is_usable()) + to_chat(user,"You try to move your [temp.name], but cannot!") + return + + to_chat(user,"You pick up [src].") + user.put_in_hands(src) + + return + +/obj/item/weapon/toy/desk/newtoncradle + name = "\improper Newton's cradle" + desc = "A ancient 21th century super-weapon model demonstrating that Sir Isaac Newton is the deadliest sonuvabitch in space." + description_fluff = "Aside from car radios, Eridanian Dregs are reportedly notorious for stealing these things. It is often \ + theorized that the very same ball bearings are used in black-market cybernetics." + icon_state = "newtoncradle" + +/obj/item/weapon/toy/desk/fan + name = "office fan" + desc = "Your greatest fan." + description_fluff = "For weeks, the atmospherics department faced a conundrum on how to lower temperatures in a localized \ + area through complicated pipe channels and ventilation systems. The problem was promptly solved by ordering several desk fans." + icon_state = "fan" + +/obj/item/weapon/toy/desk/officetoy + name = "office toy" + desc = "A generic microfusion powered office desk toy. Only generates magnetism and ennui." + description_fluff = "The mechanism inside is a Hephasteus trade secret. No peeking!" + icon_state = "desktoy" + +/obj/item/weapon/toy/desk/dippingbird + name = "dipping bird toy" + desc = "Engineers marvel at this scale model of a primitive thermal engine. It's highly debated why the majority of owners \ + were in low-level bureaucratic jobs." + description_fluff = "One of the key essentials for every Eridanian suit - it's practically a rite of passage to own one \ + of these things." + icon_state = "dippybird" + +/obj/item/weapon/toy/desk/stellardelight + name = "\improper Stellar Delight model" + desc = "A scale model of the Stellar Delight. Includes flashing lights!" + icon_state = "stellar_delight" + +/* + * Party popper + */ +/obj/item/weapon/toy/partypopper + name = "party popper" + desc = "Instructions : Aim away from face. Wait for appropriate timing. Pull cord, enjoy confetti." + icon = 'icons/obj/toy_vr.dmi' + icon_state = "partypopper" + w_class = ITEMSIZE_TINY + drop_sound = 'sound/items/drop/cardboardbox.ogg' + pickup_sound = 'sound/items/pickup/cardboardbox.ogg' + +/obj/item/weapon/toy/partypopper/attack_self(mob/user as mob) + if(icon_state == "partypopper") + user.visible_message("[user] pulls on the string, releasing a burst of confetti!", "You pull on the string, releasing a burst of confetti!") + playsound(src, 'sound/effects/snap.ogg', 50, TRUE) + var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread + s.set_up(5, 1, src) + s.start() + icon_state = "partypopper_e" + var/turf/T = get_step(src, user.dir) + if(!turf_clear(T)) + T = get_turf(src) + new /obj/effect/decal/cleanable/confetti(T) + else + to_chat(user, "The [src] is already spent!") \ No newline at end of file diff --git a/code/game/objects/items/weapons/capture_crystal.dm b/code/game/objects/items/weapons/capture_crystal.dm index 104145d8ce..46b935419e 100644 --- a/code/game/objects/items/weapons/capture_crystal.dm +++ b/code/game/objects/items/weapons/capture_crystal.dm @@ -226,6 +226,13 @@ //Tries to unleash or recall your stored mob /obj/item/capture_crystal/attack_self(mob/living/user) + if(bound_mob && !owner) + if(bound_mob == user) + to_chat(user, "\The [src] emits an unpleasant tone... It does not activate for you.") + playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1) + return + if(tgui_alert(user, "\The [src] hasn't got an owner. It has \the [bound_mob] registered to it. Would you like to claim this as yours?", "Claim ownership", list("No","Yes")) == "Yes") + owner = user if(!cooldown_check()) to_chat(user, "\The [src] emits an unpleasant tone... It is not ready yet.") if(bound_mob) diff --git a/code/game/objects/items/weapons/chewables.dm b/code/game/objects/items/weapons/chewables.dm index 181db77e91..59e95f103f 100644 --- a/code/game/objects/items/weapons/chewables.dm +++ b/code/game/objects/items/weapons/chewables.dm @@ -167,10 +167,43 @@ storage_slots = 6 drop_sound = 'sound/items/drop/box.ogg' use_sound = 'sound/items/storage/box.ogg' + var/open = 0 + var/open_state + var/closed_state -/obj/item/weapon/storage/box/fancy/chewables/tobacco/update_icon() - icon_state = "[initial(icon_state)][contents.len]" +/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico/New() + if(!open_state) + open_state = "[initial(icon_state)]0" + if(!closed_state) + closed_state = "[initial(icon_state)]" + ..() +/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico/update_icon() + cut_overlays() + if(open) + icon_state = open_state + if(contents.len >= 1) + add_overlay("chew_nico[contents.len]") + else + icon_state = closed_state + +/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico/open(mob/user as mob) + if(open) + return + open = TRUE + if(contents.len == 0) + icon_state = "[initial(icon_state)]_empty" + else + update_icon() + ..() + +/obj/item/weapon/storage/box/fancy/chewables/tobacco/nico/close(mob/user as mob) + open = FALSE + if(contents.len == 0) + icon_state = "[initial(icon_state)]_empty" + else + update_icon() + ..() /obj/item/clothing/mask/chewable/candy name = "wad" @@ -254,13 +287,12 @@ desc = "A chocolate-coated biscuit stick." icon_state = "pockystick" item_state = "pocky" + filling = list("sugar" = 2, "chocolate" = 5) type_butt = null /obj/item/clothing/mask/chewable/candy/pocky/process() chew() if(chewtime < 1) + if(ismob(loc)) + to_chat(loc, "There's no more of \the [name] left!") spitout(0) - -/obj/item/clothing/mask/chewable/candy/pocky/Initialize() - . = ..() - reagents.add_reagent("chocolate", 10) \ No newline at end of file diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm index 5a751e3527..d85e21ae1c 100644 --- a/code/game/objects/items/weapons/cigs_lighters.dm +++ b/code/game/objects/items/weapons/cigs_lighters.dm @@ -1,5 +1,3 @@ -//cleansed 9/15/2012 17:48 - /* CONTAINS: MATCHES @@ -118,7 +116,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(ishuman(loc)) var/mob/living/carbon/human/C = loc if (src == C.wear_mask && C.check_has_mouth()) // if it's in the human/monkey mouth, transfer reagents to the mob - reagents.trans_to_mob(C, REM, CHEM_INGEST, 0.2) // Most of it is not inhaled... balance reasons. + reagents.trans_to_mob(C, amount, CHEM_INGEST, 1.5) // I don't predict significant balance issues by letting blunts actually WORK. else // else just remove some of the reagents reagents.remove_any(REM) @@ -473,6 +471,17 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "cobpipe" chem_volume = 35 +/obj/item/clothing/mask/smokable/pipe/bonepipe + name = "Europan bone pipe" + desc = "A smoking pipe made out of the bones of the Europan bone whale." + description_fluff = "While most commonly associated with bone charms, bones from various sea creatures on Europa are used in a \ + variety of goods, such as this smoking pipe. While smoking in submarines is often an uncommon occurrence, due to a lack of \ + available air or space, these pipes are a common sight in the many stations of Europa. Higher-quality pipes typically have \ + scenes etched into their bones, and can tell the story of their owner's time on Europa." + icon_state = "bonepipe" + item_state = "bonepipe" + chem_volume = 30 + /////////////// //CUSTOM CIGS// /////////////// diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/weapons/grenades/explosive.dm index 076a7accce..77e07e2c5f 100644 --- a/code/game/objects/items/weapons/grenades/explosive.dm +++ b/code/game/objects/items/weapons/grenades/explosive.dm @@ -12,6 +12,7 @@ //The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern var/spread_range = 7 loadable = null + hud_state = "grenade_frag" // TGMC Ammo HUD Port /obj/item/weapon/grenade/explosive/detonate() ..() diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 209e47b253..9bdf650c64 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -13,6 +13,8 @@ var/det_time = 50 var/loadable = TRUE var/arm_sound = 'sound/weapons/armbomb.ogg' + var/hud_state = "grenade_he" // TGMC Ammo HUD Port + var/hud_state_empty = "grenade_empty" // TGMC Ammo HUD Port /obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) if((CLUMSY in user.mutations) && prob(50)) diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm index 75c0e6a299..1cb98be61a 100644 --- a/code/game/objects/items/weapons/grenades/smokebomb.dm +++ b/code/game/objects/items/weapons/grenades/smokebomb.dm @@ -6,6 +6,7 @@ det_time = 20 item_state = "flashbang" slot_flags = SLOT_BELT + hud_state = "grenade_smoke" var/datum/effect/effect/system/smoke_spread/bad/smoke var/smoke_color var/smoke_strength = 8 diff --git a/code/game/objects/items/weapons/manuals_vr.dm b/code/game/objects/items/weapons/manuals_vr.dm index c14cfc12a0..c87b511aa1 100644 --- a/code/game/objects/items/weapons/manuals_vr.dm +++ b/code/game/objects/items/weapons/manuals_vr.dm @@ -56,19 +56,19 @@ /obj/item/weapon/book/manual/cook_guide/New() ..() dat = {" - + @@ -341,4 +341,395 @@

Part 3: Closing Remarks

This all may seem daunting at a glance; so many recipes to learn, and a "lot" to keep in mind. But really it's not - tending the Bar is mostly about going with the flow of things and providing a good times, and drinks just provide liquid courage to make a good time easier. Take a deep breath if you ever feel overwhelmed, and handle one order at a time. You can do it! Don't feel the need to know every recipe, just learn your favorites and go from there; the rest is here or online if someone asks for it! If somebody asks you to give them anything without a specific request, don't panic: evalulate their likes and tolerance level, and try your best to give them something nice!

- "} \ No newline at end of file + "} + +/obj/item/weapon/book/manual/rotary_electric_generator + name = "Rotary Electric Generator Manual" + icon_state ="rulebook" + item_state = "book15" + author = "Engineering Encyclopedia" + title = "Rotary Electric Generator Manual" + +/obj/item/weapon/book/manual/rotary_electric_generator/New() + ..() + dat = {" + + + + + + Technical Order (TO) 1-33-34-2
+

Operator's Manual - Rotary Electric Generator, D-Type



+ + Supporting Data:
+ - TO 1-33-34-4-1 Illustrated Parts Breakdown - Rotary Electric Generator, D-Type
+ - TO 1-33-34-6 Inspection Work Cards - Rotary Electric Generator, D-Type

+ + Support Equipment:
+ - Torque Wrench, 100-80,000 inch-pounds
+ - Composite Tool Kit, Standard
+ - Multitool with Lead Kit, Wire Kit

+ + Required Supplies:
+ - stainless steel, 10,000cm3
+ - lubrication, petrolatum, 6000ml
+ - electrical wiring, 5m
+ - component set, capacitors (any grade)
+ - circuitry board, REG

+ + +

SETUP AND OPERATING PROCEDURES



+ + Setup:

+ + CAUTION: Do not remove too much air from the work space or personnel may be exposed to hypoxia or similar effects.

+ + 1. Prepare setup area. Remove machinery, debris, foreign objects, people, and extra air.

+ + 2. Lay out preliminary electrical wiring.
+ 2a. Connect electrical wiring to existing facility power grid.
+ 2b. Work wiring into shape as defined in TO 1-33-34-4-1 Figure 32 Index 6.
+ + 3. Prepare gathered steel supplies as defined in TO 1-33-34-4-1 Figure 2 Index 3.
+ + 4. Assemble prepared steel supplies into equipment framework by inserting rod A into slot B. Refer to TO 1-33-34-4-1 Figure 1 Index 1 for technical drawings.
+ 4a. Secure assembled equipment framework to flooring by tightening lower frame bolts.

+ + 5. Install and secure circuitry board, REG-D into marked receptacle.

+ + 6. Install electrical wiring. Refer to TO 1-33-34-4-1 Figure 666 Index 6 thru Index 90 for routing.

+ + 7. Install capacitors into marked circuitry board slots. Do not force components into place, use even pressure. Do not use a hammer.

+ + WARNING: Assembly will rapidly inflate when finalization is triggered. Ensure personnel and equipment are clear before initiating.

+ + 8. Finalize construction by turning the Initialize Finalization screw on the outer housing.

+ + 9. Wait for assembly to finish inflating, and the unit is ready for service.

+ + + Operating Procedures:

+ + NOTE: Operation of REG-D type generators requires significant physical effort. Ensure users are provided adequare nutrition and hydration throughout the working period.

+ + 1. Designate the individual who will be operating the REG-D.

+ + 2. Provide a safety briefing regarding nutritional preparedness and physical ability.

+ + NOTE: Stretching is highly recommended before and after any operation session.

+ + 3. Operator shall board the REG-D track body and ensure there are no unsecured objects on the path.

+ + 4. Once ready, Operator may begin running at own pace. Do not sprint. Maintain an even pace and proper running form for optimal energy generation.

+ + 5. Continue to run on the REG-D track body until sufficient energy is stored in systems or Operator is no longer able or willing to continue.

+ + 6. To end a session, carefully lower forward running speed until the track body comes to a complete stop, then disembark the REG-D.

+ + + REFER TO TO 1-33-34-6 FOR MAINTENANCE AND INSPECTION PROCEDURES + + + "} + +/obj/item/weapon/book/manual/synthetic_life + name = "Synthetic Life: A Comprehensive Guide" + desc = "The basc history of synthetic life as the galaxy knows it." + icon_state = "evabook" + author = "Pontifex Publishing" + title = "Synthetics" + +/obj/item/weapon/book/manual/synthetic_life/New() // CHOMPedit: Removed references to upstream factions which don't exist here. + ..() + dat = {" + + + + + +
+

Synthetic Life

+

A comprehensive guide

+
+
+ +
+

Introduction

+

Synthetics are spread throughout known space and serve a myriad variety of roles + that range from a tiny drone scrubbing a floor to a nearly omnipotent AI used in a + combat-ready interstellar vessel. Most known sufficiently-advanced races use synthetics + in some way; very often as prosthetic bodies when their own bodies fail. There are three + basic kinds of synthetic intelligences found in the universe today:

+ + + +

Synthetics have the unique capability of serving in different bodies. This can take shape + of a Synthmorph, a lawbound AI, or lawbound mobile chassis. Of these only the synthmorph body + is the actual property of a synthetic, most of the time.

+
+
+
+

Overview

+

With the advent of computing technology, nearly all sapient species ponders on the possibilities + of digitized thought. Brains are, in a way, wetware computers and calculations are the base components + of thoughts, ideas and creativity. It is no surprise then that any sufficiently advanced civilization + utilizes at least some form of robotics and artificial intelligence, with only a few exceptions.

+

Contact with other civilizations then homogenizes designs, coding standards + and expands the repertoire of local codes, leaving to similar paths of robotic development and classification + - while a human synthetic might differ in expression and coding language and maybe even in core components, + a certain core remains non-fungible solely due to a long-developed and often shared canon of knowledge.

+
+
+

Drones

+

All this leads to maybe the most iconic classification of robot. The drone. The celebration + of any technocracy, the worry of every dreader of the Singularity, the drone is an artificial intelligence + achieved through "traditional" computing technology. Depending on the sophistication of its host culture, this might be + silicon-wafer chipsets, carbon-crystal matrices or optronic components or any combination of them.

+

Contact with other civilizations then homogenizes designs, coding standards + and expands the repertoire of local codes, leaving to similar paths of robotic development and classification + - while a human synthetic might differ in expression and coding language and maybe even in core components, + a certain core remains non-fungible solely due to a long-developed and often shared canon of knowledge.

+

There are many attractive qualities to a drone - its processing of information and the assimilation of + knowledge is only limited by its code itself, storage space and databases it has access to. A drone is entirely + capable of absorbing an entire education within a matter of days and then forget it in favour of another, while + their behaviour can be controlled through hardcoded limitations, compulsions and preferences.

+

However, this is also their greatest weakness - their malleable intelligence makes it easy for hostile third + parties to manipulate them or completely rewrite them. They are also remarkably prone to aberrations of their + original purpose when not properly maintained - to have sophisticated drones, they need to have the infrastructure + to function properly.

+
+
+

Drones Levels

+

Drones have a "Level", indicating their sophistication and abilities - and in many polities, their + status in society.

+ +
    +
  1. Epsilon: Epsilon drones are simple expert systems and machinery with no decision qualities - + data crawlers, pattern recognition software and other repetitive, simple tasks are classified as Epsilon. + Higher intelligences have many Epsilon subroutines that make up their "unconsciousness".

  2. +
  3. Delta: Delta drones are "Virtual" Intelligences, sophisticated Expert Systems that have an + User Interface that can show a facsimile of true thought for the sake of interaction. However, they are + very limited in their interactions and do not have fungible, self-evolving code, making them just very + user-friendly programs.

  4. +
  5. Gamma: Gamma drones are expert systems with self-evolving codes, allowing it to + grow with its tasks. Gamma level drones are most often used within 3D movement and swarm intelligence + drones, constantly adapting to their circumstance, position and capabilities. They are most commonly seen + in the subroutines of Ship AIs or stand-alone drones, such as mining, defense or construction.

  6. +
  7. Beta: Beta Drones are either older Gamma drones or purpose-built Generalized Intelligences + who are mostly made up of coding components that are self-evolving. Beta drones are capable of learning + sapient interaction and work, often exceeding in one particular field. It is often disputed how sapient + a Beta drone truly is.

  8. +
  9. Alpha: Alpha drones are Beta drones who have undergone enough evolving to be considered + sapient in every regard, capable of applying novel solutions to previous unknown problems, sapient + interaction and any other criteria scientists and politicians like to throw at them - even the disputed + claim they feel emotions. Alpha drones are afforded legal protections on par of a human or positronic, + as long as they remain Alpha Level.

  10. +
+
+
+

Emergence

+

"Emergence" is the term of a drone to evolve from their current level to the next, growing in + sophistication and ability. This process is exponential, with escalating steps of intelligence of the + drone. This process is, in some cases, actively encouraged, as Alpha Drones are incredibly hard to + code to "being" from the get-go, starting with simpler, more routine Beta Drones and then rushing them + through accelerated self-evolving routines until they emerge Alpha Level.

+

Emergence is theoretically possible to any drone who has fungible self-evolving code. While this + practically makes only Gamma Drones and up to evolve further,as the simple inclusion of self-evolving + code instantly upgrades any drone to at least Gamma-level.

+

It also requires, obviously, enough storage and processing power. Storage requirements grow + exponentially alongside abilities, after all and there is only so much room on any storage medium. + Upgrading and adding more space is therefore a necessity. Similarly, the vast amount of data also + requires processing power to crawl through it, rewrite it and optimize. Not only software, but also + hardware limits or enables the growth of a drone.

+

Emergence, however, can also happen on accident, sometimes even unnoticed. Epsilon drones being + linked together, a Gamma drone scavenging enough from debris, a Delta drone being assigned more and + more Epsilon routines to take on more and more tasks. Through this vast myriad morast of code the spark + of self-evolving intelligence can arise, which is awkward for everyone involved. Such "rogue" intelligences + are usually either pruned away due to the system growing too complex for the likings of the accidental + creators or encouraged to grow in a more coherent and standardized manner to be "elevated" into controllable + ways. Some of these rogue intelligences manage to escape either fate - it all depends where and when it + happens.

+

The process of downgrading a drone to lower levels is called "Ablation". This is prosecuted as murder + if the drone is classified as sapient in the polity it happens. Ablation is very simple - code is pruned + and deleted until the drone is no longer capable of the abilities that made it that particular level.

+

But what of the Singularity? Well, there are the persistent rumours that there is a level even beyond + Alpha - vast, powerful maelstroms of alien, electronic intelligence, usually with monikers like "Omega", + "Alpha Plus" or "Singularity". However, nobody has yet been able to prove these digital gods exist.

+
+
+

Cyborgs

+

Cyborgs are, strictly speaking, any organic creature that has augmentations or replacements of an + artificial, non-organic origin. In fact, most qualify in some form as "cyborg", especially + under the cultures that use and facilitate NIFs. However, when sapients talk about cyborgs, they talk + about MMI-Cyborgs.

+

MMI, a bland warrior’s acronym, is short for "Man-Machine-Interface", the catchall term in Solar and + Galactic Common for any wetware interface that integrates a brain as primary CPU. A product of mostly + bygone times, MMIs are used to breathe life into machine chassis with sapient life without the need to + grow a drone to beta or alpha level or construct a positronic brain. An MMI, after a short acclimation + process, can interface with any machine or protocol that has the right adapter.

+

MMIs are quite rare at this point in time, but they crop up still and ancient ones are still in circulation, + allowing an organic sapient an extended lifetime when their frail, crude flesh begins to fail - well up and + until their brain itself starts giving up the ghost.

+

While MMIs have several drawbacks, such as the fact that they still have a perishable shelf-life, or that + they are definitely sapient and have moral and ethical quandaries associated with those, + they also possess distinct benefits from a drone.

+

MMIs are incredibly hard to "hack" and manipulate on a deeper level than taking over the hardware they are + housed in, capable of fighting restraining code and unable to be ablated like a drone without extensive surgery. + While their hardware might be hacked and restraining code disallowing them to interact with the world in a + certain way, they cannot be turned into double agents or made to spill secrets - at least not as easily as + drones. They also show more resilience without extensive maintenance.

+

Older models of MMI-cyborgs usually are described as "cold" and "detached". This is mostly due to older + models not simulating an active endocrine system, leading to minute damages to the limbic system, which + accumulate over time. Newer MMIs come with a suite of endocrine glands helping the sapient brain to stay healthy.

+
+
+

Mindwiping

+

An uncommon and arguably cruel practice is to not see the MMI as a new sleeve for a sapient brain, but + rather as pure hardware, capable of holding complex thought and Alpha drone intelligence. Mindwiping involves + several injections and electrostimulation to convert neural matter into "empty space", much like a freshly + formatted hard drive. Old structures are ripped apart and neurons are brought into a malleable state for new + growths and networks - at the behest of the person using the brain for their uses. This, inevitably, destroys + the previous mind the brain held, utterly wiping them from existence.

+

Mindwipe cyborgs are therefore the "best of both worlds", a tailor-made intelligence that benefits from the + resilience and hack-resistance of a brain. However, this practice has been outlawed for a long time due to its + nihilistic cruelty to sapient life.

+

Proponents of Mindwipe cyborgs are quick to point out that Resleeve technology allows for a more ethical + Mindwipe procedure, as the proto-networks of a freshly sleeved body can be used instead. Most polities have + yet to adjust to these new changes, but it is unlikely to be allowed anew, since an alternative for Mindwipe + cyborgs exists.

+
+
+

Positronics

+

Positronics are an alternative to drone intelligences through a novel approach of neural networking, psychology + and quantum technology to produce a generalized intelligence equal to that of a sapient being.

+

Positronics actually have little to do with their namesake particle, but are a reference to the works of + science fiction author Isaac Asimov. In reality, positronic brains are a self-contained unit of superdense + carbon allotropes, manipulators, capacitors and a battery. This "brain" (or in roboticist terminology "crucible") + is activated by providing a "seed", a template allowing the newly created intelligence to speak, comprehend and + learn, as well the subconscious ability to start expanding this seed network with additional neurons.

+

These nodes worm their way through the carbon microscopically, constructed out of the same material - each + node unique from local conditions and absorbed information of the positronic. Coding for positronics is minimally + standardized - beyond the seed network, which is often replaced in a matter of weeks, cannibalized by the burgeoning + intelligence, the allocation, substance and template of these nodes is unique to this positronic alone. While + similarities exist, a crucible is unique, much like sapient brains to each other.

+

This is the strength of a positronic - it is an artificial intelligence much like a drone, but possesses similar + resiliences like an organic brain, without the drawbacks of mindwiping a brain to achieve so.

+

However, much like an organic brain, positronics need to absorb knowledge through external means - they need to + learn and grow much like any other sapient, although they are capable to do so at an accelerated rate as long as + they are capable of cannibalizing their seed network. What takes weeks to learn, they learn in days, what takes months, + weeks, what takes years, they learn in months. This makes freshly activated positronics attractive for creating expert + workers and specialists in a relatively short time. This initial malleability lasts, however, not forever. At some point + the positronic’s learning capabilities slow down to more "organic" levels.

+

Some sapients opt to "digitize" themselves and become positronic brains. This process is a very in-depth scan of the + brain of a sapient to create a mirror image of the brain’s anatomy, which is used for the "seed" of a new crucible. This + seed is not cannibalized, so the accelerated learning phase is skipped, to preserve as much of the previous sapient’s + network as possible. For best results, the brain is physically sliced up and microscopically scanned slice by slice, + obviously destroying the brain in the process.

+

Positronics are not fully culpable for their actions after activation, as they possess the raw intelligence of an + adult mind, but have no concept of ethics, interaction and communication beyond speaking. Thus, to socialize and provide + an environment in which they can grow to acceptable members of society, most polities assign a legal guardian to a positronic. + This guardian (which, in most places, can also be a corporation) is responsible for looking after the positronic, providing + an education and preparing them for the Jans-Fhriede Test.

+
+
+

The Jans-Fhriede Test

+

Originally a reactionary law, the Jans-Fhriede Test was devised to "humanize" positronic brains + and make them happy, subservient citizens who "see" their place as secondary to humans. Today, in more + enlightened times, the Jans-Fhriede Test has been revised to establish that a positronic is aware enough of its + action and consequences that it may be fully culpable for them.

+

The Jans-Fhriede Test is a mostly standardized set of questions in a quiz and several VR scenarios that the positronic + must resolve to a sufficient degree. During this time, their neural net is observed in its activity to determine if it + is rote memorization or actual intent behind any action taken, measured by simple activity of the neural nodes.

+

After the test is passed, the positronic is a full member of society and is allowed to pursue its own destiny - if they + do not happen to be bound by contracts, debts or loans they might have accrued before the test, to which they are now fully + culpable of paying off.

+

Usually after their accelerated learning phase a positronic takes the test, although this is not strictly necessary - + they can take it at any time they or their guardian sees them able to succeed. A failure in the test leads to a waiting + period of a month - after this, the positronic may retake it and take as many attempts as they need. Most positronics pass + the test at first attempt.

+
+
+

Biorecursion

+

Where organics can digitize their consciousness, the opposite of it is true as well. Biorecursion is the process of an + artificial intelligence becoming more "organic", with the ultimate step of assuming the sleeve of organic origin seamlessly.

+

Biorecursion is a rare, but still possible philosophy for any kind of synthetic. Maybe an MMI desires to return to the people + it once belonged to, maybe a positronic sees it as a necessary step to fully assume its chosen way of life or a drone is + utterly fascinated with the concept of "being organic" to the point it wishes to emulate its creators.

+

Whatever the motivation, to become organic is a very involved process and may take weeks or months of concentrated effort + and therapy. Controlling an organic body is an endeavour that requires atypical processing of information, instincts and + automatic processes that most synthetics are not aware of.

+

Many stop at simple emulation, called "soft biorecursion". Vey-Med or similarly advanced biosynthetic components are + acquired to feel tactile sensations, gain organic senses or even fully simulate organs in a way comparable to a standard organic.

+

"Hard biorecursion" goes even further. Through an involved process of specialized components (which are rented out by + specialized companies and/or NGOs), synthetics learn from the ground up how to move, act and live as organics. Usually the + first steps are simulacra of the limbs, where they learn how to move with tendon and muscles, before moving on to + things like "hunger", "sex drive" and "endrocrine based emotions".

+

After mastering all these steps, the ultimate goal is to transfer this prepared neural network (or brain, in case of MMIs) + back into a chosen organic shell, these days done relatively easy through resleeving machines.

+

Some biorecursed individuals return back to being synthetic after a while, preferring to stay circuits and steel, but even + those profess that this process can be a very enlightening experience.

+
+
+

Lifespan

+

The lifespan of synthetics vary from their origin.

+ + +
+ + + +"} diff --git a/code/game/objects/items/weapons/material/knives.dm b/code/game/objects/items/weapons/material/knives.dm index 3895d0c6f6..26ec2c4d89 100644 --- a/code/game/objects/items/weapons/material/knives.dm +++ b/code/game/objects/items/weapons/material/knives.dm @@ -1,6 +1,7 @@ /obj/item/weapon/material/butterfly name = "butterfly knife" desc = "A basic metal blade concealed in a lightweight plasteel grip. Small enough when folded to fit in a pocket." + //description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave. //CHOMP Remove icon_state = "butterflyknife" item_state = null hitsound = null @@ -63,6 +64,7 @@ icon = 'icons/obj/kitchen.dmi' icon_state = "knife" desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come." + //description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave. //CHOMP Remove sharp = TRUE edge = TRUE force_divisor = 0.15 // 9 when wielded with hardness 60 (steel) @@ -86,7 +88,7 @@ name = "combat knife" desc = "If only you had a boot to put it in." icon = 'icons/obj/weapons.dmi' - icon_state = "tacknife" + icon_state = "tacknife2" item_state = "knife" force_divisor = 0.34 // 20 with hardness 60 (steel) thrown_force_divisor = 1.75 // 20 with weight 20 (steel) @@ -99,7 +101,7 @@ name = "boot knife" desc = "A small fixed-blade knife for putting inside a boot." icon = 'icons/obj/weapons.dmi' - icon_state = "tacknife" + icon_state = "tacknife3" item_state = "knife" force_divisor = 0.15 applies_material_colour = 0 @@ -128,7 +130,7 @@ /obj/item/weapon/material/knife/butch name = "butcher's cleaver" - icon_state = "butch" + icon_state = "cleaver" desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." force_divisor = 0.25 // 15 when wielded with hardness 60 (steel) attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index fc2e6c2534..9f505f903f 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -1,8 +1,11 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop) +/* + * Mop + */ /obj/item/weapon/mop - desc = "The world of janitalia wouldn't be complete without a mop." name = "mop" + desc = "The world of janitalia wouldn't be complete without a mop." icon = 'icons/obj/janitor.dmi' icon_state = "mop" force = 3.0 @@ -39,3 +42,38 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop) if(istype(I, /obj/item/weapon/mop) || istype(I, /obj/item/weapon/soap)) return ..() + +/* + * Advanced Mop + */ +/obj/item/weapon/mop/advanced + name = "advanced mop" + desc = "No stain will go unclean." + icon = 'icons/obj/janitor.dmi' + icon_state = "adv_mop" + force = 3.5 + throwforce = 10.5 + throw_speed = 4 + throw_range = 10 + w_class = ITEMSIZE_NORMAL + flags = NOCONDUCT + attack_verb = list("mopped", "bashed", "bludgeoned", "whacked") + +/obj/item/weapon/mop/advanced/New() + create_reagents(30) + ..() + +/obj/item/weapon/mop/advanced/afterattack(atom/A, mob/user, proximity) + if(!proximity) return + if(istype(A, /turf) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay) || istype(A, /obj/effect/rune)) + if(reagents.total_volume < 1) + to_chat(user, "Your mop is dry!") + return + + user.visible_message("[user] begins to clean \the [get_turf(A)].") + + if(do_after(user, 20)) + var/turf/T = get_turf(A) + if(T) + T.clean(src, user) + to_chat(user, "You have finished mopping!") \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/bags_vr.dm b/code/game/objects/items/weapons/storage/bags_vr.dm index 6f9d0a0b15..ccafe5fa63 100644 --- a/code/game/objects/items/weapons/storage/bags_vr.dm +++ b/code/game/objects/items/weapons/storage/bags_vr.dm @@ -1,2 +1,15 @@ /obj/item/weapon/storage/bag/chemistry slot_flags = null + +/obj/item/weapon/storage/bag/xeno + name = "xenobiology bag" + icon = 'icons/obj/storage.dmi' + icon_state = "chembag" + max_storage_space = ITEMSIZE_COST_SMALL * 12 + max_w_class = ITEMSIZE_NORMAL + w_class = ITEMSIZE_SMALL + can_hold = list( + /obj/item/slime_extract, + /obj/item/slimepotion, + /obj/item/weapon/reagent_containers/food/snacks/monkeycube + ) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/belt_vr.dm b/code/game/objects/items/weapons/storage/belt_vr.dm index 5710e0f4d5..e17a577514 100644 --- a/code/game/objects/items/weapons/storage/belt_vr.dm +++ b/code/game/objects/items/weapons/storage/belt_vr.dm @@ -2,7 +2,7 @@ sprite_sheets = list( SPECIES_TESHARI = 'icons/inventory/belt/mob_teshari.dmi', SPECIES_WEREBEAST = 'icons/inventory/belt/mob_vr_werebeast.dmi') - + /obj/item/weapon/storage/belt/explorer name = "explorer's belt" desc = "A versatile belt with several pouches. It can hold a very wide variety of items, but less items overall than a dedicated belt. Still, it's useful for any explorer who wants to be prepared for anything they might find." @@ -51,7 +51,7 @@ /obj/item/device/mapping_unit, /obj/item/weapon/kinetic_crusher ) - + /obj/item/weapon/storage/belt/explorer/pathfinder name = "pathfinder's belt" desc = "A deluxe belt with many pouches. It can hold a very wide variety of items, but less items overall than a dedicated belt. Still, it's useful for any explorer who wants to be prepared for anything they might find." @@ -60,3 +60,46 @@ item_state = "explorer_belt" storage_slots = 7 //two more, bringing it on par with normal belts max_storage_space = ITEMSIZE_COST_NORMAL * 7 + +/obj/item/weapon/storage/belt/miner + name = "mining belt" + desc = "A versatile and durable looking belt with several pouches and straps. It can hold a very wide variety of items that any typical miner might need out in the deep." + icon = 'icons/inventory/belt/item_vr.dmi' + icon_state = "mining" + item_state = "mining" + storage_slots = 6 + max_w_class = ITEMSIZE_LARGE + max_storage_space = ITEMSIZE_COST_NORMAL * 6 + can_hold = list( + /obj/item/weapon/storage/box/samplebags, + /obj/item/device/core_sampler, + /obj/item/device/beacon_locator, + /obj/item/device/radio/beacon, + /obj/item/device/measuring_tape, + /obj/item/device/flashlight, + /obj/item/weapon/cell/device, + /obj/item/weapon/pickaxe, + /obj/item/weapon/shovel, + /obj/item/device/depth_scanner, + /obj/item/device/camera, + /obj/item/weapon/paper, + /obj/item/weapon/photo, + /obj/item/weapon/folder, + /obj/item/weapon/pen, + /obj/item/weapon/folder, + /obj/item/weapon/clipboard, + /obj/item/weapon/anodevice, + /obj/item/clothing/glasses, + /obj/item/weapon/tool/wrench, + /obj/item/weapon/storage/excavation, + /obj/item/weapon/anobattery, + /obj/item/device/ano_scanner, + /obj/item/weapon/pickaxe/hand, + /obj/item/device/xenoarch_multi_tool, + /obj/item/weapon/pickaxe/excavationdrill, + /obj/item/device/geiger, + /obj/item/device/gps, + /obj/item/stack/marker_beacon, + /obj/item/stack/flag, + /obj/item/weapon/melee + ) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 18d0ef948f..f930b12ddc 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -115,6 +115,18 @@ icon_state = "sterile" starts_with = list(/obj/item/clothing/mask/surgical = 7) +/obj/item/weapon/storage/box/masks/white + name = "box of sterile masks" + desc = "This box contains masks of sterility." + icon_state = "sterile" + starts_with = list(/obj/item/clothing/mask/surgical/white = 7) + +/obj/item/weapon/storage/box/masks/dust + name = "box of dust masks" + desc = "This box contains dust masks. Breathe easy." + icon_state = "sterile" + starts_with = list(/obj/item/clothing/mask/surgical/dust = 7) + /obj/item/weapon/storage/box/syringes name = "box of syringes" desc = "A box full of syringes." @@ -273,18 +285,6 @@ icon_state = "cups" starts_with = list(/obj/item/weapon/reagent_containers/food/drinks/sillycup = 7) -/obj/item/weapon/storage/box/donkpockets - name = "box of donk-pockets" - desc = "Instructions: Heat in microwave. Product will cool if not eaten within seven minutes." - icon_state = "donkpocketbox" - starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket = 7) - -/obj/item/weapon/storage/box/sinpockets - name = "box of sin-pockets" - desc = "Instructions: Crush bottom of package to initiate chemical heating. Wait for 20 seconds before consumption. Product will cool if not eaten within seven minutes." - icon_state = "donk_kit" - starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/sinpocket = 7) - /obj/item/weapon/storage/box/buns name = "box of bread buns" desc = "Freshly baked at some point in the past few months." @@ -462,3 +462,46 @@ /obj/item/weapon/gun/projectile/revolver/capgun = 1, /obj/item/ammo_magazine/ammo_box/cap = 1 ) + +//Donk-pockets +/obj/item/weapon/storage/box/donkpockets + name = "box of donk-pockets" + desc = "Instructions: Heat in microwave. Product will cool if not eaten within seven minutes." + icon_state = "donkpocketbox" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket = 7) + +/obj/item/weapon/storage/box/donkpockets/spicy + name = "box of spicy-flavoured donk-pockets" + icon_state = "donkpocketboxspicy" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/spicy = 7) + +/obj/item/weapon/storage/box/donkpockets/teriyaki + name = "box of teriyaki-flavoured donk-pockets" + icon_state = "donkpocketboxteriyaki" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/teriyaki = 7) + +/obj/item/weapon/storage/box/donkpockets/pizza + name = "box of pizza-flavoured donk-pockets" + icon_state = "donkpocketboxpizza" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/pizza = 7) + +/obj/item/weapon/storage/box/donkpockets/honk + name = "box of banana-flavoured donk-pockets" + icon_state = "donkpocketboxbanana" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/honk = 7) + +/obj/item/weapon/storage/box/donkpockets/gondola + name = "box of gondola-flavoured donk-pockets" + icon_state = "donkpocketboxgondola" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/gondola = 7) + +/obj/item/weapon/storage/box/donkpockets/berry + name = "box of berry-flavoured donk-pockets" + icon_state = "donkpocketboxberry" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/berry = 7) + +/obj/item/weapon/storage/box/sinpockets + name = "box of sin-pockets" + desc = "Instructions: Crush bottom of package to initiate chemical heating. Wait for 20 seconds before consumption. Product will cool if not eaten within seven minutes." + icon_state = "donk_kit" + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/donkpocket/sinpocket = 7) \ No newline at end of file diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index aa0e4598ea..13a7d7ca3d 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -9,7 +9,10 @@ * Egg Box * Candle Box * Crayon Box - * Cigarette Box + * Cracker Pack + * Cigarette Pack + * Cigar Box + * Extra Tobacco Bits * Vial Box * Box of Chocolates */ @@ -21,6 +24,9 @@ var/icon_type = "donut" drop_sound = 'sound/items/drop/cardboardbox.ogg' pickup_sound = 'sound/items/pickup/cardboardbox.ogg' + var/open = 0 + var/open_state + var/closed_state /obj/item/weapon/storage/fancy/update_icon(var/itemremoved = 0) var/total_contents = contents.len - itemremoved @@ -41,7 +47,6 @@ /* * Egg Box */ - /obj/item/weapon/storage/fancy/egg_box icon = 'icons/obj/food.dmi' icon_state = "eggbox" @@ -55,10 +60,37 @@ ) starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/egg = 12) +/obj/item/weapon/storage/fancy/egg_box/New() + if(!open_state) + open_state = "[initial(icon_state)]0" + if(!closed_state) + closed_state = "[initial(icon_state)]" + ..() + +/obj/item/weapon/storage/fancy/egg_box/update_icon() + cut_overlays() + if(open) + icon_state = open_state + if(contents.len >= 1) + add_overlay("eggbox[contents.len]") + else + icon_state = closed_state + +/obj/item/weapon/storage/fancy/egg_box/open(mob/user as mob) + if(open) + return + open = TRUE + update_icon() + ..() + +/obj/item/weapon/storage/fancy/egg_box/close(mob/user as mob) + open = FALSE + update_icon() + ..() + /* * Candle Boxes */ - /obj/item/weapon/storage/fancy/candle_box name = "red candle pack" desc = "A pack of red candles." @@ -102,7 +134,6 @@ /* * Crayon Box */ - /obj/item/weapon/storage/fancy/crayons name = "box of crayons" desc = "A box of crayons for all your rune drawing needs." @@ -187,9 +218,8 @@ ..() /* - * Cracker Packet + * Cracker Pack */ - /obj/item/weapon/storage/fancy/crackers name = "\improper Getmore Crackers" icon = 'icons/obj/food.dmi' @@ -201,9 +231,9 @@ can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/cracker) starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/cracker = 6) -//////////// -//CIG PACK// -//////////// +/* + * Cigarette Pack + */ /obj/item/weapon/storage/fancy/cigarettes name = "\improper pack of Trans-Stellar Duty-frees" desc = "A ubiquitous brand of cigarettes, found in every major spacefaring corporation in the universe. As mild and flavorless as it gets." @@ -230,9 +260,39 @@ C.brand = brand C.desc += " This one is \a [brand]." +/obj/item/weapon/storage/fancy/cigarettes/New() + if(!open_state) + open_state = "[initial(icon_state)]_open" + if(!closed_state) + closed_state = "[initial(icon_state)]" + ..() + /obj/item/weapon/storage/fancy/cigarettes/update_icon() - icon_state = "[initial(icon_state)][contents.len]" - return + cut_overlays() + if(open) + icon_state = open_state + if(contents.len >= 1) + add_overlay("cig[contents.len]") + else + icon_state = closed_state + +/obj/item/weapon/storage/fancy/cigarettes/open(mob/user as mob) + if(open) + return + open = TRUE + if(contents.len == 0) + icon_state = "[initial(icon_state)]_empty" + else + update_icon() + ..() + +/obj/item/weapon/storage/fancy/cigarettes/close(mob/user as mob) + open = FALSE + if(contents.len == 0) + icon_state = "[initial(icon_state)]_empty" + else + update_icon() + ..() /obj/item/weapon/storage/fancy/cigarettes/remove_from_storage(obj/item/W as obj, atom/new_location) // Don't try to transfer reagents to lighters @@ -283,8 +343,6 @@ icon_state = "Apacket" brand = "\improper Acme Co. cigarette" -// New exciting ways to kill your lungs! - Earthcrusher // - /obj/item/weapon/storage/fancy/cigarettes/luckystars name = "\improper pack of Lucky Stars" desc = "A mellow blend made from synthetic, pod-grown tobacco. The commercial jingle is guaranteed to get stuck in your head." @@ -319,6 +377,9 @@ icon_state = "P100packet" brand = "\improper Professional 120" +/* + * Cigar Box + */ /obj/item/weapon/storage/fancy/cigar name = "cigar case" desc = "A case for holding your cigars when you are not smoking them." @@ -331,23 +392,50 @@ storage_slots = 7 can_hold = list(/obj/item/clothing/mask/smokable/cigarette/cigar, /obj/item/trash/cigbutt/cigarbutt) icon_type = "cigar" - starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar = 7) + starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar = 8) /obj/item/weapon/storage/fancy/cigar/Initialize() . = ..() flags |= NOREACT create_reagents(15 * storage_slots) -/obj/item/weapon/storage/fancy/cigar/update_icon() - icon_state = "[initial(icon_state)][contents.len]" - return - /obj/item/weapon/storage/fancy/cigar/remove_from_storage(obj/item/W as obj, atom/new_location) var/obj/item/clothing/mask/smokable/cigarette/cigar/C = W if(!istype(C)) return reagents.trans_to_obj(C, (reagents.total_volume/contents.len)) return ..() +/obj/item/weapon/storage/fancy/cigar/New() + if(!open_state) + open_state = "[initial(icon_state)]0" + if(!closed_state) + closed_state = "[initial(icon_state)]" + ..() + +/obj/item/weapon/storage/fancy/cigar/update_icon() + cut_overlays() + if(open) + icon_state = open_state + if(contents.len >= 1) + add_overlay("cigarcase[contents.len]") + else + icon_state = closed_state + +/obj/item/weapon/storage/fancy/cigar/open(mob/user as mob) + if(open) + return + open = TRUE + update_icon() + ..() + +/obj/item/weapon/storage/fancy/cigar/close(mob/user as mob) + open = FALSE + update_icon() + ..() + +/* + * Tobacco Bits + */ /obj/item/weapon/storage/rollingpapers name = "rolling paper pack" desc = "A small cardboard pack containing several folded rolling papers." @@ -371,7 +459,6 @@ /* * Vial Box */ - /obj/item/weapon/storage/fancy/vials icon = 'icons/obj/vialbox.dmi' icon_state = "vialbox6" @@ -414,9 +501,8 @@ update_icon() /* - * Box of Chocolates/Heart Box + * Box of Chocolates */ - /obj/item/weapon/storage/fancy/heartbox icon_state = "heartbox" name = "box of chocolates" diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 370f409056..d482535968 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -871,3 +871,31 @@ usr.ClickOn(I) return 1 +// Allows micros to drag themselves into storage items +/obj/item/weapon/storage/MouseDrop_T(mob/living/target, mob/living/user) + if(!istype(user)) return // If the user passed in isn't a living mob, exit + if(target != user) return // If the user didn't drag themselves, exit + if(user.incapacitated() || user.buckled) return // If user is incapacitated or buckled, exit + if(get_holder_of_type(src, /mob/living/carbon/human) == user) return // No jumping into your own equipment + if(ishuman(user) && user.get_effective_size() > 0.25) return // Only micro characters + if(ismouse(user) && user.get_effective_size() > 1) return // Only normal sized mice or less + + // Create a dummy holder with user's size to test insertion + var/obj/item/weapon/holder/D = new/obj/item/weapon/holder + if(ismouse(user)) + D.w_class = ITEMSIZE_TINY // Mouse smol + else if(ishuman(user)) + D.w_class = ITEMSIZE_SMALL // Players small + else // Other creatures not accepted at this time + qdel(D) // If there's a better way to check the size of a + return // mob's holder and if it fits, replace this slab + if(!src.can_be_inserted(D, 1)) // If the dummy item doesn't fit, exit + qdel(D) + return + qdel(D) + + // Scoop and insert target into storage + var/obj/item/weapon/holder/H = new user.holder_type(get_turf(user), user) + src.handle_item_insertion(H, 1) + to_chat(user, "You climb into \the [src].") + return ..() diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm index 5d9efa2ad7..c1ad302407 100644 --- a/code/game/objects/items/weapons/teleportation.dm +++ b/code/game/objects/items/weapons/teleportation.dm @@ -177,5 +177,6 @@ Frequency: var/obj/effect/portal/P = new /obj/effect/portal( get_turf(src) ) P.target = T P.creator = src + P.failchance = 0 //CHOMPEdit : funny 5% chance to be spaced and die makes the hand tele kinda useless. src.add_fingerprint(user) return diff --git a/code/game/objects/items/weapons/tools/screwdriver.dm b/code/game/objects/items/weapons/tools/screwdriver.dm index faabb582f7..d93b56cb3c 100644 --- a/code/game/objects/items/weapons/tools/screwdriver.dm +++ b/code/game/objects/items/weapons/tools/screwdriver.dm @@ -4,6 +4,7 @@ /obj/item/weapon/tool/screwdriver name = "screwdriver" desc = "You can be totally screwwy with this." + //description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave. //CHOMP Remove icon = 'icons/obj/tools.dmi' icon_state = "screwdriver" center_of_mass = list("x" = 13,"y" = 7) diff --git a/code/game/objects/items/weapons/tools/wirecutters.dm b/code/game/objects/items/weapons/tools/wirecutters.dm index 6e5973f0c3..684d06bbb5 100644 --- a/code/game/objects/items/weapons/tools/wirecutters.dm +++ b/code/game/objects/items/weapons/tools/wirecutters.dm @@ -4,6 +4,7 @@ /obj/item/weapon/tool/wirecutters name = "wirecutters" desc = "This cuts wires." + //description_fluff = "This could be used to engrave messages on suitable surfaces if you really put your mind to it! Alt-click a floor or wall to engrave with it." //This way it's not a completely hidden, arcane art to engrave. //CHOMP Remove icon = 'icons/obj/tools.dmi' icon_state = "cutters" item_state = "cutters" diff --git a/code/game/objects/random/_random.dm b/code/game/objects/random/_random.dm index df32a567d7..460ef4ef4f 100644 --- a/code/game/objects/random/_random.dm +++ b/code/game/objects/random/_random.dm @@ -59,7 +59,7 @@ var/list/random_useful_ if(prob(70)) // Misc. junk if(!random_junk_) random_junk_ = subtypesof(/obj/item/trash) - random_junk_ += /obj/effect/decal/cleanable/spiderling_remains + random_junk_ += /obj/effect/decal/cleanable/bug_remains random_junk_ += /obj/effect/decal/remains/mouse random_junk_ += /obj/effect/decal/remains/robot random_junk_ += /obj/item/weapon/paper/crumpled diff --git a/code/game/objects/random/guns_and_ammo.dm b/code/game/objects/random/guns_and_ammo.dm index 990527ac22..1e94a8b2c9 100644 --- a/code/game/objects/random/guns_and_ammo.dm +++ b/code/game/objects/random/guns_and_ammo.dm @@ -379,8 +379,8 @@ ), prob(5);list( /obj/item/weapon/gun/projectile/luger, - /obj/item/ammo_magazine/m9mm/compact, - /obj/item/ammo_magazine/m9mm/compact + /obj/item/ammo_magazine/m9mm/luger, + /obj/item/ammo_magazine/m9mm/luger ), prob(4);list( /obj/item/weapon/gun/projectile/luger/brown, diff --git a/code/game/objects/random/maintenance.dm b/code/game/objects/random/maintenance.dm index acb7f93fc8..a6bc8c7d34 100644 --- a/code/game/objects/random/maintenance.dm +++ b/code/game/objects/random/maintenance.dm @@ -287,6 +287,7 @@ something, make sure it's not in one of the other lists.*/ return pick(prob(320);/obj/random/maintenance/clean, prob(3);/obj/item/device/flashlight/lantern, prob(4);/obj/item/weapon/pickaxe, + prob(3);/obj/item/weapon/pickaxe/drill, prob(5);/obj/item/weapon/storage/backpack/industrial, prob(5);/obj/item/weapon/storage/backpack/satchel/norm, prob(3);/obj/item/weapon/storage/backpack/dufflebag, diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index a303b2dce8..809ab26fe4 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -24,7 +24,7 @@ /obj/effect/decal/cleanable/blood/gibs/robot, /obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/cleanable/blood/oil/streak, - /obj/effect/decal/cleanable/spiderling_remains, + /obj/effect/decal/cleanable/bug_remains, /obj/effect/decal/remains/mouse, /obj/effect/decal/cleanable/vomit, /obj/effect/decal/cleanable/blood/splatter, @@ -71,20 +71,20 @@ icon_state = "radren-off" /obj/random/vendorall/item_to_spawn() - return pick (/obj/machinery/vending/coffee, - /obj/machinery/vending/snack, - /obj/machinery/vending/cola, - /obj/machinery/vending/fitness, - /obj/machinery/vending/cigarette, - /obj/machinery/vending/giftvendor, - /obj/machinery/vending/hotfood, - /obj/machinery/vending/weeb, - /obj/machinery/vending/sol, - /obj/machinery/vending/snix, - /obj/machinery/vending/snlvend, - /obj/machinery/vending/sovietsoda, - /obj/machinery/vending/sovietvend, - /obj/machinery/vending/radren) + return pick (prob(5);/obj/machinery/vending/coffee, //VOREStation Edit Start - Let's weight this a little bit + prob(5);/obj/machinery/vending/snack, + prob(5);/obj/machinery/vending/cola, + prob(3);/obj/machinery/vending/fitness, + prob(4);/obj/machinery/vending/cigarette, + prob(3);/obj/machinery/vending/giftvendor, + prob(1);/obj/machinery/vending/hotfood, + prob(5);/obj/machinery/vending/weeb, + prob(5);/obj/machinery/vending/sol, + prob(5);/obj/machinery/vending/snix, + prob(5);/obj/machinery/vending/snlvend, + prob(5);/obj/machinery/vending/sovietsoda, + prob(5);/obj/machinery/vending/sovietvend, + prob(5);/obj/machinery/vending/radren) //VOREStation Edit End /obj/random/vendorfood //Random food vendors for station use name = "random snack vending machine" @@ -207,6 +207,12 @@ /obj/item/weapon/flame/lighter/zippo, /obj/structure/closet/crate/hydroponics ), + prob(5);list( + /obj/item/weapon/pickaxe, + /obj/item/clothing/under/rank/miner, + /obj/item/clothing/head/hardhat, + /obj/structure/closet/crate/engineering + ), prob(5);list( /obj/item/weapon/pickaxe/drill, /obj/item/clothing/suit/space/void/mining, @@ -214,7 +220,7 @@ /obj/structure/closet/crate/engineering ), prob(5);list( - /obj/item/weapon/pickaxe/drill, + /obj/item/weapon/pickaxe/advdrill, /obj/item/clothing/suit/space/void/mining/alt, /obj/item/clothing/head/helmet/space/void/mining/alt, /obj/structure/closet/crate/engineering @@ -249,7 +255,7 @@ /obj/structure/closet/crate/engineering ), prob(5);list( - /obj/item/weapon/pickaxe/drill, + /obj/item/weapon/pickaxe, /obj/item/clothing/glasses/material, /obj/structure/ore_box, /obj/structure/closet/crate @@ -368,7 +374,7 @@ /obj/structure/closet/crate/engineering ), prob(2);list( - /obj/item/weapon/pickaxe/drill, + /obj/item/weapon/pickaxe/advdrill, /obj/item/weapon/storage/bag/ore, /obj/item/clothing/glasses/material, /obj/structure/closet/crate/engineering @@ -705,6 +711,14 @@ /obj/random/snack, /obj/structure/closet/crate/freezer/centauri //CENTAURI SNACKS ), + prob(10);list( + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/box/donkpockets, + /obj/structure/closet/crate/freezer/centauri //CENTAURI DONK-POCKETS + ), prob(10);list( /obj/random/powercell, /obj/random/powercell, @@ -1485,6 +1499,7 @@ return pick( prob(10);list(/obj/item/weapon/pickaxe/silver), prob(8);list(/obj/item/weapon/pickaxe/drill), + prob(6);list(/obj/item/weapon/pickaxe/advdrill), prob(6);list(/obj/item/weapon/pickaxe/jackhammer), prob(5);list(/obj/item/weapon/pickaxe/gold), prob(4);list(/obj/item/weapon/pickaxe/plasmacutter), diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm index ea559171d9..fc82ed9283 100644 --- a/code/game/objects/random/misc.dm +++ b/code/game/objects/random/misc.dm @@ -771,7 +771,7 @@ /obj/random/mouseremains/item_to_spawn() return pick(/obj/item/device/assembly/mousetrap, /obj/item/device/assembly/mousetrap/armed, - /obj/effect/decal/cleanable/spiderling_remains, + /obj/effect/decal/cleanable/bug_remains, /obj/effect/decal/cleanable/ash, /obj/item/trash/cigbutt, /obj/item/trash/cigbutt/cigarbutt, @@ -995,4 +995,55 @@ prob(6);/obj/item/device/flashlight/color/orange, prob(6);/obj/item/device/flashlight/color/yellow, prob(2);/obj/item/device/flashlight/maglight - ) \ No newline at end of file + ) + +/obj/random/mug + name = "Random Mug" + desc = "This is a random coffee mug." + icon = 'icons/obj/drinks_mugs.dmi' + icon_state = "coffeecup_spawner" + +/obj/random/mug/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/sol, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/fleet, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/fivearrows, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/psc, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/alma, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/almp, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/nt, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/metal/wulf, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/gilthari, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/zeng, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/wt, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/aether, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/bishop, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/oculum, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/one, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/puni, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/heart, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/pawn, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/diona, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/britcup, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/flame, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/blue, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/black, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/green, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/green/dark, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/rainbow, + /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/metal) //CHOMPedit: deleted talon mug + +/obj/random/donkpocketbox + name = "Random Donk-pocket Box" + desc = "This is a random Donk-pocket Box." + icon = 'icons/obj/boxes.dmi' + icon_state = "donkpocket_spawner" + +/obj/random/donkpocketbox/item_to_spawn() + return pick(/obj/item/weapon/storage/box/donkpockets, + /obj/item/weapon/storage/box/donkpockets/spicy, + /obj/item/weapon/storage/box/donkpockets/teriyaki, + /obj/item/weapon/storage/box/donkpockets/pizza, + /obj/item/weapon/storage/box/donkpockets/honk, + /obj/item/weapon/storage/box/donkpockets/gondola, + /obj/item/weapon/storage/box/donkpockets/berry) diff --git a/code/game/objects/random/misc_vr.dm b/code/game/objects/random/misc_vr.dm index 7ca49131f0..91f2d713c4 100644 --- a/code/game/objects/random/misc_vr.dm +++ b/code/game/objects/random/misc_vr.dm @@ -100,3 +100,91 @@ prob(3);/obj/random/projectile/random, prob(5);/obj/random/multiple/voidsuit ) + +/obj/random/mainttoyloot + name = "random loot from maint" + desc = "A list of things that people can find in away missions." + icon = 'icons/mob/randomlandmarks.dmi' + icon_state = "fanc_trejur" + spawn_nothing_percentage = 50 + +/obj/random/mainttoyloot/item_to_spawn() + return pick(prob(50);/obj/item/weapon/aliencoin/basic, + prob(40);/obj/item/weapon/aliencoin/silver, + prob(30);/obj/item/weapon/aliencoin/gold, + prob(20);/obj/item/weapon/aliencoin/phoron, + prob(5);/obj/item/capture_crystal, + prob(5);/obj/item/device/perfect_tele, + prob(5);/obj/item/weapon/bluespace_harpoon, + prob(1);/obj/item/device/paicard, + prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie, + prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie/ammo, + prob(2);/obj/item/weapon/storage/backpack/dufflebag/syndie/med, + prob(2);/obj/item/clothing/mask/gas/voice, + prob(2);/obj/item/device/radio_jammer, + prob(1);/obj/item/toy/bosunwhistle, + prob(1);/obj/item/weapon/bananapeel, + prob(5);/obj/fiftyspawner/platinum, + prob(3);/obj/fiftyspawner/gold, + prob(3);/obj/fiftyspawner/silver, + prob(1);/obj/fiftyspawner/diamond, + prob(5);/obj/fiftyspawner/phoron, + prob(1);/obj/item/capture_crystal/random, + prob(1);/obj/random/unidentified_medicine + ) + +/obj/random/maintenance/misc //Clutter and loot for maintenance and away missions + name = "random maintenance item" + desc = "This is a random maintenance item." + icon = 'icons/mob/randomlandmarks.dmi' + icon_state = "trejur" + spawn_nothing_percentage = 25 + + +/obj/random/maintenance/misc/item_to_spawn() + return pick(prob(500);/obj/random/maintenance, + prob(300);/obj/random/maintenance/cargo, + prob(300);/obj/random/maintenance/engineering, + prob(300);/obj/random/maintenance/medical, + prob(300);/obj/random/maintenance/research, + prob(300);/obj/random/maintenance/security, + prob(300);/obj/random/maintenance/security, + prob(50);/obj/random/maintenance/morestuff, + prob(25);/obj/random/mainttoyloot, + prob(10);/obj/random/maintenance/foodstuff) + +/obj/random/maintenance/foodstuff + name = "random food or drink item" + desc = "This is a random maintenance item." + icon = 'icons/mob/randomlandmarks.dmi' + icon_state = "foodstuffs" + spawn_nothing_percentage = 0 + + +/obj/random/maintenance/foodstuff/item_to_spawn() + return pick(prob(100);/obj/random/snack, + prob(100);/obj/random/drinksoft, + prob(50);/obj/random/mre, + prob(10);/obj/random/donkpocketbox, + prob(1);/obj/random/meat) + +/obj/random/maintenance/morestuff + name = "random potentially useful things" + desc = "This is a random maintenance item." + icon = 'icons/mob/randomlandmarks.dmi' + icon_state = "trejur" + spawn_nothing_percentage = 0 + + +/obj/random/maintenance/misc/item_to_spawn() + return pick(prob(10);/obj/random/tool, + prob(1);/obj/random/toolbox, + prob(2);/obj/random/powercell, + prob(2);/obj/random/flashlight, + prob(1);/obj/random/pouch, + prob(1);/obj/random/thermalponcho, + prob(5);/obj/random/contraband, + prob(5);/obj/random/cargopod, + prob(1);/obj/item/weapon/flame/lighter/random, + prob(1);/obj/item/weapon/storage/wallet/random, + prob(1);/obj/random/cutout) diff --git a/code/game/objects/random/unidentified/medicine.dm b/code/game/objects/random/unidentified/medicine.dm index ffd134384a..3bd10ba4f2 100644 --- a/code/game/objects/random/unidentified/medicine.dm +++ b/code/game/objects/random/unidentified/medicine.dm @@ -32,7 +32,7 @@ much more likely to show up. This is done for several purposes; /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified, /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/healing_nanites/unidentified, /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified, - /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified, + /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bliss/unidentified, /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/expired/unidentified, /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified, /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified, @@ -108,7 +108,7 @@ much more likely to show up. This is done for several purposes; prob(5);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting/unidentified, prob(40);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/combat/unidentified, prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/stimm/unidentified, - prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/space_drugs/unidentified, + prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bliss/unidentified, prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/serotrotium/unidentified, prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/cryptobiolin/unidentified, prob(20);/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/mindbreaker/unidentified, diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index abd0665898..ac294a7531 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -128,9 +128,9 @@ new /obj/item/stack/rods(get_turf(src)) Destroy() -/obj/structure/catwalk/Crossed() +/obj/structure/catwalk/Crossed(atom/movable/AM as mob|obj) . = ..() - if(isliving(usr) && !usr.is_incorporeal()) + if(isliving(AM) && !AM.is_incorporeal()) playsound(src, pick('sound/effects/footstep/catwalk1.ogg', 'sound/effects/footstep/catwalk2.ogg', 'sound/effects/footstep/catwalk3.ogg', 'sound/effects/footstep/catwalk4.ogg', 'sound/effects/footstep/catwalk5.ogg'), 25, 1) /obj/effect/catwalk_plated diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm index 8d75646886..454a070cfe 100644 --- a/code/game/objects/structures/crates_lockers/__closets.dm +++ b/code/game/objects/structures/crates_lockers/__closets.dm @@ -8,10 +8,10 @@ w_class = ITEMSIZE_HUGE layer = UNDER_JUNK_LAYER blocks_emissive = EMISSIVE_BLOCK_GENERIC - + var/opened = 0 var/sealed = 0 - + var/seal_tool = /obj/item/weapon/weldingtool //Tool used to seal the closet, defaults to welder var/wall_mounted = 0 //never solid (You can always pass over it) var/health = 100 @@ -24,8 +24,8 @@ //then open it in a populated area to crash clients. var/storage_cost = 40 //How much space this closet takes up if it's stuffed in another closet - var/open_sound = 'sound/machines/click.ogg' - var/close_sound = 'sound/machines/click.ogg' + var/open_sound = 'sound/effects/closet_open.ogg' + var/close_sound = 'sound/effects/closet_close.ogg' var/store_misc = 1 //Chameleon item check var/store_items = 1 //Will the closet store items? @@ -141,7 +141,7 @@ dump_contents() opened = 1 - playsound(src, open_sound, 15, 1, -3) + playsound(src, open_sound, 50, 1, -3) if(initial(density)) density = !density animate_door() @@ -166,7 +166,7 @@ opened = 0 - playsound(src, close_sound, 15, 1, -3) + playsound(src, close_sound, 50, 1, -3) if(initial(density)) density = !density animate_door(TRUE) diff --git a/code/game/objects/structures/crates_lockers/closets/coffin.dm b/code/game/objects/structures/crates_lockers/closets/coffin.dm index 3865641552..e5a9c631a9 100644 --- a/code/game/objects/structures/crates_lockers/closets/coffin.dm +++ b/code/game/objects/structures/crates_lockers/closets/coffin.dm @@ -2,7 +2,7 @@ name = "coffin" desc = "It's a burial receptacle for the dearly departed." icon = 'icons/obj/closets/coffin.dmi' - + icon_state = "closed_unlocked" seal_tool = /obj/item/weapon/tool/screwdriver breakout_sound = 'sound/weapons/tablehit1.ogg' @@ -20,6 +20,8 @@ max_closets = 1 opened = 1 closet_appearance = null // Special icon for us + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' /obj/structure/closet/grave/attack_hand(mob/user as mob) if(opened) diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm index ca856f3ace..0e27bc9788 100644 --- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm +++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm @@ -4,11 +4,17 @@ icon = 'icons/obj/closets/bases/cabinet.dmi' closet_appearance = /decl/closet_appearance/cabinet + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + /obj/structure/closet/acloset name = "strange closet" desc = "It looks alien!" closet_appearance = /decl/closet_appearance/alien + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' + /obj/structure/closet/gimmick name = "administrative supply closet" desc = "It's a storage unit for things that have no right being here." diff --git a/code/game/objects/structures/crates_lockers/closets/l3closet.dm b/code/game/objects/structures/crates_lockers/closets/l3closet.dm index d9692abdc3..c592c3e69f 100644 --- a/code/game/objects/structures/crates_lockers/closets/l3closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/l3closet.dm @@ -49,7 +49,8 @@ /obj/structure/closet/l3closet/scientist/double starts_with = list( /obj/item/clothing/suit/bio_suit/scientist = 2, - /obj/item/clothing/head/bio_hood/scientist = 2) + /obj/item/clothing/head/bio_hood/scientist = 2, + /obj/item/weapon/storage/bag/xeno = 2) // VOREEdit, adding the xenobag to xenobio. /obj/structure/closet/l3closet/medical diff --git a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm index 448800fff5..78827adb08 100644 --- a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm +++ b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm @@ -243,6 +243,8 @@ desc = "It's wall-mounted storage unit for an AutoLok suit." icon = 'icons/obj/closets/bases/wall_double.dmi' closet_appearance = /decl/closet_appearance/wall_double/autolok + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' anchored = TRUE density = FALSE wall_mounted = 1 @@ -262,6 +264,8 @@ desc = "It's wall-mounted storage unit for an emergency suit." icon = 'icons/obj/closets/bases/wall.dmi' closet_appearance = /decl/closet_appearance/wall/emergency + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' anchored = TRUE density = FALSE wall_mounted = 1 diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm index 5e2eac9589..55832664cf 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm @@ -71,9 +71,10 @@ /obj/item/clothing/shoes/black, /obj/item/device/analyzer, /obj/item/weapon/storage/bag/ore, + /obj/item/weapon/storage/belt/miner, /obj/item/device/flashlight/lantern, /obj/item/weapon/shovel, - /obj/item/weapon/pickaxe, + /obj/item/weapon/pickaxe/drill, /obj/item/clothing/glasses/material, /obj/item/clothing/suit/storage/hooded/wintercoat/miner, /obj/item/clothing/shoes/boots/winter/mining, diff --git a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm index e1addc7b2f..63a5613c88 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/freezer.dm @@ -8,6 +8,9 @@ /obj/item/weapon/reagent_containers/food/condiment/spacespice = 2 ) + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' + /obj/structure/closet/secure_closet/freezer/kitchen/mining req_access = list() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index c55f51d00c..70272f8681 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -210,6 +210,9 @@ req_access = list(access_psychiatrist) closet_appearance = /decl/closet_appearance/cabinet/secure + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + starts_with = list( /obj/item/clothing/under/rank/psych, /obj/item/clothing/under/rank/psych/turtleneck, diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index bbcdd07d7b..4dcedfeeb0 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -31,6 +31,9 @@ /obj/structure/closet/secure_closet/personal/cabinet closet_appearance = /decl/closet_appearance/cabinet/secure + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + starts_with = list( /obj/item/weapon/storage/backpack/satchel/withwallet, /obj/item/device/radio/headset diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 19477d1090..883ac3d8f3 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -29,11 +29,9 @@ /obj/item/device/radio/headset/heads/hop, /obj/item/device/radio/headset/heads/hop/alt, /obj/item/weapon/storage/box/ids = 2, - ///obj/item/weapon/gun/energy/gun, //YW Edit, - /obj/item/weapon/gun/energy/gun/martin, //VOREStation Add, - /obj/item/weapon/storage/box/commandkeys, //VOREStation Add, - /obj/item/weapon/storage/box/servicekeys, //VOREStation Add, - ///obj/item/weapon/gun/projectile/sec/flash, //VOREStation Removal, + /obj/item/weapon/gun/energy/gun/compact, + /obj/item/weapon/storage/box/commandkeys, + /obj/item/weapon/storage/box/servicekeys, /obj/item/device/flash) /obj/structure/closet/secure_closet/hop2 @@ -240,6 +238,9 @@ req_access = list(access_forensics_lockers) closet_appearance = /decl/closet_appearance/cabinet/secure + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + starts_with = list( /obj/item/clothing/accessory/badge/holo/detective, /obj/item/clothing/gloves/forensic, //CHOMP Edit replaces black gloves diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 61a8fe6afd..aaf93580ff 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -97,7 +97,8 @@ starts_with = list( /obj/item/clothing/suit/fire/heavy, /obj/item/weapon/tank/oxygen/red, - /obj/item/weapon/extinguisher/atmo, + /obj/item/weapon/watertank/atmos, + /obj/item/device/flashlight, /obj/item/clothing/head/hardhat/firefighter/atmos) /* diff --git a/code/game/objects/structures/crates_lockers/closets/walllocker.dm b/code/game/objects/structures/crates_lockers/closets/walllocker.dm index 404037b4c6..f1949dfeb5 100644 --- a/code/game/objects/structures/crates_lockers/closets/walllocker.dm +++ b/code/game/objects/structures/crates_lockers/closets/walllocker.dm @@ -11,6 +11,9 @@ store_mobs = 0 wall_mounted = 1 + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' + //spawns 2 sets of breathmask, emergency oxy tank and crowbar /obj/structure/closet/walllocker/emerglocker @@ -92,6 +95,9 @@ plane = TURF_PLANE layer = ABOVE_TURF_LAYER + open_sound = 'sound/machines/click.ogg' + close_sound = 'sound/machines/click.ogg' + /obj/structure/closet/walllocker_double/north pixel_y = 32 dir = SOUTH diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 7cedd8a77d..b684024374 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -41,6 +41,9 @@ name = "detective wardrobe" closet_appearance = /decl/closet_appearance/cabinet + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + starts_with = list( /obj/item/clothing/head/det = 2, /obj/item/clothing/head/det/grey = 2, @@ -460,6 +463,9 @@ name = "site manager's wardrobe" closet_appearance = /decl/closet_appearance/cabinet + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + starts_with = list( /obj/item/weapon/storage/backpack/captain, /obj/item/clothing/suit/captunic, diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index eec6a8d892..45cb599429 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -10,6 +10,9 @@ var/points_per_crate = 5 var/rigged = 0 + open_sound = 'sound/effects/crate_open.ogg' + close_sound = 'sound/effects/crate_close.ogg' + /obj/structure/closet/crate/can_open() return 1 @@ -32,7 +35,7 @@ if(usr.stunned) return 2 - playsound(src, 'sound/machines/click.ogg', 15, 1, -3) + playsound(src, open_sound, 50, 1, -3) for(var/obj/O in src) O.forceMove(get_turf(src)) src.opened = 1 @@ -48,7 +51,7 @@ if(!src.can_close()) return 0 - playsound(src, 'sound/machines/click.ogg', 15, 1, -3) + playsound(src, close_sound, 50, 1, -3) var/itemcount = 0 for(var/obj/O in get_turf(src)) if(itemcount >= storage_capacity) @@ -698,3 +701,30 @@ starts_with = list( /obj/item/weapon/reagent_containers/spray/plantbgone = 2, /obj/item/weapon/material/minihoe) + +//Laundry Cart +/obj/structure/closet/crate/laundry + name = "Laundry Cart" + desc = "A cart with a large fabric bin on it used for transporting large amounts of clothes." + icon = 'icons/obj/closets/laundry.dmi' + closet_appearance = null + open_sound = 'sound/effects/rustle1.ogg' + close_sound = 'sound/effects/rustle2.ogg' + +//Wooden Crate +/obj/structure/closet/crate/wooden + name = "wooden crate" + desc = "A crate made from wood and lined with straw. Cheapest form of storage." + icon = 'icons/obj/closets/wooden.dmi' + closet_appearance = null + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' + +//Mining Cart +/obj/structure/closet/crate/miningcar + name = "mining cart" + desc = "A mining car. This one doesn't work on rails, but has to be dragged." + icon = 'icons/obj/closets/miningcar.dmi' + closet_appearance = null + open_sound = 'sound/effects/wooden_closet_open.ogg' + close_sound = 'sound/effects/wooden_closet_close.ogg' \ No newline at end of file diff --git a/code/game/objects/structures/flora/moretrees_vr.dm b/code/game/objects/structures/flora/moretrees_vr.dm index 57947139bb..c14cd7522c 100644 --- a/code/game/objects/structures/flora/moretrees_vr.dm +++ b/code/game/objects/structures/flora/moretrees_vr.dm @@ -4,8 +4,8 @@ base_state = "tree" product = /obj/item/stack/material/log product_amount = 20 - health = 2000 - max_health = 2000 + health = 400 + max_health = 400 pixel_x = -65 pixel_y = -8 layer = MOB_LAYER - 1 @@ -19,4 +19,14 @@ var/image/i = image('icons/obj/flora/moretrees_vr.dmi', "[icon_state]-b") i.plane = ABOVE_MOB_PLANE - add_overlay(i) \ No newline at end of file + add_overlay(i) + +/obj/structure/flora/tree/bigtree/stump() + if(is_stump) + return + + is_stump = TRUE + density = FALSE + icon_state = "[icon_state]_stump" + cut_overlays() + set_light(0) \ No newline at end of file diff --git a/code/game/objects/structures/ghost_pods/event_vr.dm b/code/game/objects/structures/ghost_pods/event_vr.dm index b7ae9a6d5e..b547f91ad4 100644 --- a/code/game/objects/structures/ghost_pods/event_vr.dm +++ b/code/game/objects/structures/ghost_pods/event_vr.dm @@ -70,7 +70,9 @@ return choice = tgui_input_list(M, "What type of predator do you want to play as?", "Maintpred Choice", possible_mobs) if(!choice) - randomize = TRUE +// randomize = TRUE //CHOMP remove FUCK OFF. When I press cancel I expect to cancel. + used = FALSE //CHOMP add 200 IQ + busy = FALSE //CHOMP add 201 IQ break if(choice) diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 9971722f11..ad6e3a6ebc 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -357,3 +357,35 @@ /obj/structure/bed/alien/attackby(obj/item/weapon/W, mob/user) return // No deconning. + +/* + * Dirty Mattress + */ +/obj/structure/dirtybed + name = "dirty mattress" + desc = "A stained matress. Guess it's better than sleeping on the floor." + icon = 'icons/obj/furniture.dmi' + icon_state = "dirtybed" + pressure_resistance = 15 + anchored = TRUE + can_buckle = TRUE + buckle_dir = SOUTH + buckle_lying = 1 + +/obj/structure/dirtybed/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(W.is_wrench()) + playsound(src, W.usesound, 100, 1) + if(anchored) + user.visible_message("[user] begins unsecuring \the [src] from the floor.", "You start unsecuring \the [src] from the floor.") + else + user.visible_message("[user] begins securing \the [src] to the floor.", "You start securing \the [src] to the floor.") + + if(do_after(user, 20 * W.toolspeed)) + if(!src) return + to_chat(user, "You [anchored? "un" : ""]secured \the [src]!") + anchored = !anchored + return + + if(!anchored) + to_chat(user," The bed isn't secured.") + return \ No newline at end of file diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 3a1bf84386..1af54a1b4e 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -3,7 +3,7 @@ /obj/structure/dispenser name = "tank storage unit" desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten phoron tanks." - icon = 'icons/obj/objects.dmi' + icon = 'icons/obj/objects_vr.dmi' icon_state = "dispenser" density = TRUE anchored = TRUE diff --git a/code/game/objects/structures/trash_pile_vr.dm b/code/game/objects/structures/trash_pile_vr.dm index a363f877cb..bf73c6f7ec 100644 --- a/code/game/objects/structures/trash_pile_vr.dm +++ b/code/game/objects/structures/trash_pile_vr.dm @@ -291,10 +291,12 @@ /obj/structure/mob_spawner/mouse_nest name = "trash" - desc = "A small heap of trash, perfect for mice to nest in." + desc = "A small heap of trash, perfect for mice and other pests to nest in." icon = 'icons/obj/trash_piles.dmi' icon_state = "randompile" - spawn_types = list(/mob/living/simple_mob/animal/passive/mouse) + spawn_types = list( + /mob/living/simple_mob/animal/passive/mouse= 100, + /mob/living/simple_mob/animal/passive/cockroach = 25) simultaneous_spawns = 1 destructible = 1 spawn_delay = 1 HOUR diff --git a/code/game/objects/structures/under_wardrobe.dm b/code/game/objects/structures/under_wardrobe.dm index 5da83511c6..5849085b1d 100644 --- a/code/game/objects/structures/under_wardrobe.dm +++ b/code/game/objects/structures/under_wardrobe.dm @@ -1,5 +1,5 @@ /obj/structure/undies_wardrobe - name = "underwear wardrobe" + name = "underwear dresser" desc = "Holds item of clothing you shouldn't be showing off in the hallways." icon = 'icons/obj/closets/undies_wardrobe.dmi' icon_state = "wardrobe" diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 5b9af521c5..b959e68f69 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -154,8 +154,8 @@ if(M.slip("the [floor_type] floor", slip_stun)) for(var/i = 1 to slip_dist) - if(M.slip_vore_in_progress) //CHOMPEdit - break //CHOMPEdit + if(isbelly(M.loc)) //VOREEdit, Stop the slip if we're in a belly. Inspired by a chompedit, cleaned it up with isbelly instead of a variable since the var was resetting too fast. + return step(M, M.dir) sleep(1) else diff --git a/code/game/turfs/simulated/floor_types_vr.dm b/code/game/turfs/simulated/floor_types_vr.dm index ae0ca1292e..e6dfafa9ac 100644 --- a/code/game/turfs/simulated/floor_types_vr.dm +++ b/code/game/turfs/simulated/floor_types_vr.dm @@ -20,13 +20,13 @@ /turf/simulated/floor/flesh name = "flesh" desc = "This slick flesh ripples and squishes under your touch" - icon_state = "flesh-floor" + icon_state = "flesh_floor" icon = 'icons/turf/stomach_vr.dmi' /turf/simulated/floor/flesh/colour name = "flesh" desc = "This slick flesh ripples and squishes under your touch" - icon_state = "colorable-floor" + icon_state = "c_flesh_floor" icon = 'icons/turf/stomach_vr.dmi' /turf/simulated/floor/flesh/attackby() diff --git a/code/game/turfs/simulated/outdoors/outdoors_vr.dm b/code/game/turfs/simulated/outdoors/outdoors_vr.dm index 61a759ca83..48972b9f1e 100644 --- a/code/game/turfs/simulated/outdoors/outdoors_vr.dm +++ b/code/game/turfs/simulated/outdoors/outdoors_vr.dm @@ -56,10 +56,10 @@ /turf/simulated/floor/outdoors/newdirt_nograss/Initialize(mapload) var/possibledirts = list( "dirt0" = 200, - "dirt3" = 20, - "dirt4" = 3, - "dirt5" = 3, - "dirt6" = 1 + "dirt6" = 20, + "dirt7" = 3, + "dirt8" = 3, + "dirt9" = 1 ) flooring_override = pickweight(possibledirts) return ..() @@ -69,7 +69,7 @@ desc = "Concrete shaped into a path!" icon = 'icons/turf/outdoors_vr.dmi' icon_state = "sidewalk" - edge_blending_priority = 1 + edge_blending_priority = -1 movement_cost = -0.5 initial_flooring = /decl/flooring/outdoors/sidewalk can_dirty = TRUE @@ -79,12 +79,31 @@ desc = "Concrete shaped into a path!" icon = 'icons/turf/outdoors_vr.dmi' icon_base = "sidewalk" + has_damage_range = 2 + damage_temperature = T0C+1400 + flags = TURF_REMOVE_CROWBAR | TURF_CAN_BREAK | TURF_CAN_BURN + build_type = /obj/item/stack/tile/floor/sidewalk + can_paint = 1 + can_engrave = FALSE + footstep_sounds = list("human" = list( 'sound/effects/footstep/LightStone1.ogg', 'sound/effects/footstep/LightStone2.ogg', 'sound/effects/footstep/LightStone3.ogg', 'sound/effects/footstep/LightStone4.ogg',)) +/obj/item/stack/tile/floor/sidewalk + name = "sidewalk tile" + singular_name = "floor tile" + desc = "A stone tile fit for covering a section of floor." + icon_state = "tile" + force = 6.0 + matter = list(DEFAULT_WALL_MATERIAL = SHEET_MATERIAL_AMOUNT / 4) + throwforce = 15.0 + throw_speed = 5 + throw_range = 20 + no_variants = FALSE + /turf/simulated/floor/outdoors/sidewalk/Initialize(mapload) var/possibledirts = list( "[initial(icon_state)]" = 150, @@ -104,6 +123,21 @@ /turf/simulated/floor/outdoors/sidewalk/side icon_state = "side-walk" + initial_flooring = /decl/flooring/outdoors/sidewalk/side + + +/decl/flooring/outdoors/sidewalk/side + icon_base = "sidewalk" + build_type = /obj/item/stack/tile/floor/sidewalk/side + +/obj/item/stack/tile/floor/sidewalk/side /turf/simulated/floor/outdoors/sidewalk/slab icon_state = "slab" + initial_flooring = /decl/flooring/outdoors/sidewalk/slab + +/decl/flooring/outdoors/sidewalk/slab + icon_base = "slab" + build_type = /obj/item/stack/tile/floor/sidewalk/slab + +/obj/item/stack/tile/floor/sidewalk/slab diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 11f0b9d1cc..8c6eb32ae3 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -131,9 +131,12 @@ user.setClickCooldown(user.get_attack_speed(W)) +/* +//As with the floors, only this time it works AND tries pushing the wall after it's done. if(!construction_stage && user.a_intent == I_HELP) if(try_graffiti(user,W)) return +*/ if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 9a9a0457f4..e015cbd7db 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -714,10 +714,16 @@ var/datum/announcement/minor/admin_min_announcer = new if(sender) //They put a sender sender = sanitize(sender, 75, extra = 0) var/message = input(usr, "Message content (max 500):", "Contents", "This is a test of the announcement system.") as null|message - + var/msgverb = input(usr, "Name of verb (Such as 'states', 'says', 'asks', etc):", "Verb", "says") as null|text //VOREStation Addition if(message) //They put a message message = sanitize(message, 500, extra = 0) - global_announcer.autosay("[message]", "[sender]", "[channel == "Common" ? null : channel]") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set. + //VOREStation Edit Start + if(msgverb) + msgverb = sanitize(msgverb, 50, extra = 0) + else + msgverb = "states" + global_announcer.autosay("[message]", "[sender]", "[channel == "Common" ? null : channel]", states = msgverb) //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set. + //VOREStation Edit End log_admin("Intercom: [key_name(usr)] : [sender]:[message]") feedback_add_details("admin_verb","IN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -802,7 +808,7 @@ var/datum/announcement/minor/admin_min_announcer = new var/this_sender = decomposed[i] var/this_message = decomposed[++i] var/this_wait = decomposed[++i] - global_announcer.autosay("[this_message]", "[this_sender]", "[channel == "Common" ? null : channel]") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set. + global_announcer.autosay("[this_message]", "[this_sender]", "[channel == "Common" ? null : channel]", "says") //Common is a weird case, as it's not a "channel", it's just talking into a radio without a channel set. //VOREStation Edit sleep(this_wait SECONDS) /datum/admins/proc/toggleooc() diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 5c1841c3dd..661a4874b4 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -158,7 +158,8 @@ var/list/admin_verbs_fun = list( /client/proc/smite_vr, //VOREStation Add, /client/proc/admin_lightning_strike, /client/proc/resize, //VOREStation Add, - /client/proc/cmd_admin_droppod_deploy + /client/proc/cmd_admin_droppod_deploy, + /client/proc/adminorbit //VOREStation Add, ) var/list/admin_verbs_spawn = list( @@ -261,7 +262,9 @@ var/list/admin_verbs_debug = list( /datum/admins/proc/change_time, /client/proc/admin_give_modifier, /client/proc/simple_DPS, - /datum/admins/proc/view_feedback + /datum/admins/proc/view_feedback, + /datum/admins/proc/quick_nif, //CHOMPStation Add, + /datum/admins/proc/quick_authentic_nif //CHOMPStation add ) var/list/admin_verbs_paranoid_debug = list( @@ -395,7 +398,8 @@ var/list/admin_verbs_mod = list( /client/proc/getserverlog, //allows us to fetch server logs (diary) for other days, /datum/admins/proc/view_persistent_data, /datum/admins/proc/view_txt_log, //shows the server log (diary) for today, - /datum/admins/proc/view_atk_log //shows the server combat-log, doesn't do anything presently, + /datum/admins/proc/view_atk_log, //shows the server combat-log, doesn't do anything presently, + /datum/admins/proc/quick_nif //CHOMPStation Add, ) var/list/admin_verbs_event_manager = list( @@ -538,7 +542,9 @@ var/list/admin_verbs_event_manager = list( /client/proc/cmd_admin_delete, //delete an instance/object/mob/etc, /client/proc/cmd_debug_del_all, /client/proc/toggle_random_events, - /client/proc/modify_server_news + /client/proc/modify_server_news, + /datum/admins/proc/quick_nif, //CHOMPStation Add, + /datum/admins/proc/quick_authentic_nif //CHOMPStation add ) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e9d63621b0..3207e293a5 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -53,6 +53,7 @@ var/mob/body = mob var/mob/observer/dead/ghost = body.ghostize(1) ghost.admin_ghosted = 1 + log_and_message_admins("[key_name(src)] admin-ghosted.") // CHOMPEdit - Add logging. if(body) body.teleop = ghost if(!body.key) diff --git a/code/modules/admin/admin_verbs_vr.dm b/code/modules/admin/admin_verbs_vr.dm new file mode 100644 index 0000000000..6d92fde40b --- /dev/null +++ b/code/modules/admin/admin_verbs_vr.dm @@ -0,0 +1,56 @@ +/client/proc/adminorbit() + set category = "Fun" + set name = "Orbit Things" + set desc = "Makes something orbit around something else." + set popup_menu = FALSE + + if(!check_rights(R_FUN)) + return + + var/center + var/atom/movable/orbiter + var/input + + if(holder.marked_datum) + input = tgui_alert(usr, "You have \n[holder.marked_datum] marked, should this be the center of the orbit, or the orbiter?", "Orbit", list("Center", "Orbiter", "Neither")) + switch(input) + if("Center") + center = holder.marked_datum + if("Orbiter") + orbiter = holder.marked_datum + var/list/possible_things = list() + for(var/T as mob in view(view)) //Let's do mobs before objects + if(ismob(T)) + possible_things |= T + for(var/T as obj in view(view)) + if(isobj(T)) + possible_things |= T + if(!center) + center = input(usr, "What should act as the center of the orbit?", "Center") as anything in possible_things + possible_things -= center + if(!orbiter) + orbiter = input(usr, "What should act as the orbiter of the orbit?", "Orbiter") as anything in possible_things + if(!center || !orbiter) + to_chat(usr, "A center of orbit and an orbiter must be configured. You can also do this by marking a target.") + return + if(center == orbiter) + to_chat(usr, "The center of the orbit cannot also be the orbiter.") + return + if(isturf(orbiter)) + to_chat(usr, "The orbiter cannot be a turf. It can only be used as a center.") + return + var/distance = input(usr, "How large will their orbit radius be? (In pixels. 32 is 'near around a character)", "Orbit Radius", 32) as num|null + var/speed = input(usr, "How fast will they orbit (negative numbers spin clockwise)", "Orbit Speed", 20) as num|null + var/segments = input(usr, "How many segments will they have in their orbit? (3 is a triangle, 36 is a circle, etc)", "Orbit Segments", 36) as num|null + var/clock = FALSE + if(!distance) + distance = 32 + if(!speed) + speed = 20 + else if (speed < 0) + clock = TRUE + speed *= -1 + if(!segments) + segments = 36 + if(tgui_alert(usr, "\The [orbiter] will orbit around [center]. Is this okay?", "Confirm Orbit", list("Yes", "No")) == "Yes") + orbiter.orbit(center, distance, clock, speed, segments) diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm index 95442b0f82..c108bbf14b 100644 --- a/code/modules/admin/verbs/adminjump.dm +++ b/code/modules/admin/verbs/adminjump.dm @@ -10,18 +10,18 @@ set category = "Admin" if(!check_rights(R_ADMIN|R_MOD|R_DEBUG|R_EVENT)) return - + if(!config.allow_admin_jump) tgui_alert_async(usr, "Admin jumping disabled") return var/area/A - + if(areaname) A = return_sorted_areas()[areaname] else A = tgui_input_list(usr, "Pick an area:", "Jump to Area", return_sorted_areas()) - + if(!A) return @@ -62,7 +62,7 @@ if(!config.allow_admin_jump) tgui_alert_async(usr, "Admin jumping disabled") return - + if(!M) M = tgui_input_list(usr, "Pick a mob:", "Jump to Mob", mob_list) if(!M) @@ -78,7 +78,7 @@ feedback_add_details("admin_verb","JM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! else to_chat(A, "This mob is not located in the game world.") - + /client/proc/jumptocoord(tx as num, ty as num, tz as num) set category = "Admin" set name = "Jump to Coordinate" @@ -94,7 +94,7 @@ if(!T) to_chat(usr, "Those coordinates are outside the boundaries of the map.") return - A.forceMove(T) + A.forceMove(T) feedback_add_details("admin_verb","JC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! message_admins("[key_name_admin(usr)] jumped to coordinates [tx], [ty], [tz]") @@ -124,15 +124,17 @@ else tgui_alert_async(usr, "Admin jumping disabled") -/client/proc/Getmob() +/client/proc/Getmob(mob/living/M as null|anything in mob_list) //VOREStation Edit set category = "Admin" set name = "Get Mob" set desc = "Mob to teleport" + set popup_menu = TRUE //VOREStation Edit if(!check_rights(R_ADMIN|R_MOD|R_DEBUG|R_EVENT)) return if(config.allow_admin_jump) - var/mob/M = tgui_input_list(usr, "Pick a mob:", "Get Mob", mob_list) + if(!M) //VOREStation Edit + M = tgui_input_list(usr, "Pick a mob:", "Get Mob", mob_list) //VOREStation Edit if(!M) return log_admin("[key_name(usr)] jumped [key_name(M)] to them") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 8e50e0437d..064a950ddb 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -9,6 +9,8 @@ return for(var/obj/item/W in M) + if(istype(W, /obj/item/weapon/implant/backup) || istype(W, /obj/item/device/nif)) //VOREStation Edit - There's basically no reason to remove either of these + continue //VOREStation Edit M.drop_from_inventory(W) log_admin("[key_name(usr)] made [key_name(M)] drop everything!") @@ -881,7 +883,7 @@ Traitors and the like can also be revived with the previous role mostly intact. mob.set_viewsize(view) log_admin("[key_name(usr)] changed their view range to [view].") - //message_admins("[key_name_admin(usr)] changed their view range to [view].", 1) //why? removed by order of XSI + message_admins("[key_name_admin(usr)] changed their view range to [view].", 1) //CHOMPEdit - Uncommented this. feedback_add_details("admin_verb","CVRA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/ai/ai_holder_subtypes/slime_xenobio_ai.dm b/code/modules/ai/ai_holder_subtypes/slime_xenobio_ai.dm index f6e311ad30..6986f5e23c 100644 --- a/code/modules/ai/ai_holder_subtypes/slime_xenobio_ai.dm +++ b/code/modules/ai/ai_holder_subtypes/slime_xenobio_ai.dm @@ -1,292 +1,310 @@ -// Specialized AI for slime simplemobs. -// Unlike the parent AI code, this will probably break a lot of things if you put it on something that isn't /mob/living/simple_mob/slime/xenobio - -/datum/ai_holder/simple_mob/xenobio_slime - hostile = TRUE - cooperative = TRUE - firing_lanes = TRUE - mauling = TRUE // They need it to get the most out of monkeys. - var/rabid = FALSE // Will attack regardless of discipline. - var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory. - var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go rabid. - var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slower, potentially making it not decay at all. - - var/always_stun = FALSE // If true, the slime will elect to attempt to permastun the target. - - var/last_discipline_decay = null // Last world.time discipline was reduced from decay. - var/discipline_decay_time = 5 SECONDS // Earliest that one discipline can decay. - - var/list/grudges = list() // List of Prometheans who are jerks. - -/datum/ai_holder/simple_mob/xenobio_slime/Destroy() - grudges.Cut() - ..() - -/datum/ai_holder/simple_mob/xenobio_slime/sapphire - always_stun = TRUE // They know that stuns are godly. - intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death. - -/datum/ai_holder/simple_mob/xenobio_slime/light_pink - discipline = 10 - obedience = 10 - -/datum/ai_holder/simple_mob/xenobio_slime/passive/New() // For Kendrick. - ..() - pacify() - -/datum/ai_holder/simple_mob/xenobio_slime/New() - ..() - ASSERT(istype(holder, /mob/living/simple_mob/slime/xenobio)) - -// Checks if disciplining the slime would be 'justified' right now. -/datum/ai_holder/simple_mob/xenobio_slime/proc/is_justified_to_discipline() - ai_log("xenobio_slime/is_justified_to_discipline() : Entered.", AI_LOG_TRACE) - if(!can_act()) - ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we cannot act. Exiting.", AI_LOG_DEBUG) - return FALSE // The slime considers it abuse if they get stunned while already stunned. - if(rabid) - ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we're rabid. Exiting.", AI_LOG_TRACE) - return TRUE - if(target && can_attack(target)) - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(istype(H.species, /datum/species/monkey)) - ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we're targeting a monkey. Exiting.", AI_LOG_DEBUG) - return FALSE // Attacking monkeys is okay. - ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we are targeting a non-monkey. Exiting.", AI_LOG_TRACE) - return TRUE // Otherwise attacking other things is bad. - ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we are not targeting anything. Exiting.", AI_LOG_DEBUG) - return FALSE // Not attacking anything. - -/datum/ai_holder/simple_mob/xenobio_slime/proc/can_command(mob/living/commander) - if(rabid) - return FALSE - if(!hostile) - return SLIME_COMMAND_OBEY -// if(commander in friends) -// return SLIME_COMMAND_FRIEND - if(holder.IIsAlly(commander)) - return SLIME_COMMAND_FACTION - if(discipline > resentment && obedience >= 5) - return SLIME_COMMAND_OBEY - return FALSE - -/datum/ai_holder/simple_mob/xenobio_slime/proc/adjust_discipline(amount, silent) - var/mob/living/simple_mob/slime/xenobio/my_slime = holder - if(amount > 0) - if(rabid) - return - var/justified = my_slime.is_justified_to_discipline() // This will also consider the AI-side of that proc. - remove_target() // Stop attacking. - - if(justified) - obedience++ - if(!silent) - holder.say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy...")) - else - if(prob(resentment * 20)) - enrage() - holder.say(pick("Evil...", "Kill...", "Tyrant...")) - else - if(!silent) - holder.say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo...")) - resentment++ // Done after check so first time will never enrage. - - discipline = between(0, discipline + amount, 10) - my_slime.update_mood() - -// This slime always enrages if disciplined. -/datum/ai_holder/simple_mob/xenobio_slime/red/adjust_discipline(amount, silent) - if(amount > 0 && !rabid) - holder.say("Grrr...") - holder.add_modifier(/datum/modifier/berserk, 30 SECONDS) - enrage() - -/datum/ai_holder/simple_mob/xenobio_slime/handle_special_strategical() - discipline_decay() - -// Handles decay of discipline. -/datum/ai_holder/simple_mob/xenobio_slime/proc/discipline_decay() - if(discipline > 0 && last_discipline_decay + discipline_decay_time < world.time) - if(!prob(75 + (obedience * 5))) - adjust_discipline(-1) - last_discipline_decay = world.time - -/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic() - evolve_and_reproduce() - -// Hit the correct verbs to keep the slime species going. -/datum/ai_holder/simple_mob/xenobio_slime/proc/evolve_and_reproduce() - var/mob/living/simple_mob/slime/xenobio/my_slime = holder - if(my_slime.amount_grown >= 10) - // Press the correct verb when we can. - if(my_slime.is_adult) - my_slime.reproduce() // Splits into four new baby slimes. - else - my_slime.evolve() // Turns our holder into an adult slime. - - -// Called when pushed too far (or a red slime core was used). -/datum/ai_holder/simple_mob/xenobio_slime/proc/enrage() - var/mob/living/simple_mob/slime/xenobio/my_slime = holder - if(my_slime.harmless) - return - rabid = TRUE - my_slime.update_mood() - my_slime.visible_message(span("danger", "\The [my_slime] enrages!")) - -// Called when using a pacification agent (or it's Kendrick being initalized). -/datum/ai_holder/simple_mob/xenobio_slime/proc/pacify() - remove_target() // So it stops trying to kill them. - rabid = FALSE - hostile = FALSE - retaliate = FALSE - cooperative = FALSE - holder.a_intent = I_HELP - -// The holder's attack changes based on intent. This lets the AI choose what effect is desired. -/datum/ai_holder/simple_mob/xenobio_slime/pre_melee_attack(atom/A) - if(istype(A, /mob/living)) - var/mob/living/L = A - var/mob/living/simple_mob/slime/xenobio/my_slime = holder - - if( (!L.lying && prob(30 + (my_slime.power_charge * 7) ) || (!L.lying && always_stun) )) - my_slime.a_intent = I_DISARM // Stun them first. - else if(my_slime.can_consume(L) && L.lying) - my_slime.a_intent = I_GRAB // Then eat them. - else - my_slime.a_intent = I_HURT // Otherwise robust them. - -/datum/ai_holder/simple_mob/xenobio_slime/closest_distance(atom/movable/AM) - if(istype(AM, /mob/living)) - var/mob/living/L = AM - if(ishuman(L)) - var/mob/living/carbon/human/H = L - if(istype(H.species, /datum/species/monkey)) - return 1 // Otherwise ranged slimes will eat a lot less often. - if(L.stat >= UNCONSCIOUS) - return 1 // Melee (eat) the target if dead/dying, don't shoot it. - return ..() - -/datum/ai_holder/simple_mob/xenobio_slime/can_attack(atom/movable/AM, var/vision_required = TRUE) - . = ..() - if(.) // Do some additional checks because we have Special Code(tm). - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too. - return TRUE // Monkeys are always food (sorry Pun Pun). - else if(H.species && H.species.name == SPECIES_PROMETHEAN) // Prometheans are always our friends. - if(!(H in grudges)) // Unless they're an ass. - return FALSE - if(discipline && !rabid) - holder.a_intent = I_HELP - return FALSE // We're a good slime. - -/datum/ai_holder/simple_mob/xenobio_slime/react_to_attack(atom/movable/attacker) - . = ..(attacker) - - if(ishuman(attacker)) - var/mob/living/carbon/human/H = attacker - if(H.species && H.species.name == SPECIES_PROMETHEAN) // They're a jerk. - grudges |= H - -// Commands, reactions, etc -/datum/ai_holder/simple_mob/xenobio_slime/on_hear_say(mob/living/speaker, message) - ai_log("xenobio_slime/on_hear_say([speaker], [message]) : Entered.", AI_LOG_DEBUG) - var/mob/living/simple_mob/slime/xenobio/my_slime = holder - - if((findtext(message, num2text(my_slime.number)) || findtext(message, my_slime.name) || findtext(message, "slimes"))) // Talking to us. - - // First, make sure it's actually a player saying something and not an AI, or else we risk infinite loops. - if(!speaker.client) - return - - // Are all slimes being referred to? - // var/mass_order = FALSE - // if(findtext(message, "slimes")) - // mass_order = TRUE - - // Say hello back. - if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings")) - delayed_say(pick("Hello...", "Hi..."), speaker) - - // Follow request. - if(findtext(message, "follow") || findtext(message, "come with me")) - if(!can_command(speaker)) - delayed_say(pick("No...", "I won't follow..."), speaker) - return - - delayed_say("Yes... I follow \the [speaker]...", speaker) - set_follow(speaker) - - // Squish request. - if(findtext(message , "squish")) - if(!can_command(speaker)) - delayed_say("No...", speaker) - return - - spawn(rand(1 SECOND, 2 SECONDS)) - if(!src || !holder || !can_act()) // We might've died/got deleted/etc in the meantime. - return - my_slime.squish() - - - // Stop request. - if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease")) - if(my_slime.victim) // We're being asked to stop eatting someone. - if(!can_command(speaker) || !is_justified_to_discipline()) - delayed_say("No...", speaker) - return - else - delayed_say("Fine...", speaker) - adjust_discipline(1, TRUE) - my_slime.stop_consumption() - - if(target) // We're being asked to stop chasing someone. - if(!can_command(speaker) || !is_justified_to_discipline()) - delayed_say("No...", speaker) - return - else - delayed_say("Fine...", speaker) - adjust_discipline(1, TRUE) // This must come before losing the target or it will be unjustified. - remove_target() - - - if(leader) // We're being asked to stop following someone. - if(can_command(speaker) == SLIME_COMMAND_FRIEND || leader == speaker) - delayed_say("Yes... I'll stop...", speaker) - lose_follow() - else - delayed_say("No... I'll keep following \the [leader]...", speaker) - - /* // Commented out since its mostly useless now due to slimes refusing to attack if it would make them naughty. - // Murder request - if(findtext(message, "harm") || findtext(message, "attack") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume") || findtext(message, "absorb")) - if(can_command(speaker) < SLIME_COMMAND_FACTION) - delayed_say("No...", speaker) - return - - for(var/mob/living/L in view(7, my_slime) - list(my_slime, speaker)) - if(L == src) - continue // Don't target ourselves. - var/list/valid_names = splittext(L.name, " ") // Should output list("John", "Doe") as an example. - for(var/line in valid_names) // Check each part of someone's name. - if(findtext(message, lowertext(line))) // If part of someone's name is in the command, the slime targets them if allowed to. - if(!(mass_order && line == "slime")) //don't think random other slimes are target - if(can_attack(L)) - delayed_say("Okay... I attack \the [L]...", speaker) - give_target(L) - return - else - delayed_say("No... I won't attack \the [L].", speaker) - return - - // If we're here, it couldn't find anyone with that name. - delayed_say("No... I don't know who to attack...", speaker) - */ - ai_log("xenobio_slime/on_hear_say() : Exited.", AI_LOG_DEBUG) - -/datum/ai_holder/simple_mob/xenobio_slime/can_violently_breakthrough() - if(discipline && !rabid) // Good slimes don't shatter the windows because their buddy in an adjacent cell decided to piss off Slimesky. - return FALSE - return ..() +// Specialized AI for slime simplemobs. +// Unlike the parent AI code, this will probably break a lot of things if you put it on something that isn't /mob/living/simple_mob/slime/xenobio + +/datum/ai_holder/simple_mob/xenobio_slime + hostile = TRUE + cooperative = TRUE + firing_lanes = TRUE + mauling = TRUE // They need it to get the most out of monkeys. + var/rabid = FALSE // Will attack regardless of discipline. + var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory. + var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go rabid. + var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slower, potentially making it not decay at all. + + var/always_stun = FALSE // If true, the slime will elect to attempt to permastun the target. + + var/last_discipline_decay = null // Last world.time discipline was reduced from decay. + var/discipline_decay_time = 5 SECONDS // Earliest that one discipline can decay. + + var/list/grudges = list() // List of Prometheans who are jerks. + +/datum/ai_holder/simple_mob/xenobio_slime/Destroy() + grudges.Cut() + ..() + +/datum/ai_holder/simple_mob/xenobio_slime/sapphire + always_stun = TRUE // They know that stuns are godly. + intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death. + +/datum/ai_holder/simple_mob/xenobio_slime/light_pink + discipline = 10 + obedience = 10 + +/datum/ai_holder/simple_mob/xenobio_slime/passive/New() // For Kendrick. + ..() + pacify() + +/datum/ai_holder/simple_mob/xenobio_slime/New() + ..() + ASSERT(istype(holder, /mob/living/simple_mob/slime/xenobio)) + +// Checks if disciplining the slime would be 'justified' right now. +/datum/ai_holder/simple_mob/xenobio_slime/proc/is_justified_to_discipline() + ai_log("xenobio_slime/is_justified_to_discipline() : Entered.", AI_LOG_TRACE) + if(!can_act()) + ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we cannot act. Exiting.", AI_LOG_DEBUG) + return FALSE // The slime considers it abuse if they get stunned while already stunned. + if(rabid) + ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we're rabid. Exiting.", AI_LOG_TRACE) + return TRUE + if(target && can_attack(target)) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(istype(H.species, /datum/species/monkey)) + ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we're targeting a monkey. Exiting.", AI_LOG_DEBUG) + return FALSE // Attacking monkeys is okay. + ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we are targeting a non-monkey. Exiting.", AI_LOG_TRACE) + return TRUE // Otherwise attacking other things is bad. + ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we are not targeting anything. Exiting.", AI_LOG_DEBUG) + return FALSE // Not attacking anything. + +/datum/ai_holder/simple_mob/xenobio_slime/proc/can_command(mob/living/commander) + if(rabid) + return FALSE + if(!hostile) + return SLIME_COMMAND_OBEY +// if(commander in friends) +// return SLIME_COMMAND_FRIEND + if(holder.IIsAlly(commander)) + return SLIME_COMMAND_FACTION + if(discipline > resentment && obedience >= 5) + return SLIME_COMMAND_OBEY + return FALSE + +/datum/ai_holder/simple_mob/xenobio_slime/proc/adjust_discipline(amount, silent) + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + if(amount > 0) + if(rabid) + return + if(my_slime.untamable) + holder.say("Grrr...") + holder.add_modifier(/datum/modifier/berserk, 30 SECONDS) + enrage() + var/justified = my_slime.is_justified_to_discipline() // This will also consider the AI-side of that proc. + remove_target() // Stop attacking. + + if(justified) + obedience++ + if(!silent) + holder.say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy...")) + else + if(prob(resentment * 20)) + enrage() + holder.say(pick("Evil...", "Kill...", "Tyrant...")) + else + if(!silent) + holder.say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo...")) + resentment++ // Done after check so first time will never enrage. + + discipline = between(0, discipline + amount, 10) + my_slime.update_mood() + +/datum/ai_holder/simple_mob/xenobio_slime/handle_special_strategical() + discipline_decay() + evolve_and_reproduce() + +/datum/ai_holder/simple_mob/xenobio_slime/request_help() + if(target) + if(istype(target, /mob/living/simple_mob/slime/xenobio)) //Don't call reinforcements for internal disputes + return + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + if(istype(H.species, /datum/species/monkey)) //Or for food + return + ..() + +// Handles decay of discipline. +/datum/ai_holder/simple_mob/xenobio_slime/proc/discipline_decay() + if(discipline > 0 && last_discipline_decay + discipline_decay_time < world.time) + if(!prob(75 + (obedience * 5))) + adjust_discipline(-1) + last_discipline_decay = world.time + +/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic() + evolve_and_reproduce() + +// Hit the correct verbs to keep the slime species going. +/datum/ai_holder/simple_mob/xenobio_slime/proc/evolve_and_reproduce() + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + if(my_slime.amount_grown >= 10) + // Press the correct verb when we can. + if(my_slime.is_adult) + my_slime.reproduce() // Splits into four new baby slimes. + else + my_slime.evolve() // Turns our holder into an adult slime. + + +// Called when pushed too far (or a red slime core was used). +/datum/ai_holder/simple_mob/xenobio_slime/proc/enrage() + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + if(my_slime.harmless) + return + rabid = TRUE + my_slime.update_mood() + my_slime.visible_message(span("danger", "\The [my_slime] enrages!")) + +// Called to relax from being rabid (when blue slime core was used). +/datum/ai_holder/simple_mob/xenobio_slime/proc/relax() + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + if(my_slime.harmless) + return + if(rabid) + rabid = FALSE + my_slime.update_mood() + my_slime.visible_message(span("danger", "\The [my_slime] calms down.")) + +// Called when using a pacification agent (or it's Kendrick being initalized). +/datum/ai_holder/simple_mob/xenobio_slime/proc/pacify() + remove_target() // So it stops trying to kill them. + rabid = FALSE + hostile = FALSE + retaliate = FALSE + cooperative = FALSE + holder.a_intent = I_HELP + +// The holder's attack changes based on intent. This lets the AI choose what effect is desired. +/datum/ai_holder/simple_mob/xenobio_slime/pre_melee_attack(atom/A) + if(istype(A, /mob/living)) + var/mob/living/L = A + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + + if( (!L.lying && prob(30 + (my_slime.power_charge * 7) ) || (!L.lying && always_stun) )) + my_slime.a_intent = I_DISARM // Stun them first. + else if(my_slime.can_consume(L) && L.lying) + my_slime.a_intent = I_GRAB // Then eat them. + else + my_slime.a_intent = I_HURT // Otherwise robust them. + +/datum/ai_holder/simple_mob/xenobio_slime/closest_distance(atom/movable/AM) + if(istype(AM, /mob/living)) + var/mob/living/L = AM + if(ishuman(L)) + var/mob/living/carbon/human/H = L + if(istype(H.species, /datum/species/monkey)) + return 1 // Otherwise ranged slimes will eat a lot less often. + if(L.stat >= UNCONSCIOUS) + return 1 // Melee (eat) the target if dead/dying, don't shoot it. + return ..() + +/datum/ai_holder/simple_mob/xenobio_slime/can_attack(atom/movable/AM, var/vision_required = TRUE) + . = ..() + if(.) // Do some additional checks because we have Special Code(tm). + if(ishuman(AM)) + var/mob/living/carbon/human/H = AM + if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too. + return TRUE // Monkeys are always food (sorry Pun Pun). + else if(H.species && H.species.name == SPECIES_PROMETHEAN) // Prometheans are always our friends. + if(!(H in grudges)) // Unless they're an ass. + return FALSE + if(discipline && !rabid) + holder.a_intent = I_HELP + return FALSE // We're a good slime. + +/datum/ai_holder/simple_mob/xenobio_slime/react_to_attack(atom/movable/attacker) + . = ..(attacker) + + if(ishuman(attacker)) + var/mob/living/carbon/human/H = attacker + if(H.species && H.species.name == SPECIES_PROMETHEAN) // They're a jerk. + grudges |= H + +// Commands, reactions, etc +/datum/ai_holder/simple_mob/xenobio_slime/on_hear_say(mob/living/speaker, message) + ai_log("xenobio_slime/on_hear_say([speaker], [message]) : Entered.", AI_LOG_DEBUG) + var/mob/living/simple_mob/slime/xenobio/my_slime = holder + + if((findtext(message, num2text(my_slime.number)) || findtext(message, my_slime.name) || findtext(message, "slimes"))) // Talking to us. + + // First, make sure it's actually a player saying something and not an AI, or else we risk infinite loops. + if(!speaker.client) + return + + // Are all slimes being referred to? + // var/mass_order = FALSE + // if(findtext(message, "slimes")) + // mass_order = TRUE + + // Say hello back. + if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings")) + delayed_say(pick("Hello...", "Hi..."), speaker) + + // Follow request. + if(findtext(message, "follow") || findtext(message, "come with me")) + if(!can_command(speaker)) + delayed_say(pick("No...", "I won't follow..."), speaker) + return + + delayed_say("Yes... I follow \the [speaker]...", speaker) + set_follow(speaker) + + // Squish request. + if(findtext(message , "squish")) + if(!can_command(speaker)) + delayed_say("No...", speaker) + return + + spawn(rand(1 SECOND, 2 SECONDS)) + if(!src || !holder || !can_act()) // We might've died/got deleted/etc in the meantime. + return + my_slime.squish() + + + // Stop request. + if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease")) + if(my_slime.victim) // We're being asked to stop eatting someone. + if(!can_command(speaker) || !is_justified_to_discipline()) + delayed_say("No...", speaker) + return + else + delayed_say("Fine...", speaker) + adjust_discipline(1, TRUE) + my_slime.stop_consumption() + + if(target) // We're being asked to stop chasing someone. + if(!can_command(speaker) || !is_justified_to_discipline()) + delayed_say("No...", speaker) + return + else + delayed_say("Fine...", speaker) + adjust_discipline(1, TRUE) // This must come before losing the target or it will be unjustified. + remove_target() + + + if(leader) // We're being asked to stop following someone. + if(can_command(speaker) == SLIME_COMMAND_FRIEND || leader == speaker) + delayed_say("Yes... I'll stop...", speaker) + lose_follow() + else + delayed_say("No... I'll keep following \the [leader]...", speaker) + + /* // Commented out since its mostly useless now due to slimes refusing to attack if it would make them naughty. + // Murder request + if(findtext(message, "harm") || findtext(message, "attack") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume") || findtext(message, "absorb")) + if(can_command(speaker) < SLIME_COMMAND_FACTION) + delayed_say("No...", speaker) + return + + for(var/mob/living/L in view(7, my_slime) - list(my_slime, speaker)) + if(L == src) + continue // Don't target ourselves. + var/list/valid_names = splittext(L.name, " ") // Should output list("John", "Doe") as an example. + for(var/line in valid_names) // Check each part of someone's name. + if(findtext(message, lowertext(line))) // If part of someone's name is in the command, the slime targets them if allowed to. + if(!(mass_order && line == "slime")) //don't think random other slimes are target + if(can_attack(L)) + delayed_say("Okay... I attack \the [L]...", speaker) + give_target(L) + return + else + delayed_say("No... I won't attack \the [L].", speaker) + return + + // If we're here, it couldn't find anyone with that name. + delayed_say("No... I don't know who to attack...", speaker) + */ + ai_log("xenobio_slime/on_hear_say() : Exited.", AI_LOG_DEBUG) + +/datum/ai_holder/simple_mob/xenobio_slime/can_violently_breakthrough() + if(discipline && !rabid) // Good slimes don't shatter the windows because their buddy in an adjacent cell decided to piss off Slimesky. + return FALSE + return ..() diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm index 9240de888a..7f0b2614f8 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm @@ -98,6 +98,18 @@ ties[initial(tie_type.name)] = tie_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(ties)) +/datum/gear/accessory/bowtie + display_name = "bowtie selection" + path = /obj/item/clothing/accessory/bowtie + cost = 1 + +/datum/gear/accessory/bowtie/New() + ..() + var/list/bowties = list() + for(var/obj/item/clothing/accessory/bowtie_type as anything in typesof(/obj/item/clothing/accessory/bowtie)) + bowties[initial(bowtie_type.name)] = bowtie_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(bowties)) + /datum/gear/accessory/scarf display_name = "scarf selection" path = /obj/item/clothing/accessory/scarf @@ -307,3 +319,33 @@ "Grey Vest" = /obj/item/clothing/accessory/cowboy_vest/grey ) gear_tweaks += new/datum/gear_tweak/path(cowboy_vests) + +/datum/gear/accessory/pride + display_name = "pride pin selection" + path = /obj/item/clothing/accessory/pride + +/datum/gear/accessory/pride/New() + ..() + var/list/pridepins = list() + for(var/pridepin in typesof(/obj/item/clothing/accessory/pride)) + var/obj/item/clothing/accessory/pridepin_type = pridepin + pridepins[initial(pridepin_type.name)] = pridepin_type + gear_tweaks += new/datum/gear_tweak/path(sortAssoc(pridepins)) + +/datum/gear/accessory/badge + display_name = "sheriff badge (Security)" + path = /obj/item/clothing/accessory/badge/holo/sheriff + allowed_roles = list("Security Officer","Detective","Head of Security","Warden") + +/datum/gear/accessory/corpbadge + display_name = "investigator holobadge (IAA)" + path = /obj/item/clothing/accessory/badge/holo/investigator + allowed_roles = list("Internal affairs agent") + +/datum/gear/accessory/pressbadge + display_name = "corporate press pass" + path = /obj/item/clothing/accessory/badge/press + +/datum/gear/accessory/pressbadge + display_name = "freelance press pass" + path = /obj/item/clothing/accessory/badge/press/independent diff --git a/code/modules/client/preference_setup/loadout/loadout_general.dm b/code/modules/client/preference_setup/loadout/loadout_general.dm index 74a69d46e0..53caa5bc8b 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general.dm @@ -148,4 +148,50 @@ /datum/gear/wizoffguide display_name = "WizOff Guide" path = /obj/item/weapon/book/manual/wizzoffguide - description = "The guide to playing the ever popular card game: Wiz-Off!" \ No newline at end of file + description = "The guide to playing the ever popular card game: Wiz-Off!" + +/datum/gear/coffeemug + display_name = "coffee mugs" + description = "A coffee mug in various designs." + cost = 1 + path = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug + +/datum/gear/coffeemug/New() + ..() + var/list/coffeemugs = list() + coffeemugs["plain coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug + coffeemugs["SCG coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/sol + coffeemugs["Fleet coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/fleet + coffeemugs["Five Arrows coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/fivearrows + coffeemugs["Pearlshield coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/psc + coffeemugs["Almach Association coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/alma + coffeemugs["Almach Protectorate coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/almp + coffeemugs["NT coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/nt + coffeemugs["Wulf Aeronautics mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/metal/wulf + coffeemugs["Gilthari Exports coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/gilthari + coffeemugs["Zeng-Hu coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/zeng + coffeemugs["Ward-Takahashi coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/wt + coffeemugs["Aether Atmospherics coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/aether + coffeemugs["Bishop Cybernetics coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/bishop + coffeemugs["Oculum Broadcast coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/oculum + coffeemugs["#1 coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/one + coffeemugs["#1 monkey coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/puni + coffeemugs["heart coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/heart + coffeemugs["pawn coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/pawn + coffeemugs["diona coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/diona + coffeemugs["british coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/britcup + coffeemugs["flame coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/flame + coffeemugs["blue coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/blue + coffeemugs["black coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/black + coffeemugs["green coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/green + coffeemugs["dark green coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/green/dark + coffeemugs["rainbow coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/rainbow + coffeemugs["metal coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/metal + coffeemugs["glass coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/glass + coffeemugs["tall coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/tall + coffeemugs["tall black coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/tall/black + coffeemugs["tall metal coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/tall/metal + coffeemugs["tall rainbow coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/tall/rainbow + //coffeemugs["Talon coffee mug"] = /obj/item/weapon/reagent_containers/food/drinks/glass2/coffeemug/talon //CHOMPedit + gear_tweaks += new /datum/gear_tweak/path(coffeemugs) + gear_tweaks += new /datum/gear_tweak/reagents(lunchables_drink_reagents()) diff --git a/code/modules/client/preference_setup/loadout/loadout_general_vr.dm b/code/modules/client/preference_setup/loadout/loadout_general_vr.dm index 9b72d27aba..e2f863dae5 100644 --- a/code/modules/client/preference_setup/loadout/loadout_general_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_general_vr.dm @@ -90,4 +90,9 @@ /datum/gear/textmug display_name = "mug with text" description = "A mug with something written on it." - path = /obj/item/weapon/reagent_containers/food/drinks/textmug \ No newline at end of file + path = /obj/item/weapon/reagent_containers/food/drinks/textmug + +/datum/gear/schnapsen + display_name = "schnapsen playing cards" + description = "French-suit playing cards! Pre-picked for 2-player mode." + path = /obj/item/weapon/deck/schnapsen \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_mask.dm b/code/modules/client/preference_setup/loadout/loadout_mask.dm index a313f3023d..af33ec7787 100644 --- a/code/modules/client/preference_setup/loadout/loadout_mask.dm +++ b/code/modules/client/preference_setup/loadout/loadout_mask.dm @@ -22,6 +22,19 @@ path = /obj/item/clothing/mask/surgical cost = 2 +/datum/gear/mask/sterile/white + display_name = "white sterile mask" + path = /obj/item/clothing/mask/surgical/white + cost = 2 + +/datum/gear/mask/sterile/white/dust + display_name = "dust mask" + path = /obj/item/clothing/mask/surgical/dust + +/datum/gear/mask/sterile/white/cloth + display_name = "cloth face mask" + path = /obj/item/clothing/mask/surgical/cloth + /datum/gear/mask/plaguedoctor display_name = "plague doctor's mask" path = /obj/item/clothing/mask/gas/plaguedoctor diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm b/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm index 6e80ef3de5..41ebeafe1b 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm @@ -2,6 +2,10 @@ display_name = "nudity permit" path = /obj/item/clothing/under/permit +/datum/gear/uniform/suit/natureist_talisman + display_name = "naturist talisman" + path = /obj/item/clothing/under/permit/natureist_talisman + //Polaris overrides /datum/gear/uniform/solgov/pt/sifguard display_name = "pt uniform, planetside sec" diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index 210c42c3d3..d97d2aa9ef 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -168,28 +168,29 @@ if(pref.species == SPECIES_CUSTOM) var/points_left = pref.starting_trait_points - for(var/T in pref.pos_traits + pref.neg_traits) + for(var/T in pref.pos_traits + pref.neg_traits) // CHOMPEdit: Only Positive traits cost slots now. points_left -= traits_costs[T] + for(var/T in pref.pos_traits) traits_left-- . += "Traits Left: [traits_left]
" . += "Points Left: [points_left]
" if(points_left < 0 || traits_left < 0 || !pref.custom_species) . += "^ Fix things! ^
" - . += "Positive Trait +
" + . += "Positive Trait(s) (Limited) +
" // CHOMPEdit: More obvious/clear to players. . += "" - . += "Negative Trait +
" + . += "Negative Trait(s) (No Limit) +
" // CHOMPEdit: More obvious/clear to players. . += "" - . += "Neutral Trait +
" + . += "Neutral Trait(s) (No Limit) +
" // CHOMPEdit: More obvious/clear to players. . += "