diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 9099488143b..19a0ceb7dec 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/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index b53d722458b..64b54904727 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -161,7 +161,16 @@
if(istype(target, /turf/simulated))
var/turf/simulated/modeled_location = target
+
+ if(modeled_location.special_temperature)//First do special interactions then the usuall stuff
+ var/delta_temp = modeled_location.special_temperature - air.temperature//2200C - 20C = 2180K
+ //assuming aluminium with thermal conductivity 235 W * K / m, Copper (400), Silver (430), steel (50), gold (320)
+ var/heat_gain = 23500 * 100 * delta_temp
+ air.add_thermal_energy(heat_gain)
+ if(network)
+ network.update = 1
+
if(modeled_location.blocks_air)
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
diff --git a/code/ATMOSPHERICS/pipes/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm
index 11802b9f643..0d9e673e689 100644
--- a/code/ATMOSPHERICS/pipes/he_pipes.dm
+++ b/code/ATMOSPHERICS/pipes/he_pipes.dm
@@ -98,7 +98,8 @@
else
var/datum/gas_mixture/environment = loc.return_air()
environment_temperature = environment.temperature
- if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
+ var/turf/simulated/loc_as_turf = loc
+ if((abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) || (loc_as_turf.special_temperature))
parent.temperature_interact(loc, volume, thermal_conductivity)
else if(istype(loc, /turf/space/))
parent.radiate_heat_to_space(surface, 1)
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index f1de2ddd45e..80f25e5fb87 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -36,6 +36,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
@@ -46,7 +47,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 53584a56487..2cb576c0ef5 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/integrated_circuits.dm b/code/__defines/integrated_circuits.dm
index b2859a232dd..03cfa358e3b 100644
--- a/code/__defines/integrated_circuits.dm
+++ b/code/__defines/integrated_circuits.dm
@@ -1,3 +1,4 @@
// Methods of obtaining a circuit.
#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer.
-#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
\ No newline at end of file
+#define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it.
+#define IC_SPAWN_ILLEGAL 3 // If the circuit design will be available if upgrading the IC printer illegally.
\ No newline at end of file
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index 07c25a40ab5..0fbcd3c719f 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/span_vr.dm b/code/__defines/span_vr.dm
new file mode 100644
index 00000000000..618fd52b3d1
--- /dev/null
+++ b/code/__defines/span_vr.dm
@@ -0,0 +1,89 @@
+// Sorted by however I felt like it
+// We have two other ways of doing this, so why not a third. This one atleast has more span options.
+#define span_ooc(str) ("" + str + "")
+#define span_looc(str) ("" + str + "")
+
+#define span_deadsay(str) ("" + str + "")
+#define span_radio(str) ("" + str + "")
+#define span_deptradio(str) ("" + str + "")
+#define span_newscaster(str) ("" + str + "")
+
+#define span_comradio(str) ("" + str + "")
+#define span_syndradio(str) ("" + str + "")
+#define span_centradio(str) ("" + str + ""
+#define span_airadio(str) ("" + str + "")
+#define span_entradio(str) ("" + str + "")
+
+#define span_secradio(str) ("" + str + "")
+#define span_engradio(str) ("" + str + "")
+#define span_medradio(str) ("" + str + "")
+#define span_sciradio(str) ("" + str + "")
+#define span_supradio(str) ("" + str + ""
+#define span_srvradio(str) ("" + str + "")
+#define span_expradio(str) ("" + str + "")
+
+#define span_name(str) ("" + str + "")
+#define span_say(str) ("" + str + "")
+#define span_alert(str) ("" + str + "")
+#define span_ghostalert(str) ("" + str + "")
+
+
+#define span_emote(str) ("" + str + "")
+#define span_emote_subtle(str) ("" + str + "")
+
+#define span_attack(str) ("" + str + "")
+#define span_moderate(str) ("" + str + "")
+#define span_disarm(str) ("" + str + "")
+#define span_passive(str) ("" + str + "")
+
+#define span_critical(str) ("" + str + "")
+#define span_danger(str) ("" + str + "")
+#define span_warning(str) ("" + str + "")
+#define span_rose(str) ("" + str + "")
+#define span_info(str) ("" + str + ""
+#define span_notice(str) ("" + str + "")
+#define span_alium(str) ("" + str + "")
+#define span_cult(str) ("" + str + "")
+
+#define span_reflex_shoot(str) ("" + str + "")
+
+/* Languages */
+
+#define span_alien(str) ("" + str + "")
+#define span_tajaran(str) ("" + str + "")
+#define span_tajaran_signlang(str) ("" + str + "")
+#define span_akhani(str) ("" + str + "")
+#define span_skrell(str) ("" + str + "")
+#define span_skrellfar(str) ("" + str + "")
+#define span_soghun(str) ("" + str + "")
+#define span_solcom(str) ("" + str + "")
+#define span_changeling(str) ("" + str + "")
+#define span_sergal(str) ("" + str + "")
+#define span_birdsongc(str) ("" + str + "")
+#define span_vulpkanin(str) ("" + str + "")
+#define span_enochian(str) ("" + str + "")
+#define span_daemon(str) ("" + str + "")
+#define span_bug(str) ("" + str + "")
+#define span_vox(str) ("" + str + "")
+#define span_zaddat(str) ("" + str + "")
+#define span_promethean(str) ("" + str + "")
+#define span_rough(str) ("" + str + "")
+#define span_say_quote(str) ("" + str + "")
+#define span_terminus(str) ("" + str + "")
+#define span_interface(str) ("" + str + "")
+#define span_spacer(str) ("" + str + "")
+#define span_blob(str) ("" + str + "")
+
+#define span_debug_error(str) ("" + str + "")
+#define span_debug_warning(str) ("" + str + "")
+#define span_debug_info(str) ("" + str + "")
+#define span_debug_debug(str) ("" + str + "")
+#define span_debug_trace(str) ("" + str + "")
+
+#define span_black(str) ("" + str + "")
+#define span_darkgray(str) ("" + str + "")
+#define span_gray(str) ("" + str + "")
+#define span_red(str) ("" + str + "")
+#define span_orange(str) ("" + str + "")
+#define span_blue(str) ("" + str + "")
+#define span_green(str) ("" + str + "")
\ No newline at end of file
diff --git a/code/__defines/species_languages.dm b/code/__defines/species_languages.dm
index 46cff510cbd..67d6b6e7d6f 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 455732fa7c6..76b1b0d4d84 100644
--- a/code/_helpers/global_lists_vr.dm
+++ b/code/_helpers/global_lists_vr.dm
@@ -566,3 +566,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 d4e38272899..bea5e6780c4 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 44037305dda..14feaf1b5f8 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 6cb86b152fa..988c11df10d 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 19310ad3150..da56de56854 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.
+*/
\ No newline at end of file
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 98c187fc97d..62987479014 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 910646f261f..c1a4795001e 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -902,3 +902,80 @@ INITIALIZE_IMMEDIATE(/obj/screen/splash)
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_vr.dm b/code/_onclick/hud/screen_objects_vr.dm
index 1d8df98a38b..4d837803279 100644
--- a/code/_onclick/hud/screen_objects_vr.dm
+++ b/code/_onclick/hud/screen_objects_vr.dm
@@ -45,11 +45,26 @@
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)) // 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
diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm
index 6b0815999b4..f185c4bbb81 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.
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/engineering_vr.dm b/code/datums/autolathe/engineering_vr.dm
index 90970c6e481..577d9febd2c 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 97f6be5e395..ce268e893a5 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 bcb00d0d076..68f01b54e9f 100644
--- a/code/datums/components/crafting/recipes/weapons.dm
+++ b/code/datums/components/crafting/recipes/weapons.dm
@@ -60,10 +60,8 @@
/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(
- /obj/item/device/binoculars/scope = 1,
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 1
- )
+ 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
\ No newline at end of file
+ subcategory = CAT_WEAPON
diff --git a/code/datums/managed_browsers/changelingevolution.dm b/code/datums/managed_browsers/changelingevolution.dm
new file mode 100644
index 00000000000..4458604b9b3
--- /dev/null
+++ b/code/datums/managed_browsers/changelingevolution.dm
@@ -0,0 +1,167 @@
+/client
+ var/datum/managed_browser/changelingevolution/changelingevolution = null
+
+/datum/managed_browser/changelingevolution
+ base_browser_id = "evolution_tree"
+ title = "Evolution Tree"
+ size_x = 480
+ size_y = 600
+ var/textbody = null
+
+/datum/managed_browser/changelingevolution/New(client/new_client)
+ if(!new_client.mob || !new_client.mob.mind || !new_client.mob.mind.changeling)
+ message_admins("[new_client] tried to access changeling evolutions while not changeling.")
+ qdel(src)
+
+ ..()
+
+/datum/managed_browser/changelingevolution/Destroy()
+ if(my_client)
+ my_client.changelingevolution = null
+ return ..()
+
+/datum/managed_browser/changelingevolution/get_html()
+ var/list/dat = list("
")
+ var/geneticpoints_current = my_client.mob.mind.changeling.geneticpoints
+ var/geneticpoints_max = my_client.mob.mind.changeling.max_geneticpoints
+
+ dat += "Genetic Points Available: [geneticpoints_current] / [geneticpoints_max]
"
+ dat += "Obtain more by feeding on your own kind.
"
+ dat += "What am I?
"
+ dat += "Inherent"
+ dat += "Armor"
+ dat += "Weapons"
+ dat += "Stings"
+ dat += "Shrieks"
+ dat += "Health"
+ dat += "Enhancements"
+ if(textbody)
+ dat += ""
+ dat += "[textbody]"
+ dat += "
"
+ dat += ""
+
+ return dat.Join()
+
+/datum/managed_browser/changelingevolution/Topic(href, href_list[])
+ if(!my_client)
+ return FALSE
+
+ if(href_list["close"])
+ return
+
+ if(href_list["inherent"])
+ generate_abilitylist(CHANGELING_POWER_INHERENT)
+
+ if(href_list["armor"])
+ generate_abilitylist(CHANGELING_POWER_ARMOR)
+
+ if(href_list["weapons"])
+ generate_abilitylist(CHANGELING_POWER_WEAPONS)
+
+ if(href_list["stings"])
+ generate_abilitylist(CHANGELING_POWER_STINGS)
+
+ if(href_list["shrieks"])
+ generate_abilitylist(CHANGELING_POWER_SHRIEKS)
+
+ if(href_list["health"])
+ generate_abilitylist(CHANGELING_POWER_HEALTH)
+
+ if(href_list["enhancements"])
+ generate_abilitylist(CHANGELING_POWER_ENHANCEMENTS)
+
+ if(href_list["evolve"])
+ var/datum/mind/M = my_client.mob.mind
+ var/datum/changeling/C = my_client.mob.mind.changeling
+ var/datum/power/changeling/Thepower = href_list["evolve"]
+
+ for (var/datum/power/changeling/P in powerinstances)
+ if(P.name == Thepower)
+ Thepower = P
+ break
+
+ if(!istype(M))
+ return
+
+ if(Thepower == null)
+ to_chat(M.current, "Purchase failed. Inform a dev of this error.")
+ return
+
+ if(Thepower in C.purchased_powers)
+ to_chat(M.current, "You already have this ability! Inform a dev of this error.") /// Should not be possible
+ return
+
+ if(C.geneticpoints < Thepower.genomecost)
+ to_chat(M.current, "We cannot evolve this... yet. We must acquire more DNA.")
+ return
+
+ C.purchased_powers += Thepower /// Set it to purchased
+ C.geneticpoints -= Thepower.genomecost
+ generate_abilitylist(Thepower.power_category) /// Refresh the UI
+
+ my_client.mob.mind.changeling.purchasePower(M, Thepower)
+
+ if(href_list["tutorial"])
+ textbody = "What am I?
|
"
+ textbody += ""
+ textbody += "You are a changeling, a creature empowered with genetic-based abilities that change your body in bizarre ways."
+ textbody += " It's probably best the crew doesn't know about your power -- at least not right away.
"
+ textbody += "What a changeling is, however, is up to you. Are you a strange alien impersonating crew? Are you a"
+ textbody += " normal crewmember infected with a parasite? An experiment gone wrong? It's up to you to make the story.
"
+ textbody += "Of course, you need to know how it works to begin with.
"
+ textbody += "Your abilities cost chemicals that your body will slowly regenerate with varying speeds based on enhancements obtained."
+ textbody += " There are a set of inherent abilities you will always have while the rest may be purchased through genomes.
"
+ textbody += "You may obtain more genomes if you find another changeling and absorb them, but this is not required. If you've found "
+ textbody += "your abilities aren't to your liking, you have up to two re-adapts available, and these may be refilled by absorbing anyone -- including monkeys.
"
+ textbody += "Good luck and remember, killing isn't always the end goal."
+ display()
+
+/datum/managed_browser/changelingevolution/proc/generate_abilitylist(cat)
+ var/list/ability_list = list()
+ var/info = ""
+ var/catname = ""
+ for(var/datum/power/changeling/P in powerinstances)
+ if(P.power_category == cat)
+ ability_list[++ability_list.len] = P
+ switch(cat)
+ if(CHANGELING_POWER_INHERENT)
+ catname = "Inherent"
+ info = "These powers are inherent to your kind and will always be accessible, provided you have the chemicals to use them."
+ if(CHANGELING_POWER_ARMOR)
+ catname = "Armor"
+ info = "These abilities will provide you with space protection -- and potentially armor."
+ if(CHANGELING_POWER_WEAPONS)
+ catname = "Weapons"
+ info = "These abilities will provide you the means to fight back."
+ if(CHANGELING_POWER_STINGS)
+ catname = "Stings"
+ info = "These abilities provide the means to sting organic beings for various effects -- though you must be close enough, and they must have exposed flesh."
+ if(CHANGELING_POWER_SHRIEKS)
+ catname = "Shrieks"
+ info = "These abilities enhance your vocal chords, empowering your screams."
+ if(CHANGELING_POWER_HEALTH)
+ catname = "Health"
+ info = "These abilities will enhance your health or aid you in mending your wounds."
+ if(CHANGELING_POWER_ENHANCEMENTS)
+ catname = "Enhancements"
+ info = "These abilities enhance you in various ways."
+ create_textbody(ability_list, catname, info)
+
+/datum/managed_browser/changelingevolution/proc/create_textbody(ability_list, cat, catinfo)
+ textbody = " |
[cat] Skills
|
"
+ textbody += "[catinfo]
|
"
+ for(var/A in ability_list)
+ var/datum/power/changeling/powerdata = A
+ textbody += "[initial(powerdata.name)] "
+ textbody += "[initial(powerdata.desc)]
"
+ textbody += "[powerdata.helptext] "
+ if(powerdata.enhancedtext != "")
+ textbody += "WHEN EHANCED: [powerdata.enhancedtext] "
+ if(powerdata in my_client.mob.mind.changeling.purchased_powers)
+ textbody += "This ability is already evolved!"
+ else if(cat != "Inherent")
+ textbody += "Cost: [powerdata.genomecost]"
+ textbody += "Evolve"
+ textbody += " |
"
+ display()
diff --git a/code/datums/supplypacks/atmospherics.dm b/code/datums/supplypacks/atmospherics.dm
index 3630b9bea0d..a18b6308923 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/engineering_vr.dm b/code/datums/supplypacks/engineering_vr.dm
index ae02babaca1..6bf6899628d 100644
--- a/code/datums/supplypacks/engineering_vr.dm
+++ b/code/datums/supplypacks/engineering_vr.dm
@@ -26,6 +26,13 @@
/obj/item/clothing/head/radiation = 3
)
+/datum/supply_pack/eng/dosimeter
+ contains = list(/obj/item/weapon/storage/box/dosimeter = 6)
+ name = "Dosimeters"
+ cost = 10
+ containertype = /obj/structure/closet/crate
+ containername = "dosimeter crate"
+
/datum/supply_pack/eng/algae
contains = list(/obj/item/stack/material/algae/ten)
name = "Algae Sheets (10)"
diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm
index c19c4b00970..18cc82af767 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 6b2cc3d10f6..11c4f1f6b32 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 506165642e4..6721ca70277 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -702,7 +702,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_vr.dm b/code/game/area/Space Station 13 areas_vr.dm
index f25c8e5f5f2..1c9ff79460f 100644
--- a/code/game/area/Space Station 13 areas_vr.dm
+++ b/code/game/area/Space Station 13 areas_vr.dm
@@ -50,3 +50,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 371701e5b65..e356063e2ab 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 4639f571388..c52e51d5b53 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/machinery/biogenerator.dm b/code/game/machinery/biogenerator.dm
index e98e687af43..227e36948cd 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 19800790981..d36a9be13da 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 b39e8513bfb..5962f9aa8f6 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 7a6954e610b..5a210c91365 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
@@ -528,13 +529,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 f9f5a897810..637cd1f6bd0 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/landmarks_poi_vr.dm b/code/game/objects/effects/landmarks_poi_vr.dm
new file mode 100644
index 00000000000..c46be055bd3
--- /dev/null
+++ b/code/game/objects/effects/landmarks_poi_vr.dm
@@ -0,0 +1,73 @@
+var/global/list/global_used_pois = list()
+
+
+
+/obj/effect/landmark/poi_loader
+ name = "PoI Loader"
+ var/size_x
+ var/size_y
+ var/poi_type = null
+ var/remove_from_pool = TRUE
+
+/obj/effect/landmark/poi_loader/New()
+INITIALIZE_IMMEDIATE(/obj/effect/landmark/poi_loader)
+
+/obj/effect/landmark/poi_loader/Initialize()
+ src.load_poi()
+ return ..()
+
+/obj/effect/landmark/poi_loader/proc/get_turfs_to_clean()
+ return block(locate(src.x, src.y, src.z), locate((src.x + size_x - 1), (src.y + size_y - 1), src.z))
+
+/obj/effect/landmark/poi_loader/proc/annihilate_bounds()
+ //var/deleted_atoms = 0
+ //admin_notice("Annihilating objects in poi loading location.", R_DEBUG)
+ var/list/turfs_to_clean = get_turfs_to_clean()
+ if(turfs_to_clean.len)
+ for(var/x in 1 to 2) // Requires two passes to get everything.
+ for(var/turf/T in turfs_to_clean)
+ for(var/atom/movable/AM in T)
+ //++deleted_atoms
+ qdel(AM)
+ //admin_notice("Annihilated [deleted_atoms] objects.", R_DEBUG)
+
+/obj/effect/landmark/poi_loader/proc/load_poi()
+ var/turf/T = get_turf(src)
+ if(!isturf(T))
+ to_world_log("[log_info_line(src)] not on a turf! Cannot place poi template.")
+ return
+
+ // Choose a poi
+ if(!poi_type)
+ return
+
+ if(!(global_used_pois.len) || !(global_used_pois[poi_type]))
+ global_used_pois[poi_type] = list()
+ var/list/poi_list = global_used_pois[poi_type]
+ for(var/map in SSmapping.map_templates)
+ var/template = SSmapping.map_templates[map]
+ if(istype(template, poi_type))
+ poi_list += template
+
+ var/datum/map_template/template_to_use = null
+
+ var/list/our_poi_list = global_used_pois[poi_type]
+
+ if(!our_poi_list.len)
+ return
+ else
+ template_to_use = pick(our_poi_list)
+
+ if(!template_to_use)
+ return
+
+ //admin_notice("Chosen Predefined PoI Map: [chosen_type.name]", R_DEBUG)
+
+ if(remove_from_pool)
+ global_used_pois[poi_type] -= template_to_use
+
+ // Annihilate movable atoms
+ annihilate_bounds()
+ //CHECK_TICK //Don't let anything else happen for now
+ // Actually load it
+ template_to_use.load(T)
\ No newline at end of file
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 9a12f48904d..53c562f712e 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/effects/wire_deleter.dm b/code/game/objects/effects/wire_deleter.dm
new file mode 100644
index 00000000000..89130ed7cb2
--- /dev/null
+++ b/code/game/objects/effects/wire_deleter.dm
@@ -0,0 +1,17 @@
+/obj/effect/wire_deleter
+ name = "wire deleter"
+ icon = 'icons/mob/screen1.dmi'
+ icon_state = "x2"
+ anchored = TRUE
+ unacidable = TRUE
+ simulated = FALSE
+ invisibility = 100
+
+/obj/effect/wire_deleter/Initialize(mapload)
+ . = ..()
+
+ for(var/c in loc.contents)
+ if(istype(c, /obj/structure/cable))
+ if(prob(33))
+ qdel(c)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index bbcf7bb7407..12e0c29cf5f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -228,6 +228,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 a6e1ef3c2df..b9895428b76 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/defib.dm b/code/game/objects/items/devices/defib.dm
index bf549bbb6c6..d11c8c47280 100644
--- a/code/game/objects/items/devices/defib.dm
+++ b/code/game/objects/items/devices/defib.dm
@@ -497,6 +497,11 @@
M.Weaken(rand(10,25))
M.updatehealth()
apply_brain_damage(M)
+ // 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 f56a50c73d4..ebd146b92a6 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))
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 6fc7c0fe59b..8489920262f 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -296,7 +296,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
@@ -312,12 +313,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 e8125e993e6..cc1194d1489 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.
" // 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()
diff --git a/code/game/objects/items/gunbox.dm b/code/game/objects/items/gunbox.dm
index d97aa51ba08..249daf1b4e7 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 00000000000..1ff6496aa22
--- /dev/null
+++ b/code/game/objects/items/stacks/stack_vr.dm
@@ -0,0 +1,37 @@
+// Porting stack dragging/auto stacking from TG.
+
+/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
+ 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/proc/can_merge(obj/item/stack/S)
+ 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
+ if(!isturf(loc) || !isturf(S.loc))
+ return FALSE
+ if(src == S)
+ return FALSE
+ if(ismob(S.loc) || ismob(loc))
+ return FALSE
+ if(S.throwing || throwing)
+ return FALSE
+ if(S.amount < 1 || amount < 1)
+ return FALSE
+ return TRUE
+
+/obj/item/stack/Crossed(var/atom/movable/AM)
+ if(istype(AM, src.type)) // Sanity so we don't try to merge non-stacks.
+ if(can_merge(AM))
+ 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 a13046dc63c..8a3f59feaed 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
*/
@@ -962,3 +963,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 104145d8ce7..46b935419ec 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 181db77e91b..59e95f103fb 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 917fd8e0721..0271e44f755 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/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
index e3e300f0ce3..2c9ef1a7a0c 100644
--- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm
+++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm
@@ -203,9 +203,6 @@
name = T_BOARD("sensors console")
build_path = /obj/machinery/computer/ship/sensors
-
-
-
/obj/item/weapon/circuitboard/area_atmos
name = T_BOARD("area air control console")
build_path = /obj/machinery/computer/area_atmos
@@ -224,4 +221,9 @@
/obj/item/weapon/circuitboard/shutoff_monitor
name = T_BOARD("automatic shutoff valve monitor")
build_path = /obj/machinery/computer/shutoff_monitor
- origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
\ No newline at end of file
+ origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4)
+
+/obj/item/weapon/circuitboard/stockexchange
+ name = T_BOARD("stock exchange console")
+ build_path = /obj/machinery/computer/stockexchange
+ origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 1)
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/grenades/explosive.dm b/code/game/objects/items/weapons/grenades/explosive.dm
index 076a7acccea..77e07e2c5f0 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 209e47b2532..9bdf650c64d 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 c1c67b4d38d..255727800e4 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 9eaaa56265f..1325a0e1ca7 100644
--- a/code/game/objects/items/weapons/manuals_vr.dm
+++ b/code/game/objects/items/weapons/manuals_vr.dm
@@ -342,3 +342,395 @@
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!