diff --git a/_maps/map_files/templates/shelter_1.dmm b/_maps/map_files/templates/shelter_1.dmm
new file mode 100644
index 00000000000..19071ada955
--- /dev/null
+++ b/_maps/map_files/templates/shelter_1.dmm
@@ -0,0 +1,23 @@
+"a" = (/turf/simulated/wall/survival,/area/survivalpod)
+"b" = (/obj/structure/sign/mining/survival{tag = "icon-survival (NORTH)"; icon_state = "survival"; dir = 1},/turf/simulated/wall/survival,/area/survivalpod)
+"c" = (/obj/structure/fans,/turf/simulated/floor/pod,/area/survivalpod)
+"d" = (/obj/machinery/smartfridge/survival_pod/loaded,/turf/simulated/floor/pod,/area/survivalpod)
+"e" = (/obj/item/device/gps/computer,/turf/simulated/floor/pod,/area/survivalpod)
+"f" = (/obj/structure/sign/mining/survival{dir = 8},/turf/simulated/wall/survival,/area/survivalpod)
+"g" = (/obj/machinery/sleeper/survival_pod,/turf/simulated/floor/pod,/area/survivalpod)
+"h" = (/turf/simulated/floor/pod,/area/survivalpod)
+"i" = (/obj/structure/stool/bed/pod,/obj/item/weapon/bedsheet/brown,/turf/simulated/floor/pod,/area/survivalpod)
+"j" = (/obj/structure/sign/mining/survival{tag = "icon-survival (EAST)"; icon_state = "survival"; dir = 4},/turf/simulated/wall/survival,/area/survivalpod)
+"k" = (/obj/structure/table/survival_pod,/turf/simulated/floor/pod,/area/survivalpod)
+"l" = (/obj/structure/tubes,/obj/structure/stool/bed/chair/comfy/black{dir = 8},/turf/simulated/floor/pod,/area/survivalpod)
+"m" = (/obj/structure/sign/mining/survival,/turf/simulated/wall/survival,/area/survivalpod)
+"n" = (/obj/structure/fans/tiny,/obj/machinery/door/airlock/survival_pod,/turf/simulated/floor/pod,/area/survivalpod)
+"o" = (/obj/structure/sign/mining,/turf/simulated/wall/survival,/area/survivalpod)
+
+(1,1,1) = {"
+aabaa
+acdea
+fghij
+akhla
+amnoa
+"}
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index ab1357a5833..85221f5cf3c 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -1,5 +1,3 @@
-#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
-
//Object specific defines
#define CANDLE_LUM 3 //For how bright candles are
@@ -281,4 +279,11 @@
// Sound
#define SOUND_MINIMUM_PRESSURE 10
-#define FALLOFF_SOUNDS 0.5
\ No newline at end of file
+#define FALLOFF_SOUNDS 0.5
+
+
+// Bluespace shelter deploy checks
+#define SHELTER_DEPLOY_ALLOWED "allowed"
+#define SHELTER_DEPLOY_BAD_TURFS "bad turfs"
+#define SHELTER_DEPLOY_BAD_AREA "bad area"
+#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index 3042ff6d302..b623ce72158 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -6,4 +6,7 @@
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_PUTINPOOL 5 //qdel will put this object in the atom pool.
#define QDEL_HINT_FINDREFERENCE 6 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
- //if TESTING is enabled, qdel will call this object's find_references() verb.
\ No newline at end of file
+ //if TESTING is enabled, qdel will call this object's find_references() verb.
+
+// A convenient wrapper around checking for qdeletion/non-existence
+#define exists(A) (A && !qdeleted(A))
diff --git a/code/__DEFINES/zlevel.dm b/code/__DEFINES/zlevel.dm
index e69de29bb2d..274fbb75f07 100644
--- a/code/__DEFINES/zlevel.dm
+++ b/code/__DEFINES/zlevel.dm
@@ -0,0 +1,12 @@
+#define Z_LEVEL_NORTH "1"
+#define Z_LEVEL_SOUTH "2"
+#define Z_LEVEL_EAST "4"
+#define Z_LEVEL_WEST "8"
+
+#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
+
+// Defining these here so everything is consistent
+#define TRANSITION_BORDER_NORTH (world.maxy - TRANSITIONEDGE - 1)
+#define TRANSITION_BORDER_SOUTH TRANSITIONEDGE
+#define TRANSITION_BORDER_EAST (world.maxx - TRANSITIONEDGE - 1)
+#define TRANSITION_BORDER_WEST TRANSITIONEDGE
diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm
index abc81f9d52a..44b678a8f67 100644
--- a/code/_globalvars/mapping.dm
+++ b/code/_globalvars/mapping.dm
@@ -52,3 +52,4 @@ var/list/datum/map_template/map_templates = list()
var/list/datum/map_template/ruins_templates = list()
var/list/datum/map_template/space_ruins_templates = list()
//var/list/datum/map_template/lava_ruins_templates = list()
+var/list/datum/map_template/shelter_templates = list()
\ No newline at end of file
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
index 8b61be7d12b..0d52cdc9463 100644
--- a/code/datums/helper_datums/map_template.dm
+++ b/code/datums/helper_datums/map_template.dm
@@ -116,7 +116,7 @@
if(!config.disable_space_ruins) // so we don't unnecessarily clutter start-up
preloadRuinTemplates()
- //preloadShuttleTemplates()
+ preloadShelterTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
@@ -147,15 +147,12 @@
if(istype(R, /datum/map_template/ruin/space))
space_ruins_templates[R.name] = R
-/*
-/proc/preloadShuttleTemplates()
- for(var/item in subtypesof(/datum/map_template/shuttle))
- var/datum/map_template/shuttle/shuttle_type = item
- if(!(initial(shuttle_type.suffix)))
+/proc/preloadShelterTemplates()
+ for(var/item in subtypesof(/datum/map_template/shelter))
+ var/datum/map_template/shelter/shelter_type = item
+ if(!(initial(shelter_type.mappath)))
continue
+ var/datum/map_template/shelter/S = new shelter_type()
- var/datum/map_template/shuttle/S = new shuttle_type()
-
- shuttle_templates[S.shuttle_id] = S
- map_templates[S.shuttle_id] = S
-*/
+ shelter_templates[S.shelter_id] = S
+ map_templates[S.shelter_id] = S
\ No newline at end of file
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index b2185b15d33..843e4e1258b 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -340,7 +340,8 @@ var/round_start_time = 0
if(player.ready && player.mind)
if(player.mind.assigned_role == "AI")
player.close_spawn_windows()
- player.AIize()
+ var/mob/living/silicon/ai/ai_character = player.AIize()
+ ai_character.moveToAILandmark()
else if(!player.mind.assigned_role)
continue
else
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index a0b3f147b46..60e650691e5 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -577,4 +577,17 @@
light_color = LIGHT_COLOR_DARKRED
+/obj/machinery/sleeper/syndie/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/sleeper/syndicate(null)
+ var/obj/item/weapon/stock_parts/matter_bin/B = new(null)
+ B.rating = initial_bin_rating
+ component_parts += B
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ RefreshParts()
+
#undef ADDICTION_SPEEDUP_TIME
\ No newline at end of file
diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm
index f06771cc288..29e315ec001 100644
--- a/code/game/machinery/computer/ai_core.dm
+++ b/code/game/machinery/computer/ai_core.dm
@@ -264,9 +264,9 @@ atom/proc/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/A
if(interaction == AI_TRANS_FROM_CARD)
AI.control_disabled = 0
AI.aiRadio.disabledAi = 0
- AI.loc = loc//To replace the terminal.
+ AI.forceMove(loc)//To replace the terminal.
to_chat(AI, "You have been uploaded to a stationary terminal. Remote device connection restored.")
- to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
+ to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.")
qdel(src)
else //If for some reason you use an empty card on an empty AI terminal.
to_chat(user, "There is no AI loaded on this terminal!")
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 2defdbf4623..2c6740ffbb3 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -744,6 +744,15 @@ obj/item/weapon/circuitboard/rdserver
/obj/item/stack/cable_coil = 1,
/obj/item/weapon/stock_parts/console_screen = 2)
+/obj/item/weapon/circuitboard/sleeper/syndicate
+ name = "circuit board (Sleeper Syndicate)"
+ build_path = /obj/machinery/sleeper/syndie
+
+/obj/item/weapon/circuitboard/sleeper/survival
+ name = "circuit board (Sleeper Survival Pod)"
+ build_path = /obj/machinery/sleeper/survival_pod
+
+
/obj/item/weapon/circuitboard/bodyscanner
name = "circuit board (Body Scanner)"
build_path = /obj/machinery/bodyscanner
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 518304fda5f..b003d9ef1d6 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -386,6 +386,8 @@ Class Procs:
I.crit_fail = 1
I.forceMove(loc)
qdel(src)
+ return 1
+ return 0
/obj/machinery/proc/default_deconstruction_screwdriver(var/mob/user, var/icon_state_open, var/icon_state_closed, var/obj/item/weapon/screwdriver/S)
if(istype(S))
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 4cdc3494927..4a9d8c439ae 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -113,7 +113,9 @@ var/const/SAFETY_COOLDOWN = 100
for(var/i in to_eat)
var/atom/movable/AM = i
- if(isliving(AM))
+ if(!exists(AM))
+ continue
+ else if(isliving(AM))
if(emagged)
crush_living(AM)
else
@@ -123,7 +125,7 @@ var/const/SAFETY_COOLDOWN = 100
items_recycled++
else
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
- AM.loc = loc
+ AM.forceMove(loc)
if(items_recycled && sound)
playsound(loc, item_recycle_sound, 100, 0)
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index bfbd0a4ccb6..f5b3650c5bb 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -129,3 +129,11 @@
turf_type = /turf/simulated/floor/silent
mineralType = "tranquillite"
materials = list(MAT_TRANQUILLITE=500)
+
+//Pod floor
+/obj/item/stack/tile/pod
+ name = "pod floor tile"
+ singular_name = "pod floor tile"
+ desc = "A grooved floor tile."
+ icon_state = "tile_pod"
+ turf_type = /turf/simulated/floor/pod
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index 0b090581595..6399a11c291 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -1,16 +1,49 @@
-/obj/item/weapon/dice
- name = "d6"
+/obj/item/weapon/storage/pill_bottle/dice
+ name = "bag of dice"
+ desc = "Contains all the luck you'll ever need."
+ icon = 'icons/obj/dice.dmi'
+ icon_state = "dicebag"
+
+/obj/item/weapon/storage/pill_bottle/dice/New()
+ ..()
+ var/special_die = pick("1","2","fudge","00","100")
+ if(special_die == "1")
+ new /obj/item/weapon/dice/d1(src)
+ if(special_die == "2")
+ new /obj/item/weapon/dice/d2(src)
+ new /obj/item/weapon/dice/d4(src)
+ new /obj/item/weapon/dice/d6(src)
+ if(special_die == "fudge")
+ new /obj/item/weapon/dice/fudge(src)
+ new /obj/item/weapon/dice/d8(src)
+ new /obj/item/weapon/dice/d10(src)
+ if(special_die == "00")
+ new /obj/item/weapon/dice/d00(src)
+ new /obj/item/weapon/dice/d12(src)
+ new /obj/item/weapon/dice/d20(src)
+ if(special_die == "100")
+ new /obj/item/weapon/dice/d100(src)
+
+/obj/item/weapon/dice //depreciated d6, use /obj/item/weapon/dice/d6 if you actually want a d6
+ name = "die"
desc = "A die with six sides. Basic and servicable."
icon = 'icons/obj/dice.dmi'
icon_state = "d6"
w_class = 1
var/sides = 6
var/result = null
+ var/list/special_faces = list() //entries should match up to sides var if used
/obj/item/weapon/dice/New()
result = rand(1, sides)
update_icon()
+/obj/item/weapon/dice/d1
+ name = "d1"
+ desc = "A die with one side. Deterministic!"
+ icon_state = "d1"
+ sides = 1
+
/obj/item/weapon/dice/d2
name = "d2"
desc = "A die with two sides. Coins are undignified!"
@@ -23,6 +56,16 @@
icon_state = "d4"
sides = 4
+/obj/item/weapon/dice/d6
+ name = "d6"
+
+/obj/item/weapon/dice/fudge
+ name = "fudge die"
+ desc = "A die with six sides but only three results. Is this a plus or a minus? Your mind is drawing a blank..."
+ sides = 3 //shhh
+ icon_state = "fudge"
+ special_faces = list("minus","blank","plus")
+
/obj/item/weapon/dice/d8
name = "d8"
desc = "A die with eight sides. It feels... lucky."
@@ -53,6 +96,15 @@
icon_state = "d20"
sides = 20
+/obj/item/weapon/dice/d100
+ name = "d100"
+ desc = "A die with one hundred sides! Probably not fairly weighted..."
+ icon_state = "d100"
+ sides = 100
+
+/obj/item/weapon/dice/d100/update_icon()
+ return
+
/obj/item/weapon/dice/d20/e20
var/triggered = 0
@@ -64,8 +116,9 @@
return
diceroll(user)
-/obj/item/weapon/dice/proc/diceroll(mob/user as mob)
+/obj/item/weapon/dice/proc/diceroll(mob/user)
result = rand(1, sides)
+ var/fake_result = rand(1, sides)//Daredevil isn't as good as he used to be
var/comment = ""
if(sides == 20 && result == 20)
comment = "Nat 20!"
@@ -74,20 +127,14 @@
update_icon()
if(initial(icon_state) == "d00")
result = (result - 1)*10
+ if(special_faces.len == sides)
+ result = special_faces[result]
if(user != null) //Dice was rolled in someone's hand
user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
"You throw [src]. It lands on [result]. [comment]", \
- "You hear [src] landing on [result]. [comment]")
+ "You hear [src] rolling, it sounds like a [fake_result].")
else if(src.throwing == 0) //Dice was thrown and is coming to rest
visible_message("[src] rolls to a stop, landing on [result]. [comment]")
-/*
-/obj/item/weapon/dice/d4/Crossed(var/mob/living/carbon/human/H)
- if(istype(H) && !H.shoes)
- to_chat(H, "You step on the D4!")
- H.apply_damage(4,BRUTE,(pick("l_leg", "r_leg")))
- H.Weaken(3)
-*///ew.
-
/obj/item/weapon/dice/d20/e20/diceroll(mob/user as mob, thrown)
if(triggered)
@@ -112,6 +159,7 @@
/obj/item/weapon/dice/update_icon()
overlays.Cut()
overlays += "[src.icon_state][src.result]"
+
/obj/item/weapon/storage/box/dice
name = "Box of dice"
desc = "ANOTHER ONE!? FUCK!"
diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm
index 03ba6bed54b..67d44c53b2d 100644
--- a/code/game/objects/items/weapons/storage/firstaid.dm
+++ b/code/game/objects/items/weapons/storage/firstaid.dm
@@ -276,16 +276,6 @@
new /obj/item/weapon/reagent_containers/food/pill/charcoal( src )
new /obj/item/weapon/reagent_containers/food/pill/charcoal( src )
-/obj/item/weapon/storage/pill_bottle/dice
- name = "pack of dice"
- desc = "It's a small container with dice inside."
-
- New()
- ..()
- new /obj/item/weapon/dice( src )
- new /obj/item/weapon/dice/d20( src )
-
-
/obj/item/weapon/storage/pill_bottle/painkillers
name = "Pill Bottle (Salicylic Acid)"
desc = "Contains various pills for minor pain relief."
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 4ec1b1587c8..d498109b2dd 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -83,7 +83,7 @@
icon = loc
if(!in_range(src, user))
if(icon == src)
- to_chat(user, "\blue It's \a [bicon(icon)][src]! If you want any more information you'll need to get closer.")
+ to_chat(user, "It's \a [bicon(icon)][src]! If you want any more information you'll need to get closer.")
return
var/celsius_temperature = air_contents.temperature-T0C
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 1831b983f2c..ed0092cf60d 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -65,7 +65,10 @@
/obj/structure/closet/proc/moveMob(var/mob/M, var/atom/destination)
loc.Exited(M)
M.loc = destination
- loc.Entered(M, ignoreRest = 1)
+ if(isturf(loc))
+ loc.Entered(M, src, ignoreRest = 1)
+ else
+ loc.Entered(M, src)
for(var/atom/movable/AM in loc)
if(istype(AM, /obj/item))
continue
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index c1b6d7d2122..a247e35a86f 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -116,6 +116,8 @@
if(!..())
return 0
+ if(!istype(M)) // To avoid non-humans from causing runtimes whena dding blood to the floor
+ return 0
var/obj/effect/decal/cleanable/blood/B = locate() in contents //check for existing blood splatter
if(!B)
blood_splatter(src,M.get_blood(M.vessel),1)
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index fb10d23ae9c..c8c454383ea 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -213,21 +213,21 @@
/turf/space/proc/set_transition_north(dest_z)
destination_x = x
- destination_y = TRANSITIONEDGE + 2
+ destination_y = TRANSITION_BORDER_SOUTH + 1
destination_z = dest_z
/turf/space/proc/set_transition_south(dest_z)
destination_x = x
- destination_y = world.maxy - TRANSITIONEDGE - 2
+ destination_y = TRANSITION_BORDER_NORTH - 1
destination_z = dest_z
/turf/space/proc/set_transition_east(dest_z)
- destination_x = TRANSITIONEDGE + 2
+ destination_x = TRANSITION_BORDER_WEST + 1
destination_y = y
destination_z = dest_z
/turf/space/proc/set_transition_west(dest_z)
- destination_x = world.maxx - TRANSITIONEDGE - 2
+ destination_x = TRANSITION_BORDER_EAST - 1
destination_y = y
destination_z = dest_z
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 9548e189695..a457a843ffb 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1416,7 +1416,8 @@
message_admins("\red Admin [key_name_admin(usr)] AIized [key_name_admin(H)]!", 1)
log_admin("[key_name(usr)] AIized [key_name(H)]")
- H.AIize()
+ var/mob/living/silicon/ai/ai_character = H.AIize()
+ ai_character.moveToAILandmark()
else if(href_list["makealien"])
if(!check_rights(R_SPAWN)) return
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 577d16233d8..b776eb9a649 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -416,6 +416,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
call(/datum/game_mode/proc/add_law_zero)(new_character)
if("AI")
new_character = new_character.AIize()
+ var/mob/living/silicon/ai/ai_character = new_character
+ ai_character.moveToAILandmark()
if(new_character.mind.special_role=="traitor")
call(/datum/game_mode/proc/add_law_zero)(new_character)
//Add aliens.
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index ed4e648e6d0..b70c2741e83 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -295,7 +295,8 @@
prefs.last_id = computer_id //these are gonna be used for banning
. = ..() //calls mob.Login()
- chatOutput.start()
+ spawn() // Goonchat does some non-instant checks in start()
+ chatOutput.start()
if(custom_event_msg && custom_event_msg != "")
to_chat(src, "
Custom Event
")
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index a012afa74f9..d403b4aae4b 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -779,6 +779,17 @@
Post_Consume(mob/living/M)
M.reagents.add_reagent("omnizine", 15)
+/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak
+ name = "Lightly Warm Donk-pocket"
+ desc = "The food of choice for the seasoned traitor. This one is lukewarm."
+ icon_state = "donkpocket"
+ filling_color = "#DEDEAB"
+
+/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak/New()
+ ..()
+ reagents.add_reagent("nutriment", 4)
+ reagents.add_reagent("weak_omnizine", 3)
+
/obj/item/weapon/reagent_containers/food/snacks/syndidonkpocket
name = "Donk-pocket"
desc = "This donk-pocket is emitting a small amount of heat."
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 9a670e42d7a..c6f7e54a003 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -49,6 +49,8 @@
/obj/machinery/smartfridge/Destroy()
qdel(wires)
wires = null
+ for(var/atom/movable/A in contents)
+ A.forceMove(loc)
return ..()
/obj/machinery/smartfridge/proc/accept_check(var/obj/item/O as obj)
@@ -207,7 +209,8 @@
power_change()
return
- default_deconstruction_crowbar(O)
+ if(default_deconstruction_crowbar(O))
+ return
if(istype(O, /obj/item/device/multitool)||istype(O, /obj/item/weapon/wirecutters))
if(panel_open)
diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm
index 994f141d373..22fb9156004 100644
--- a/code/modules/hydroponics/seed.dm
+++ b/code/modules/hydroponics/seed.dm
@@ -250,11 +250,11 @@
var/no_los
var/turf/last_turf = origin_turf
for(var/turf/target_turf in getline(origin_turf,neighbor))
- if(!last_turf.Enter(target_turf) || target_turf.density)
+ if(!last_turf.Enter(thrown,target_turf) || target_turf.density)
no_los = 1
break
last_turf = target_turf
- if(!no_los && !origin_turf.Enter(neighbor))
+ if(!no_los && !origin_turf.Enter(thrown, neighbor))
no_los = 1
if(no_los)
closed_turfs |= neighbor
@@ -406,8 +406,10 @@
/datum/seed/proc/randomize()
roundstart = 0
- seed_name = "strange plant" // TODO: name generator.
+ // TODO: Better name generator
+ seed_name = "cultivar #[uid]"
display_name = "strange plants" // TODO: name generator.
+ base_name = seed_name
mysterious = 1
seed_noun = pick("spores","nodes","cuttings","seeds")
modular_icon = 1
diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm
index aaa30c3275f..7e56c57a45f 100644
--- a/code/modules/hydroponics/seed_controller.dm
+++ b/code/modules/hydroponics/seed_controller.dm
@@ -96,9 +96,9 @@ var/global/datum/controller/plants/plant_controller // Set in New().
// Proc for creating a random seed type.
/datum/controller/plants/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
- seed.randomize()
seed.uid = plant_controller.seeds.len + 1
seed.name = "[seed.uid]"
+ seed.randomize()
seeds[seed.name] = seed
if(survive_on_station)
@@ -106,8 +106,7 @@ var/global/datum/controller/plants/plant_controller // Set in New().
seed.consume_gasses["plasma"] = null
seed.consume_gasses["carbon_dioxide"] = null
if(seed.chems && !isnull(seed.chems["pacid"]))
- seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous.
- seed.chems -= null // Setting to null does not actually remove the entry, which is weird.
+ seed.chems -= "pacid" // Eating through the hull will make these plants completely inviable, albeit very dangerous.
seed.set_trait(TRAIT_IDEAL_HEAT,293)
seed.set_trait(TRAIT_HEAT_TOLERANCE,20)
seed.set_trait(TRAIT_IDEAL_LIGHT,8)
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index e774ef23924..1b1e4755e9b 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -263,6 +263,198 @@
icon_state = "mobcap[colorindex]"
update_icon()
+/*****************************Survival Pod********************************/
+
+
+/area/survivalpod
+ name = "\improper Emergency Shelter"
+ icon_state = "away"
+ requires_power = 0
+ has_gravity = 1
+
+/obj/item/weapon/survivalcapsule
+ name = "bluespace shelter capsule"
+ desc = "An emergency shelter stored within a pocket of bluespace."
+ icon_state = "capsule"
+ icon = 'icons/obj/mining.dmi'
+ w_class = 1
+ origin_tech = "engineering=3;bluespace=3"
+ var/template_id = "shelter_alpha"
+ var/datum/map_template/shelter/template
+ var/used = FALSE
+
+/obj/item/weapon/survivalcapsule/proc/get_template()
+ if(template)
+ return
+ template = shelter_templates[template_id]
+ if(!template)
+ log_runtime("Shelter template ([template_id]) not found!", src)
+ qdel(src)
+
+/obj/item/weapon/survivalcapsule/examine(mob/user)
+ . = ..()
+ get_template()
+ to_chat(user, "This capsule has the [template.name] stored.")
+ to_chat(user, template.description)
+
+/obj/item/weapon/survivalcapsule/attack_self()
+ // Can't grab when capsule is New() because templates aren't loaded then
+ get_template()
+ if(used == FALSE)
+ loc.visible_message("[src] begins to shake. Stand back!")
+ used = TRUE
+ sleep(50)
+ var/turf/deploy_location = get_turf(src)
+ var/status = template.check_deploy(deploy_location)
+ switch(status)
+ if(SHELTER_DEPLOY_BAD_AREA)
+ loc.visible_message("[src] will not function in this area.")
+ if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS)
+ var/width = template.width
+ var/height = template.height
+ loc.visible_message("[src] doesn't have room to deploy! You need to clear a [width]x[height] area!")
+
+ if(status != SHELTER_DEPLOY_ALLOWED)
+ used = FALSE
+ return
+
+ playsound(get_turf(src), 'sound/effects/phasein.ogg', 100, 1)
+
+ var/turf/T = deploy_location
+ if(!is_mining_level(T.z))//only report capsules away from the mining/lavaland level
+ message_admins("[key_name_admin(usr)] (?) (FLW) activated a bluespace capsule away from the mining level! (JMP)")
+ log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [T.x], [T.y], [T.z]")
+ template.load(deploy_location, centered = TRUE)
+ new /obj/effect/effect/harmless_smoke(get_turf(src))
+ qdel(src)
+
+//Pod turfs and objects
+
+
+//Floors
+/turf/simulated/floor/pod
+ name = "pod floor"
+ icon_state = "podfloor"
+ icon_regular_floor = "podfloor"
+ floor_tile = /obj/item/stack/tile/pod
+
+//Walls
+/turf/simulated/wall/survival
+ name = "pod wall"
+ desc = "An easily-compressable wall used for temporary shelter."
+ icon = 'icons/turf/walls/survival_pod_walls.dmi'
+ icon_state = "smooth"
+ walltype = "shuttle"
+ smooth = SMOOTH_MORE // To Do: Add in Diagnaol Smooth Support
+ canSmoothWith = list(/turf/simulated/wall/survival, /obj/machinery/door/airlock/survival_pod)
+
+//Door
+/obj/machinery/door/airlock/survival_pod
+ name = "Airlock"
+ icon = 'icons/obj/doors/survival.dmi'
+ assembly_type = /obj/structure/door_assembly/door_assembly_pod
+ opacity = 0
+ glass = 1
+
+/obj/structure/door_assembly/door_assembly_pod
+ base_icon_state = "survival_pod"
+ glass_type = "/survival_pod"
+
+//Table
+/obj/structure/table/survival_pod
+ icon = 'icons/obj/lavaland/survival_pod.dmi'
+ icon_state = "table"
+ smooth = SMOOTH_FALSE
+
+//Sleeper
+/obj/machinery/sleeper/survival_pod
+ icon = 'icons/obj/lavaland/survival_pod.dmi'
+ icon_state = "sleeper-open"
+ density = 0
+
+/obj/machinery/sleeper/survival_pod/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/sleeper/survival(null)
+ var/obj/item/weapon/stock_parts/matter_bin/B = new(null)
+ B.rating = initial_bin_rating
+ component_parts += B
+ component_parts += new /obj/item/weapon/stock_parts/manipulator(null)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
+ component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ RefreshParts()
+
+//Computer
+/obj/item/device/gps/computer
+ name = "pod computer"
+ icon_state = "pod_computer"
+ icon = 'icons/obj/lavaland/pod_computer.dmi'
+ anchored = 1
+ density = 1
+ pixel_y = -32
+
+/obj/item/device/gps/computer/attackby(obj/item/weapon/W, mob/user, params)
+ if(istype(W, /obj/item/weapon/wrench))
+ playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
+ user.visible_message("[user] disassembles the gps.", \
+ "You start to disassemble the gps...", "You hear clanking and banging noises.")
+ if(do_after(user, 20, target = src))
+ new /obj/item/device/gps(loc)
+ qdel(src)
+ return ..()
+
+/obj/item/device/gps/computer/attack_hand(mob/user)
+ attack_self(user)
+
+//Bed
+/obj/structure/stool/bed/pod
+ icon = 'icons/obj/lavaland/survival_pod.dmi'
+ icon_state = "bed"
+
+//Survival Storage Unit
+/obj/machinery/smartfridge/survival_pod
+ name = "survival pod storage"
+ desc = "A heated storage unit."
+ icon_state = "donkvendor"
+ icon = 'icons/obj/lavaland/donkvendor.dmi'
+ icon_on = "donkvendor"
+ icon_off = "donkvendor"
+ light_range = 8
+ max_n_of_items = 10
+ pixel_y = -4
+
+/obj/item/weapon/circuitboard/smartfridge/survival
+ name = "circuit board (Smartfridge Survival)"
+ build_path = /obj/machinery/smartfridge/survival_pod
+
+/obj/item/weapon/circuitboard/smartfridge/attackby(obj/item/I, mob/user, params)
+ return
+
+/obj/machinery/smartfridge/survival_pod/accept_check(obj/item/O)
+ if(istype(O, /obj/item))
+ return 1
+ return 0
+
+/obj/machinery/smartfridge/survival_pod/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/smartfridge/survival(null)
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
+ RefreshParts()
+
+/obj/machinery/smartfridge/survival_pod/loaded/New()
+ ..()
+ for(var/i in 1 to 5)
+ var/obj/item/weapon/reagent_containers/food/snacks/warmdonkpocket_weak/W = new(src)
+ load(W)
+ if(prob(50))
+ var/obj/item/weapon/storage/pill_bottle/dice/D = new(src)
+ load(D)
+ else
+ var/obj/item/device/guitar/G = new(src)
+ load(G)
+
//Fans
/obj/structure/fans
icon = 'icons/obj/lavaland/survival_pod.dmi'
@@ -307,4 +499,36 @@
return ..()
/obj/structure/fans/CanAtmosPass(turf/T)
- return !arbitraryatmosblockingvar
\ No newline at end of file
+ return !arbitraryatmosblockingvar
+
+//Signs
+/obj/structure/sign/mining
+ name = "nanotrasen mining corps sign"
+ desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims."
+ icon = 'icons/turf/walls/survival_pod_walls.dmi'
+ icon_state = "ntpod"
+
+/obj/structure/sign/mining/survival
+ name = "shelter sign"
+ desc = "A high visibility sign designating a safe shelter."
+ icon = 'icons/turf/walls/survival_pod_walls.dmi'
+ icon_state = "survival"
+
+//Fluff
+/obj/structure/tubes
+ icon_state = "tubes"
+ icon = 'icons/obj/lavaland/survival_pod.dmi'
+ name = "tubes"
+ anchored = 1
+ layer = MOB_LAYER - 0.2
+ density = 0
+
+/obj/structure/tubes/attackby(obj/item/weapon/W, mob/user, params)
+ if(istype(W, /obj/item/weapon/wrench))
+ playsound(loc, 'sound/items/Ratchet.ogg', 50, 1)
+ user.visible_message("[user] disassembles [src].", \
+ "You start to disassemble [src]...", "You hear clanking and banging noises.")
+ if(do_after(user, 20, target = src))
+ new /obj/item/stack/rods(loc)
+ qdel(src)
+ return ..()
\ No newline at end of file
diff --git a/code/modules/mining/shelters.dm b/code/modules/mining/shelters.dm
new file mode 100644
index 00000000000..38750b12d19
--- /dev/null
+++ b/code/modules/mining/shelters.dm
@@ -0,0 +1,42 @@
+/datum/map_template/shelter
+ var/shelter_id
+ var/description
+ var/blacklisted_turfs
+ var/whitelisted_turfs
+ var/banned_areas
+
+/datum/map_template/shelter/New()
+ . = ..()
+ blacklisted_turfs = typecacheof(list(/turf/simulated/wall, /turf/simulated/mineral, /turf/simulated/shuttle/wall))
+ whitelisted_turfs = list()
+ banned_areas = typecacheof(/area/shuttle)
+
+/datum/map_template/shelter/proc/check_deploy(turf/deploy_location)
+ var/affected = get_affected_turfs(deploy_location, centered=TRUE)
+ for(var/turf/T in affected)
+ var/area/A = get_area(T)
+ if(is_type_in_typecache(A, banned_areas))
+ return SHELTER_DEPLOY_BAD_AREA
+
+ var/banned = is_type_in_typecache(T, blacklisted_turfs)
+ var/permitted = is_type_in_typecache(T, whitelisted_turfs)
+ if(banned && !permitted)
+ return SHELTER_DEPLOY_BAD_TURFS
+
+ for(var/obj/O in T)
+ if(O.density && O.anchored)
+ return SHELTER_DEPLOY_ANCHORED_OBJECTS
+ return SHELTER_DEPLOY_ALLOWED
+
+/datum/map_template/shelter/alpha
+ name = "Shelter Alpha"
+ shelter_id = "shelter_alpha"
+ description = "A cosy self-contained pressurized shelter, with \
+ built-in navigation, entertainment, medical facilities and a \
+ sleeping area! Order now, and we'll throw in a TINY FAN, \
+ absolutely free!"
+ mappath = "_maps/map_files/templates/shelter_1.dmm"
+
+/datum/map_template/shelter/alpha/New()
+ . = ..()
+ whitelisted_turfs = typecacheof(/turf/simulated/mineral)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 857ff6b2de2..981dad22bf5 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -12,6 +12,7 @@
var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0)
+
if(!dna)
dna = new /datum/dna(null)
// Species name is handled by set_species()
@@ -22,6 +23,8 @@
else
set_species(delay_icon_update = 1)
+ ..()
+
if(species)
real_name = species.get_random_name(gender)
name = real_name
@@ -32,8 +35,6 @@
reagents = R
R.my_atom = src
- ..()
-
prev_gender = gender // Debug for plural genders
make_blood()
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 0aa2daa0f4f..3f7a76c0470 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -201,7 +201,8 @@
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
- sec_hud_set_ID()
+ if(hud_list.len)
+ sec_hud_set_ID()
update_inv_wear_mask(redraw_mob)
if(slot_handcuffed)
handcuffed = W
@@ -220,7 +221,8 @@
update_inv_belt(redraw_mob)
if(slot_wear_id)
wear_id = W
- sec_hud_set_ID()
+ if(!hud_list.len)
+ sec_hud_set_ID()
update_inv_wear_id(redraw_mob)
if(slot_wear_pda)
wear_pda = W
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index 024172abe8b..1e255ea50cc 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -99,4 +99,4 @@
desc = "strong adamantine hands"
icon_state = "golem"
item_state = null
- flags = ABSTRACT | NODROP
\ No newline at end of file
+ flags = ABSTRACT | NODROP
diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm
index d869b72eff3..56cee4f651f 100644
--- a/code/modules/mob/living/silicon/ai/latejoin.dm
+++ b/code/modules/mob/living/silicon/ai/latejoin.dm
@@ -37,4 +37,42 @@ var/global/list/empty_playable_ai_cores = list()
var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode
current_mode.possible_traitors.Remove(src)
- qdel(src)
\ No newline at end of file
+ qdel(src)
+
+// TODO: Move away from the insane name-based landmark system
+/mob/living/silicon/ai/proc/moveToAILandmark()
+ var/obj/loc_landmark
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if(sloc.name != "AI")
+ continue
+ if(locate(/mob/living) in sloc.loc)
+ continue
+ loc_landmark = sloc
+ if(!loc_landmark)
+ for(var/obj/effect/landmark/tripai in landmarks_list)
+ if(tripai.name == "tripai")
+ if(locate(/mob/living) in tripai.loc)
+ continue
+ loc_landmark = tripai
+ if(!loc_landmark)
+ to_chat(src, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.")
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if(sloc.name == "AI")
+ loc_landmark = sloc
+
+ forceMove(loc_landmark.loc)
+
+// Before calling this, make sure an empty core exists, or this will no-op
+/mob/living/silicon/ai/proc/moveToEmptyCore()
+ if(!empty_playable_ai_cores.len)
+ log_debug("moveToEmptyCore called without any available cores")
+ return
+
+ // IsJobAvailable for AI checks that there is an empty core available in this list
+ var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1]
+ empty_playable_ai_cores -= C
+
+ forceMove(C.loc)
+
+
+ qdel(C)
diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm
index adc0e54e661..dfa79a0d0d1 100644
--- a/code/modules/mob/living/silicon/pai/software_modules.dm
+++ b/code/modules/mob/living/silicon/pai/software_modules.dm
@@ -56,7 +56,7 @@
while(!istype(M, /mob/living))
if(!M || !M.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
- to_chat(src, "You are not being carried by anyone!")
+ to_chat(P, "You are not being carried by anyone!")
return 0
M = M.loc
count++
@@ -705,7 +705,7 @@
while(!isliving(held))
if(!held || !held.loc || count > 6)
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
- to_chat(src, "You are not being carried by anyone!")
+ to_chat(user, "You are not being carried by anyone!")
return 0
held = held.loc
count++
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 682abdb383d..d820f984ec1 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -296,18 +296,13 @@
// AIs don't need a spawnpoint, they must spawn at an empty core
if(character.mind.assigned_role == "AI")
- character = character.AIize(move=0) // AIize the character, but don't move them yet
+ var/mob/living/silicon/ai/ai_character = character.AIize() // AIize the character, but don't move them yet
// IsJobAvailable for AI checks that there is an empty core available in this list
- var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1]
- empty_playable_ai_cores -= C
+ ai_character.moveToEmptyCore()
+ AnnounceCyborg(ai_character, rank, "has been downloaded to the empty core in \the [get_area(ai_character)]")
- character.loc = C.loc
-
- AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [get_area(character)]")
- ticker.mode.latespawn(character)
-
- qdel(C)
+ ticker.mode.latespawn(ai_character)
qdel(src)
return
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index ea710335c77..43970987724 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -7,14 +7,6 @@
spawning = 1
return ..()
-/mob/living/carbon/human/AIize(move=1) // 'move' argument needs defining here too because BYOND is dumb
- if(notransform)
- return
- for(var/t in organs)
- qdel(t)
-
- return ..(move)
-
/mob/living/carbon/AIize()
if(notransform)
return
@@ -40,34 +32,12 @@
else
O.key = key
- var/obj/loc_landmark
- for(var/obj/effect/landmark/start/sloc in landmarks_list)
- if(sloc.name != "AI")
- continue
- if(locate(/mob/living) in sloc.loc)
- continue
- loc_landmark = sloc
- if(!loc_landmark)
- for(var/obj/effect/landmark/tripai in landmarks_list)
- if(tripai.name == "tripai")
- if(locate(/mob/living) in tripai.loc)
- continue
- loc_landmark = tripai
- if(!loc_landmark)
- to_chat(O, "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone.")
- for(var/obj/effect/landmark/start/sloc in landmarks_list)
- if(sloc.name == "AI")
- loc_landmark = sloc
-
- O.loc = loc_landmark.loc
-
O.on_mob_init()
O.add_ai_verbs()
O.rename_self("AI",1)
- spawn
- qdel(src)
+ qdel(src)
return O
diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm
index e5e7af93b66..c9cb554b64f 100644
--- a/code/modules/reagents/newchem/medicine.dm
+++ b/code/modules/reagents/newchem/medicine.dm
@@ -1007,4 +1007,55 @@
M.adjustToxLoss(-5*REM)
M.adjustBrainLoss(-15*REM)
M.adjustCloneLoss(-3*REM)
- ..()
\ No newline at end of file
+ ..()
+
+
+/datum/reagent/omnizine_diluted
+ name = "Diluted Omnizine"
+ id = "weak_omnizine"
+ description = "Slowly heals all damage types. A far weaker substitute than actual omnizine."
+ reagent_state = LIQUID
+ color = "#DCDCDC"
+ overdose_threshold = 30
+ metabolization_rate = 0.1
+
+/datum/reagent/omnizine_diluted/on_mob_life(mob/living/M)
+ M.adjustToxLoss(-0.5*REM)
+ M.adjustOxyLoss(-0.5*REM)
+ M.adjustBruteLoss(-0.5*REM)
+ M.adjustFireLoss(-0.5*REM)
+ ..()
+
+/datum/reagent/omnizine_diluted/overdose_process(mob/living/M, severity)
+ var/effect = ..()
+ if(severity == 1) //lesser
+ M.stuttering += 1
+ if(effect <= 1)
+ M.visible_message("[M] suddenly cluches their gut!")
+ M.emote("scream")
+ M.Stun(4)
+ M.Weaken(4)
+ else if(effect <= 3)
+ M.visible_message("[M] completely spaces out for a moment.")
+ M.confused += 15
+ else if(effect <= 5)
+ M.visible_message("[M] stumbles and staggers.")
+ M.Dizzy(5)
+ M.Weaken(3)
+ else if(effect <= 7)
+ M.visible_message("[M] shakes uncontrollably.")
+ M.Jitter(30)
+ else if(severity == 2) // greater
+ if(effect <= 2)
+ M.visible_message("[M] suddenly cluches their gut!")
+ M.emote("scream")
+ M.Stun(7)
+ M.Weaken(7)
+ else if(effect <= 5)
+ M.visible_message("[M] jerks bolt upright, then collapses!")
+ M.Paralyse(5)
+ M.Weaken(4)
+ else if(effect <= 8)
+ M.visible_message("[M] stumbles and staggers.")
+ M.Dizzy(5)
+ M.Weaken(3)
\ No newline at end of file
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 39945505aed..85657dd2b5b 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -27,12 +27,10 @@
idle_power_usage = 100
// create a new disposal
-// find the attached trunk (if present) and init gas resvr.
+// find the attached trunk (if present)
/obj/machinery/disposal/New()
..()
trunk_check()
-
- air_contents = new/datum/gas_mixture()
//gas.volume = 1.05 * CELLSTANDARD
update()
@@ -59,6 +57,7 @@
var/datum/gas_mixture/env = new
env.copy_from(L.return_air())
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
+ air_contents = new
air_contents.merge(removed)
trunk_check()
diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm
index 83309c3764f..ae5d6447aae 100644
--- a/code/modules/space_management/level_traits.dm
+++ b/code/modules/space_management/level_traits.dm
@@ -38,7 +38,7 @@
var/list/default_map_traits = MAP_TRANSITION_CONFIG
/proc/check_level_trait(z, trait)
- if(z == 0)
+ if(!z)
return 0 // If you're nowhere, you have no traits
var/list/trait_list
if(space_manager.initialized)
diff --git a/code/modules/space_management/space_level.dm b/code/modules/space_management/space_level.dm
index 02c16552c12..dc598ccab42 100644
--- a/code/modules/space_management/space_level.dm
+++ b/code/modules/space_management/space_level.dm
@@ -39,57 +39,57 @@
/datum/space_level/proc/build_space_destination_arrays()
// We skip `add_to_transit` here because we want to skip the checks in order to save time
// Bottom border
- for(var/turf/space/S in block(locate(1,1,zpos),locate(world.maxx,TRANSITIONEDGE+1,zpos)))
+ for(var/turf/space/S in block(locate(1,1,zpos),locate(world.maxx,TRANSITION_BORDER_SOUTH,zpos)))
transit_south |= S
// Top border
- for(var/turf/space/S in block(locate(1,world.maxy,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 1,zpos)))
+ for(var/turf/space/S in block(locate(1,world.maxy,zpos),locate(world.maxx,TRANSITION_BORDER_NORTH,zpos)))
transit_north |= S
// Left border
- for(var/turf/space/S in block(locate(1,TRANSITIONEDGE+1,zpos),locate(TRANSITIONEDGE+1,world.maxy - TRANSITIONEDGE - 2,zpos)))
+ for(var/turf/space/S in block(locate(1,TRANSITION_BORDER_SOUTH + 1,zpos),locate(TRANSITION_BORDER_WEST,TRANSITION_BORDER_NORTH - 1,zpos)))
transit_west |= S
// Right border
- for(var/turf/space/S in block(locate(world.maxx - TRANSITIONEDGE - 1,TRANSITIONEDGE+1,zpos),locate(world.maxx,world.maxy - TRANSITIONEDGE - 2,zpos)))
+ for(var/turf/space/S in block(locate(TRANSITION_BORDER_EAST,TRANSITION_BORDER_SOUTH + 1,zpos),locate(world.maxx,TRANSITION_BORDER_NORTH - 1,zpos)))
transit_east |= S
/datum/space_level/proc/add_to_transit(turf/space/S)
- if(S.y <= TRANSITIONEDGE)
+ if(S.y <= TRANSITION_BORDER_SOUTH)
transit_south |= S
return
// Top border
- if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
+ if(S.y >= TRANSITION_BORDER_NORTH)
transit_north |= S
return
// Left border
- if(S.x <= TRANSITIONEDGE)
+ if(S.x <= TRANSITION_BORDER_WEST)
transit_west |= S
return
// Right border
- if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
+ if(S.x >= TRANSITION_BORDER_EAST)
transit_east |= S
/datum/space_level/proc/remove_from_transit(turf/space/S)
- if(S.y <= TRANSITIONEDGE)
+ if(S.y <= TRANSITION_BORDER_SOUTH)
transit_south -= S
return
// Top border
- if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
+ if(S.y >= TRANSITION_BORDER_NORTH)
transit_north -= S
return
// Left border
- if(S.x <= TRANSITIONEDGE)
+ if(S.x <= TRANSITION_BORDER_WEST)
transit_west -= S
return
// Right border
- if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
+ if(S.x >= TRANSITION_BORDER_EAST)
transit_east -= S
/datum/space_level/proc/apply_transition(turf/space/S)
@@ -101,16 +101,16 @@
if(SELFLOOPING,CROSSLINKED)
var/datum/space_level/E = get_connection()
if(S in transit_north)
- E = get_connection("[NORTH]")
+ E = get_connection(Z_LEVEL_NORTH)
S.set_transition_north(E.zpos)
if(S in transit_south)
- E = get_connection("[SOUTH]")
+ E = get_connection(Z_LEVEL_SOUTH)
S.set_transition_south(E.zpos)
if(S in transit_east)
- E = get_connection("[EAST]")
+ E = get_connection(Z_LEVEL_EAST)
S.set_transition_east(E.zpos)
if(S in transit_west)
- E = get_connection("[WEST]")
+ E = get_connection(Z_LEVEL_WEST)
S.set_transition_west(E.zpos)
diff --git a/code/modules/space_management/space_transition.dm b/code/modules/space_management/space_transition.dm
index b7691ce6601..f432d9733a5 100644
--- a/code/modules/space_management/space_transition.dm
+++ b/code/modules/space_management/space_transition.dm
@@ -1,9 +1,5 @@
//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube
-#define Z_LEVEL_NORTH "1"
-#define Z_LEVEL_SOUTH "2"
-#define Z_LEVEL_EAST "4"
-#define Z_LEVEL_WEST "8"
/proc/get_opposite_direction(direction)
switch(direction)
@@ -430,9 +426,3 @@
else
our_spot = our_spot.ChangeTurf(/turf/simulated/floor/fakespace)
our_spot.desc = grid_desc
-
-
-#undef Z_LEVEL_NORTH
-#undef Z_LEVEL_SOUTH
-#undef Z_LEVEL_EAST
-#undef Z_LEVEL_WEST
diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm
index e2702b36afe..699b9ed1ee3 100644
--- a/code/modules/surgery/organs/organ_external.dm
+++ b/code/modules/surgery/organs/organ_external.dm
@@ -69,13 +69,14 @@
if(parent && parent.children)
parent.children -= src
- if(owner)
- owner.organs_by_name[limb_name] = null
-
if(internal_organs)
for(var/obj/item/organ/internal/O in internal_organs)
internal_organs -= O
O.remove(owner,special = 1)
+ qdel(O)
+
+ if(owner)
+ owner.organs_by_name[limb_name] = null
if(children)
for(var/obj/item/organ/external/C in children)
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index a902dc55afa..2d9ddf78e80 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -39,7 +39,7 @@
var/mob/living/carbon/human/H = M
parent = H.get_organ(check_zone(parent_organ))
if(!istype(parent))
- log_to_dd("[src] attempted to insert into a [parent], but [parent] wasn't an organ! Area: [get_area(M)]")
+ log_debug("[src] attempted to insert into a [parent_organ], but [parent_organ] wasn't an organ! [atom_loc_line(M)]")
else
parent.internal_organs |= src
//M.internal_organs_by_name[src] |= src(H,1)
@@ -52,6 +52,8 @@
// Returns the removed object, which is usually just itself
// However, you MUST set the object's positiion yourself when you call this!
/obj/item/organ/internal/remove(mob/living/carbon/M, special = 0)
+ if(!owner)
+ log_debug("\'remove\' called on [src] without an owner! Mob: [M], [atom_loc_line(M)]")
owner = null
if(M)
M.internal_organs -= src
@@ -63,7 +65,7 @@
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/parent = H.get_organ(check_zone(parent_organ))
if(!istype(parent))
- log_to_dd("[src] attempted to remove from a [parent], but [parent] didn't exist! Area: [get_area(M)], Mob: [M]")
+ log_debug("[src] attempted to remove from a [parent_organ], but [parent_organ] didn't exist! [atom_loc_line(M)]")
else
parent.internal_organs -= src
diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm
index e8af8c93430..bc5392e2251 100644
--- a/goon/code/datums/browserOutput.dm
+++ b/goon/code/datums/browserOutput.dm
@@ -37,6 +37,9 @@ var/list/chatResources = list(
broken = TRUE
return 0
+ if(!owner) // In case the client vanishes before winexists returns
+ return 0
+
if(winget(owner, "browseroutput", "is-disabled") == "false")
doneLoading()
diff --git a/html/changelogs/AutoChangeLog-pr-5509.yml b/html/changelogs/AutoChangeLog-pr-5509.yml
new file mode 100644
index 00000000000..f20d11714c9
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-5509.yml
@@ -0,0 +1,5 @@
+author: Fox McCloud and KorPhaeron
+delete-after: True
+changes:
+ - rscadd: "Adds in mining shelters"
+ - rscadd: "Adds in a few more dice types and ensure dice are packed in bags and not pill bottles"
diff --git a/icons/obj/dice.dmi b/icons/obj/dice.dmi
index d1a2dde4550..9ec030df05e 100644
Binary files a/icons/obj/dice.dmi and b/icons/obj/dice.dmi differ
diff --git a/icons/obj/doors/door_assembly.dmi b/icons/obj/doors/door_assembly.dmi
index 2c927cb8047..232a54da317 100644
Binary files a/icons/obj/doors/door_assembly.dmi and b/icons/obj/doors/door_assembly.dmi differ
diff --git a/icons/obj/doors/survival.dmi b/icons/obj/doors/survival.dmi
new file mode 100644
index 00000000000..fcc10adaa17
Binary files /dev/null and b/icons/obj/doors/survival.dmi differ
diff --git a/icons/obj/lavaland/donkvendor.dmi b/icons/obj/lavaland/donkvendor.dmi
new file mode 100644
index 00000000000..0b78a5168e4
Binary files /dev/null and b/icons/obj/lavaland/donkvendor.dmi differ
diff --git a/icons/obj/lavaland/pod_computer.dmi b/icons/obj/lavaland/pod_computer.dmi
new file mode 100644
index 00000000000..8417cfb8802
Binary files /dev/null and b/icons/obj/lavaland/pod_computer.dmi differ
diff --git a/icons/obj/lavaland/survival_pod.dmi b/icons/obj/lavaland/survival_pod.dmi
index 62aad7854d2..fae242d524f 100644
Binary files a/icons/obj/lavaland/survival_pod.dmi and b/icons/obj/lavaland/survival_pod.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index c39dbef36a8..ef7ea2ddac7 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/turf/walls/survival_pod_walls.dmi b/icons/turf/walls/survival_pod_walls.dmi
new file mode 100644
index 00000000000..12dc44e9ea2
Binary files /dev/null and b/icons/turf/walls/survival_pod_walls.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 26679b0288d..a2f58dff96d 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1416,6 +1416,7 @@
#include "code\modules\mining\money_bag.dm"
#include "code\modules\mining\ore.dm"
#include "code\modules\mining\satchel_ore_boxdm.dm"
+#include "code\modules\mining\shelters.dm"
#include "code\modules\mining\laborcamp\laborminerals.dm"
#include "code\modules\mining\laborcamp\laborshuttle.dm"
#include "code\modules\mining\laborcamp\laborstacker.dm"