diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm index 63e5e4fe325..3aeacb942a7 100644 --- a/code/LINDA/LINDA_turf_tile.dm +++ b/code/LINDA/LINDA_turf_tile.dm @@ -56,10 +56,6 @@ /turf/simulated/New() ..() - levelupdate() - if(smooth) - smooth_icon(src) - visibilityChanged() if(!blocks_air) air = new @@ -259,7 +255,7 @@ atmos_overlay = get_atmos_overlay_by_name(new_overlay_type) if (atmos_overlay) overlays += atmos_overlay - atmos_overlay_type = new_overlay_type + atmos_overlay_type = new_overlay_type /turf/simulated/proc/get_atmos_overlay_by_name(var/name) switch(name) diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index 5ae2ddb07a8..d9b7091247f 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -61,81 +61,80 @@ /proc/smooth_icon(atom/A) if(qdeleted(A)) return - spawn(0) //don't remove this, otherwise smoothing breaks - if(A && A.smooth) - var/adjacencies = calculate_adjacencies(A) + if(A && A.smooth) + var/adjacencies = calculate_adjacencies(A) - //NW CORNER - var/nw = "1-i" - if((adjacencies & N_NORTH) && (adjacencies & N_WEST)) - if(adjacencies & N_NORTHWEST) - nw = "1-f" - else - nw = "1-nw" + //NW CORNER + var/nw = "1-i" + if((adjacencies & N_NORTH) && (adjacencies & N_WEST)) + if(adjacencies & N_NORTHWEST) + nw = "1-f" else - if(adjacencies & N_NORTH) - nw = "1-n" - else if(adjacencies & N_WEST) - nw = "1-w" + nw = "1-nw" + else + if(adjacencies & N_NORTH) + nw = "1-n" + else if(adjacencies & N_WEST) + nw = "1-w" - //NE CORNER - var/ne = "2-i" - if((adjacencies & N_NORTH) && (adjacencies & N_EAST)) - if(adjacencies & N_NORTHEAST) - ne = "2-f" - else - ne = "2-ne" + //NE CORNER + var/ne = "2-i" + if((adjacencies & N_NORTH) && (adjacencies & N_EAST)) + if(adjacencies & N_NORTHEAST) + ne = "2-f" else - if(adjacencies & N_NORTH) - ne = "2-n" - else if(adjacencies & N_EAST) - ne = "2-e" + ne = "2-ne" + else + if(adjacencies & N_NORTH) + ne = "2-n" + else if(adjacencies & N_EAST) + ne = "2-e" - //SW CORNER - var/sw = "3-i" - if((adjacencies & N_SOUTH) && (adjacencies & N_WEST)) - if(adjacencies & N_SOUTHWEST) - sw = "3-f" - else - sw = "3-sw" + //SW CORNER + var/sw = "3-i" + if((adjacencies & N_SOUTH) && (adjacencies & N_WEST)) + if(adjacencies & N_SOUTHWEST) + sw = "3-f" else - if(adjacencies & N_SOUTH) - sw = "3-s" - else if(adjacencies & N_WEST) - sw = "3-w" + sw = "3-sw" + else + if(adjacencies & N_SOUTH) + sw = "3-s" + else if(adjacencies & N_WEST) + sw = "3-w" - //SE CORNER - var/se = "4-i" - if((adjacencies & N_SOUTH) && (adjacencies & N_EAST)) - if(adjacencies & N_SOUTHEAST) - se = "4-f" - else - se = "4-se" + //SE CORNER + var/se = "4-i" + if((adjacencies & N_SOUTH) && (adjacencies & N_EAST)) + if(adjacencies & N_SOUTHEAST) + se = "4-f" else - if(adjacencies & N_SOUTH) - se = "4-s" - else if(adjacencies & N_EAST) - se = "4-e" + se = "4-se" + else + if(adjacencies & N_SOUTH) + se = "4-s" + else if(adjacencies & N_EAST) + se = "4-e" - if(A.top_left_corner != nw) - A.overlays -= A.top_left_corner - A.top_left_corner = nw - A.overlays += nw + if(A.top_left_corner != nw) + A.overlays -= A.top_left_corner + A.top_left_corner = nw + A.overlays += nw - if(A.top_right_corner != ne) - A.overlays -= A.top_right_corner - A.top_right_corner = ne - A.overlays += ne + if(A.top_right_corner != ne) + A.overlays -= A.top_right_corner + A.top_right_corner = ne + A.overlays += ne - if(A.bottom_right_corner != sw) - A.overlays -= A.bottom_right_corner - A.bottom_right_corner = sw - A.overlays += sw + if(A.bottom_right_corner != sw) + A.overlays -= A.bottom_right_corner + A.bottom_right_corner = sw + A.overlays += sw - if(A.bottom_left_corner != se) - A.overlays -= A.bottom_left_corner - A.bottom_left_corner = se - A.overlays += se + if(A.bottom_left_corner != se) + A.overlays -= A.bottom_left_corner + A.bottom_left_corner = se + A.overlays += se /proc/find_type_in_direction(atom/source, direction, range=1) var/x_offset = 0 diff --git a/code/_globalvars/lists/misc.dm b/code/_globalvars/lists/misc.dm index 52d05ac6d65..6641bf50e7d 100644 --- a/code/_globalvars/lists/misc.dm +++ b/code/_globalvars/lists/misc.dm @@ -1,5 +1,5 @@ var/global/list/alphabet = list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z") -var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") +var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") var/global/list/zero_character_only = list("0") var/global/list/hex_characters = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f") var/global/list/binary = list("0","1") @@ -22,3 +22,5 @@ var/list/restricted_camera_networks = list( //Those networks can only be accesse "UO45R", "Xeno" ) + +var/list/datum/map_template/map_templates = list() \ No newline at end of file diff --git a/code/controllers/Processes/air.dm b/code/controllers/Processes/air.dm index 58456b76d8b..4846b850790 100644 --- a/code/controllers/Processes/air.dm +++ b/code/controllers/Processes/air.dm @@ -30,8 +30,8 @@ var/global/datum/controller/process/air_system/air_master var/watch = start_watch() log_startup_progress("Processing geometry...") - setup_allturfs() // Get all currently active tiles that need processing each atmos tick. setup_overlays() // Assign icons and such for gas-turf-overlays + setup_allturfs() // Get all currently active tiles that need processing each atmos tick. log_startup_progress(" Geometry processed in [stop_watch(watch)]s.") /datum/controller/process/air_system/doWork() diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 3aa23ee09f9..d2bd83461f8 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -41,6 +41,7 @@ datum/controller/game_controller/New() datum/controller/game_controller/proc/setup() world.tick_lag = config.Ticklag + preloadTemplates() if(!config.disable_away_missions) createRandomZlevel() @@ -58,12 +59,12 @@ datum/controller/game_controller/proc/setup_objects() var/watch = start_watch() var/count = 0 var/overwatch = start_watch() // Overall. - + log_startup_progress("Populating asset cache...") populate_asset_cache() log_startup_progress(" Populated [asset_cache.len] assets in [stop_watch(watch)]s.") - watch = start_watch() + watch = start_watch() log_startup_progress("Initializing objects...") for(var/atom/movable/object in world) object.initialize() @@ -82,8 +83,8 @@ datum/controller/game_controller/proc/setup_objects() var/obj/machinery/atmospherics/unary/vent_scrubber/T = U T.broadcast_status() count++ - log_startup_progress(" Initialized [count] atmospherics machines in [stop_watch(watch)]s.") - + log_startup_progress(" Initialized [count] atmospherics machines in [stop_watch(watch)]s.") + watch = start_watch() count = 0 log_startup_progress("Initializing pipe networks...") @@ -91,5 +92,5 @@ datum/controller/game_controller/proc/setup_objects() machine.build_network() count++ log_startup_progress(" Initialized [count] pipe networks in [stop_watch(watch)]s.") - + log_startup_progress("Finished object initializations in [stop_watch(overwatch)]s.") diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm new file mode 100644 index 00000000000..22419fa6edb --- /dev/null +++ b/code/datums/helper_datums/map_template.dm @@ -0,0 +1,67 @@ +/datum/map_template + var/name = "Default Template Name" + var/width = 0 + var/height = 0 + var/mappath = null + var/mapfile = null + var/loaded = 0 // Times loaded this round + +/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 = 0) + if(centered) + T = locate(T.x - round(width / 2), T.y - round(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-1, T.y-1, T.z) + late_setup_level( + block(T, locate(T.x + width - 1, T.y + height - 1, T.z)), + block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + width, T.y + height, T.z))) + + 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 = 0) + var/turf/placement = T + if(centered) + var/turf/corner = locate(placement.x - round(width/2), placement.y - round(height/2), placement.z) + if(corner) + placement = corner + return block(placement, locate(placement.x+width-1, placement.y+height-1, placement.z)) + + +/proc/preloadTemplates(path = "_maps/map_files/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 \ No newline at end of file diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 952a647f3aa..2bcabd8ac15 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -30,8 +30,9 @@ /obj/structure/New() ..() if(smooth) - smooth_icon(src) - smooth_icon_neighbors(src) + if(ticker && ticker.current_state == GAME_STATE_PLAYING) + smooth_icon(src) + smooth_icon_neighbors(src) icon_state = "" if(climbable) verbs += /obj/structure/proc/climb_on @@ -42,7 +43,9 @@ if(ticker) cameranet.updateVisibility(src) if(smooth) - smooth_icon_neighbors(src) + var/turf/T = get_turf(src) + spawn(0) + smooth_icon_neighbors(T) return ..() /obj/structure/proc/climb_on() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index ad478bb3893..17a4233ffa9 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -33,7 +33,8 @@ for(var/obj/structure/table/T in src.loc) if(T != src) qdel(T) - update_icon() + if(flipped) + update_icon() /obj/structure/table/proc/destroy() new parts(loc) @@ -221,9 +222,10 @@ return if (istype(W, /obj/item/weapon/wrench)) - to_chat(user, "\blue Now disassembling table") - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - if(do_after(user,50, target = src)) + user.visible_message("[user] is disassembling \a [src].", "You start disassembling \the [src].") + playsound(loc, 'sound/items/Ratchet.ogg', 50, 1) + if(do_after(user, 50, target = src)) + playsound(loc, 'sound/items/Deconstruct.ogg', 50, 1) destroy() return @@ -367,55 +369,18 @@ parts = /obj/item/weapon/table_parts/wood health = 50 canSmoothWith = list(/obj/structure/table/woodentable, /obj/structure/table/woodentable/poker) + var/canPokerize = 1 /obj/structure/table/woodentable/attackby(obj/item/I as obj, mob/user as mob, params) - - if (istype(I, /obj/item/stack/tile/grass)) + if(canPokerize && istype(I, /obj/item/stack/tile/grass)) var/obj/item/stack/tile/grass/gr = I gr.use(1) new /obj/structure/table/woodentable/poker( src.loc ) qdel(src) visible_message("[user] adds the grass to the wooden table") - - - if (istype(I, /obj/item/weapon/grab)) - tablepush(I, user) - return - - if (istype(I, /obj/item/weapon/wrench)) - to_chat(user, "\blue Now disassembling the wooden table") - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - sleep(50) - new /obj/item/weapon/table_parts/wood( src.loc ) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src) - return - - if(isrobot(user)) - return - if(istype(I, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/system/spark_spread/spark_system = new /datum/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 4)) - O.show_message("\blue The wooden table was sliced apart by [user]!", 1, "\red You hear wood coming apart.", 2) - new /obj/item/weapon/table_parts/wood( src.loc ) - qdel(src) - return - - if(!(I.flags & ABSTRACT) && !(istype(I, /obj/item/stack/tile/grass))) - if(user.drop_item()) - I.Move(loc) - var/list/click_params = params2list(params) - //Center the icon where the user clicked. - if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) - return - //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) - I.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) - I.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - + return 1 + else + return ..() return 1 @@ -425,51 +390,11 @@ icon = 'icons/obj/smooth_structures/poker_table.dmi' icon_state = "pokertable" canSmoothWith = list(/obj/structure/table/woodentable/poker, /obj/structure/table/woodentable) + canPokerize = 0 - -/obj/structure/table/woodentable/poker/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - - if (istype(W, /obj/item/weapon/grab)) - tablepush(W, user) - return - - if (istype(W, /obj/item/weapon/wrench)) - to_chat(user, "\blue Now disassembling the wooden table") - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - sleep(50) - new /obj/item/weapon/table_parts/wood( src.loc ) - new /obj/item/stack/tile/grass( src.loc) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src) - return - - if(isrobot(user)) - return - if(istype(W, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/system/spark_spread/spark_system = new /datum/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 4)) - O.show_message("\blue The wooden table was sliced apart by [user]!", 1, "\red You hear wood coming apart.", 2) - new /obj/item/weapon/table_parts/wood( src.loc ) - new /obj/item/stack/tile/grass( src.loc) - qdel(src) - return - - if(!(W.flags & ABSTRACT)) - if(user.drop_item()) - W.Move(loc) - var/list/click_params = params2list(params) - //Center the icon where the user clicked. - if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) - return - //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) - W.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) - W.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - - return 1 +/obj/structure/table/woodentable/poker/destroy() + new /obj/item/stack/tile/grass(loc) + ..() /obj/structure/glasstable_frame name = "glass table frame" @@ -513,64 +438,24 @@ canSmoothWith = null /obj/structure/table/glass/flip(var/direction) - src.collapse() + collapse() /obj/structure/table/glass/proc/collapse() //glass table collapse is called twice in this code, more efficent to just have a proc src.visible_message("\The [src] shatters, and the frame collapses!", "You hear metal collapsing and glass shattering.") playsound(src.loc, "shatter", 50, 1) - new /obj/item/weapon/table_parts/glass(loc) - new /obj/item/weapon/shard(loc) - qdel(src) + destroy(1) + +/obj/structure/table/glass/destroy(dirty) + if(dirty) + new /obj/item/weapon/shard(loc) + else + new /obj/item/stack/sheet/glass(loc) + ..() /obj/structure/table/glass/tablepush(obj/item/I, mob/user) if(..()) collapse() -/obj/structure/table/glass/attackby(obj/item/I as obj, mob/user as mob, params) - - if (istype(I, /obj/item/weapon/grab)) - tablepush(I, user) - return - - if (istype(I, /obj/item/weapon/wrench)) - to_chat(user, "\blue Now disassembling the glass table") - playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1) - sleep(50) - new /obj/item/weapon/table_parts/glass( src.loc ) - new /obj/item/stack/sheet/glass( src.loc ) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1) - qdel(src) - return - - if(isrobot(user)) - return - if(istype(I, /obj/item/weapon/melee/energy/blade)) - var/datum/effect/system/spark_spread/spark_system = new /datum/effect/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - spark_system.start() - playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1) - playsound(src.loc, "sparks", 50, 1) - for(var/mob/O in viewers(user, 4)) - O.show_message("\The [src] was sliced apart by [user]!", 1, "You hear glass being sliced apart.", 2) - new /obj/item/weapon/table_parts/glass( src.loc ) - new /obj/item/stack/sheet/glass( src.loc ) - qdel(src) - return - - if(!(I.flags & ABSTRACT)) - if(user.drop_item()) - I.Move(loc) - var/list/click_params = params2list(params) - //Center the icon where the user clicked. - if(!click_params || !click_params["icon-x"] || !click_params["icon-y"]) - return - //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) - I.pixel_x = Clamp(text2num(click_params["icon-x"]) - 16, -(world.icon_size/2), world.icon_size/2) - I.pixel_y = Clamp(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) - - return 1 - - /* * Reinforced tables */ diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 9023edcda55..be8828a2dc9 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -14,6 +14,7 @@ /turf/simulated/New() ..() levelupdate() + visibilityChanged() /turf/simulated/proc/burn_tile() diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index 0a569d91378..a328769d8dc 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -62,8 +62,8 @@ /turf/simulated/floor/carpet/New() ..() - spawn(1) - update_icon() + if(broken || burnt) + make_plating() /turf/simulated/floor/carpet/update_icon() if(!..()) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 363b7d7b150..7c0035cc445 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -37,6 +37,21 @@ ..() for(var/atom/movable/AM in src) Entered(AM) + if(smooth && ticker && ticker.current_state == GAME_STATE_PLAYING) + smooth_icon(src) + +/hook/startup/proc/smooth_world() + var/watch = start_watch() + log_startup_progress("Smoothing atoms...") + for(var/turf/T in world) + if(T.smooth) + smooth_icon(T) + for(var/A in T) + var/atom/AA = A + if(AA.smooth) + smooth_icon(AA) + log_startup_progress(" Smoothed atoms in [stop_watch(watch)]s.") + return 1 /turf/Destroy() // Adds the adjacent turfs to the current atmos processing diff --git a/code/game/turfs/unsimulated/beach.dm b/code/game/turfs/unsimulated/beach.dm index f71222c3b5e..cc3b2fcedc7 100644 --- a/code/game/turfs/unsimulated/beach.dm +++ b/code/game/turfs/unsimulated/beach.dm @@ -55,7 +55,6 @@ /turf/unsimulated/beach/water/drop/New() ..() - smooth_icon(src) spawn(1) overlays += image(icon, "[top_left_corner]-o", MOB_LAYER + 0.1) overlays += image(icon, "[top_right_corner]-o", MOB_LAYER + 0.1) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index a2d62b29c8a..8c719c14a80 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -151,7 +151,9 @@ var/list/admin_verbs_debug = list( /client/proc/test_movable_UI, /client/proc/test_snap_UI, /client/proc/cinematic, - /proc/machine_upgrade + /proc/machine_upgrade, + /client/proc/map_template_load, + /client/proc/map_template_upload ) var/list/admin_verbs_possess = list( /proc/possess, diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm new file mode 100644 index 00000000000..4a15552a789 --- /dev/null +++ b/code/modules/admin/verbs/map_template_loadverb.dm @@ -0,0 +1,45 @@ +/client/proc/map_template_load() + set category = "Debug" + set name = "Map Template - Place" + + if(!holder) + return + + 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 map_templates + if(!map) + return + template = map_templates[map] + + var/turf/T = get_turf(mob) + if(!T) + return + + var/list/preview = list() + for(var/S in template.get_affected_turfs(T,centered = TRUE)) + preview += image('icons/turf/overlays.dmi',S,"greenOverlay") + usr.client.images += preview + if(alert(usr,"Confirm location.","Template Confirm","Yes","No") == "Yes") + template.load(T, centered = TRUE) + message_admins("[key_name_admin(usr)] has placed a map template ([template.name]) at (JMP)") + usr.client.images -= preview + +/client/proc/map_template_upload() + set category = "Debug" + set name = "Map Template - Upload" + + if(!holder) + return + + var/map = input(usr, "Choose a Map Template to upload to template storage","Upload Map Template") as null|file + if(!map) + return + if(copytext("[map]",-4) != ".dmm") + usr << "Bad map file: [map]" + return + + var/datum/map_template/M = new(map=map, rename="[map]") + M.preload_size(map) + map_templates[M.name] = M + message_admins("[key_name_admin(usr)] has uploaded a map template ([map])") diff --git a/code/modules/awaymissions/maploader/dmm_suite.dm b/code/modules/awaymissions/maploader/dmm_suite.dm index e2311ed7eee..21c2dac0dc8 100644 --- a/code/modules/awaymissions/maploader/dmm_suite.dm +++ b/code/modules/awaymissions/maploader/dmm_suite.dm @@ -53,7 +53,7 @@ dmm_suite{ */ - verb/load_map(var/dmm_file as file, var/z_offset as num){ + verb/load_map(var/dmm_file as file, var/x_offset as num, var/y_offset as num, var/z_offset as num, do_sleep as num){ // dmm_file: A .dmm file to load (Required). // z_offset: A number representing the z-level on which to start loading the map (Optional). } diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index 01b728d4a35..e58714de9f3 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -3,7 +3,8 @@ ////////////////////////////////////////////////////////////// //global datum that will preload variables on atoms instanciation -var/global/dmm_suite/preloader/_preloader = null +var/global/use_preloader = FALSE +var/global/dmm_suite/preloader/_preloader = new /** @@ -16,9 +17,9 @@ var/global/dmm_suite/preloader/_preloader = null * 2) Read the map line by line, parsing the result (using parse_grid) * */ -/dmm_suite/load_map(var/dmm_file as file, var/z_offset as num) +/dmm_suite/load_map(dmm_file as file, x_offset = 0 as num, y_offset = 0 as num, z_offset as num, do_sleep = 1 as num) if(!z_offset)//what z_level we are creating the map on - z_offset = world.maxz+1 + z_offset = world.maxz + 1 var/quote = ascii2text(34) var/tfile = file2text(dmm_file)//the map file we're creating @@ -39,7 +40,8 @@ var/global/dmm_suite/preloader/_preloader = null var/model_key = copytext(tline,2,2+key_len) var/model_contents = copytext(tline,findtext(tfile,"=")+3,length(tline)) grid_models[model_key] = model_contents - sleep(-1) + if(do_sleep) + sleep(-1) /////////////////////////////////////////////////////////////////////////////////////// //now let's fill the map with turf and objects using the constructed model map @@ -47,8 +49,8 @@ var/global/dmm_suite/preloader/_preloader = null //position of the currently processed square var/zcrd=-1 - var/ycrd=0 - var/xcrd=0 + var/ycrd=y_offset + var/xcrd=x_offset for(var/zpos=findtext(tfile,"\n(1,1,",lpos,0);zpos!=0;zpos=findtext(tfile,"\n(1,1,",zpos+1,0)) //in case there's several maps to load @@ -60,8 +62,9 @@ var/global/dmm_suite/preloader/_preloader = null //if exceeding the world max x or y, increase it var/x_depth = length(copytext(zgrid,1,findtext(zgrid,"\n",2,0))) - if(world.maxxz_depth) break ycrd-- - - sleep(-1) + if(do_sleep) + sleep(-1) //reached End Of File if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len) break - sleep(-1) + if(do_sleep) + sleep(-1) /** * Fill a given tile with its area/turf/objects/mobs @@ -110,7 +115,7 @@ var/global/dmm_suite/preloader/_preloader = null * 4) Instanciates the atom with its variables * */ -/dmm_suite/proc/parse_grid(var/model as text,var/xcrd as num,var/ycrd as num,var/zcrd as num) +/dmm_suite/proc/parse_grid(model as text, xcrd as num, ycrd as num, zcrd as num, do_sleep = 1) /*Method parse_grid() - Accepts a text string containing a comma separated list of type paths of the same construction as those contained in a .dmm file, and instantiates them. @@ -143,13 +148,14 @@ var/global/dmm_suite/preloader/_preloader = null var/variables_start = findtext(full_def,"{") if(variables_start)//if there's any variable full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}' - fields = dmm_splittext(full_def,";") + fields = readlist(full_def, ";") //then fill the members_attributes list with the corresponding variables members_attributes.len++ members_attributes[index++] = fields - sleep(-1) + if(do_sleep) + sleep(-1) while(dpos != 0) @@ -165,15 +171,17 @@ var/global/dmm_suite/preloader/_preloader = null //first instance the /area and remove it from the members list index = members.len - var/atom/instance - _preloader = new(members_attributes[index])//preloader for assigning set variables on atom creation + if(members[index] != /area/template_noop) + var/atom/instance + _preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation - instance = locate(members[index]) - instance.contents.Add(locate(xcrd,ycrd,zcrd)) - - if(_preloader && instance) - _preloader.load(instance) + instance = locate(members[index]) + var/turf/crds = locate(xcrd,ycrd,zcrd) + if(crds) + instance.contents.Add(crds) + if(use_preloader && instance) + _preloader.load(instance) members.Remove(members[index]) //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect @@ -183,40 +191,47 @@ var/global/dmm_suite/preloader/_preloader = null first_turf_index++ //instanciate the first /turf - var/turf/T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],xcrd,ycrd,zcrd) + var/turf/T + if(members[first_turf_index] != /turf/template_noop) + T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],xcrd,ycrd,zcrd) - //if others /turf are presents, simulates the underlays piling effect - index = first_turf_index + 1 - while(index <= members.len) - turfs_underlays.Insert(1,image(T.icon,null,T.icon_state,T.layer,T.dir))//add the current turf image to the underlays list - var/turf/UT = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf - add_underlying_turf(UT,T,turfs_underlays)//simulates the DMM piling effect - T = UT - index++ + if(T) + //if others /turf are presents, simulates the underlays piling effect + index = first_turf_index + 1 + while(index <= members.len) + turfs_underlays.Insert(1,image(T.icon,null,T.icon_state,T.layer,T.dir))//add the current turf image to the underlays list + var/turf/UT = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf + add_underlying_turf(UT,T,turfs_underlays)//simulates the DMM piling effect + T = UT + index++ //finally instance all remainings objects/mobs - for(index=1,index < first_turf_index,index++) + for(index in 1 to first_turf_index - 1) instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd) + if(do_sleep) + sleep(-1) //////////////// //Helpers procs //////////////// //Instance an atom at (x,y,z) and gives it the variables in attributes -/dmm_suite/proc/instance_atom(var/path,var/list/attributes, var/x, var/y, var/z) +/dmm_suite/proc/instance_atom(path,list/attributes, x, y, z) var/atom/instance - _preloader = new(attributes, path) + _preloader.setup(attributes, path) - instance = new path (locate(x,y,z))//first preloader pass + var/turf/T = locate(x,y,z) + if(T) + instance = new path (T)//first preloader pass - if(_preloader && instance)//second preloader pass, for those atoms that don't ..() in New() + if(use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New() _preloader.load(instance) return instance //text trimming (both directions) helper proc //optionally removes quotes before and after the text (for variable name) -/dmm_suite/proc/trim_text(var/what as text,var/trim_quotes=0) +/dmm_suite/proc/trim_text(what as text,trim_quotes=0) while(length(what) && (findtext(what," ",1,2))) what=copytext(what,2,0) while(length(what) && (findtext(what," ",length(what),0))) @@ -230,7 +245,7 @@ var/global/dmm_suite/preloader/_preloader = null //find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape //returns 0 if reached the last delimiter -/dmm_suite/proc/find_next_delimiter_position(var/text as text,var/initial_position as num, var/delimiter=",",var/opening_escape=quote,var/closing_escape=quote) +/dmm_suite/proc/find_next_delimiter_position(text as text,initial_position as num, delimiter=",",opening_escape=quote,closing_escape=quote) var/position = initial_position var/next_delimiter = findtext(text,delimiter,position,0) var/next_opening = findtext(text,opening_escape,position,0) @@ -245,7 +260,7 @@ var/global/dmm_suite/preloader/_preloader = null //build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7)) //return the filled list -/dmm_suite/proc/dmm_splittext(var/text as text,var/delimiter=",") +/dmm_suite/proc/readlist(text as text, delimiter=",") var/list/to_return = list() @@ -279,12 +294,16 @@ var/global/dmm_suite/preloader/_preloader = null //Check for list else if(copytext(trim_right,1,5) == "list") - trim_right = dmm_splittext(copytext(trim_right,6,length(trim_right))) + trim_right = readlist(copytext(trim_right,6,length(trim_right))) //Check for file else if(copytext(trim_right,1,2) == "'") trim_right = file(copytext(trim_right,2,length(trim_right))) + //Check for path + else if(ispath(text2path(trim_right))) + trim_right = text2path(trim_right) + to_return[trim_left] = trim_right else//simple var @@ -295,7 +314,7 @@ var/global/dmm_suite/preloader/_preloader = null return to_return //simulates the DM multiple turfs on one tile underlaying -/dmm_suite/proc/add_underlying_turf(var/turf/placed,var/turf/underturf, var/list/turfs_underlays) +/dmm_suite/proc/add_underlying_turf(turf/placed,turf/underturf, list/turfs_underlays) if(underturf.density) placed.density = 1 if(underturf.opacity) @@ -304,11 +323,15 @@ var/global/dmm_suite/preloader/_preloader = null //atom creation method that preloads variables at creation /atom/New() - if(_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() + if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() _preloader.load(src) . = ..() +/dmm_suite/Destroy() + ..() + return QDEL_HINT_HARDDEL_NOW + ////////////////// //Preloader datum ////////////////// @@ -318,15 +341,19 @@ var/global/dmm_suite/preloader/_preloader = null var/list/attributes var/target_path -/dmm_suite/preloader/New(var/list/the_attributes, var/path) - .=..() - if(!the_attributes.len) - del(src) - return - attributes = the_attributes - target_path = path +/dmm_suite/preloader/proc/setup(list/the_attributes, path) + if(the_attributes.len) + use_preloader = TRUE + attributes = the_attributes + target_path = path /dmm_suite/preloader/proc/load(atom/what) for(var/attribute in attributes) what.vars[attribute] = attributes[attribute] - del(src) \ No newline at end of file + use_preloader = FALSE + +/area/template_noop + name = "Area Passthrough" + +/turf/template_noop + name = "Turf Passthrough" \ No newline at end of file diff --git a/code/modules/awaymissions/maploader/swapmaps.dm b/code/modules/awaymissions/maploader/swapmaps.dm index 8f15d071b0f..8dc9f9f6c99 100644 --- a/code/modules/awaymissions/maploader/swapmaps.dm +++ b/code/modules/awaymissions/maploader/swapmaps.dm @@ -156,14 +156,14 @@ swapmap if(z2>swapmaps_compiled_maxz ||\ y2>swapmaps_compiled_maxy ||\ x2>swapmaps_compiled_maxx) - del(src) + qdel(src) return x2=x?(x):world.maxx y2=y?(y):world.maxy z2=z?(z):1 AllocateSwapMap() - Del() + Destroy() // a temporary datum for a chunk can be deleted outright // for others, some cleanup is necessary if(!ischunk) @@ -179,13 +179,14 @@ swapmap if(!M.key) qdel(M) else M.loc=null areas[A.loc]=null - del(A) + qdel(A) // delete areas that belong only to this map for(var/area/a in areas) - if(a && !a.contents.len) del(a) + if(a && !a.contents.len) qdel(a) if(x2>=world.maxx || y2>=world.maxy || z2>=world.maxz) CutXYZ() - del(areas) + qdel(areas) ..() + return QDEL_HINT_HARDDEL_NOW /* Savefile format: @@ -226,11 +227,11 @@ swapmap S["areas"] << areas for(n in 1 to areas.len) areas[areas[n]]=n var/oldcd=S.cd - for(z=z1,z<=z2,++z) + for(z in z1 to z2) S.cd="[z-z1+1]" - for(y=y1,y<=y2,++y) + for(y in y1 to y2) S.cd="[y-y1+1]" - for(x=x1,x<=x2,++x) + for(x in x1 to x2) S.cd="[x-x1+1]" var/turf/T=locate(x,y,z) S["type"] << T.type @@ -241,7 +242,7 @@ swapmap sleep() S.cd=oldcd locked=0 - del(areas) + qdel(areas) Read(savefile/S,_id,turf/locorner) var/x @@ -269,11 +270,11 @@ swapmap locked=1 AllocateSwapMap() // adjust x1,y1,z1 - x2,y2,z2 coords var/oldcd=S.cd - for(z=z1,z<=z2,++z) + for(z in z1 to z2) S.cd="[z-z1+1]" - for(y=y1,y<=y2,++y) + for(y in y1 to y2) S.cd="[y-y1+1]" - for(x=x1,x<=x2,++x) + for(x in x1 to x2) S.cd="[x-x1+1]" var/tp S["type"]>>tp @@ -297,7 +298,7 @@ swapmap sleep() S.cd=oldcd locked=0 - del(areas) + qdel(areas) /* Find an empty block on the world map in which to load this map. @@ -321,7 +322,7 @@ swapmap x1=l[1] y1=l[2] z1=l[3] - del(l) + qdel(l) x2+=x1-1 y2+=y1-1 z2+=z1-1 @@ -377,7 +378,7 @@ swapmap // save and delete proc/Unload() Save() - del(src) + qdel(src) proc/Save() if(id==src) return 0 @@ -472,7 +473,7 @@ atom l=l.Copy() for(M in src) if(M.key) l-=M if(l.len) S["contents"]<=se.y;pos_y--){ - for(var/pos_x=nw.x;pos_x<=se.x;pos_x++){ + for(var/pos_z in nw.z to se.z){ + for(var/pos_y in nw.y to se.y){ + for(var/pos_x in nw.x to se.x){ var/turf/test_turf = locate(pos_x,pos_y,pos_z) var/test_template = make_template(test_turf, flags) var/template_number = templates.Find(test_template) @@ -67,7 +67,7 @@ dmm_suite{ } var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1) var/list/keys[templates.len] - for(var/key_pos=1;key_pos<=templates.len;key_pos++){ + for(var/key_pos in 1 to templates.len){ keys[key_pos] = get_model_key(key_pos,key_length) dmm_text += {""[keys[key_pos]]" = ([templates[key_pos]])\n"} } @@ -163,7 +163,7 @@ dmm_suite{ get_model_key(var/which as num, var/key_length as num){ var/key = "" var/working_digit = which-1 - for(var/digit_pos=key_length;digit_pos>=1;digit_pos--){ + for(var/digit_pos in key_length to 1 step -1){ var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1))) working_digit-=place_value*(letter_digits.len**(digit_pos-1)) key = "[key][letter_digits[place_value+1]]" diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index 85828a90c68..321e4033f0e 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -1,10 +1,33 @@ -proc/createRandomZlevel() +/proc/late_setup_level(turfs, smoothTurfs) + if(!smoothTurfs) + smoothTurfs = turfs + + if(air_master) + air_master.setup_allturfs(turfs) + for(var/turf/T in turfs) + if(T.dynamic_lighting) + T.lighting_build_overlays() + for(var/obj/structure/cable/PC in T) + makepowernet_for(PC) + for(var/turf/T in smoothTurfs) + if(T.smooth) + smooth_icon(T) + for(var/R in T) + var/atom/A = R + if(A.smooth) + smooth_icon(A) + +/proc/createRandomZlevel() if(awaydestinations.len) //crude, but it saves another var! return var/list/potentialRandomZlevels = list() log_startup_progress("Searching for away missions...") - var/list/Lines = file2list("_maps/map_files/RandomZLevels/fileList.txt") + var/list/Lines + if(fexists("config/away_mission_config.txt")) + Lines = file2list("config/away_mission_config.txt") + else + Lines = file2list("config/example/away_mission_config.txt") if(!Lines.len) return for (var/t in Lines) @@ -35,22 +58,14 @@ proc/createRandomZlevel() if(potentialRandomZlevels.len) var/watch = start_watch() - log_startup_progress(" Loading away mission...") + log_startup_progress("Loading away mission...") var/map = pick(potentialRandomZlevels) var/file = file(map) if(isfile(file)) - maploader.load_map(file) - var/turfs = block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz)) - if(air_master) - air_master.setup_allturfs(turfs) - for(var/turf/T in turfs) - if(T.dynamic_lighting) - T.lighting_build_overlays() - for(var/obj/structure/cable/PC in T) - makepowernet_for(PC) - smooth_zlevel(world.maxz) - log_to_dd("Away mission loaded: [map]") + maploader.load_map(file, do_sleep = 0) + late_setup_level(block(locate(1, 1, world.maxz), locate(world.maxx, world.maxy, world.maxz))) + log_to_dd(" Away mission loaded: [map]") for(var/obj/effect/landmark/L in landmarks_list) if (L.name != "awaystart") diff --git a/_maps/map_files/RandomZLevels/fileList.txt b/config/example/away_mission_config.txt similarity index 94% rename from _maps/map_files/RandomZLevels/fileList.txt rename to config/example/away_mission_config.txt index b9ad6131da0..f440c9a231a 100644 --- a/_maps/map_files/RandomZLevels/fileList.txt +++ b/config/example/away_mission_config.txt @@ -15,6 +15,7 @@ #_maps/map_files/RandomZLevels/clownplanet.dmm #_maps/map_files/RandomZLevels/example.dmm #_maps/map_files/RandomZLevels/spacebattle.dmm +#_maps/map_files/RandomZLevels/stationCollision.dmm #===================================# # USABLE AWAY MISSIONS # @@ -26,7 +27,6 @@ _maps/map_files/RandomZLevels/undergroundoutpost45.dmm _maps/map_files/RandomZLevels/academy.dmm _maps/map_files/RandomZLevels/blackmarketpackers.dmm _maps/map_files/RandomZLevels/spacehotel.dmm -_maps/map_files/RandomZLevels/stationCollision.dmm _maps/map_files/RandomZLevels/wildwest.dmm #===================================# diff --git a/paradise.dme b/paradise.dme index ca1495b92b1..202eb4130cf 100644 --- a/paradise.dme +++ b/paradise.dme @@ -255,6 +255,7 @@ #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\events.dm" #include "code\datums\helper_datums\global_iterator.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" @@ -1009,6 +1010,7 @@ #include "code\modules\admin\verbs\freeze.dm" #include "code\modules\admin\verbs\getlogs.dm" #include "code\modules\admin\verbs\honksquad.dm" +#include "code\modules\admin\verbs\map_template_loadverb.dm" #include "code\modules\admin\verbs\mapping.dm" #include "code\modules\admin\verbs\massmodvar.dm" #include "code\modules\admin\verbs\modifyvariables.dm"