You repair some damage to [AC.name].")
+ AC.integrity += min(10, AC.max_integrity-AC.integrity)
+ update_damage_alerts()
+
else
to_chat(user, "The [src.name] is at full integrity")
return
diff --git a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
index e3ae63cbad0..4d85b582fa3 100644
--- a/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
+++ b/code/game/objects/effects/temporary_visuals/projectiles/tracer.dm
@@ -2,8 +2,7 @@
var/list/beam_components = list()
/datum/beam_components_cache/Destroy()
- for(var/component in beam_components)
- qdel(component)
+ QDEL_LIST_NULL(beam_components)
return ..()
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, datum/beam_components_cache/beam_components, beam_type, color, qdel_in = 5, light_range = 2, light_color_override, light_intensity = 1, instance_key) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
diff --git a/code/game/objects/items/devices/radio/headset_vr.dm b/code/game/objects/items/devices/radio/headset_vr.dm
index 8285fade758..1285ae0709a 100644
--- a/code/game/objects/items/devices/radio/headset_vr.dm
+++ b/code/game/objects/items/devices/radio/headset_vr.dm
@@ -81,13 +81,13 @@
/obj/item/device/radio/headset/pilot
name = "pilot's headset"
- desc = "A headset used by pilots, has access to the explorer channel."
+ desc = "A headset used by pilots."
icon_state = "pilot_headset"
adhoc_fallback = TRUE
/obj/item/device/radio/headset/pilot/alt
name = "pilot's bowman headset"
- desc = "A bowman headset used by pilots, has access to the explorer channel."
+ desc = "A bowman headset used by pilots."
icon_state = "pilot_headset_alt"
/obj/item/device/radio/headset/explorer
diff --git a/code/game/objects/items/weapons/id cards/id_stacks_vr.dm b/code/game/objects/items/weapons/id cards/id_stacks_vr.dm
index 599fd9d5222..2bdd52bfa92 100644
--- a/code/game/objects/items/weapons/id cards/id_stacks_vr.dm
+++ b/code/game/objects/items/weapons/id cards/id_stacks_vr.dm
@@ -145,7 +145,7 @@
initial_sprite_stack = list("base-stamp", "top-generic", "stamp-n", "stripe-red")
/obj/item/weapon/card/id/civilian/pilot
- initial_sprite_stack = list("base-stamp", "top-generic", "stamp-n", "stripe-darkgreen")
+ initial_sprite_stack = list("base-stamp", "top-generic", "stamp-n", "stripe-olive")
/obj/item/weapon/card/id/civilian/entertainer
initial_sprite_stack = list("base-stamp", "top-generic", "stamp-n", "stripe-brown")
@@ -179,13 +179,13 @@
//Exploration
/obj/item/weapon/card/id/exploration
- initial_sprite_stack = list("base-stamp", "top-darkgreen", "stamp-n")
+ initial_sprite_stack = list("base-stamp", "top-olive", "stamp-n")
/obj/item/weapon/card/id/exploration/fm
- initial_sprite_stack = list("base-stamp", "top-darkgreen", "stamp-n", "stripe-medblu")
+ initial_sprite_stack = list("base-stamp", "top-olive", "stamp-n", "stripe-medblu")
/obj/item/weapon/card/id/exploration/head
- initial_sprite_stack = list("base-stamp-silver", "top-darkgreen", "stamp-n", "pips-white")
+ initial_sprite_stack = list("base-stamp-silver", "top-olive", "stamp-n", "pips-white")
//Talon
diff --git a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions_vr.dm b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions_vr.dm
index 419b28e9c1a..46760952427 100644
--- a/code/game/objects/structures/crates_lockers/_closets_appearance_definitions_vr.dm
+++ b/code/game/objects/structures/crates_lockers/_closets_appearance_definitions_vr.dm
@@ -65,7 +65,7 @@
)
/decl/closet_appearance/secure_closet/expedition
- color = COLOR_BRASS
+ color = COLOR_OLIVE
decals = list(
"lower_side_vent"
)
@@ -84,15 +84,13 @@
/decl/closet_appearance/secure_closet/expedition/explorer
extra_decals = list(
- "stripe_vertical_left_full" = COLOR_PURPLE,
- "stripe_vertical_right_full" = COLOR_PURPLE,
- "exped" = COLOR_PURPLE
+ "stripe_vertical_mid_full" = COLOR_GRAY40,
+ "exped" = COLOR_GRAY40
)
/decl/closet_appearance/secure_closet/expedition/pathfinder
extra_decals = list(
- "stripe_vertical_left_full" = COLOR_PURPLE,
- "stripe_vertical_mid_full" = COLOR_GRAY40,
- "stripe_vertical_right_full" = COLOR_PURPLE,
- "exped" = COLOR_GRAY40
+ "stripe_vertical_left_full" = COLOR_GRAY20,
+ "stripe_vertical_right_full" = COLOR_GRAY20,
+ "exped" = COLOR_GRAY20
)
\ No newline at end of file
diff --git a/code/game/world.dm b/code/game/world.dm
index a51b7185de0..95d6ff18d72 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -111,8 +111,10 @@ var/world_topic_spam_protect_time = world.timeofday
s["players"] = 0
s["stationtime"] = stationtime2text()
s["roundduration"] = roundduration2text()
+ s["map"] = strip_improper(using_map.full_name) //Done to remove the non-UTF-8 text macros
- if(input["status"] == "2")
+ if(input["status"] == "2") // Shiny new hip status.
+ var/active = 0
var/list/players = list()
var/list/admins = list()
@@ -122,15 +124,18 @@ var/world_topic_spam_protect_time = world.timeofday
continue
admins[C.key] = C.holder.rank
players += C.key
+ if(istype(C.mob, /mob/living))
+ active++
s["players"] = players.len
s["playerlist"] = list2params(players)
+ s["active_players"] = active
var/list/adm = get_admin_counts()
var/list/presentmins = adm["present"]
var/list/afkmins = adm["afk"]
s["admins"] = presentmins.len + afkmins.len //equivalent to the info gotten from adminwho
s["adminlist"] = list2params(admins)
- else
+ else // Legacy.
var/n = 0
var/admins = 0
diff --git a/code/global_vr.dm b/code/global_vr.dm
index 278df90f79a..f7ab6951cf0 100644
--- a/code/global_vr.dm
+++ b/code/global_vr.dm
@@ -5,6 +5,7 @@
robot_module_types += "Sci-borg"
robot_module_types += "Pupdozer"
robot_module_types += "Service-Hound"
+ robot_module_types += "BoozeHound"
robot_module_types += "KMine"
return 1
diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm
index b8a42321964..3f5e0b3344b 100644
--- a/code/modules/client/preference_setup/global/01_ui.dm
+++ b/code/modules/client/preference_setup/global/01_ui.dm
@@ -50,11 +50,11 @@
. += "tgui Window Mode: [(pref.tgui_fancy) ? "Fancy (default)" : "Compatible (slower)"]
"
. += "tgui Window Placement: [(pref.tgui_lock) ? "Primary Monitor" : "Free (default)"]
"
if(can_select_ooc_color(user))
- . += "OOC Color:�"
+ . += "OOC Color:"
if(pref.ooccolor == initial(pref.ooccolor))
. += "Using Default
"
else
- . += "[pref.ooccolor] [color_square(hex = pref.ooccolor)]�reset
"
+ . += "[pref.ooccolor] [color_square(hex = pref.ooccolor)]reset
"
/datum/category_item/player_setup_item/player_global/ui/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["select_style"])
diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm b/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm
index 7e21dd3ef8c..b006fc7a0d6 100644
--- a/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm
@@ -50,7 +50,7 @@
/datum/gear/accessory/holster
display_name = "holster selection (Security, SM, HoP, Exploration)"
- allowed_roles = list("Site Manager", "Head of Personnel", "Security Officer", "Warden", "Head of Security","Detective","Explorer","Pathfinder","Talon Guard")
+ allowed_roles = list("Site Manager", "Head of Personnel", "Security Officer", "Warden", "Head of Security","Detective","Field Medic","Explorer","Pathfinder","Talon Captain","Talon Guard")
/datum/gear/accessory/brown_vest
display_name = "webbing, brown (Eng, Sec, Med, Exploration, Miner)"
diff --git a/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm b/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm
index 68699342a4b..9504678e06b 100644
--- a/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_eyes_vr.dm
@@ -2,13 +2,20 @@
allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic")
/datum/gear/eyes/meson
- display_name = "Optical Meson Scanners (Engineering, Science)"
+ display_name = "Optical Meson Scanners (Eng, Sci, Explo)"
allowed_roles = list("Station Engineer","Chief Engineer","Atmospheric Technician", "Scientist", "Research Director", "Explorer", "Pathfinder")
/datum/gear/eyes/arglasses
display_name = "AR glasses"
path = /obj/item/clothing/glasses/omnihud
+/datum/gear/eyes/arglasses/visor
+ display_name = "AR visor"
+ path = /obj/item/clothing/glasses/omnihud/visor
+
+/datum/gear/eyes/arglasses/visor/New()
+ ..()
+ gear_tweaks = list(gear_tweak_free_color_choice)
/datum/gear/eyes/arglassespres
display_name = "AR glasses, prescription"
path = /obj/item/clothing/glasses/omnihud/prescription
@@ -48,7 +55,7 @@
path = /obj/item/clothing/glasses/fluff/science_proper
/datum/gear/eyes/meson/retinal
- display_name = "retinal projector, meson (Eng, Sci, Mining)"
+ display_name = "retinal projector, meson (Eng, Sci, Explo)"
path = /obj/item/clothing/glasses/omnihud/eng/meson
/datum/gear/eyes/security/secpatch
diff --git a/code/modules/client/preference_setup/loadout/loadout_head_vr.dm b/code/modules/client/preference_setup/loadout/loadout_head_vr.dm
index 2aebfd668f4..d7add786c52 100644
--- a/code/modules/client/preference_setup/loadout/loadout_head_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_head_vr.dm
@@ -1,3 +1,8 @@
+/datum/gear/head/cap/med
+ display_name = "cap, medical (Medical)"
+ path = /obj/item/clothing/head/soft/med
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Psychiatrist","Paramedic","Field Medic")
+
/*/datum/gear/head/cap/sol
display_name = "cap, sol"
path = /obj/item/clothing/head/soft/sol*/
diff --git a/code/modules/client/preference_setup/loadout/loadout_shoes_vr.dm b/code/modules/client/preference_setup/loadout/loadout_shoes_vr.dm
index 554300d379a..66e93fbbf62 100644
--- a/code/modules/client/preference_setup/loadout/loadout_shoes_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_shoes_vr.dm
@@ -1,6 +1,3 @@
-/datum/gear/shoes/boots/winter/science
- allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Explorer", "Pathfinder")
-
/datum/gear/shoes/boots/winter/medical
allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic")
diff --git a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm
index e681401582d..25dc8d4511a 100644
--- a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm
@@ -1,9 +1,6 @@
/datum/gear/suit/snowsuit/medical
allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic")
-/datum/gear/suit/snowsuit/science
- allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Explorer", "Pathfinder")
-
/datum/gear/suit/labcoat_colorable
display_name = "labcoat, colorable"
path = /obj/item/clothing/suit/storage/toggle/labcoat
@@ -49,7 +46,7 @@
/datum/gear/suit/roles/medical/ems_jacket
display_name = "first responder jacket"
path = /obj/item/clothing/suit/storage/toggle/fr_jacket
- allowed_roles = list("Chief Medical Officer","Paramedic","Medical Doctor")
+ allowed_roles = list("Chief Medical Officer","Paramedic","Medical Doctor","Field Medic")
//imo-superior 'martian' style jacket with the star-of-life design
/datum/gear/suit/roles/medical/ems_jacket/alt
@@ -60,7 +57,7 @@
/datum/gear/suit/roles/medical/paramedic_vest
display_name = "paramedic vest"
path = /obj/item/clothing/suit/storage/toggle/paramedic
- allowed_roles = list("Chief Medical Officer","Paramedic","Medical Doctor")
+ allowed_roles = list("Chief Medical Officer","Paramedic","Medical Doctor","Field Medic")
//greek thing
/datum/gear/suit/chiton
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 6c8fc917641..1f169dbc70c 100644
--- a/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_uniform_vr.dm
@@ -13,6 +13,10 @@
/datum/gear/uniform/job_turtle/science
allowed_roles = list("Research Director", "Scientist", "Roboticist", "Xenobiologist", "Xenobotanist")
+/datum/gear/uniform/job_turtle/medical
+ display_name = "turtleneck, medical"
+ path = /obj/item/clothing/under/rank/medical/turtleneck
+ allowed_roles = list("Chief Medical Officer", "Paramedic", "Medical Doctor", "Psychiatrist", "Field Medic", "Chemist")
//KHI Uniforms
/datum/gear/uniform/job_khi/cmd
@@ -38,7 +42,7 @@
/datum/gear/uniform/job_khi/sci
display_name = "khi uniform, sci"
path = /obj/item/clothing/under/rank/khi/sci
- allowed_roles = list("Research Director", "Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer")
+ allowed_roles = list("Research Director", "Scientist", "Roboticist", "Xenobiologist", "Xenobotanist")
/datum/gear/uniform/job_khi/crg
display_name = "khi uniform, cargo"
@@ -58,7 +62,7 @@
/datum/gear/suit/job_fed/medsci
display_name = "fed uniform, med/sci"
path = /obj/item/clothing/suit/storage/fluff/fedcoat/fedblue
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist","Xenobotanist","Pathfinder","Explorer","Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist","Xenobotanist","Field Medic")
/datum/gear/suit/job_fed/eng
display_name = "fed uniform, eng"
@@ -75,7 +79,7 @@
/datum/gear/uniform/job_trek/medsci/tos
display_name = "TOS uniform, med/sci"
path = /obj/item/clothing/under/rank/trek/medsci
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer", "Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Field Medic")
/datum/gear/uniform/job_trek/eng/tos
display_name = "TOS uniform, eng/sec"
@@ -91,7 +95,7 @@
/datum/gear/uniform/job_trek/medsci/tng
display_name = "TNG uniform, med/sci"
path = /obj/item/clothing/under/rank/trek/medsci/next
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer", "Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Field Medic")
/datum/gear/uniform/job_trek/eng/tng
display_name = "TNG uniform, eng/sec"
@@ -107,7 +111,7 @@
/datum/gear/uniform/job_trek/medsci/voy
display_name = "VOY uniform, med/sci"
path = /obj/item/clothing/under/rank/trek/medsci/voy
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer", "Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Field Medic")
/datum/gear/uniform/job_trek/eng/voy
display_name = "VOY uniform, eng/sec"
@@ -133,7 +137,7 @@
/datum/gear/uniform/job_trek/medsci/ds9
display_name = "DS9 uniform, med/sci"
path = /obj/item/clothing/under/rank/trek/medsci/ds9
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer", "Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Field Medic")
/datum/gear/uniform/job_trek/eng/ds9
display_name = "DS9 uniform, eng/sec"
@@ -150,7 +154,7 @@
/datum/gear/uniform/job_trek/medsci/ent
display_name = "ENT uniform, med/sci"
path = /obj/item/clothing/under/rank/trek/medsci/ent
- allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Pathfinder", "Explorer", "Field Medic")
+ allowed_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist", "Xenobiologist", "Xenobotanist", "Field Medic")
/datum/gear/uniform/job_trek/eng/ent
display_name = "ENT uniform, eng/sec"
diff --git a/code/modules/client/preference_setup/loadout/loadout_utility_vr.dm b/code/modules/client/preference_setup/loadout/loadout_utility_vr.dm
index 36b3ead7a66..56218337e60 100644
--- a/code/modules/client/preference_setup/loadout/loadout_utility_vr.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_utility_vr.dm
@@ -54,7 +54,7 @@
/datum/gear/utility/dufflebag/sci
display_name = "science dufflebag"
path = /obj/item/weapon/storage/backpack/dufflebag/sci
- allowed_roles = list("Research Director","Scientist","Roboticist","Xenobiologist","Xenobotanist","Explorer","Pathfinder")
+ allowed_roles = list("Research Director","Scientist","Roboticist","Xenobiologist","Xenobotanist")
/datum/gear/utility/ID
display_name = "contractor identification card"
diff --git a/code/modules/clothing/glasses/hud_vr.dm b/code/modules/clothing/glasses/hud_vr.dm
index 718b9e6908f..3487d0999c8 100644
--- a/code/modules/clothing/glasses/hud_vr.dm
+++ b/code/modules/clothing/glasses/hud_vr.dm
@@ -35,7 +35,7 @@
tgarscreen = null
spawn(20 SECONDS)
tgarscreen = disconnect_tgar
-
+
//extra fun for non-sci variants; a small chance flip the state to the dumb 3d glasses when EMP'd
if(icon_state == "glasses" || icon_state == "sun")
if(prob(10))
@@ -113,6 +113,14 @@
/obj/item/clothing/glasses/omnihud/proc/ar_interact(var/mob/living/carbon/human/user)
return 0 //The base models do nothing.
+/obj/item/clothing/glasses/omnihud/visor
+ name = "AR visor"
+ desc = "The VZR-AR are a product based upon the classic AR Glasses, just more fashionable."
+ icon_override = 'icons/mob/eyes_vr.dmi'
+ icon = 'icons/mob/eyes_vr.dmi'
+ icon_state = "visor_CIV"
+ item_state = "visor_CIV"
+
/obj/item/clothing/glasses/omnihud/prescription
name = "AR glasses (pr)"
prescription = 1
diff --git a/code/modules/emotes/definitions/_mob.dm b/code/modules/emotes/definitions/_mob.dm
index 8c10b4cde2f..46a2bf94da3 100644
--- a/code/modules/emotes/definitions/_mob.dm
+++ b/code/modules/emotes/definitions/_mob.dm
@@ -27,6 +27,7 @@ var/list/_default_mob_emotes = list(
/mob
var/list/usable_emotes
+ var/nextemote = 1 //VOREStation Add
/mob/proc/update_emotes(var/skip_sort)
usable_emotes = list()
diff --git a/code/modules/emotes/definitions/audible_scream_vr.dm b/code/modules/emotes/definitions/audible_scream_vr.dm
new file mode 100644
index 00000000000..7114d0eb662
--- /dev/null
+++ b/code/modules/emotes/definitions/audible_scream_vr.dm
@@ -0,0 +1,13 @@
+/decl/emote/audible/scream/get_emote_sound(var/atom/user)
+ var/mob/living/carbon/human/H = user
+ if(H.get_gender() == FEMALE)
+ return list(
+ "sound" = H.species.female_scream_sound,
+ "vol" = emote_volume
+ )
+ else
+ return list(
+ "sound" = H.species.male_scream_sound,
+ "vol" = emote_volume
+ )
+ return ..()
diff --git a/code/modules/emotes/definitions/visible_animated.dm b/code/modules/emotes/definitions/visible_animated.dm
index 2e035d289c7..c66fa789c17 100644
--- a/code/modules/emotes/definitions/visible_animated.dm
+++ b/code/modules/emotes/definitions/visible_animated.dm
@@ -27,7 +27,12 @@
/decl/emote/visible/flip/do_extra(mob/user)
. = ..()
- if(istype(user))
+ // VOREStation Add - Fancy flips
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.handle_flip_vr()
+ // VOREStation Add End
+ else if(istype(user))
user.SpinAnimation(7,1)
/decl/emote/visible/floorspin
diff --git a/code/modules/emotes/emote_mob.dm b/code/modules/emotes/emote_mob.dm
index 3e45f05091e..546ee4c7aec 100644
--- a/code/modules/emotes/emote_mob.dm
+++ b/code/modules/emotes/emote_mob.dm
@@ -1,4 +1,9 @@
/mob/proc/can_emote(var/emote_type)
+ //VOREStation Add
+ if(src.nextemote >= world.time)
+ return FALSE
+ src.nextemote = world.time + 12
+ //VOREStation Add End
return (stat == CONSCIOUS)
/mob/living/can_emote(var/emote_type)
diff --git a/code/modules/food/kitchen/smartfridge/drying_rack.dm b/code/modules/food/kitchen/smartfridge/drying_rack.dm
new file mode 100644
index 00000000000..c0ceea5289c
--- /dev/null
+++ b/code/modules/food/kitchen/smartfridge/drying_rack.dm
@@ -0,0 +1,71 @@
+/obj/machinery/smartfridge/drying_rack
+ name = "\improper Drying Rack"
+ desc = "A machine for drying plants."
+ wrenchable = 1
+ icon_state = "drying_rack"
+ icon_base = "drying_rack"
+
+/obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj)
+ if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/))
+ var/obj/item/weapon/reagent_containers/food/snacks/S = O
+ if (S.dried_type)
+ return 1
+
+ if(istype(O, /obj/item/stack/wetleather))
+ return 1
+
+ return 0
+
+/obj/machinery/smartfridge/drying_rack/process()
+ ..()
+ if(stat & (BROKEN|NOPOWER))
+ return
+ if(contents.len)
+ dry()
+ update_icon()
+
+/obj/machinery/smartfridge/drying_rack/update_icon()
+ var/not_working = stat & (BROKEN|NOPOWER)
+ var/hasItems
+ for(var/datum/stored_item/I in item_records)
+ if(I.get_amount())
+ hasItems = 1
+ break
+ if(hasItems)
+ if(not_working)
+ icon_state = "[icon_base]-plant-off"
+ else
+ icon_state = "[icon_base]-plant"
+ else
+ if(not_working)
+ icon_state = "[icon_base]-off"
+ else
+ icon_state = "[icon_base]"
+
+/obj/machinery/smartfridge/drying_rack/proc/dry()
+ for(var/datum/stored_item/I in item_records)
+ for(var/obj/item/weapon/reagent_containers/food/snacks/S in I.instances)
+ if(S.dry) continue
+ if(S.dried_type == S.type)
+ S.dry = 1
+ S.name = "dried [S.name]"
+ S.color = "#AAAAAA"
+ I.instances -= S
+ S.forceMove(get_turf(src))
+ else
+ var/D = S.dried_type
+ new D(get_turf(src))
+ qdel(S)
+ return
+
+ for(var/obj/item/stack/wetleather/WL in I.instances)
+ if(!WL.wetness)
+ if(WL.amount)
+ WL.forceMove(get_turf(src))
+ WL.dry()
+ I.instances -= WL
+ break
+
+ WL.wetness = max(0, WL.wetness - rand(1, 3))
+
+ return
\ No newline at end of file
diff --git a/code/modules/food/kitchen/smartfridge/engineering.dm b/code/modules/food/kitchen/smartfridge/engineering.dm
new file mode 100644
index 00000000000..8141ca496df
--- /dev/null
+++ b/code/modules/food/kitchen/smartfridge/engineering.dm
@@ -0,0 +1,32 @@
+/obj/machinery/smartfridge/sheets //Is this used anywhere? It's not secure.
+ name = "\improper Smart Sheet Storage"
+ desc = "A storage unit for metals."
+ icon_state = "fridge_dark"
+ icon_base = "fridge_dark"
+ icon_contents = "slime"
+ stored_datum_type = /datum/stored_item/stack
+
+/obj/machinery/smartfridge/sheets/persistent
+ persistent = /datum/persistent/storage/smartfridge/sheet_storage
+
+/obj/machinery/smartfridge/sheets/persistent_lossy
+ persistent = /datum/persistent/storage/smartfridge/sheet_storage/lossy
+
+/obj/machinery/smartfridge/sheets/accept_check(var/obj/item/O)
+ return istype(O, /obj/item/stack/material)
+
+/obj/machinery/smartfridge/sheets/vend(datum/stored_item/stack/I, var/count)
+ var/amount = I.get_amount()
+ if(amount < 1)
+ return
+
+ while(count > 0)
+ var/obj/item/stack/S = I.get_product(get_turf(src), min(count, amount))
+ count -= S.amount
+ SStgui.update_uis(src)
+
+/obj/machinery/smartfridge/sheets/find_record(var/obj/item/O)
+ for(var/datum/stored_item/stack/I as anything in item_records)
+ if(istype(O, I.item_path)) // Typecheck should evaluate material-specific subtype
+ return I
+ return null
\ No newline at end of file
diff --git a/code/modules/food/kitchen/smartfridge/hydroponics.dm b/code/modules/food/kitchen/smartfridge/hydroponics.dm
new file mode 100644
index 00000000000..9b50136d796
--- /dev/null
+++ b/code/modules/food/kitchen/smartfridge/hydroponics.dm
@@ -0,0 +1,53 @@
+/obj/machinery/smartfridge/produce
+ name = "\improper Smart Produce Storage"
+ desc = "For storing all sorts of perishable foods!"
+ icon = 'icons/obj/vending.dmi'
+ icon_state = "fridge_food"
+ icon_base = "fridge_food"
+ icon_contents = "food"
+
+/obj/machinery/smartfridge/produce/persistent
+ persistent = /datum/persistent/storage/smartfridge/produce
+
+/obj/machinery/smartfridge/produce/persistent_lossy
+ persistent = /datum/persistent/storage/smartfridge/produce/lossy
+
+/obj/machinery/smartfridge/produce/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/))
+ return TRUE
+ return FALSE
+
+/obj/machinery/smartfridge/drinks
+ name = "\improper Drink Showcase"
+ desc = "A refrigerated storage unit for tasty tasty alcohol."
+ icon_state = "fridge_drinks"
+ icon_base = "fridge_drinks"
+ icon_contents = "drink"
+
+/obj/machinery/smartfridge/drinks/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment))
+ return TRUE
+ return FALSE
+
+/obj/machinery/smartfridge/seeds
+ name = "\improper MegaSeed Servitor"
+ desc = "When you need seeds fast!"
+ icon_contents = "chem"
+
+/obj/machinery/smartfridge/seeds/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/seeds/))
+ return 1
+ return 0
+
+/obj/machinery/smartfridge/secure/extract
+ name = "\improper Biological Sample Storage"
+ desc = "A refrigerated storage unit for xenobiological samples."
+ icon_contents = "slime"
+ req_access = list(access_research)
+
+/obj/machinery/smartfridge/secure/extract/accept_check(var/obj/item/O as obj)
+ if(istype(O, /obj/item/slime_extract))
+ return TRUE
+ if(istype(O, /obj/item/slimepotion))
+ return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/code/modules/food/kitchen/smartfridge/medical.dm b/code/modules/food/kitchen/smartfridge/medical.dm
new file mode 100644
index 00000000000..609f707a068
--- /dev/null
+++ b/code/modules/food/kitchen/smartfridge/medical.dm
@@ -0,0 +1,40 @@
+/obj/machinery/smartfridge/secure/medbay
+ name = "\improper Refrigerated Medicine Storage"
+ desc = "A refrigerated storage unit for storing medicine and chemicals."
+ req_one_access = list(access_medical,access_chemistry)
+
+/obj/machinery/smartfridge/secure/medbay/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/weapon/reagent_containers/glass/))
+ return 1
+ if(istype(O,/obj/item/weapon/storage/pill_bottle/))
+ return 1
+ if(istype(O,/obj/item/weapon/reagent_containers/pill/))
+ return 1
+ return 0
+
+/obj/machinery/smartfridge/secure/virology
+ name = "\improper Refrigerated Virus Storage"
+ desc = "A refrigerated storage unit for storing viral material."
+ icon_contents = "drink"
+ req_access = list(access_virology)
+
+/obj/machinery/smartfridge/secure/virology/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial/))
+ return 1
+ if(istype(O,/obj/item/weapon/virusdish/))
+ return 1
+ return 0
+
+/obj/machinery/smartfridge/chemistry //Is this used anywhere? It's not secure.
+ name = "\improper Smart Chemical Storage"
+ desc = "A refrigerated storage unit for medicine and chemical storage."
+ icon_contents = "chem"
+
+/obj/machinery/smartfridge/chemistry/accept_check(var/obj/item/O as obj)
+ if(istype(O,/obj/item/weapon/storage/pill_bottle) || istype(O,/obj/item/weapon/reagent_containers))
+ return 1
+ return 0
+
+/obj/machinery/smartfridge/chemistry/virology //Same
+ name = "\improper Smart Virus Storage"
+ desc = "A refrigerated storage unit for volatile sample storage."
\ No newline at end of file
diff --git a/code/modules/food/kitchen/smartfridge.dm b/code/modules/food/kitchen/smartfridge/smartfridge.dm
similarity index 53%
rename from code/modules/food/kitchen/smartfridge.dm
rename to code/modules/food/kitchen/smartfridge/smartfridge.dm
index a6def6bd2b0..f43c9c49317 100644
--- a/code/modules/food/kitchen/smartfridge.dm
+++ b/code/modules/food/kitchen/smartfridge/smartfridge.dm
@@ -2,7 +2,7 @@
*/
/obj/machinery/smartfridge
name = "\improper SmartFridge"
- desc = "For storing all sorts of perishable foods!"
+ desc = "For storing all sorts of things! This one doesn't accept any of them!"
icon = 'icons/obj/vending.dmi'
icon_state = "fridge_food"
var/icon_base = "fridge_food" //Iconstate to base all the broken/deny/etc on
@@ -13,10 +13,10 @@
idle_power_usage = 5
active_power_usage = 100
flags = NOREACT
- var/max_n_of_items = 999 // Sorry but the BYOND infinite loop detector doesn't look things over 1000. //VOREStation Edit - Non-global
- //var/global/max_n_of_items = 999 // Sorry but the BYOND infinite loop detector doesn't look things over 1000.
+ var/max_n_of_items = 999 // Sorry but the BYOND infinite loop detector doesn't look things over 1000. //VOREStation Edit - Nonglobal so subtypes can override to lower values
var/list/item_records = list()
var/datum/stored_item/currently_vending = null //What we're putting out of the machine.
+ var/stored_datum_type = /datum/stored_item
var/seconds_electrified = 0;
var/shoot_inventory = 0
var/locked = 0
@@ -24,6 +24,7 @@
var/is_secure = 0
var/wrenchable = 0
var/datum/wires/smartfridge/wires = null
+ var/persistent = null // Path of persistence datum used to track contents
/obj/machinery/smartfridge/secure
is_secure = 1
@@ -31,8 +32,10 @@
icon_base = "fridge_sci"
icon_contents = "chem"
-/obj/machinery/smartfridge/New()
- ..()
+/obj/machinery/smartfridge/Initialize()
+ . = ..()
+ if(persistent)
+ SSpersistence.track_value(src, persistent)
if(is_secure)
wires = new/datum/wires/smartfridge/secure(src)
else
@@ -43,160 +46,13 @@
for(var/A in item_records) //Get rid of item records.
qdel(A)
wires = null
+ if(persistent)
+ SSpersistence.forget_value(src, persistent)
return ..()
/obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/seeds
- name = "\improper MegaSeed Servitor"
- desc = "When you need seeds fast!"
- icon_contents = "chem"
-
-/obj/machinery/smartfridge/seeds/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/seeds/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/extract
- name = "\improper Biological Sample Storage"
- desc = "A refrigerated storage unit for xenobiological samples."
- icon_contents = "slime"
- req_access = list(access_research)
-
-/obj/machinery/smartfridge/secure/extract/accept_check(var/obj/item/O as obj)
- if(istype(O, /obj/item/slime_extract))
- return TRUE
- if(istype(O, /obj/item/slimepotion))
- return TRUE
return FALSE
-/obj/machinery/smartfridge/secure/medbay
- name = "\improper Refrigerated Medicine Storage"
- desc = "A refrigerated storage unit for storing medicine and chemicals."
- req_one_access = list(access_medical,access_chemistry)
-
-/obj/machinery/smartfridge/secure/medbay/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/weapon/reagent_containers/glass/))
- return 1
- if(istype(O,/obj/item/weapon/storage/pill_bottle/))
- return 1
- if(istype(O,/obj/item/weapon/reagent_containers/pill/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/virology
- name = "\improper Refrigerated Virus Storage"
- desc = "A refrigerated storage unit for storing viral material."
- icon_contents = "drink"
- req_access = list(access_virology)
-
-/obj/machinery/smartfridge/secure/virology/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/weapon/reagent_containers/glass/beaker/vial/))
- return 1
- if(istype(O,/obj/item/weapon/virusdish/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/chemistry //Is this used anywhere? It's not secure.
- name = "\improper Smart Chemical Storage"
- desc = "A refrigerated storage unit for medicine and chemical storage."
- icon_contents = "chem"
-
-/obj/machinery/smartfridge/chemistry/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/weapon/storage/pill_bottle) || istype(O,/obj/item/weapon/reagent_containers))
- return 1
- return 0
-
-/obj/machinery/smartfridge/chemistry/virology //Same
- name = "\improper Smart Virus Storage"
- desc = "A refrigerated storage unit for volatile sample storage."
-
-/obj/machinery/smartfridge/drinks
- name = "\improper Drink Showcase"
- desc = "A refrigerated storage unit for tasty tasty alcohol."
- icon_state = "fridge_drinks"
- icon_base = "fridge_drinks"
- icon_contents = "drink"
-
-/obj/machinery/smartfridge/drinks/accept_check(var/obj/item/O as obj)
- if(istype(O,/obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks) || istype(O,/obj/item/weapon/reagent_containers/food/condiment))
- return 1
-
-/obj/machinery/smartfridge/drying_rack
- name = "\improper Drying Rack"
- desc = "A machine for drying plants."
- wrenchable = 1
- icon_state = "drying_rack"
- icon_base = "drying_rack"
-
-/obj/machinery/smartfridge/drying_rack/accept_check(var/obj/item/O as obj)
- if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/))
- var/obj/item/weapon/reagent_containers/food/snacks/S = O
- if (S.dried_type)
- return 1
-
- if(istype(O, /obj/item/stack/wetleather))
- return 1
-
- return 0
-
-/obj/machinery/smartfridge/drying_rack/process()
- ..()
- if(stat & (BROKEN|NOPOWER))
- return
- if(contents.len)
- dry()
- update_icon()
-
-/obj/machinery/smartfridge/drying_rack/update_icon()
- var/not_working = stat & (BROKEN|NOPOWER)
- var/hasItems
- for(var/datum/stored_item/I in item_records)
- if(I.get_amount())
- hasItems = 1
- break
- if(hasItems)
- if(not_working)
- icon_state = "[icon_base]-plant-off"
- else
- icon_state = "[icon_base]-plant"
- else
- if(not_working)
- icon_state = "[icon_base]-off"
- else
- icon_state = "[icon_base]"
-
-/obj/machinery/smartfridge/drying_rack/proc/dry()
- for(var/datum/stored_item/I in item_records)
- for(var/obj/item/weapon/reagent_containers/food/snacks/S in I.instances)
- if(S.dry) continue
- if(S.dried_type == S.type)
- S.dry = 1
- S.name = "dried [S.name]"
- S.color = "#AAAAAA"
- I.instances -= S
- S.forceMove(get_turf(src))
- else
- var/D = S.dried_type
- new D(get_turf(src))
- qdel(S)
- return
-
- for(var/obj/item/stack/wetleather/WL in I.instances)
- if(!WL.wetness)
- if(WL.amount)
- WL.forceMove(get_turf(src))
- WL.dry()
- I.instances -= WL
- break
-
- WL.wetness = max(0, WL.wetness - rand(1, 3))
-
- return
-
/obj/machinery/smartfridge/process()
if(stat & (BROKEN|NOPOWER))
return
@@ -229,7 +85,7 @@
is_off = "-off"
// Fridge contents
- if(contents) //VOREStation Edit - Some fridges do not have visible contents
+ if(contents)
switch(contents.len)
if(0)
add_overlay("empty[is_off]")
@@ -311,21 +167,28 @@
to_chat(user, "You short out the product lock on [src].")
return 1
-/obj/machinery/smartfridge/proc/stock(obj/item/O)
- var/hasRecord = FALSE //Check to see if this passes or not.
- for(var/datum/stored_item/I in item_records)
+/obj/machinery/smartfridge/proc/find_record(var/obj/item/O)
+ for(var/datum/stored_item/I as anything in item_records)
if((O.type == I.item_path) && (O.name == I.item_name))
- I.add_product(O)
- hasRecord = TRUE
- break
- if(!hasRecord)
- var/datum/stored_item/item = new/datum/stored_item(src, O.type, O.name)
- item.add_product(O)
- item_records.Add(item)
+ return I
+ return null
+
+/obj/machinery/smartfridge/proc/stock(obj/item/O)
+ var/datum/stored_item/I = find_record(O)
+ if(!istype(I))
+ I = new stored_datum_type(src, O.type, O.name)
+ item_records.Add(I)
+ I.add_product(O)
SStgui.update_uis(src)
-/obj/machinery/smartfridge/proc/vend(datum/stored_item/I)
- I.get_product(get_turf(src))
+/obj/machinery/smartfridge/proc/vend(datum/stored_item/I, var/count)
+ var/amount = I.get_amount()
+ // Sanity check, there are probably ways to press the button when it shouldn't be possible.
+ if(amount <= 0)
+ return
+
+ for(var/i = 1 to min(amount, count))
+ I.get_product(get_turf(src))
SStgui.update_uis(src)
/obj/machinery/smartfridge/attack_ai(mob/user as mob)
@@ -376,16 +239,10 @@
return FALSE
var/index = text2num(params["index"])
- var/datum/stored_item/I = item_records[index]
- var/count = I.get_amount()
-
- // Sanity check, there are probably ways to press the button when it shouldn't be possible.
- if(count > 0)
- if((count - amount) < 0)
- amount = count
- for(var/i = 1 to amount)
- vend(I)
-
+ if(index < 1 || index > LAZYLEN(item_records))
+ return TRUE
+
+ vend(item_records[index], amount)
return TRUE
return FALSE
@@ -393,7 +250,7 @@
var/obj/throw_item = null
var/mob/living/target = locate() in view(7,src)
if(!target)
- return 0
+ return FALSE
for(var/datum/stored_item/I in item_records)
throw_item = I.get_product(get_turf(src))
@@ -402,12 +259,12 @@
break
if(!throw_item)
- return 0
+ return FALSE
spawn(0)
throw_item.throw_at(target,16,3,src)
src.visible_message("[src] launches [throw_item.name] at [target.name]!")
SStgui.update_uis(src)
- return 1
+ return TRUE
/************************
* Secure SmartFridges
diff --git a/code/modules/food/kitchen/smartfridge_vr.dm b/code/modules/food/kitchen/smartfridge/smartfridge_vr.dm
similarity index 100%
rename from code/modules/food/kitchen/smartfridge_vr.dm
rename to code/modules/food/kitchen/smartfridge/smartfridge_vr.dm
diff --git a/code/modules/mob/living/carbon/breathe.dm b/code/modules/mob/living/carbon/breathe.dm
index 2b8ce410635..1945db3e90a 100644
--- a/code/modules/mob/living/carbon/breathe.dm
+++ b/code/modules/mob/living/carbon/breathe.dm
@@ -17,7 +17,7 @@
if(losebreath>0) //Suffocating so do not take a breath
AdjustLosebreath(-1)
- if (prob(10)) //Gasp per 10 ticks? Sounds about right.
+ if (prob(10) && !isbelly(loc)) //Gasp per 10 ticks? Sounds about right. //VOREStation Add
spawn emote("gasp")
else
//Okay, we can breathe, now check if we can get air
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index a705f034506..aba6241d652 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -124,6 +124,7 @@ var/list/_human_default_emotes = list(
/decl/emote/audible/croak,
/decl/emote/audible/gao,
/decl/emote/audible/cackle,
+ /decl/emote/audible/squish,
/decl/emote/visible/mlem,
/decl/emote/visible/blep,
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index cdfef35b596..3ceea87f7b4 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -68,11 +68,12 @@ emp_act
msg_admin_attack("[key_name(src)] was disarmed by a stun effect")
drop_from_inventory(c_hand)
- if (affected.robotic >= ORGAN_ROBOT)
- custom_emote(VISIBLE_MESSAGE, "drops what they were holding, their [affected.name] malfunctioning!")
- else
- var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
- custom_emote(VISIBLE_MESSAGE, "[affected.organ_can_feel_pain() ? "" : emote_scream] drops what they were holding in their [affected.name]!")
+ if(!isbelly(loc)) //VOREStation Add
+ if (affected.robotic >= ORGAN_ROBOT)
+ custom_emote(VISIBLE_MESSAGE, "drops what they were holding, their [affected.name] malfunctioning!")
+ else
+ var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
+ custom_emote(VISIBLE_MESSAGE, "[affected.organ_can_feel_pain() ? "" : emote_scream] drops what they were holding in their [affected.name]!")
..(stun_amount, agony_amount, def_zone)
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index f9c9bc831d1..4b94ff930a4 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -163,8 +163,9 @@
continue
drop_from_inventory(r_hand)
- var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
- custom_emote(VISIBLE_MESSAGE, "[(can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
+ if(!isbelly(loc)) //VOREStation Add
+ var/emote_scream = pick("screams in pain and ", "lets out a sharp cry and ", "cries out and ")
+ custom_emote(VISIBLE_MESSAGE, "[(can_feel_pain()) ? "" : emote_scream ]drops what they were holding in their [E.name]!")
else if(E.is_malfunctioning())
switch(E.body_part)
@@ -177,14 +178,15 @@
continue
drop_from_inventory(r_hand)
- custom_emote(VISIBLE_MESSAGE, "drops what they were holding, their [E.name] malfunctioning!")
+ if(!isbelly(loc)) //VOREStation Add
+ custom_emote(VISIBLE_MESSAGE, "drops what they were holding, their [E.name] malfunctioning!")
- var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
- spark_system.set_up(5, 0, src)
- spark_system.attach(src)
- spark_system.start()
- spawn(10)
- qdel(spark_system)
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, src)
+ spark_system.attach(src)
+ spark_system.start()
+ spawn(10)
+ qdel(spark_system)
//Handles chem traces
/mob/living/carbon/human/proc/handle_trace_chems()
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 767d68a56e7..dab0f0d18f6 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -1044,7 +1044,7 @@
if(client || sleeping > 3)
AdjustSleeping(-1)
throw_alert("asleep", /obj/screen/alert/asleep)
- if( prob(2) && health && !hal_crit )
+ if( prob(2) && health && !hal_crit && client )
spawn(0)
emote("snore")
//CONSCIOUS
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
index 15d5af23f24..a0fe3a017c4 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_modules_vr.dm
@@ -439,3 +439,27 @@
T.apply_damage(20, HALLOSS,, armor_block, armor_soak)
if(prob(75)) //75% chance to stun for 5 seconds, really only going to be 4 bcus click cooldown+animation.
T.apply_effect(5, WEAKEN, armor_block)
+
+
+/mob/living/silicon/robot/proc/reskin_booze()
+ set name = "Change Drink Color"
+ set category = "Robot Commands"
+ set desc = "Choose the color of drink displayed inside you."
+
+ var/mob/M = usr
+ var/list/options = list()
+ options["Beer"] = "Beer Buddy"
+ options["Curacao"] = "Brilliant Blue"
+ options["Coffee"] = "Caffine Dispenser"
+ options["Space Mountain Wind"] = "Gamer Juice Maker"
+ options["Whiskey Soda"] = "Liqour Licker"
+ options["Grape Soda"] = "The Grapist"
+ options["Demon's Blood"] = "Vampire's Aid"
+ var/choice = input(M,"Choose your drink!") in options
+ if(src && choice && !M.stat && in_range(M,src))
+ icontype = options[choice]
+ var/active_sound = 'sound/effects/bubbles.ogg'
+ playsound(src.loc, "[active_sound]", 100, 0, 4)
+ M << "Your Tank now displays [choice]. Drink up and enjoy!"
+ updateicon()
+ return 1
diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
index cc5e4aaced7..7f6a4475b89 100644
--- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
+++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm
@@ -716,3 +716,10 @@
recycles = FALSE
#undef SLEEPER_INJECT_COST
+
+
+/obj/item/device/dogborg/sleeper/compactor/brewer
+ name = "Brew Belly"
+ desc = "A mounted drunk tank unit with fuel processor."
+ icon_state = "brewer"
+ injection_chems = null
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm
index cb7e7680070..4df9b63eee5 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules/station_vr.dm
@@ -47,6 +47,7 @@
robot_modules["Sci-borg"] = /obj/item/weapon/robot_module/robot/science
robot_modules["Pupdozer"] = /obj/item/weapon/robot_module/robot/engiedog
robot_modules["Service-Hound"] = /obj/item/weapon/robot_module/robot/clerical/brodog
+ robot_modules["BoozeHound"] = /obj/item/weapon/robot_module/robot/booze
robot_modules["KMine"] = /obj/item/weapon/robot_module/robot/kmine
return 1
@@ -812,3 +813,75 @@
R.verbs -= /mob/living/proc/shred_limb
R.verbs -= /mob/living/silicon/robot/proc/rest_style
..()
+
+
+/obj/item/weapon/robot_module/robot/booze
+ name = "BoozeHound robot module"
+ channels = list("Service" = 1)
+ pto_type = PTO_CIVILIAN
+ can_be_pushed = 0
+ sprites = list(
+ "Beer Buddy" = "boozeborg",
+ "Brilliant Blue" = "boozeborg(blue)",
+ "Caffine Dispenser" = "boozeborg(coffee)",
+ "Gamer Juice Maker" = "boozeborg(green)",
+ "Liqour Licker" = "boozeborg(orange)",
+ "The Grapist" = "boozeborg(purple)",
+ "Vampire's Aid" = "boozeborg(red)"
+ )
+
+/obj/item/weapon/robot_module/robot/booze/New(var/mob/living/silicon/robot/R)
+ ..()
+ src.modules += new /obj/item/weapon/gripper/service(src)
+ //src.modules += new /obj/item/weapon/reagent_containers/glass/bucket(src)
+ //src.modules += new /obj/item/weapon/material/minihoe(src)
+ //src.modules += new /obj/item/device/analyzer/plant_analyzer(src)
+ //src.modules += new /obj/item/weapon/storage/bag/plants(src)
+ //src.modules += new /obj/item/weapon/robot_harvester(src)
+ src.modules += new /obj/item/weapon/material/knife(src)
+ src.modules += new /obj/item/weapon/material/kitchen/rollingpin(src)
+ src.modules += new /obj/item/device/multitool(src) //to freeze trays
+ src.modules += new /obj/item/weapon/dogborg/jaws/small(src)
+ src.modules += new /obj/item/weapon/tray/robotray
+ src.modules += new /obj/item/device/dogborg/boop_module(src)
+ src.modules += new /obj/item/device/dogborg/sleeper/compactor/brewer(src)
+ src.emag = new /obj/item/weapon/dogborg/pounce(src)
+ R.verbs += /mob/living/silicon/robot/proc/reskin_booze
+
+ var/obj/item/weapon/rsf/M = new /obj/item/weapon/rsf(src)
+ M.stored_matter = 30
+ src.modules += M
+
+ src.modules += new /obj/item/weapon/reagent_containers/dropper/industrial(src)
+
+ var/obj/item/weapon/flame/lighter/zippo/L = new /obj/item/weapon/flame/lighter/zippo(src)
+ L.lit = 1
+ src.modules += L
+
+ src.modules += new /obj/item/weapon/tray/robotray(src)
+ src.modules += new /obj/item/weapon/reagent_containers/borghypo/service(src)
+ src.emag = new /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer(src)
+
+ var/datum/reagents/N = new/datum/reagents(50)
+ src.emag.reagents = N
+ N.my_atom = src.emag
+ N.add_reagent("beer2", 50)
+ src.emag.name = "Mickey Finn's Special Brew"
+ R.icon = 'icons/mob/widerobot_colors_vr.dmi'
+ R.wideborg_dept = 'icons/mob/widerobot_colors_vr.dmi'
+ R.hands.icon = 'icons/mob/screen1_robot_vr.dmi'
+ R.ui_style_vr = TRUE
+ R.pixel_x = -16
+ R.old_x = -16
+ R.default_pixel_x = -16
+ R.dogborg = TRUE
+ R.wideborg = TRUE
+ R.verbs |= /mob/living/silicon/robot/proc/ex_reserve_refill
+ ..()
+
+/obj/item/weapon/robot_module/robot/booze/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
+ var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
+ E.reagents.add_reagent("enzyme", 2 * amount)
+ if(src.emag)
+ var/obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer/B = src.emag
+ B.reagents.add_reagent("beer2", 2 * amount)
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm
index 45ce8eb9ad5..a84177f29c1 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm
@@ -47,9 +47,10 @@
attack_armor_pen = 25
pixel_x = -16
- pixel_y = -16
+ pixel_y = 0
+ default_pixel_x = -16
old_x = -16
- old_y = -16
+ old_y = 0
/mob/living/simple_mob/animal/giant_spider/nurse/eggless/lay_eggs(turf/T)
return FALSE
diff --git a/code/modules/multiz/movement_vr.dm b/code/modules/multiz/movement_vr.dm
index bbca4eef0d6..cba6ebb6c58 100644
--- a/code/modules/multiz/movement_vr.dm
+++ b/code/modules/multiz/movement_vr.dm
@@ -1,6 +1,6 @@
/mob/living/handle_fall(var/turf/landing)
- var/mob/drop_mob = locate(/mob, landing)
+ var/mob/drop_mob = locate(/mob/living, landing)
if(locate(/obj/structure/stairs) in landing)
for(var/atom/A in landing)
@@ -17,7 +17,7 @@
if(!O.CanFallThru(src, landing))
return 1
- if(drop_mob && !(drop_mob == src) && ismob(drop_mob) && isliving(drop_mob)) //Shitload of checks. This is because the game finds various ways to screw me over.
+ if(drop_mob && !(drop_mob == src)) //Shitload of checks. This is because the game finds various ways to screw me over.
var/mob/living/drop_living = drop_mob
if(drop_living.dropped_onto(src))
return
@@ -105,4 +105,4 @@
if(direction == UP) //on a turf below, trying to enter
return 0
if(direction == DOWN) //on a turf above, trying to enter
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/modules/nifsoft/nif.dm b/code/modules/nifsoft/nif.dm
index 1fd3503d41c..aa2d1a99f59 100644
--- a/code/modules/nifsoft/nif.dm
+++ b/code/modules/nifsoft/nif.dm
@@ -102,9 +102,6 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
//Draw me yo.
update_icon()
- if(!our_statclick)
- our_statclick = new(null, "Open", src)
-
//Destructor cleans up references
/obj/item/device/nif/Destroy()
human = null
@@ -127,6 +124,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
human.nif = src
stat = NIF_INSTALLING
H.verbs |= /mob/living/carbon/human/proc/set_nif_examine
+ menu = H.AddComponent(/datum/component/nif_menu)
if(starting_software)
for(var/path in starting_software)
new path(src)
@@ -169,6 +167,7 @@ You can also set the stat of a NIF to NIF_TEMPFAIL without any issues to disable
stat = NIF_PREINSTALL
vis_update()
H.verbs -= /mob/living/carbon/human/proc/set_nif_examine
+ qdel_null(menu)
H.nif = null
human = null
install_done = null
diff --git a/code/modules/nifsoft/nif_statpanel.dm b/code/modules/nifsoft/nif_statpanel.dm
deleted file mode 100644
index 00e928429fb..00000000000
--- a/code/modules/nifsoft/nif_statpanel.dm
+++ /dev/null
@@ -1,79 +0,0 @@
-/mob/living/carbon/human/Stat()
- . = ..()
- if(nif && statpanel("NIF"))
- SetupNifStat()
-
-/mob/living/carbon/human/proc/SetupNifStat()
- var/nif_status = ""
- var/nif_percent = round((nif.durability/initial(nif.durability))*100)
- switch(nif.stat)
- if(NIF_WORKING)
- if(nif_percent < 20)
- nif_status = "Service Needed Soon"
- else
- nif_status = "Operating Normally"
- if(NIF_POWFAIL)
- nif_status = "Insufficient Energy!"
- if(NIF_TEMPFAIL)
- nif_status = "System Failure!"
- if(NIF_INSTALLING)
- nif_status = "Adapting To User"
- else
- nif_status = "Unknown - Error"
- nif_status += " (Condition: [nif_percent]%)"
- stat("NIF Status", nif_status)
- stat("UI", nif.our_statclick) // TGUI Hook
-
- if(nif.stat == NIF_WORKING)
- stat("- Modules -", "LMB: Toggle, Shift+LMB: Info/Uninstall")
- for(var/nifsoft in nif.nifsofts)
- if(!nifsoft) continue
- var/datum/nifsoft/NS = nifsoft
- var/obj/effect/nif_stat/stat_line = NS.stat_line
- stat("[stat_line.nifsoft_name]",stat_line.atom_button_text())
-
-///////////////////
-// Stat Line Object
-/obj/effect/nif_stat
- name = ""
- var/nifsoft_name //Prevents deeper lookups, and the name won't change
- var/datum/nifsoft/nifsoft //Reference to our nifsoft
- var/toggleable = FALSE //Won't change, prevents looking it up deeper
-
-/obj/effect/nif_stat/New(var/datum/nifsoft/new_soft)
- ..()
- nifsoft = new_soft
- nifsoft_name = new_soft.name
- name = new_soft.name
-
-/obj/effect/nif_stat/Destroy()
- nifsoft = null
- return ..()
-
-/obj/effect/nif_stat/proc/atom_button_text()
- name = nifsoft.stat_text()
- return src
-
-/obj/effect/nif_stat/Click(var/location, var/control, var/params)
- if(usr != nifsoft.nif.human) return
-
- var/list/clickprops = params2list(params)
- var/opts = clickprops["shift"]
-
- if(opts)
- var/choice = alert("Select an option","[nifsoft_name]","Display Info","Cancel","Uninstall")
- switch(choice)
- if("Display Info")
- nifsoft.nif.notify("[nifsoft_name]: [nifsoft.desc] - It consumes [nifsoft.p_drain] energy units \
- while installed, and [nifsoft.a_drain] additionally while active. It is [nifsoft.illegal ? "NOT " : ""]\
- a legal software package. The MSRP of the package is [nifsoft.cost] Thalers. The difficulty to construct \
- the associated implant is Rating [nifsoft.wear].")
- if("Uninstall")
- var/confirm = alert("Really uninstall [nifsoft_name]?","Are you sure?","Cancel","Uninstall","Cancel")
- if(confirm == "Uninstall")
- nifsoft.uninstall()
- else if(nifsoft.activates)
- if(nifsoft.active)
- nifsoft.deactivate()
- else
- nifsoft.activate()
diff --git a/code/modules/nifsoft/nif_tgui.dm b/code/modules/nifsoft/nif_tgui.dm
index 23d8102f793..b3d3aa00a7a 100644
--- a/code/modules/nifsoft/nif_tgui.dm
+++ b/code/modules/nifsoft/nif_tgui.dm
@@ -15,15 +15,75 @@
"retro",
"syndicate"
)
- var/tmp/obj/effect/statclick/nif_open/our_statclick
var/tmp/last_notification
+ var/tmp/datum/component/nif_menu/menu
/**
- * Special stat button for the interface
+ * Small helper component to manage the HUD icon
*/
-/obj/effect/statclick/nif_open
-/obj/effect/statclick/nif_open/Click(location, control, params)
- var/obj/item/device/nif/N = target
+/datum/component/nif_menu
+ var/obj/screen/nif/screen_icon
+
+/datum/component/nif_menu/Initialize()
+ if(!ismob(parent))
+ return COMPONENT_INCOMPATIBLE
+ . = ..()
+
+/datum/component/nif_menu/RegisterWithParent()
+ . = ..()
+ RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
+ var/mob/owner = parent
+ if(owner.client)
+ create_mob_button(parent)
+
+/datum/component/nif_menu/UnregisterFromParent()
+ . = ..()
+ UnregisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN)
+ if(ismob(parent))
+ var/mob/owner = parent
+ if(screen_icon)
+ owner?.client?.screen -= screen_icon
+ UnregisterSignal(screen_icon, COMSIG_CLICK)
+ qdel_null(screen_icon)
+ if(ishuman(parent))
+ owner.verbs -= /mob/living/carbon/human/proc/nif_menu
+
+
+/datum/component/nif_menu/proc/create_mob_button(mob/user)
+ var/datum/hud/HUD = user.hud_used
+ if(!screen_icon)
+ screen_icon = new()
+ screen_icon.icon = HUD.ui_style
+ HUD.other += screen_icon
+ user.client?.screen += screen_icon
+
+ user.verbs |= /mob/living/carbon/human/proc/nif_menu
+
+ RegisterSignal(screen_icon, COMSIG_CLICK, .proc/nif_menu_click)
+
+/datum/component/nif_menu/proc/nif_menu_click(atom/movable/screen/nif/image, location, control, params, user)
+ var/mob/living/carbon/human/H = user
+ if(istype(H) && H.nif)
+ INVOKE_ASYNC(H.nif, .proc/tgui_interact, user)
+
+/**
+ * Screen object for NIF menu access
+ */
+/obj/screen/nif
+ name = "nif menu"
+ icon = 'icons/mob/screen/midnight.dmi'
+ icon_state = "nif"
+ screen_loc = ui_smallquad
+
+/**
+ * Verb to open the interface
+ */
+/mob/living/carbon/human/proc/nif_menu()
+ set name = "NIF Menu"
+ set category = "IC"
+ set desc = "Open the NIF user interface."
+
+ var/obj/item/device/nif/N = nif
if(istype(N))
N.tgui_interact(usr)
@@ -111,4 +171,4 @@
return TRUE
if("dismissNotification")
last_notification = null
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/modules/nifsoft/nifsoft.dm b/code/modules/nifsoft/nifsoft.dm
index ca1d0199a69..951e2932183 100644
--- a/code/modules/nifsoft/nifsoft.dm
+++ b/code/modules/nifsoft/nifsoft.dm
@@ -39,15 +39,11 @@
var/list/incompatible_with = null // List of NIFSofts that are disabled when this one is enabled
- var/obj/effect/nif_stat/stat_line // The stat line in the statpanel for this NIFSoft
-
-
//Constructor accepts the NIF it's being loaded into
/datum/nifsoft/New(var/obj/item/device/nif/nif_load)
ASSERT(nif_load)
nif = nif_load
- stat_line = new(src)
if(!install(nif))
qdel(src)
@@ -56,7 +52,6 @@
if(nif)
uninstall()
nif = null
- QDEL_NULL(stat_line)
return ..()
//Called when the software is installed in the NIF
@@ -138,7 +133,7 @@
/datum/nifsoft/proc/disk_install(var/mob/living/carbon/human/target,var/mob/living/carbon/human/user)
return TRUE
-//Stat-line clickable text
+//Status text for menu
/datum/nifsoft/proc/stat_text()
if(activates)
return "[active ? "Active" : "Disabled"]"
diff --git a/code/modules/persistence/datum/datum_paper_sticky.dm b/code/modules/persistence/datum/datum_paper_sticky.dm
deleted file mode 100644
index 1871eb4a037..00000000000
--- a/code/modules/persistence/datum/datum_paper_sticky.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-/datum/persistent/paper/sticky
- name = "stickynotes"
- paper_type = /obj/item/weapon/paper/sticky
- requires_noticeboard = FALSE
- tokens_per_line = 10
-
-/datum/persistent/paper/sticky/LabelTokens(var/list/tokens)
- var/list/labelled_tokens = ..()
- var/entries = LAZYLEN(labelled_tokens)
- labelled_tokens["offset_x"] = tokens[entries+1]
- labelled_tokens["offset_y"] = tokens[entries+2]
- labelled_tokens["color"] = tokens[entries+3]
- return labelled_tokens
-
-/datum/persistent/paper/sticky/CreateEntryInstance(var/turf/creating, var/list/tokens)
- var/atom/paper = ..()
- if(paper)
- paper.pixel_x = text2num(tokens["offset_x"])
- paper.pixel_y = text2num(tokens["offset_y"])
- paper.color = tokens["color"]
- return paper
-
-/datum/persistent/paper/sticky/CompileEntry(var/atom/entry, var/write_file)
- . = ..()
- var/obj/item/weapon/paper/sticky/paper = entry
- LAZYADD(., "[paper.pixel_x]")
- LAZYADD(., "[paper.pixel_y]")
- LAZYADD(., "[paper.color]")
\ No newline at end of file
diff --git a/code/modules/persistence/datum/persistence_datum.dm b/code/modules/persistence/datum/persistence_datum.dm
index e001e12e302..a52b57fb66c 100644
--- a/code/modules/persistence/datum/persistence_datum.dm
+++ b/code/modules/persistence/datum/persistence_datum.dm
@@ -3,15 +3,11 @@
// of persistent data like graffiti and round to round filth.
/datum/persistent
- var/name
+ var/name = null
var/filename
- var/tokens_per_line
var/entries_expire_at // Set in rounds, this controls when the item is finally removed permanently regardless if cleaned or not.
var/entries_decay_at // Set in rounds. This controls when item messages start getting scrambled.
var/entry_decay_weight = 0.5
- var/file_entry_split_character = "\t"
- var/file_entry_substitute_character = " "
- var/file_line_split_character = "\n"
var/has_admin_data
/datum/persistent/New()
@@ -20,63 +16,57 @@
/datum/persistent/proc/SetFilename()
if(name)
- filename = "data/persistent/[lowertext(using_map.name)]-[lowertext(name)].txt"
+ filename = "data/persistent/[lowertext(using_map.name)]-[lowertext(name)].json"
if(!isnull(entries_decay_at) && !isnull(entries_expire_at))
entries_decay_at = round(entries_expire_at * entries_decay_at)
-/datum/persistent/proc/LabelTokens(var/list/tokens)
- var/list/labelled_tokens = list()
- labelled_tokens["x"] = text2num(tokens[1])
- labelled_tokens["y"] = text2num(tokens[2])
- labelled_tokens["z"] = text2num(tokens[3])
- labelled_tokens["age"] = text2num(tokens[4])
- return labelled_tokens
-
-/datum/persistent/proc/GetValidTurf(var/turf/T, var/list/tokens)
- if(T && CheckTurfContents(T, tokens))
+/datum/persistent/proc/GetValidTurf(var/turf/T, var/list/token)
+ if(T && CheckTurfContents(T, token))
return T
-/datum/persistent/proc/CheckTurfContents(var/turf/T, var/list/tokens)
+/datum/persistent/proc/CheckTurfContents(var/turf/T, var/list/token)
return TRUE
-/datum/persistent/proc/CheckTokenSanity(var/list/tokens)
+/datum/persistent/proc/CheckTokenSanity(var/list/token)
return ( \
- !isnull(tokens["x"]) && \
- !isnull(tokens["y"]) && \
- !isnull(tokens["z"]) && \
- !isnull(tokens["age"]) && \
- tokens["age"] <= entries_expire_at \
+ !isnull(token["x"]) && \
+ !isnull(token["y"]) && \
+ !isnull(token["z"]) && \
+ !isnull(token["age"]) && \
+ token["age"] <= entries_expire_at \
)
-/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/tokens)
+// Restores saved data to world
+/datum/persistent/proc/CreateEntryInstance(var/turf/creating, var/list/token)
return
/datum/persistent/proc/ProcessAndApplyTokens(var/list/tokens)
// If it's old enough we start to trim down any textual information and scramble strings.
- if(tokens["message"] && !isnull(entries_decay_at) && !isnull(entry_decay_weight))
- var/_n = tokens["age"]
- var/_message = tokens["message"]
- if(_n >= entries_decay_at)
- var/decayed_message = ""
- for(var/i = 1 to length(_message))
- var/char = copytext(_message, i, i + 1)
- if(prob(round(_n * entry_decay_weight)))
- if(prob(99))
- decayed_message += pick(".",",","-","'","\\","/","\"",":",";")
- else
- decayed_message += char
- _message = decayed_message
- if(length(_message))
- tokens["message"] = _message
- else
- return
+ for(var/list/token in tokens)
+ if(token["message"] && !isnull(entries_decay_at) && !isnull(entry_decay_weight))
+ var/_n = token["age"]
+ var/_message = token["message"]
+ if(_n >= entries_decay_at)
+ var/decayed_message = ""
+ for(var/i = 1 to length(_message))
+ var/char = copytext(_message, i, i + 1)
+ if(prob(round(_n * entry_decay_weight)))
+ if(prob(99))
+ decayed_message += pick(".",",","-","'","\\","/","\"",":",";")
+ else
+ decayed_message += char
+ _message = decayed_message
+ if(length(_message))
+ token["message"] = _message
+ else
+ return
- var/_z = tokens["z"]
- if(_z in using_map.station_levels)
- . = GetValidTurf(locate(tokens["x"], tokens["y"], _z), tokens)
- if(.)
- CreateEntryInstance(., tokens)
+ var/_z = token["z"]
+ if(_z in using_map.station_levels)
+ . = GetValidTurf(locate(token["x"], token["y"], _z), token)
+ if(.)
+ CreateEntryInstance(., token)
/datum/persistent/proc/IsValidEntry(var/atom/entry)
if(!istype(entry))
@@ -96,46 +86,46 @@
/datum/persistent/proc/CompileEntry(var/atom/entry)
var/turf/T = get_turf(entry)
- . = list(
- T.x,
- T.y,
- T.z,
- GetEntryAge(entry)
+ return list(
+ "x" = T.x,
+ "y" = T.y,
+ "z" = T.z,
+ "age" = GetEntryAge(entry)
)
/datum/persistent/proc/Initialize()
if(fexists(filename))
- for(var/entry_line in file2list(filename, file_line_split_character))
- if(!entry_line)
- continue
- var/list/tokens = splittext(entry_line, file_entry_split_character)
- if(LAZYLEN(tokens) < tokens_per_line)
- continue
- tokens = LabelTokens(tokens)
- if(!CheckTokenSanity(tokens))
- continue
- ProcessAndApplyTokens(tokens)
+ var/list/tokens = json_decode(file2text(filename))
+ for(var/list/token in tokens)
+ if(!CheckTokenSanity(token))
+ tokens -= token
+ ProcessAndApplyTokens(tokens)
/datum/persistent/proc/Shutdown()
if(fexists(filename))
fdel(filename)
- var/write_file = file(filename)
+
+ var/list/to_store = list()
for(var/thing in SSpersistence.tracking_values[type])
- if(IsValidEntry(thing))
- var/list/entry = CompileEntry(thing)
- if(LAZYLEN(entry) == tokens_per_line)
- for(var/i = 1 to LAZYLEN(entry))
- if(istext(entry[i]))
- entry[i] = replacetext(entry[i], file_entry_split_character, file_entry_substitute_character)
- to_file(write_file, jointext(entry, file_entry_split_character))
+ if(!IsValidEntry(thing))
+ continue
+ to_store[++to_store.len] = CompileEntry(thing)
+
+ if(to_store.len)
+ to_file(file(filename), json_encode(to_store))
/datum/persistent/proc/RemoveValue(var/atom/value)
qdel(value)
/datum/persistent/proc/GetAdminSummary(var/mob/user, var/can_modify)
+ var/list/my_tracks = SSpersistence.tracking_values[type]
+ if(!my_tracks?.len)
+ return
+
. = list("| [capitalize(name)] |
")
. += "
|
"
- for(var/thing in SSpersistence.tracking_values[type])
+
+ for(var/thing in my_tracks)
. += "[GetAdminDataStringFor(thing, can_modify, user)]
"
. += "
|
"
diff --git a/code/modules/persistence/datum/datum_filth.dm b/code/modules/persistence/effects/filth.dm
similarity index 59%
rename from code/modules/persistence/datum/datum_filth.dm
rename to code/modules/persistence/effects/filth.dm
index 10b304e18ee..166c374c02c 100644
--- a/code/modules/persistence/datum/datum_filth.dm
+++ b/code/modules/persistence/effects/filth.dm
@@ -1,26 +1,22 @@
/datum/persistent/filth
name = "filth"
- tokens_per_line = 5
entries_expire_at = 4 // 4 rounds, 24 hours.
-/datum/persistent/filth/LabelTokens(var/list/tokens)
- var/list/labelled_tokens = ..()
- labelled_tokens["path"] = text2path(tokens[LAZYLEN(labelled_tokens)+1])
- return labelled_tokens
-
/datum/persistent/filth/IsValidEntry(var/atom/entry)
. = ..() && entry.invisibility == 0
-/datum/persistent/filth/CheckTokenSanity(var/list/tokens)
- return ..() && ispath(tokens["path"])
+/datum/persistent/filth/CheckTokenSanity(var/list/token)
+ // byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json
+ token["path"] = istext(token["path"]) ? text2path(token["path"]) : token["path"]
+ return ..() && ispath(token["path"])
-/datum/persistent/filth/CheckTurfContents(var/turf/T, var/list/tokens)
- var/_path = tokens["path"]
+/datum/persistent/filth/CheckTurfContents(var/turf/T, var/list/token)
+ var/_path = token["path"]
return (locate(_path) in T) ? FALSE : TRUE
-/datum/persistent/filth/CreateEntryInstance(var/turf/creating, var/list/tokens)
- var/_path = tokens["path"]
- new _path(creating, tokens["age"]+1)
+/datum/persistent/filth/CreateEntryInstance(var/turf/creating, var/list/token)
+ var/_path = token["path"]
+ new _path(creating, token["age"]+1)
/datum/persistent/filth/GetEntryAge(var/atom/entry)
var/obj/effect/decal/cleanable/filth = entry
@@ -32,4 +28,4 @@
/datum/persistent/filth/CompileEntry(var/atom/entry)
. = ..()
- LAZYADD(., "[GetEntryPath(entry)]")
\ No newline at end of file
+ LAZYADDASSOC(., "path", "[GetEntryPath(entry)]")
\ No newline at end of file
diff --git a/code/modules/persistence/datum/datum_graffiti.dm b/code/modules/persistence/effects/graffiti.dm
similarity index 72%
rename from code/modules/persistence/datum/datum_graffiti.dm
rename to code/modules/persistence/effects/graffiti.dm
index 6ca1bbf32f9..369f9156b49 100644
--- a/code/modules/persistence/datum/datum_graffiti.dm
+++ b/code/modules/persistence/effects/graffiti.dm
@@ -1,22 +1,14 @@
/datum/persistent/graffiti
name = "graffiti"
- tokens_per_line = 6
entries_expire_at = 4 // This previously was at 50 rounds??? Over 10 days.
has_admin_data = TRUE
-/datum/persistent/graffiti/LabelTokens(var/list/tokens)
- var/list/labelled_tokens = ..()
- var/entries = LAZYLEN(labelled_tokens)
- labelled_tokens["author"] = tokens[entries+1]
- labelled_tokens["message"] = tokens[entries+2]
- return labelled_tokens
-
-/datum/persistent/graffiti/GetValidTurf(var/turf/T, var/list/tokens)
+/datum/persistent/graffiti/GetValidTurf(var/turf/T, var/list/token)
var/turf/checking_turf = ..()
if(istype(checking_turf) && checking_turf.can_engrave())
return checking_turf
-/datum/persistent/graffiti/CheckTurfContents(var/turf/T, var/list/tokens)
+/datum/persistent/graffiti/CheckTurfContents(var/turf/T, var/list/token)
var/too_much_graffiti = 0
for(var/obj/effect/decal/writing/W in .)
too_much_graffiti++
@@ -24,8 +16,10 @@
return FALSE
return TRUE
-/datum/persistent/graffiti/CreateEntryInstance(var/turf/creating, var/list/tokens)
- new /obj/effect/decal/writing(creating, tokens["age"]+1, tokens["message"], tokens["author"])
+/datum/persistent/graffiti/CreateEntryInstance(var/turf/creating, var/list/token)
+ var/obj/effect/decal/writing/inst = new /obj/effect/decal/writing(creating, token["age"]+1, token["message"], token["author"])
+ if(token["icon_state"])
+ inst.icon_state = token["icon_state"]
/datum/persistent/graffiti/IsValidEntry(var/atom/entry)
. = ..()
@@ -40,8 +34,9 @@
/datum/persistent/graffiti/CompileEntry(var/atom/entry, var/write_file)
. = ..()
var/obj/effect/decal/writing/save_graffiti = entry
- LAZYADD(., "[save_graffiti.author ? save_graffiti.author : "unknown"]")
- LAZYADD(., "[save_graffiti.message]")
+ LAZYADDASSOC(., "author", "[save_graffiti.author ? save_graffiti.author : "unknown"]")
+ LAZYADDASSOC(., "message", "[save_graffiti.message]")
+ LAZYADDASSOC(., "icon_state", "[save_graffiti.icon_state]")
/datum/persistent/graffiti/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
var/obj/effect/decal/writing/save_graffiti = thing
diff --git a/code/modules/persistence/datum/datum_paper.dm b/code/modules/persistence/effects/paper.dm
similarity index 74%
rename from code/modules/persistence/datum/datum_paper.dm
rename to code/modules/persistence/effects/paper.dm
index fe2ef813681..95968274eba 100644
--- a/code/modules/persistence/datum/datum_paper.dm
+++ b/code/modules/persistence/effects/paper.dm
@@ -1,32 +1,24 @@
/datum/persistent/paper
name = "paper"
- tokens_per_line = 7
entries_expire_at = 50
has_admin_data = TRUE
var/paper_type = /obj/item/weapon/paper
var/requires_noticeboard = TRUE
-/datum/persistent/paper/LabelTokens(var/list/tokens)
- var/list/labelled_tokens = ..()
- var/entries = LAZYLEN(labelled_tokens)
- labelled_tokens["author"] = tokens[entries+1]
- labelled_tokens["message"] = tokens[entries+2]
- labelled_tokens["title"] = tokens[entries+3]
- return labelled_tokens
-
-/datum/persistent/paper/CheckTurfContents(var/turf/T, var/list/tokens)
+/datum/persistent/paper/CheckTurfContents(var/turf/T, var/list/token)
if(requires_noticeboard && !(locate(/obj/structure/noticeboard) in T))
new /obj/structure/noticeboard(T)
. = ..()
-/datum/persistent/paper/CreateEntryInstance(var/turf/creating, var/list/tokens)
+/datum/persistent/paper/CreateEntryInstance(var/turf/creating, var/list/token)
var/obj/structure/noticeboard/board = locate() in creating
if(requires_noticeboard && LAZYLEN(board.notices) >= board.max_notices)
return
var/obj/item/weapon/paper/paper = new paper_type(creating)
- paper.info = tokens["message"]
- paper.name = tokens["title"]
- paper.last_modified_ckey = tokens["author"]
+ paper.info = token["message"]
+ paper.name = token["title"]
+ paper.last_modified_ckey = token["author"]
+ paper.age = token["age"]+1
if(requires_noticeboard)
board.add_paper(paper)
if(!paper.was_maploaded) // If we were created/loaded when the map was made, skip us!
@@ -40,9 +32,9 @@
/datum/persistent/paper/CompileEntry(var/atom/entry, var/write_file)
. = ..()
var/obj/item/weapon/paper/paper = entry
- LAZYADD(., "[paper.last_modified_ckey ? paper.last_modified_ckey : "unknown"]")
- LAZYADD(., "[paper.info]")
- LAZYADD(., "[paper.name]")
+ LAZYADDASSOC(., "author", "[paper.last_modified_ckey ? paper.last_modified_ckey : "unknown"]")
+ LAZYADDASSOC(., "message", "[paper.info]")
+ LAZYADDASSOC(., "name", "[paper.name]")
/datum/persistent/paper/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
var/obj/item/weapon/paper/paper = thing
diff --git a/code/modules/persistence/effects/paper_sticky.dm b/code/modules/persistence/effects/paper_sticky.dm
new file mode 100644
index 00000000000..08fb9050093
--- /dev/null
+++ b/code/modules/persistence/effects/paper_sticky.dm
@@ -0,0 +1,23 @@
+/datum/persistent/paper/sticky
+ name = "stickynotes"
+ paper_type = /obj/item/weapon/paper/sticky
+ requires_noticeboard = FALSE
+
+/datum/persistent/paper/sticky/CreateEntryInstance(var/turf/creating, var/list/token)
+ var/atom/paper = ..()
+ if(paper)
+ if(prob(90))
+ paper.pixel_x = token["offset_x"]
+ paper.pixel_y = token["offset_y"]
+ else
+ paper.pixel_x = rand(-5,5)
+ paper.pixel_y = rand(-5,5)
+ paper.color = token["color"]
+ return paper
+
+/datum/persistent/paper/sticky/CompileEntry(var/atom/entry, var/write_file)
+ . = ..()
+ var/obj/item/weapon/paper/sticky/paper = entry
+ LAZYADDASSOC(., "offset_x", paper.pixel_x)
+ LAZYADDASSOC(., "offset_y", paper.pixel_y)
+ LAZYADDASSOC(., "color", paper.color)
\ No newline at end of file
diff --git a/code/modules/persistence/datum/datum_trash.dm b/code/modules/persistence/effects/trash.dm
similarity index 100%
rename from code/modules/persistence/datum/datum_trash.dm
rename to code/modules/persistence/effects/trash.dm
diff --git a/code/modules/persistence/persistence.dm b/code/modules/persistence/serialize.dm
similarity index 100%
rename from code/modules/persistence/persistence.dm
rename to code/modules/persistence/serialize.dm
diff --git a/code/modules/persistence/storage/smartfridge.dm b/code/modules/persistence/storage/smartfridge.dm
new file mode 100644
index 00000000000..0584ab9e79e
--- /dev/null
+++ b/code/modules/persistence/storage/smartfridge.dm
@@ -0,0 +1,97 @@
+/datum/persistent/storage/smartfridge/get_storage_list(var/obj/machinery/smartfridge/entry)
+ if(!istype(entry))
+ return ..()
+
+ . = list()
+ for(var/datum/stored_item/I in entry.item_records)
+ .[I.item_path] = I.get_amount()
+
+/datum/persistent/storage/smartfridge/CreateEntryInstance(var/turf/creating, var/list/token)
+ var/obj/machinery/smartfridge/S = find_specific_instance(creating)
+ var/list/L = generate_items(token["items"])
+ for(var/atom/A in L)
+ if(S.accept_check(A))
+ S.stock(A)
+ else
+ qdel(A) // Should clean this up here, it couldn't be stocked
+
+
+
+
+
+/datum/persistent/storage/smartfridge/sheet_storage
+ name = "sheet storage"
+ max_storage = 50
+ store_per_type = TRUE
+ target_type = /obj/machinery/smartfridge/sheets
+
+ var/stacks_go_missing = FALSE // Variable rate depletion of stacks inter-round
+
+/datum/persistent/storage/smartfridge/sheet_storage/lossy
+ name = "sheet storage lossy"
+ max_storage = 250
+ stacks_go_missing = TRUE
+
+/datum/persistent/storage/smartfridge/sheet_storage/generate_items(var/list/L)
+ . = list()
+ for(var/obj/item/stack/material/S as anything in L)
+ var/real_path = istext(S) ? text2path(S) : S
+ if(!ispath(real_path, /obj/item/stack/material))
+ log_debug("Warning: Sheet_storage persistent datum tried to create [S]")
+ continue
+
+ // Skip entire stack if we hit the chance
+ if(prob(go_missing_chance))
+ continue
+
+ var/count = L[S]
+
+ var/obj/item/stack/material/inst = real_path
+ var/max_amount = initial(inst.max_amount)
+
+ // Delete some stacks if we want
+ if(stacks_go_missing)
+ var/fuzzy = rand(-5,5)
+ switch(count / max_amount)
+ if(0 to 1)
+ count -= 10+fuzzy // 1 stack or less, lose 10
+ if(1 to 10)
+ count -= max_amount+fuzzy // 1 to 10 stacks, lose a stack
+ if(10 to INFINITY)
+ count -= max_amount*3+fuzzy // 10+ stacks, lose 3 stacks
+ if(count <= 0)
+ continue
+
+ while(count > 0)
+ inst = new real_path
+ inst.amount = min(count, max_amount)
+ count -= inst.get_amount()
+ . += inst
+
+
+/datum/persistent/storage/smartfridge/produce
+ name = "fruit storage"
+ max_storage = 50
+ store_per_type = FALSE
+ target_type = /obj/machinery/smartfridge/produce
+
+/datum/persistent/storage/smartfridge/produce/lossy
+ name = "fruit storage lossy"
+ go_missing_chance = 12.5 // 10% loss between rounds
+
+/datum/persistent/storage/smartfridge/produce/create_item(var/seedtype)
+ return new /obj/item/weapon/reagent_containers/food/snacks/grown(null, seedtype) // Smartfridge will be stock()ed with it, loc is unimportant
+
+/datum/persistent/storage/smartfridge/produce/get_storage_list(var/obj/machinery/smartfridge/produce/entry)
+ if(!istype(entry))
+ return ..()
+
+ . = list()
+ for(var/datum/stored_item/I in entry.item_records)
+ if(prob(go_missing_chance))
+ continue
+ if(LAZYLEN(I.instances))
+ var/obj/item/weapon/reagent_containers/food/snacks/grown/G = I.instances[1]
+ if(!istype(G))
+ continue
+ .[G.plantname] = I.get_amount() // Store the seed type, because that's what's used to generate the fruit
\ No newline at end of file
diff --git a/code/modules/persistence/storage/storage.dm b/code/modules/persistence/storage/storage.dm
new file mode 100644
index 00000000000..58b23a6ce94
--- /dev/null
+++ b/code/modules/persistence/storage/storage.dm
@@ -0,0 +1,74 @@
+/datum/persistent/storage
+ name = "storage"
+ entries_expire_at = 1
+ has_admin_data = TRUE
+
+ // Don't use these for storage persistence. If someone takes some sheets out and puts them back in mixed in with
+ // new sheets, how do you know the age of the stack? If you want sheets to 'decay', see go_missing_chance
+ entries_decay_at = 0
+ entry_decay_weight = 0
+ // // // //
+
+ var/max_storage = 0
+ var/store_per_type = FALSE // If true, will store up to max_storage for each type stored
+ var/target_type = null // Path of the thing that this expects to put stuff into
+
+ var/go_missing_chance = 0 // Chance an item will fail to be spawned in from persistence and need to be restocked
+
+/datum/persistent/storage/SetFilename()
+ if(name)
+ filename = "data/persistent/storage/[lowertext(using_map.name)]-[lowertext(name)].json"
+
+/datum/persistent/storage/IsValidEntry(var/atom/entry)
+ return ..() && istype(entry, target_type)
+
+/datum/persistent/storage/CompileEntry(var/atom/entry)
+ . = ..()
+ var/stored = max_storage
+ var/list/item_list = get_storage_list(entry)
+ var/list/storage_list = list()
+ for(var/item in item_list)
+ storage_list[item] = min(stored, storage_list[item] + item_list[item]) // Can't store more than max_storage
+
+ // stored gets reduced by qty stored, if greater than stored,
+ // previous assignment will handle overage, and we set to 0
+ if(!store_per_type)
+ stored = max(stored - item_list[item], 0)
+
+ LAZYADDASSOC(., "items", storage_list)
+
+// Usage: returns list with structure:
+// list(
+// [type1] = [stored_quantity],
+// [type2] = [stored_quantity]
+// )
+/datum/persistent/storage/proc/get_storage_list(var/atom/entry)
+ return list() // Subtypes define list structure
+
+/datum/persistent/storage/proc/find_specific_instance(var/turf/T)
+ return locate(target_type) in T
+
+/datum/persistent/storage/CheckTurfContents(var/turf/T, var/list/token)
+ return istype(find_specific_instance(T), target_type)
+
+/datum/persistent/storage/proc/generate_items(var/list/L)
+ . = list()
+ for(var/path in L)
+ // byond's json implementation is "questionable", and uses types as keys and values without quotes sometimes even though they aren't valid json
+ var/real_path = istext(path) ? text2path(path) : path
+ for(var/i in 1 to L[path])
+ if(prob(go_missing_chance))
+ continue
+ var/atom/A = create_item(real_path)
+ if(!QDELETED(A))
+ . += A
+
+/datum/persistent/storage/proc/create_item(var/path)
+ return new path()
+
+/datum/persistent/storage/GetAdminDataStringFor(var/thing, var/can_modify, var/mob/user)
+ var/atom/T = thing
+ if(!istype(T))
+ return "| "
+ else
+ . = " | [T.name] | [T.x],[T.y],[T.z] | "
diff --git a/code/modules/reagents/reagents/dispenser.dm b/code/modules/reagents/reagents/dispenser.dm
index 8d825ef91c7..6dd8a79285a 100644
--- a/code/modules/reagents/reagents/dispenser.dm
+++ b/code/modules/reagents/reagents/dispenser.dm
@@ -419,7 +419,7 @@
if(affecting.take_damage(0, removed * power * 0.1))
H.UpdateDamageIcon()
if(prob(100 * removed / meltdose)) // Applies disfigurement
- if (affecting.organ_can_feel_pain())
+ if (affecting.organ_can_feel_pain() && !isbelly(H.loc)) //VOREStation Add
H.emote("scream")
H.status_flags |= DISFIGURED
else
diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm
index 3c56beda17a..8ff26d3d011 100644
--- a/code/modules/research/mechfab_designs.dm
+++ b/code/modules/research/mechfab_designs.dm
@@ -571,6 +571,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 7500, "gold" = 750, "silver" = 1500, MAT_ALUMINIUM = 3750)
build_path = /obj/item/mecha_parts/mecha_equipment/repair_droid
+/* These are way too OP to be buildable
/datum/design/item/mecha/combat_shield
name = "linear combat shield"
desc = "Linear shield projector. Deploys a large, familiar, and rectangular shield in one direction at a time."
@@ -586,6 +587,7 @@
req_tech = list(TECH_PHORON = 3, TECH_MAGNET = 6, TECH_ILLEGAL = 4)
materials = list(DEFAULT_WALL_MATERIAL = 8000, "gold" = 2000, "silver" = 3000, "phoron" = 5000, "glass" = 3750)
build_path = /obj/item/mecha_parts/mecha_equipment/omni_shield
+*/
/datum/design/item/mecha/crisis_drone
name = "Crisis Drone"
diff --git a/config/alienwhitelist.txt b/config/alienwhitelist.txt
index 8444ddc1f86..359fc752e1b 100644
--- a/config/alienwhitelist.txt
+++ b/config/alienwhitelist.txt
@@ -38,6 +38,7 @@ killjaden - Protean
ktccd - Diona
liache - Black-Eyed Shadekin
lizehrd - Xenochimera
+lordlag - Black-Eyed Shadekin
magpiemayhem - Vox
marco_barko - Protean
mewchild - Diona
diff --git a/icons/mecha/fighters64x64.dmi b/icons/mecha/fighters64x64.dmi
index 6025a94c864..4c9fd660bfa 100644
Binary files a/icons/mecha/fighters64x64.dmi and b/icons/mecha/fighters64x64.dmi differ
diff --git a/icons/mob/dogborg_vr.dmi b/icons/mob/dogborg_vr.dmi
index 0dc89d2b50a..30e0bb5e374 100644
Binary files a/icons/mob/dogborg_vr.dmi and b/icons/mob/dogborg_vr.dmi differ
diff --git a/icons/mob/eyes_vr.dmi b/icons/mob/eyes_vr.dmi
index 89805954f7a..f19fed9626a 100644
Binary files a/icons/mob/eyes_vr.dmi and b/icons/mob/eyes_vr.dmi differ
diff --git a/icons/mob/screen/holo.dmi b/icons/mob/screen/holo.dmi
index a0fff5d7819..8acd77b9b26 100644
Binary files a/icons/mob/screen/holo.dmi and b/icons/mob/screen/holo.dmi differ
diff --git a/icons/mob/screen/midnight.dmi b/icons/mob/screen/midnight.dmi
index b1f37cb2239..db6197abd9e 100644
Binary files a/icons/mob/screen/midnight.dmi and b/icons/mob/screen/midnight.dmi differ
diff --git a/icons/mob/screen/minimalist.dmi b/icons/mob/screen/minimalist.dmi
index a60c9b196ae..48ff4008640 100644
Binary files a/icons/mob/screen/minimalist.dmi and b/icons/mob/screen/minimalist.dmi differ
diff --git a/icons/mob/screen/old-noborder.dmi b/icons/mob/screen/old-noborder.dmi
index ddc72353ee3..b11c0b0d529 100644
Binary files a/icons/mob/screen/old-noborder.dmi and b/icons/mob/screen/old-noborder.dmi differ
diff --git a/icons/mob/screen/old.dmi b/icons/mob/screen/old.dmi
index f165b01b5bf..93d51e042a4 100644
Binary files a/icons/mob/screen/old.dmi and b/icons/mob/screen/old.dmi differ
diff --git a/icons/mob/screen/orange.dmi b/icons/mob/screen/orange.dmi
index d0b52d10d4a..c50d41b49b5 100644
Binary files a/icons/mob/screen/orange.dmi and b/icons/mob/screen/orange.dmi differ
diff --git a/icons/mob/screen/white.dmi b/icons/mob/screen/white.dmi
index 0a1a31bc31e..cf232ae5c36 100644
Binary files a/icons/mob/screen/white.dmi and b/icons/mob/screen/white.dmi differ
diff --git a/icons/mob/screen1_robot_vr.dmi b/icons/mob/screen1_robot_vr.dmi
index 162a3375090..33046af1959 100644
Binary files a/icons/mob/screen1_robot_vr.dmi and b/icons/mob/screen1_robot_vr.dmi differ
diff --git a/icons/mob/widerobot_colors_vr.dmi b/icons/mob/widerobot_colors_vr.dmi
new file mode 100644
index 00000000000..44295e3b891
Binary files /dev/null and b/icons/mob/widerobot_colors_vr.dmi differ
diff --git a/icons/obj/card_new_vr.dmi b/icons/obj/card_new_vr.dmi
index 20e3c855832..496b1fda27a 100644
Binary files a/icons/obj/card_new_vr.dmi and b/icons/obj/card_new_vr.dmi differ
diff --git a/maps/expedition_vr/space/_debrisfield.dm b/maps/expedition_vr/space/_debrisfield.dm
index f1b36da15ad..cf63350a596 100644
--- a/maps/expedition_vr/space/_debrisfield.dm
+++ b/maps/expedition_vr/space/_debrisfield.dm
@@ -184,10 +184,10 @@
shuttle_tag = "Debris Carrier"
req_one_access = list()
-/obj/mecha/combat/fighter/baron/loaded/busted
+/obj/mecha/combat/fighter/baron/busted
starting_components = list(/obj/item/mecha_parts/component/hull/lightweight,/obj/item/mecha_parts/component/actuator/hispeed,/obj/item/mecha_parts/component/armor,/obj/item/mecha_parts/component/gas,/obj/item/mecha_parts/component/electrical/high_current)
-/obj/mecha/combat/fighter/baron/loaded/busted/Initialize()
+/obj/mecha/combat/fighter/baron/busted/Initialize()
. = ..()
health = round(rand(50,120))
cell?.charge = 0
diff --git a/maps/offmap_vr/om_ships/shelter_6.dmm b/maps/offmap_vr/om_ships/shelter_6.dmm
index 5918d23ad43..c7d3a9fec8b 100644
--- a/maps/offmap_vr/om_ships/shelter_6.dmm
+++ b/maps/offmap_vr/om_ships/shelter_6.dmm
@@ -1561,12 +1561,13 @@
/obj/machinery/mech_recharger{
icon = 'icons/turf/shuttle_alien_blue.dmi'
},
-/obj/mecha/combat/fighter/baron{
+/obj/mecha/combat/fighter/baron/loaded{
ground_capable = 1;
- health = 800;
- internal_damage_threshold = 100;
- maxhealth = 800;
- name = "Panther"
+ health = 600;
+ maxhealth = 600;
+ name = "Duke";
+ desc = "A heavily modified Baron-class fighter from the commonwealth. It has been retrofitted with heavier armor and additional maneuvering thrusters. Can be used in atmospheric operations.";
+ starting_components = list(/obj/item/mecha_parts/component/hull/lightweight,/obj/item/mecha_parts/component/actuator/hispeed,/obj/item/mecha_parts/component/armor/military,/obj/item/mecha_parts/component/gas/reinforced,/obj/item/mecha_parts/component/electrical)
},
/turf/simulated/floor/reinforced,
/area/shuttle/tabiranth)
diff --git a/maps/offmap_vr/talon/talon_v2.dmm b/maps/offmap_vr/talon/talon_v2.dmm
index 53aa8895f59..1e00adc6a00 100644
--- a/maps/offmap_vr/talon/talon_v2.dmm
+++ b/maps/offmap_vr/talon/talon_v2.dmm
@@ -1679,6 +1679,18 @@
/obj/structure/closet/walllocker_double/hydrant/west,
/turf/simulated/floor/tiled/techmaint,
/area/talon_v2/secure_storage)
+"fk" = (
+/obj/structure/railing/grey{
+ dir = 1
+ },
+/obj/structure/window/reinforced{
+ dir = 1
+ },
+/obj/machinery/smartfridge/sheets/persistent_lossy{
+ layer = 3.3
+ },
+/turf/simulated/floor/tiled/techfloor,
+/area/talon_v2/refining)
"fm" = (
/obj/machinery/door/airlock/glass_external{
req_one_access = list(301)
@@ -8802,7 +8814,9 @@
/obj/structure/closet/walllocker/medical/north,
/obj/item/weapon/storage/firstaid/regular,
/obj/item/weapon/storage/firstaid/o2,
-/obj/item/device/radio/off/talon,
+/obj/item/device/radio/off{
+ channels = list("Talon" = 1)
+ },
/turf/simulated/floor/wood,
/area/talon_v2/crew_quarters/cap_room)
"Fk" = (
@@ -11190,7 +11204,10 @@
pixel_y = 24
},
/obj/structure/table/rack/shelf/steel,
-/obj/item/device/radio/off/talon,
+/obj/item/device/radio/off{
+ channels = list("Talon" = 1);
+ pixel_y = 6
+ },
/turf/simulated/floor/tiled/techfloor,
/area/talon_v2/armory)
"Nw" = (
@@ -26588,7 +26605,7 @@ ca
rj
fW
jS
-tX
+fk
VS
mQ
ZR
diff --git a/maps/southern_cross/southern_cross-1.dmm b/maps/southern_cross/southern_cross-1.dmm
index c7f43260bad..c6767f4d7d3 100644
--- a/maps/southern_cross/southern_cross-1.dmm
+++ b/maps/southern_cross/southern_cross-1.dmm
@@ -66668,10 +66668,6 @@
/turf/simulated/floor/tiled,
/area/quartermaster/foyer)
"cvi" = (
-/obj/structure/bed/chair,
-/obj/machinery/alarm{
- pixel_y = 22
- },
/obj/effect/floor_decal/borderfloor/corner{
dir = 1
},
@@ -70398,6 +70394,10 @@
/obj/effect/floor_decal/corner/brown/bordercorner2{
dir = 9
},
+/obj/machinery/alarm{
+ dir = 4;
+ pixel_x = -22
+ },
/turf/simulated/floor/tiled,
/area/quartermaster/foyer)
"cCs" = (
@@ -86952,9 +86952,9 @@
/turf/simulated/floor/plating,
/area/maintenance/bar)
"deS" = (
-/obj/machinery/smartfridge,
/obj/structure/disposalpipe/segment,
-/turf/simulated/wall/r_wall,
+/obj/machinery/smartfridge/produce/persistent,
+/turf/simulated/floor/plating,
/area/hydroponics)
"deT" = (
/turf/simulated/wall,
@@ -114220,6 +114220,10 @@
},
/turf/simulated/floor/tiled,
/area/hallway/primary/seconddeck/stairwell)
+"xjf" = (
+/obj/machinery/smartfridge/sheets/persistent,
+/turf/simulated/floor/plating,
+/area/quartermaster/foyer)
(1,1,1) = {"
aaa
@@ -201992,7 +201996,7 @@ cmS
chE
cpX
crX
-ctL
+xjf
cvi
cxl
cxl
diff --git a/maps/submaps/admin_use_vr/kk_mercship.dmm b/maps/submaps/admin_use_vr/kk_mercship.dmm
index 362023e72c4..c1d6949036c 100644
--- a/maps/submaps/admin_use_vr/kk_mercship.dmm
+++ b/maps/submaps/admin_use_vr/kk_mercship.dmm
@@ -4199,7 +4199,6 @@
"sM" = (
/obj/structure/table/rack,
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,
-/obj/item/mecha_parts/mecha_equipment/omni_shield,
/obj/item/mecha_parts/mecha_equipment/repair_droid,
/obj/machinery/firealarm/alarms_hidden{
pixel_y = 26
diff --git a/maps/submaps/pois_vr/debris_field/tinycarrier.dmm b/maps/submaps/pois_vr/debris_field/tinycarrier.dmm
index 5be1f1456bb..908afdd05d1 100644
--- a/maps/submaps/pois_vr/debris_field/tinycarrier.dmm
+++ b/maps/submaps/pois_vr/debris_field/tinycarrier.dmm
@@ -1109,7 +1109,7 @@
/turf/simulated/floor/reinforced/airless,
/area/submap/debrisfield/tinyshuttle/hangar)
"bW" = (
-/obj/mecha/combat/fighter/baron/loaded/busted{
+/obj/mecha/combat/fighter/baron/busted{
dir = 8;
dir_in = 8
},
diff --git a/maps/tether/submaps/_tether_submaps.dm b/maps/tether/submaps/_tether_submaps.dm
index cbcc1b5c369..f1f848972c1 100644
--- a/maps/tether/submaps/_tether_submaps.dm
+++ b/maps/tether/submaps/_tether_submaps.dm
@@ -527,6 +527,6 @@
/datum/map_z_level/tether_lateload/talon_v2
name = "Talon"
- flags = MAP_LEVEL_PLAYER
+ flags = MAP_LEVEL_PLAYER|MAP_LEVEL_PERSIST
base_turf = /turf/space
z = Z_LEVEL_OFFMAP1
\ No newline at end of file
diff --git a/maps/tether/tether-03-surface3.dmm b/maps/tether/tether-03-surface3.dmm
index 40b1869e5c4..dd0c6dd9ea1 100644
--- a/maps/tether/tether-03-surface3.dmm
+++ b/maps/tether/tether-03-surface3.dmm
@@ -18423,13 +18423,13 @@
/turf/simulated/floor/tiled,
/area/tether/surfacebase/surface_three_hall)
"aDX" = (
-/obj/machinery/smartfridge,
/obj/effect/floor_decal/borderfloor{
dir = 1
},
/obj/effect/floor_decal/corner/lime/border{
dir = 1
},
+/obj/machinery/smartfridge/produce/persistent_lossy,
/turf/simulated/floor/tiled,
/area/tether/surfacebase/botanystorage)
"aDY" = (
diff --git a/maps/tether/tether-07-station3.dmm b/maps/tether/tether-07-station3.dmm
index 9717e5f4f0e..af77aa1e468 100644
--- a/maps/tether/tether-07-station3.dmm
+++ b/maps/tether/tether-07-station3.dmm
@@ -19061,7 +19061,6 @@
/turf/simulated/floor,
/area/maintenance/station/ai)
"aSj" = (
-/obj/structure/closet/emcloset,
/obj/machinery/atmospherics/unary/vent_pump/on{
dir = 8
},
@@ -19534,6 +19533,7 @@
/obj/machinery/atmospherics/unary/vent_scrubber/on{
dir = 8
},
+/obj/structure/closet/emcloset,
/turf/simulated/floor/tiled,
/area/quartermaster/belterdock)
"aTA" = (
@@ -23197,6 +23197,10 @@
},
/turf/simulated/floor/tiled/eris/dark/techfloor,
/area/shuttle/medivac/engines)
+"kPM" = (
+/obj/machinery/smartfridge/sheets/persistent_lossy,
+/turf/simulated/wall,
+/area/quartermaster/belterdock)
"kPW" = (
/obj/machinery/door/blast/regular{
dir = 4;
@@ -38467,7 +38471,7 @@ aHB
aMz
aBU
aBU
-aQG
+kPM
aSj
aOu
aOL
diff --git a/maps/tether/tether_areas.dm b/maps/tether/tether_areas.dm
index 71c93bb2894..16ca71ce364 100644
--- a/maps/tether/tether_areas.dm
+++ b/maps/tether/tether_areas.dm
@@ -698,6 +698,7 @@
name = "\improper South Maintenance"
/area/maintenance/lower/trash_pit
name = "\improper Trash Pit"
+ flags = RAD_SHIELDED|AREA_FLAG_IS_NOT_PERSISTENT
/area/maintenance/lower/solars
name = "\improper Solars Maintenance"
/area/maintenance/lower/mining_eva
diff --git a/maps/tether/tether_defines.dm b/maps/tether/tether_defines.dm
index 58a05910ab3..caab265dfb6 100644
--- a/maps/tether/tether_defines.dm
+++ b/maps/tether/tether_defines.dm
@@ -299,14 +299,14 @@
// We have a bunch of stuff common to the station z levels
/datum/map_z_level/tether/station
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
holomap_legend_x = 220
holomap_legend_y = 160
/datum/map_z_level/tether/station/surface_low
z = Z_LEVEL_SURFACE_LOW
name = "Surface 1"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*0
@@ -314,7 +314,7 @@
/datum/map_z_level/tether/station/surface_mid
z = Z_LEVEL_SURFACE_MID
name = "Surface 2"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
base_turf = /turf/simulated/open
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*1
@@ -322,7 +322,7 @@
/datum/map_z_level/tether/station/surface_high
z = Z_LEVEL_SURFACE_HIGH
name = "Surface 3"
- flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT
+ flags = MAP_LEVEL_STATION|MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_CONSOLES|MAP_LEVEL_SEALED|MAP_LEVEL_XENOARCH_EXEMPT|MAP_LEVEL_PERSIST
base_turf = /turf/simulated/open
holomap_offset_x = TETHER_HOLOMAP_MARGIN_X
holomap_offset_y = TETHER_HOLOMAP_MARGIN_Y + TETHER_MAP_SIZE*2
@@ -359,11 +359,11 @@
/datum/map_z_level/tether/mine
z = Z_LEVEL_SURFACE_MINE
name = "Mining Outpost"
- flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED
+ flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED|MAP_LEVEL_PERSIST
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
/datum/map_z_level/tether/solars
z = Z_LEVEL_SOLARS
name = "Solar Field"
- flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED
+ flags = MAP_LEVEL_CONTACT|MAP_LEVEL_PLAYER|MAP_LEVEL_SEALED|MAP_LEVEL_PERSIST
base_turf = /turf/simulated/floor/outdoors/rocks/virgo3b
diff --git a/maps/~map_system/maps.dm b/maps/~map_system/maps.dm
index 07c72230261..b7a320a6bd7 100644
--- a/maps/~map_system/maps.dm
+++ b/maps/~map_system/maps.dm
@@ -33,6 +33,7 @@ var/list/all_maps = list()
var/static/list/player_levels = list() // Z-levels a character can typically reach
var/static/list/sealed_levels = list() // Z-levels that don't allow random transit at edge
var/static/list/xenoarch_exempt_levels = list() //Z-levels exempt from xenoarch finds and digsites spawning.
+ var/static/list/persist_levels = list() // Z-levels where SSpersistence should persist between rounds. Defaults to station_levels if unset.
var/static/list/empty_levels = null // Empty Z-levels that may be used for various things (currently used by bluespace jump)
// End Static Lists
@@ -135,8 +136,10 @@ var/list/all_maps = list()
if(zlevel_datum_type)
for(var/type in subtypesof(zlevel_datum_type))
new type(src)
- if(!map_levels)
+ if(!map_levels?.len)
map_levels = station_levels.Copy()
+ if(!persist_levels?.len)
+ persist_levels = station_levels.Copy()
if(!allowed_jobs || !allowed_jobs.len)
allowed_jobs = subtypesof(/datum/job)
if(default_skybox) //Type was specified
@@ -295,6 +298,7 @@ var/list/all_maps = list()
if(flags & MAP_LEVEL_PLAYER) map.player_levels += z
if(flags & MAP_LEVEL_SEALED) map.sealed_levels += z
if(flags & MAP_LEVEL_XENOARCH_EXEMPT) map.xenoarch_exempt_levels += z
+ if(flags & MAP_LEVEL_PERSIST) map.persist_levels += z
if(flags & MAP_LEVEL_EMPTY)
if(!map.empty_levels) map.empty_levels = list()
map.empty_levels += z
diff --git a/vorestation.dme b/vorestation.dme
index b883ec6234e..aa4ad30081a 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -975,7 +975,6 @@
#include "code\game\mecha\combat\combat.dm"
#include "code\game\mecha\combat\durand.dm"
#include "code\game\mecha\combat\fighter.dm"
-#include "code\game\mecha\combat\fighter_vr.dm"
#include "code\game\mecha\combat\gorilla.dm"
#include "code\game\mecha\combat\gygax.dm"
#include "code\game\mecha\combat\marauder.dm"
@@ -2087,6 +2086,7 @@
#include "code\modules\emotes\definitions\audible_cough.dm"
#include "code\modules\emotes\definitions\audible_furry_vr.dm"
#include "code\modules\emotes\definitions\audible_scream.dm"
+#include "code\modules\emotes\definitions\audible_scream_vr.dm"
#include "code\modules\emotes\definitions\audible_slap.dm"
#include "code\modules\emotes\definitions\audible_snap.dm"
#include "code\modules\emotes\definitions\audible_sneeze.dm"
@@ -2217,8 +2217,6 @@
#include "code\modules\food\kitchen\gibber.dm"
#include "code\modules\food\kitchen\icecream.dm"
#include "code\modules\food\kitchen\microwave.dm"
-#include "code\modules\food\kitchen\smartfridge.dm"
-#include "code\modules\food\kitchen\smartfridge_vr.dm"
#include "code\modules\food\kitchen\cooking_machines\_appliance.dm"
#include "code\modules\food\kitchen\cooking_machines\_cooker.dm"
#include "code\modules\food\kitchen\cooking_machines\_cooker_output.dm"
@@ -2229,6 +2227,12 @@
#include "code\modules\food\kitchen\cooking_machines\fryer.dm"
#include "code\modules\food\kitchen\cooking_machines\grill.dm"
#include "code\modules\food\kitchen\cooking_machines\oven.dm"
+#include "code\modules\food\kitchen\smartfridge\drying_rack.dm"
+#include "code\modules\food\kitchen\smartfridge\engineering.dm"
+#include "code\modules\food\kitchen\smartfridge\hydroponics.dm"
+#include "code\modules\food\kitchen\smartfridge\medical.dm"
+#include "code\modules\food\kitchen\smartfridge\smartfridge.dm"
+#include "code\modules\food\kitchen\smartfridge\smartfridge_vr.dm"
#include "code\modules\gamemaster\defines.dm"
#include "code\modules\gamemaster\event2\event.dm"
#include "code\modules\gamemaster\event2\meta.dm"
@@ -3157,7 +3161,6 @@
#include "code\modules\news\newspaper_layout.dm"
#include "code\modules\nifsoft\nif.dm"
#include "code\modules\nifsoft\nif_softshop.dm"
-#include "code\modules\nifsoft\nif_statpanel.dm"
#include "code\modules\nifsoft\nif_tgui.dm"
#include "code\modules\nifsoft\nifsoft.dm"
#include "code\modules\nifsoft\software\01_vision.dm"
@@ -3282,13 +3285,15 @@
#include "code\modules\persistence\filth.dm"
#include "code\modules\persistence\graffiti.dm"
#include "code\modules\persistence\noticeboard.dm"
-#include "code\modules\persistence\persistence.dm"
-#include "code\modules\persistence\datum\datum_filth.dm"
-#include "code\modules\persistence\datum\datum_graffiti.dm"
-#include "code\modules\persistence\datum\datum_paper.dm"
-#include "code\modules\persistence\datum\datum_paper_sticky.dm"
-#include "code\modules\persistence\datum\datum_trash.dm"
+#include "code\modules\persistence\serialize.dm"
#include "code\modules\persistence\datum\persistence_datum.dm"
+#include "code\modules\persistence\effects\filth.dm"
+#include "code\modules\persistence\effects\graffiti.dm"
+#include "code\modules\persistence\effects\paper.dm"
+#include "code\modules\persistence\effects\paper_sticky.dm"
+#include "code\modules\persistence\effects\trash.dm"
+#include "code\modules\persistence\storage\smartfridge.dm"
+#include "code\modules\persistence\storage\storage.dm"
#include "code\modules\planet\planet.dm"
#include "code\modules\planet\time.dm"
#include "code\modules\planet\virgo3b_better_vr.dm"
| |