diff --git a/_maps/map_files/templates/shelter_1.dmm b/_maps/map_files/templates/shelter_1.dmm
new file mode 100644
index 00000000000..a3535c89361
--- /dev/null
+++ b/_maps/map_files/templates/shelter_1.dmm
@@ -0,0 +1,110 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"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,
+/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) = {"
+a
+a
+f
+a
+a
+"}
+(2,1,1) = {"
+a
+c
+g
+k
+m
+"}
+(3,1,1) = {"
+b
+d
+h
+h
+n
+"}
+(4,1,1) = {"
+a
+e
+i
+l
+o
+"}
+(5,1,1) = {"
+a
+a
+j
+a
+a
+"}
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index ab1357a5833..f8ac8d0176f 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -281,4 +281,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"
\ No newline at end of file
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/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index dcd32582046..6399a11c291 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -130,18 +130,12 @@
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]", \
+ user.visible_message("[user] has thrown [src]. It lands on [result]. [comment]", \
"You throw [src]. It lands 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)
-
/obj/item/weapon/dice/d20/e20/diceroll(mob/user as mob, thrown)
if(triggered)
return
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index c79f2aa4046..4e490479697 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -278,153 +278,60 @@
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)
+ throw EXCEPTION("Shelter template ([template_id]) not found!")
+ qdel(src)
+
+/obj/item/weapon/survivalcapsule/Destroy()
+ template = null // without this, capsules would be one use. per round.
+ return ..()
+
+/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/T = get_turf(src)
- var/clear = TRUE
- for(var/turf/turf in range(2, T))
- if(turf.density && !istype(turf, /turf/simulated/mineral))
- clear = FALSE
- break
- for(var/obj/obj in turf)
- if(obj.density && obj.anchored)
- clear = FALSE
- break
- if(!clear)
- loc.visible_message("[src] doesn't have room to deploy! You need to clear a 5x5 area!")
+ 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]")
- load()
- new /obj/effect/effect/smoke(loc)
+ template.load(deploy_location, centered = TRUE)
+ new /obj/effect/effect/harmless_smoke(get_turf(src))
qdel(src)
-/obj/item/weapon/survivalcapsule/proc/load()
- var/list/blacklist = list(/area/shuttle) //Shuttles move based on area, and we'd like not to break them
- var/turf/start_turf = get_turf(loc)
- var/turf/cur_turf
- var/x_size = 5
- var/y_size = 5
- var/list/walltypes = list(/turf/simulated/wall/survival)
- var/floor_type = /turf/simulated/floor/pod
- var/room
-
- //Center the room/spawn it
- start_turf = locate(start_turf.x -2, start_turf.y - 2, start_turf.z)
-
- room = spawn_room(start_turf, x_size, y_size, walltypes, floor_type, "Emergency Shelter")
-
- start_turf = get_turf(loc)
-
- //Fill it
-
- //The door
- cur_turf = locate(start_turf.x, start_turf.y-2, start_turf.z)
- new /obj/machinery/door/airlock/survival_pod(cur_turf)
-
-
- //Bed middle right
- cur_turf = locate(start_turf.x+1, start_turf.y, start_turf.z)
- new /obj/structure/stool/bed/pod(cur_turf)
- new /obj/item/weapon/bedsheet/brown(cur_turf)
-
- //Chair bottom right
- cur_turf = locate(start_turf.x+1, start_turf.y-1, start_turf.z)
- new /obj/structure/tubes(cur_turf)
- var/obj/structure/stool/bed/chair/comfy/black/C = new (cur_turf)
- C.dir = 8
-
- //GPS computer top right
- cur_turf = locate(start_turf.x+1, start_turf.y+1, start_turf.z)
- new /obj/item/device/gps/computer(cur_turf)
-
- //Donk Pocket Storage Top/middle
- cur_turf = locate(start_turf.x, start_turf.y+1, start_turf.z)
- new /obj/machinery/smartfridge/survival_pod(cur_turf)
-
- //Table in Bottom Left
- cur_turf = locate(start_turf.x-1, start_turf.y-1, start_turf.z)
- new /obj/structure/table/survival_pod(cur_turf)
-
- //Sleeper Middle Left
- cur_turf = locate(start_turf.x-1, start_turf.y, start_turf.z)
- new /obj/machinery/sleeper/survival_pod(cur_turf)
-
- //Fans Top Left
- cur_turf = locate(start_turf.x-1, start_turf.y+1, start_turf.z)
- new /obj/structure/fans(cur_turf)
-
- //Signs
- cur_turf = locate(start_turf.x-2, start_turf.y, start_turf.z)
- var/obj/structure/sign/mining/survival/S1 = new(cur_turf)
- S1.dir = EAST
-
- cur_turf = locate(start_turf.x+2, start_turf.y, start_turf.z)
- var/obj/structure/sign/mining/survival/S2 = new(cur_turf)
- S2.dir = WEST
-
- cur_turf = locate(start_turf.x, start_turf.y+2, start_turf.z)
- var/obj/structure/sign/mining/survival/S3 = new(cur_turf)
- S3.dir = NORTH
-
- cur_turf = locate(start_turf.x-1, start_turf.y-2, start_turf.z)
- var/obj/structure/sign/mining/survival/S4 = new(cur_turf)
- S4.dir = SOUTH
-
- cur_turf = locate(start_turf.x+1, start_turf.y-2, start_turf.z)
- new /obj/structure/sign/mining(cur_turf)
-
- var/area/survivalpod/L = new /area/survivalpod
-
- var/turf/threshhold = locate(start_turf.x, start_turf.y-2, start_turf.z)
- threshhold.ChangeTurf(/turf/simulated/floor/pod)
- var/turf/simulated/floor/pod/doorturf = threshhold
- air_master.remove_from_active(doorturf)
- doorturf.oxygen = 21
- doorturf.temperature = 293.15
- doorturf.nitrogen = 82
- doorturf.carbon_dioxide = 0
- doorturf.toxins = 0
- doorturf.air.oxygen = 21
- doorturf.air.carbon_dioxide = 0
- doorturf.air.nitrogen = 82
- doorturf.air.toxins = 0
- doorturf.air.temperature = 293.15
- air_master.add_to_active(doorturf)
- var/area/ZZ = get_area(threshhold)
- if(!is_type_in_list(ZZ, blacklist))
- L.contents += threshhold
- threshhold.overlays.Cut()
-
- new /obj/structure/fans/tiny(threshhold) //a tiny fan, to keep the air in.
-
- var/list/turfs = room["floors"]
- for(var/turf/simulated/floor/A in turfs)
- air_master.remove_from_active(A)
- A.oxygen = 21
- A.temperature = 293.15
- A.nitrogen = 82
- A.carbon_dioxide = 0
- A.toxins = 0
- A.air.oxygen = 21
- A.air.carbon_dioxide = 0
- A.air.nitrogen = 82
- A.air.toxins = 0
- A.air.temperature = 293.15
- air_master.add_to_active(A)
- A.overlays.Cut()
- var/area/Z = get_area(A)
- if(!is_type_in_list(Z, blacklist))
- L.contents += A
-
//Pod turfs and objects
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/paradise.dme b/paradise.dme
index 883e8908d01..9e0e34dabc1 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1412,6 +1412,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"