diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm
index 9b49fb95f0a..1c01bd82780 100644
--- a/code/_globalvars/lists/mapping.dm
+++ b/code/_globalvars/lists/mapping.dm
@@ -52,3 +52,8 @@ var/list/awaydestinations = list() //a list of landmarks that the warpgate can t
//used by jump-to-area etc. Updated by area/updateName()
var/list/sortedAreas = list()
+
+//List of preloaded templates
+var/list/datum/map_template/map_templates = list()
+var/list/datum/map_template/space_ruins_templates = list()
+var/list/datum/map_template/lava_ruins_templates = list()
\ No newline at end of file
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 67fdc91a090..6800c95e2b4 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -72,6 +72,7 @@ var/global/datum/controller/master/Master = new()
return
world << "Initializing subsystems..."
+ preloadTemplates()
// Pick a random away mission.
createRandomZlevel()
// Generate asteroid.
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
new file mode 100644
index 00000000000..46a8f576e99
--- /dev/null
+++ b/code/datums/helper_datums/map_template.dm
@@ -0,0 +1,87 @@
+/datum/map_template
+ var/name = "Default Template Name"
+ var/width = 0
+ var/height = 0
+ var/mappath = null
+ var/mapfile = null
+
+/datum/map_template/New(path = null, map = null, rename = null)
+ if(path)
+ mappath = path
+ preload_size(mappath)
+ if(map)
+ mapfile = map
+ if(rename)
+ name = rename
+
+/datum/map_template/proc/preload_size(path)
+ var/quote = ascii2text(34)
+ var/map_file = file2text(path)
+ var/key_len = length(copytext(map_file,2,findtext(map_file,quote,2,0)))
+ //assuming one map per file since more makes no sense for templates anyway
+ var/mapstart = findtext(map_file,"\n(1,1,") //todo replace with something saner
+ var/content = copytext(map_file,findtext(map_file,quote+"\n",mapstart,0)+2,findtext(map_file,"\n"+quote,mapstart,0)+1)
+ var/line_len = length(copytext(content,1,findtext(content,"\n",2,0)))
+
+ width = line_len/key_len
+ height = length(content)/(line_len+1)
+
+/datum/map_template/proc/load(turf/T, centered = FALSE)
+ if(centered)
+ T = locate(T.x - width/2 , T.y - height/2 , T.z)
+ if(!T)
+ return
+ if(T.x+width > world.maxx)
+ return
+ if(T.y+height > world.maxy)
+ return
+
+ maploader.load_map(get_file(), T.x, T.y, T.z)
+ //initialize
+ for(var/A in block(T,locate(T.x+width, T.y+height, T.z)))
+ var/turf/B = A
+ for(var/atom/movable/AM in B)
+ AM.initialize()
+ if(istype(AM,/obj/structure/cable))
+ var/obj/structure/cable/PC = AM
+ if(!PC.powernet)
+ var/datum/powernet/NewPN = new()
+ NewPN.add_cable(PC)
+ propagate_network(PC,PC.powernet)
+
+ log_game("[name] loaded at at [T.x],[T.y],[T.z]")
+
+/datum/map_template/proc/get_file()
+ if(mapfile)
+ return mapfile
+ if(mappath)
+ mapfile = file(mappath)
+ return mapfile
+
+/datum/map_template/proc/get_affected_turfs(turf/T, centered = FALSE)
+ var/turf/placement = T
+ if(centered)
+ var/turf/corner = locate(placement.x - width/2, placement.y - height/2, placement.z)
+ if(corner)
+ placement = corner
+ return block(placement, locate(placement.x + width, placement.y + height, placement.z))
+
+
+/proc/preloadTemplates(path = "_maps/templates/") //see master controller setup
+ var/list/filelist = flist(path)
+ for(var/map in filelist)
+ var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
+ map_templates[T.name] = T
+
+ preloadRuinTemplates()
+
+/proc/preloadRuinTemplates()
+ var/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRuinConfig.txt")
+ for(var/ruin in potentialSpaceRuins)
+ var/datum/map_template/T = new(path = "[ruin]", rename = "[ruin]")
+ space_ruins_templates[T.name] = T
+
+ var/list/potentialLavaRuins = generateMapList(filename = "config/lavaRuinConfig.txt")
+ for(var/ruin in potentialLavaRuins)
+ var/datum/map_template/T = new(path = "[ruin]", rename = "[ruin]")
+ lava_ruins_templates[T.name] = T
\ No newline at end of file
diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm
index 73ca6e5d680..be9bc8c4aec 100644
--- a/code/modules/admin/verbs/map_template_loadverb.dm
+++ b/code/modules/admin/verbs/map_template_loadverb.dm
@@ -1,4 +1,3 @@
-
/client/proc/map_template_load()
set category = "Debug"
set name = "Map template - Place"
@@ -7,30 +6,15 @@
if(!T)
return
- var/list/filelist = flist("_maps/templates/")
- filelist |= map_template_uploads
+ var/datum/map_template/template
- var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in filelist
+ var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in map_templates
if(!map)
return
- var/mapfile
- if(map in map_template_uploads) //in the cache, not the template folder
- mapfile = map
- else
- mapfile = file("_maps/templates/[map]")
-
- if(isfile(mapfile))
- maploader.load_map(mapfile, T.x, T.y, T.z)
- message_admins("[key_name_admin(usr)] has placed a map template ([map]) at (JMP)")
- else
- usr << "Bad map file: [map]"
-
-
-//A list of map files that have been uploaded by admins
-//It's NOT persistent between rounds
-var/global/list/map_template_uploads = list()
-
+ template = map_templates[map]
+ template.load(T)
+ message_admins("[key_name_admin(usr)] has placed a map template ([template.name]) at (JMP)")
/client/proc/map_template_upload()
set category = "Debug"
@@ -43,5 +27,6 @@ var/global/list/map_template_uploads = list()
usr << "Bad map file: [map]"
return
- map_template_uploads |= file(map)
+ var/datum/map_template/M = new(map=map, rename="[map]")
+ map_templates[M.name] = M
message_admins("[key_name_admin(usr)] has uploaded a map template ([map])")
diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm
index eb284af8c41..6eee3c026f3 100644
--- a/code/modules/awaymissions/zlevel.dm
+++ b/code/modules/awaymissions/zlevel.dm
@@ -7,10 +7,6 @@
var/global/list/potentialRandomZlevels = generateMapList(filename = "config/awaymissionconfig.txt")
-var/global/list/potentialLavaRuins = generateMapList(filename = "config/lavaRuinConfig.txt")
-
-var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRuinConfig.txt")
-
/proc/createRandomZlevel()
if(awaydestinations.len) //crude, but it saves another var!
return
@@ -71,12 +67,13 @@ var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRu
return potentialMaps
-/proc/seedRuins(z_level = 1, ruin_number = 0, whitelist = /area/space, list/potentialRuins = potentialSpaceRuins)
+/proc/seedRuins(z_level = 1, ruin_number = 0, whitelist = /area/space, list/potentialRuins = space_ruins_templates)
ruin_number = min(ruin_number, potentialRuins.len)
while(ruin_number)
var/sanity = 0
var/valid = FALSE
+ var/datum/map_template/template = potentialRuins[pick(potentialRuins)]
while(!valid)
valid = TRUE
sanity++
@@ -85,17 +82,16 @@ var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRu
break
var/turf/T = locate(rand(RANDOM_LOWER_X, RANDOM_UPPER_X), rand(RANDOM_LOWER_Y, RANDOM_UPPER_Y), z_level)
- for(var/turf/check in range(T, 15))
+ for(var/turf/check in template.get_affected_turfs(T,1))
var/area/new_area = get_area(check)
if(!(istype(new_area, whitelist)))
valid = FALSE
break
-
if(valid)
world.log << "Ruins marker placed at [T.x][T.y][T.z]"
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
- R.Load(potentialRuins, -15, -15)
+ R.Load(potentialRuins,template)
ruin_number --
return
@@ -107,16 +103,13 @@ var/global/list/potentialSpaceRuins = generateMapList(filename = "config/spaceRu
icon_state = "syndballoon"
invisibility = 0
-/obj/effect/ruin_loader/proc/Load(list/potentialRuins = potentialSpaceRuins, x_offset = 0, y_offset = 0)
+/obj/effect/ruin_loader/proc/Load(list/potentialRuins = space_ruins_templates, datum/map_template/template = null)
if(potentialRuins.len)
world << "Loading ruins..."
-
- var/map = pick(potentialRuins)
- var/file = file(map)
- if(isfile(file))
- maploader.load_map(file, src.x + x_offset, src.y + y_offset, src.z)
- world.log << "[map] loaded at at [src.x + x_offset],[src.y + y_offset],[src.z]"
- potentialRuins -= map //Don't want to load the same one twice
+ if(!template)
+ template = potentialRuins[pick(potentialRuins)]
+ template.load(get_turf(src),centered = TRUE)
+ potentialRuins -= template //Don't want to load the same one twice
world << "Ruins loaded."
else
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index 852437a948e..6809cea83ed 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -180,6 +180,7 @@
..()
SSshuttle.mobile += src
+/obj/docking_port/mobile/initialize()
var/area/A = get_area(src)
if(istype(A, /area/shuttle))
areaInstance = A
diff --git a/tgstation.dme b/tgstation.dme
index b85628713c8..f1bcb25338e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -244,6 +244,7 @@
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\icon_snapshot.dm"
+#include "code\datums\helper_datums\map_template.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\spells\area_teleport.dm"