Merge pull request #4780 from Crazylemon64/space_ruins

Crazypilot's Space Ruins Port
This commit is contained in:
Fox McCloud
2016-07-15 22:55:51 -04:00
committed by GitHub
108 changed files with 3107 additions and 569 deletions
+2 -2
View File
@@ -32,6 +32,8 @@ Pipelines + Other Objects -> Pipe network
var/global/datum/pipe_icon_manager/icon_manager
/obj/machinery/atmospherics/New()
..()
if(!icon_manager)
icon_manager = new()
@@ -42,8 +44,6 @@ Pipelines + Other Objects -> Pipe network
if(!pipe_color_check(pipe_color))
pipe_color = null
..()
/obj/machinery/atmospherics/initialize()
..()
@@ -60,13 +60,13 @@
icon_state = "map_vent_in"
/obj/machinery/atmospherics/unary/vent_pump/New()
..()
icon = null
initial_loc = get_area(loc)
area_uid = initial_loc.uid
if(!id_tag)
assign_uid()
id_tag = num2text(uid)
..()
/obj/machinery/atmospherics/unary/vent_pump/high_volume
name = "large air vent"
@@ -41,13 +41,13 @@
connect_types = list(1,3) //connects to regular and scrubber pipes
/obj/machinery/atmospherics/unary/vent_scrubber/New()
..()
icon = null
initial_loc = get_area(loc)
area_uid = initial_loc.uid
if(!id_tag)
assign_uid()
id_tag = num2text(uid)
..()
/obj/machinery/atmospherics/unary/vent_scrubber/Destroy()
if(initial_loc && frequency == 1439)
+30 -31
View File
@@ -17,6 +17,11 @@
layer = 2.4 //under wires with their 2.44
/obj/machinery/atmospherics/pipe/manifold/New()
..()
alpha = 255
icon = null
switch(dir)
if(NORTH)
initialize_directions = EAST|SOUTH|WEST
@@ -27,11 +32,6 @@
if(WEST)
initialize_directions = NORTH|EAST|SOUTH
..()
alpha = 255
icon = null
/obj/machinery/atmospherics/pipe/manifold/initialize()
..()
for(var/D in cardinal)
@@ -62,7 +62,6 @@
/obj/machinery/atmospherics/pipe/manifold/hide(var/i)
if(level == 1 && istype(loc, /turf/simulated))
invisibility = i ? 101 : 0
update_icon()
/obj/machinery/atmospherics/pipe/manifold/pipeline_expansion()
return list(node1, node2, node3)
@@ -102,6 +101,7 @@
if(istype(node3, /obj/machinery/atmospherics/pipe))
qdel(parent)
node3 = null
check_nodes_exist()
update_icon()
..()
@@ -121,40 +121,39 @@
alpha = 255
if(!node1 && !node2 && !node3)
var/turf/T = get_turf(src)
new /obj/item/pipe(loc, make_from=src)
for(var/obj/machinery/meter/meter in T)
if(meter.target == src)
new /obj/item/pipe_meter(T)
qdel(meter)
qdel(src)
else
overlays.Cut()
overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type)
overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type)
underlays.Cut()
overlays.Cut()
overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type)
overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type)
underlays.Cut()
var/turf/T = get_turf(src)
if(!istype(T)) return
var/list/directions = list(NORTH, SOUTH, EAST, WEST)
var/node1_direction = get_dir(src, node1)
var/node2_direction = get_dir(src, node2)
var/node3_direction = get_dir(src, node3)
var/turf/T = get_turf(src)
if(!istype(T)) return
var/list/directions = list(NORTH, SOUTH, EAST, WEST)
var/node1_direction = get_dir(src, node1)
var/node2_direction = get_dir(src, node2)
var/node3_direction = get_dir(src, node3)
directions -= dir
directions -= dir
directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
for(var/D in directions)
add_underlay(T,,D,icon_connect_type)
for(var/D in directions)
add_underlay(T,,D,icon_connect_type)
/obj/machinery/atmospherics/pipe/manifold/update_underlays()
..()
update_icon()
// A check to make sure both nodes exist - self-delete if they aren't present
/obj/machinery/atmospherics/pipe/manifold/check_nodes_exist()
if(!node1 && !node2 && !node3)
Deconstruct()
return 0 // 0: No nodes exist
// 1: 1-3 nodes exist, we continue existing
return 1
/obj/machinery/atmospherics/pipe/manifold/visible
icon_state = "map"
level = 2
+29 -42
View File
@@ -72,6 +72,7 @@
qdel(parent)
node4 = null
check_nodes_exist()
update_icon()
..()
@@ -93,59 +94,45 @@
return
alpha = 255
overlays.Cut()
overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type)
overlays += icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type)
underlays.Cut()
if(!node1 && !node2 && !node3 && !node4)
var/turf/T = get_turf(src)
new /obj/item/pipe(loc, make_from=src)
for(var/obj/machinery/meter/meter in T)
if(meter.target == src)
new /obj/item/pipe_meter(T)
qdel(meter)
qdel(src)
else
overlays.Cut()
overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type)
overlays += icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type)
underlays.Cut()
var/turf/T = get_turf(src)
if(!istype(T)) return
var/list/directions = list(NORTH, SOUTH, EAST, WEST)
var/node1_direction = get_dir(src, node1)
var/node2_direction = get_dir(src, node2)
var/node3_direction = get_dir(src, node3)
var/node4_direction = get_dir(src, node4)
/*
var/list/directions = list(NORTH, SOUTH, EAST, WEST)
directions -= dir
directions -= add_underlay(node1)
directions -= add_underlay(node2)
directions -= add_underlay(node3)
directions -= add_underlay(node4)
directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
directions -= add_underlay(T,node4,node4_direction,icon_connect_type)
for(var/D in directions)
add_underlay(,D)
*/
var/turf/T = get_turf(src)
if(!istype(T)) return
var/list/directions = list(NORTH, SOUTH, EAST, WEST)
var/node1_direction = get_dir(src, node1)
var/node2_direction = get_dir(src, node2)
var/node3_direction = get_dir(src, node3)
var/node4_direction = get_dir(src, node4)
directions -= dir
directions -= add_underlay(T,node1,node1_direction,icon_connect_type)
directions -= add_underlay(T,node2,node2_direction,icon_connect_type)
directions -= add_underlay(T,node3,node3_direction,icon_connect_type)
directions -= add_underlay(T,node4,node4_direction,icon_connect_type)
for(var/D in directions)
add_underlay(T,,D,icon_connect_type)
for(var/D in directions)
add_underlay(T,,D,icon_connect_type)
/obj/machinery/atmospherics/pipe/manifold4w/update_underlays()
..()
update_icon()
// A check to make sure both nodes exist - self-delete if they aren't present
/obj/machinery/atmospherics/pipe/manifold4w/check_nodes_exist()
if(!node1 && !node2 && !node3 && !node4)
Deconstruct()
return 0 // 0: No nodes exist
// 1: 1-4 nodes exist, we continue existing
return 1
/obj/machinery/atmospherics/pipe/manifold4w/hide(var/i)
if(level == 1 && istype(loc, /turf/simulated))
invisibility = i ? 101 : 0
update_icon()
/obj/machinery/atmospherics/pipe/manifold4w/initialize()
..()
@@ -244,4 +231,4 @@
color = PIPE_COLOR_GREEN
/obj/machinery/atmospherics/pipe/manifold4w/hidden/purple
color = PIPE_COLOR_PURPLE
color = PIPE_COLOR_PURPLE
+4
View File
@@ -85,3 +85,7 @@
return node.pipe_color
else
return pipe_color
// A check to make sure both nodes exist - self-delete if they aren't present
/obj/machinery/atmospherics/pipe/proc/check_nodes_exist()
return
+12 -10
View File
@@ -66,6 +66,7 @@
connected_to = c
node2 = target
break
var/turf/T = loc // hide if turf is not intact
hide(T.intact)
update_icon()
@@ -120,7 +121,9 @@
if(istype(node2, /obj/machinery/atmospherics/pipe))
qdel(parent)
node2 = null
check_nodes_exist()
update_icon()
..()
/obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
return list(node1, node2)
@@ -141,23 +144,22 @@
overlays.Cut()
if(!node1 && !node2)
var/turf/T = get_turf(src)
new /obj/item/pipe(loc, make_from=src)
for(var/obj/machinery/meter/meter in T)
if(meter.target == src)
new /obj/item/pipe_meter(T)
qdel(meter)
qdel(src)
else if(node1 && node2)
if(node1 && node2)
overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, pipe_icon + "intact" + icon_connect_type)
else
overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, pipe_icon + "exposed[node1?1:0][node2?1:0]" + icon_connect_type)
// A check to make sure both nodes exist - self-delete if they aren't present
/obj/machinery/atmospherics/pipe/simple/check_nodes_exist()
if(!node1 && !node2)
Deconstruct()
return 0 // 0: No nodes exist
// 1: 1-2 nodes exist, we continue existing
return 1
/obj/machinery/atmospherics/pipe/simple/update_underlays()
return
/obj/machinery/atmospherics/pipe/simple/hide(var/i)
if(level == 1 && istype(loc, /turf/simulated))
invisibility = i ? 101 : 0
update_icon()
+2 -2
View File
@@ -78,7 +78,7 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0)
if(T.atmos_adjacent_turfs & counterdir)
T.atmos_adjacent_turfs_amount -= 1
T.atmos_adjacent_turfs &= ~counterdir
//returns a list of adjacent turfs that can share air with this one.
//alldir includes adjacent diagonal tiles that can share
// air with both of the related adjacent cardinal tiles
@@ -184,4 +184,4 @@ var/const/SPAWN_AIR = 256
G.nitrogen += MOLES_N2STANDARD * amount
air.merge(G)
air_master.add_to_active(src, 0)
air_master.add_to_active(src, 0)
+8
View File
@@ -244,6 +244,14 @@
#define REGION_COMMAND 7
#define REGION_CENTCOMM 8
//used for maploader
#define MAP_MINX 1
#define MAP_MINY 2
#define MAP_MINZ 3
#define MAP_MAXX 4
#define MAP_MAXY 5
#define MAP_MAXZ 6
//Matricies
#define MATRIX_DEFAULT list(1, 0, 0, 0,\
0, 1, 0, 0,\
+10
View File
@@ -386,6 +386,16 @@
//log_to_dd(" output: [out.len]")
return reverselist(out)
//Copies a list, and all lists inside it recusively
//Does not copy any other reference type
/proc/deepCopyList(list/l)
if(!islist(l))
return l
. = l.Copy()
for(var/i = 1 to l.len)
if(islist(.[i]))
.[i] = .(.[i])
/proc/dd_sortedObjectList(var/list/L, var/cache=list())
if(L.len < 2)
return L
+6
View File
@@ -93,6 +93,12 @@
to_chat(world, "<span class='danger'>[message]</span>")
log_to_dd(message)
// A logging proc that only outputs after setup is done, to
// help devs test initialization stuff that happens a lot
/proc/log_after_setup(var/message)
if(ticker && ticker.current_state > GAME_STATE_SETTING_UP)
to_chat(world, "<span class='danger'>[message]</span>")
log_to_dd(message)
// Helper procs for building detailed log lines
/proc/datum_info_line(var/datum/d)
+1 -2
View File
@@ -24,5 +24,4 @@ var/list/restricted_camera_networks = list( //Those networks can only be accesse
"Hotel"
)
var/list/map_templates = list()
var/list/mineral_turfs = list()
var/list/mineral_turfs = list()
+7
View File
@@ -54,3 +54,10 @@ var/list/carplist = list() //list of all carp-spawn landmarks
//away missions
var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
//List of preloaded templates
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()
+1 -1
View File
@@ -146,4 +146,4 @@ var/global/datum/controller/process/air_system/air_master
icemaster.icon = 'icons/turf/overlays.dmi'
icemaster.icon_state = "snowfloor"
icemaster.layer = TURF_LAYER+0.1
icemaster.mouse_opacity = 0
icemaster.mouse_opacity = 0
+1
View File
@@ -11,6 +11,7 @@ var/global/datum/controller/process/sun/sun
name = "sun"
schedule_interval = 600 // every 60 seconds
sun = src
log_startup_progress("Sun ticker starting up.")
angle = rand (0,360) // the station position to the sun is randomised at round start
rate = rand(50,200)/100 // 50% - 200% of standard rotation
+1
View File
@@ -9,6 +9,7 @@ var/global/datum/controller/process/ticker/tickerProcess
schedule_interval = 20 // every 2 seconds
lastTickerTime = world.timeofday
log_startup_progress("Time ticker starting up.")
if(!ticker)
ticker = new
+2 -1
View File
@@ -8,6 +8,7 @@ var/global/datum/controller/process/timer/timer_master
name = "timer"
schedule_interval = 5 //every 0.5 seconds
timer_master = src
log_startup_progress("Timer process starting up.")
/datum/controller/process/timer/statProcess()
..()
@@ -79,4 +80,4 @@ var/global/datum/controller/process/timer/timer_master
if(event.id == id)
qdel(event)
return 1
return 0
return 0
+1
View File
@@ -1,6 +1,7 @@
/datum/controller/process/vote/setup()
name = "vote"
schedule_interval = 10 // every second
log_startup_progress("Voting ticker starting up.")
/datum/controller/process/vote/doWork()
vote.process()
+4
View File
@@ -167,6 +167,7 @@
var/list/overflow_whitelist = list() //whitelist for overflow
var/disable_away_missions = 0 // disable away missions
var/disable_space_ruins = 0 //disable space ruins
var/ooc_allowed = 1
var/looc_allowed = 1
@@ -547,6 +548,9 @@
if("disable_away_missions")
config.disable_away_missions = 1
if("disable_space_ruins")
config.disable_space_ruins = 1
if("disable_lobby_music")
config.disable_lobby_music = 1
+16 -12
View File
@@ -11,16 +11,16 @@ var/global/air_processing_killed = 0
var/global/pipe_processing_killed = 0
/datum/controller
var/processing = 0
var/iteration = 0
var/processing_interval = 0
var/processing = 0
var/iteration = 0
var/processing_interval = 0
/datum/controller/proc/recover() // If we are replacing an existing controller (due to a crash) we attempt to preserve as much as we can.
datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
/datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
datum/controller/game_controller/New()
/datum/controller/game_controller/New()
//There can be only one master_controller. Out with the old and in with the new.
if(master_controller != src)
if(istype(master_controller))
@@ -38,12 +38,16 @@ datum/controller/game_controller/New()
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
datum/controller/game_controller/proc/setup()
/datum/controller/game_controller/proc/setup()
world.tick_lag = config.Ticklag
zlevels.initialize()
preloadTemplates()
if(!config.disable_away_missions)
createRandomZlevel()
if(!config.disable_space_ruins)
seedRuins(7, rand(0, 3), /area/space, space_ruins_templates)
setup_objects()
setupgenetics()
@@ -55,21 +59,21 @@ datum/controller/game_controller/proc/setup()
populate_spawn_points()
datum/controller/game_controller/proc/setup_objects()
/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.")
log_startup_progress(" Populated [asset_cache.len] assets in [stop_watch(watch)]s.")
watch = start_watch()
log_startup_progress("Initializing objects...")
for(var/atom/movable/object in world)
object.initialize()
count++
log_startup_progress(" Initialized [count] objects in [stop_watch(watch)]s.")
log_startup_progress(" Initialized [count] objects in [stop_watch(watch)]s.")
watch = start_watch()
count = 0
@@ -83,7 +87,7 @@ 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
@@ -91,6 +95,6 @@ datum/controller/game_controller/proc/setup_objects()
for(var/obj/machinery/atmospherics/machine in machines)
machine.build_network()
count++
log_startup_progress(" Initialized [count] pipe networks in [stop_watch(watch)]s.")
log_startup_progress(" Initialized [count] pipes in [stop_watch(watch)]s.")
log_startup_progress("Finished object initializations in [stop_watch(overwatch)]s.")
+13 -6
View File
@@ -234,6 +234,7 @@
body += "<option value='?_src_=vars;mark_object=\ref[D]'>Mark Object</option>"
body += "<option value='?_src_=vars;proc_call=\ref[D]'>Call Proc</option>"
body += "<option value='?_src_=vars;jump_to=\ref[D]'>Jump to Object</option>"
if(ismob(D))
body += "<option value='?_src_=vars;mob_player_panel=\ref[D]'>Show player panel</option>"
@@ -394,11 +395,7 @@ body
html += "<ul>"
var/index = 1
for(var/entry in L)
if(istext(entry))
html += debug_variable(entry, L[entry], level + 1)
//html += debug_variable("[index]", L[index], level + 1)
else
html += debug_variable(index, L[index], level + 1)
html += debug_variable(index, L[index], level + 1)
index++
html += "</ul>"
@@ -736,6 +733,17 @@ body
if(T)
callproc_datum(T)
else if(href_list["jump_to"])
if(!check_rights(R_ADMIN))
return
var/atom/A = locate(href_list["jump_to"])
var/turf/T = get_turf(A)
if(T)
usr.client.jumptoturf(T)
href_list["datumrefresh"] = href_list["jump_to"]
else if(href_list["rotatedatum"])
if(!check_rights(R_DEBUG|R_ADMIN)) return
@@ -1080,4 +1088,3 @@ body
src.debug_variables(DAT)
return
+123 -29
View File
@@ -9,6 +9,7 @@
/datum/map_template/New(path = null, map = null, rename = null)
if(path)
mappath = path
if(mappath)
preload_size(mappath)
if(map)
mapfile = map
@@ -16,52 +17,145 @@
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)
var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1)
if(bounds)
width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1
height = bounds[MAP_MAXY]
return bounds
/datum/map_template/proc/load(turf/T, centered = 0)
var/turf/placement = T
var/min_x = placement.x
var/min_y = placement.y
if(centered)
T = locate(T.x - round(width / 2), T.y - round(height / 2), T.z)
min_x -= round(width/2)
min_y -= round(height/2)
var/max_x = min_x + width - 1
var/max_y = min_y + height - 1
if(!T)
return
if(T.x+width > world.maxx)
return
if(T.y+height > world.maxy)
return
return 0
var/turf/bot_left = locate(max(1, min_x), max(1, min_y), placement.z)
var/turf/top_right = locate(min(world.maxx, max_x), min(world.maxy, max_y), placement.z)
// 1 bigger, to update the turf smoothing
var/turf/ST_bot_left = locate(max(1, min_x-1), max(1, min_y-1), placement.z)
var/turf/ST_top_right = locate(min(world.maxx, max_x+1), min(world.maxy, max_y+1), placement.z)
// This is to place a freeze on initialization until the map's done loading
// otherwise atmos and stuff will start running mid-load
// This system will metaphorically snap in half (not postpone init everywhere)
// if given a multi-z template
// it might need to be adapted for that when that time comes
zlevels.add_dirt(placement.z)
var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1)
if(!bounds)
return 0
if(bot_left == null || top_right == null)
log_debug("One of the late setup corners is bust")
else
log_debug("Late Setup from ([bot_left.x],[bot_left.y]) to ([top_right.x],[top_right.y])")
if(ST_bot_left == null || ST_top_right == null)
log_debug("One of the smoothing corners is bust")
else
log_debug("Tile smoothing from ([ST_bot_left.x],[ST_bot_left.y]) to ([ST_top_right.x],[ST_top_right.y])")
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)))
block(bot_left, top_right),
block(ST_bot_left, ST_top_right))
zlevels.remove_dirt(placement.z)
log_game("[name] loaded at at [T.x],[T.y],[T.z]")
log_game("[name] loaded at [min_x],[min_y],[placement.z]")
return 1
/datum/map_template/proc/get_file()
if(mapfile)
return mapfile
if(mappath)
mapfile = file(mappath)
return mapfile
. = mapfile
else if(mappath)
. = file(mappath)
if(!.)
log_to_dd(" The file of [src] appears to be empty/non-existent.")
/datum/map_template/proc/get_affected_turfs(turf/T, centered = 0)
var/turf/placement = T
var/min_x = placement.x
var/min_y = placement.y
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))
min_x -= round(width/2)
min_y -= round(height/2)
var/max_x = min_x + width-1
var/max_y = min_y + height-1
placement = locate(max(min_x,1), max(min_y,1), placement.z)
return block(placement, locate(min(max_x, world.maxx), min(max_y, world.maxy), placement.z))
/datum/map_template/proc/fits_in_map_bounds(turf/T, centered = 0)
var/turf/placement = T
var/min_x = placement.x
var/min_y = placement.y
if(centered)
min_x -= round(width/2)
min_y -= round(height/2)
var/max_x = min_x + width-1
var/max_y = min_y + height-1
if(min_x < 1 || min_y < 1 || max_x > world.maxx || max_y > world.maxy)
return 0
else
return 1
/proc/preloadTemplates(path = "_maps/map_files/templates/") //see master controller setup
for(var/map in flist(path))
if(cmptext(copytext(map, length(map) - 3), ".dmm"))
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
map_templates[T.name] = T
map_templates[T.name] = T
if(!config.disable_space_ruins) // so we don't unnecessarily clutter start-up
preloadRuinTemplates()
//preloadShuttleTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
var/list/banned
if(fexists("config/spaceRuinBlacklist.txt"))
banned = generateMapList("config/spaceRuinBlacklist.txt")
else
banned = generateMapList("config/example/spaceRuinBlacklist.txt")
//banned += generateMapList("config/lavaRuinBlacklist.txt")
for(var/item in subtypesof(/datum/map_template/ruin))
var/datum/map_template/ruin/ruin_type = item
// screen out the abstract subtypes
if(!initial(ruin_type.id))
continue
var/datum/map_template/ruin/R = new ruin_type()
if(banned.Find(R.mappath))
continue
map_templates[R.name] = R
ruins_templates[R.name] = R
/*
if(istype(R, /datum/map_template/ruin/lavaland))
lava_ruins_templates[R.name] = R
*/
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)))
continue
var/datum/map_template/shuttle/S = new shuttle_type()
shuttle_templates[S.shuttle_id] = S
map_templates[S.shuttle_id] = S
*/
+21
View File
@@ -0,0 +1,21 @@
/datum/map_template/ruin
//name = "A Chest of Doubloons"
name = null
var/id = null // For blacklisting purposes, all ruins need an id
var/description = "In the middle of a clearing in the rockface, there's a \
chest filled with gold coins with Spanish engravings. How is there a \
wooden container filled with 18th century coinage in the middle of a \
lavawracked hellscape? It is clearly a mystery."
var/cost = null
var/allow_duplicates = FALSE //A bit boring, don't you think? You can always explicitly allow it on a ruin definition
var/prefix = null
var/suffix = null
/datum/map_template/ruin/New()
if(!name && id)
name = id
mappath = prefix + suffix
..(path = mappath)
+162
View File
@@ -0,0 +1,162 @@
//The bigger ones lag like hell if there is more than one on a z-level, so cost 2 for them
/datum/map_template/ruin/space
prefix = "_maps/map_files/RandomRuins/SpaceRuins/"
cost = 1
/datum/map_template/ruin/space/zoo
id = "zoo"
suffix = "abandonedzoo.dmm"
name = "Biological Storage Facility"
description = "In case society crumbles, we will be able to restore our \
zoos to working order with the breeding stock kept in these 100% \
secure and unbreachable storage facilities. At no point has anything \
escaped. That's our story, and we're sticking to it."
cost = 2
/datum/map_template/ruin/space/asteroid1
id = "asteroid1"
suffix = "asteroid1.dmm"
name = "Asteroid 1"
description = "I-spy with my little eye, something beginning with R."
/datum/map_template/ruin/space/asteroid2
id = "asteroid2"
suffix = "asteroid2.dmm"
name = "Asteroid 2"
description = "Oh my god, a giant rock!"
/datum/map_template/ruin/space/asteroid3
id = "asteroid3"
suffix = "asteroid3.dmm"
name = "Asteroid 3"
description = "This asteroid floating in space has no official \
designation, because the scientist that discovered it deemed it \
'super dull'."
/datum/map_template/ruin/space/asteroid4
id = "asteroid4"
suffix = "asteroid4.dmm"
name = "Asteroid 4"
description = "Nanotrasen Escape Pods have a 100%* success rate, and a \
99%* customer satisfaction rate. *Please note that these statistics, \
are taken from pods that have successfully docked with a recovery \
vessel."
/datum/map_template/ruin/space/asteroid5
id = "asteroid5"
suffix = "asteroid5.dmm"
name = "Asteroid 5"
description = "Oh my god, another giant rock!"
/datum/map_template/ruin/space/deep_storage
id = "deep-storage"
suffix = "deepstorage.dmm"
name = "Survivalist Bunker"
description = "Assume the best, prepare for the worst. Generally, you \
should do so by digging a three man heavily fortified bunker into \
a giant unused asteroid. Then make it self sufficient, mask any \
evidence of construction, hook it covertly into the \
telecommunications network and hope for the best."
cost = 2
/datum/map_template/ruin/space/derelict1
id = "derelict1"
suffix = "derelict1.dmm"
name = "Derelict 1"
description = "Nothing to see here citizen, move along, certainly no \
xeno outbreaks on this piece of station debris. That purple stuff? \
It's uh... station nectar. It's a top secret research installation."
/datum/map_template/ruin/space/derelict2
id = "derelict2"
suffix = "derelict2.dmm"
name = "Dinner for Two"
description = "Oh this is the night\n\
It's a beautiful night\n\
And we call it bella notte"
/datum/map_template/ruin/space/derelict3
id = "derelict3"
suffix = "derelict3.dmm"
name = "Derelict 3"
description = "These hulks were once part of a larger structure, where \
the three great \[REDACTED\] were forged."
/datum/map_template/ruin/space/derelict4
id = "derelict4"
suffix = "derelict4.dmm"
name = "Derelict 4"
description = "Centcom ferries have never crashed, will never crash, \
there is no current investigation into a crashed ferry, and we \
will not let Internal Affairs trample over high security information \
in the name of this baseless witchhunt."
/datum/map_template/ruin/space/derelict5
id = "derelict5"
suffix = "derelict5.dmm"
name = "Derelict 5"
description = "The plan is, we put a whole bunch of crates full of \
treasure in this disused warehouse, launch it into space, and then \
ignore it. Forever."
/datum/map_template/ruin/space/empty_shell
id = "empty-shell"
suffix = "emptyshell.dmm"
name = "Empty Shell"
description = "Cosy, rural property availible for young professional \
couple. Only twelve parsecs from the nearest hyperspace lane!"
/datum/map_template/ruin/space/gas_the_lizards
id = "gas-the-lizards"
suffix = "gasthelizards.dmm"
name = "Disposal Facility 17"
description = "Gas efficiency at 95.6%, fluid elimination at 96.2%. \
Will require renewed supplies of 'carpet' before the end of the \
quarter."
/datum/map_template/ruin/space/intact_empty_ship
id = "intact-empty-ship"
suffix = "intactemptyship.dmm"
name = "Authorship"
description = "Just somewhere quiet, where I can focus on my work with \
no interruptions."
/datum/map_template/ruin/space/mech_transport
id = "mech-transport"
suffix = "mechtransport.dmm"
name = "CF Corsair"
description = "Well, when is it getting here? I have bills to pay; very \
well-armed clients who want their shipments as soon as possible! I \
don't care, just find it!"
/datum/map_template/ruin/space/onehalf
id = "onehalf"
suffix = "onehalf.dmm"
name = "DK Excavator 453"
description = "Based on the trace elements we've detected on the \
gutted asteroids, we suspect that a mining ship using a restricted \
engine is somewhere in the area. We'd like to request a patrol vessel \
to investigate."
cost = 2
/datum/map_template/ruin/space/spacebar
id = "spacebar"
suffix = "spacebar.dmm"
name = "The Rampant Golem and Yellow Hound"
description = "No questions asked. No shoes/foot protection, no service. \
No tabs. No violence in the inside areas. That's it. Welcome to the \
Rampant Golem and Yellow Hound. Can I take your order?"
cost = 2
/datum/map_template/ruin/space/turreted_outpost
id = "turreted-outpost"
suffix = "turretedoutpost.dmm"
name = "Unnamed Turreted Outpost"
description = "We'd ask them to stop blaring that ruskiepop music, but \
none of us are brave enough to go near those death turrets they have."
/datum/map_template/ruin/space/way_home
id = "way-home"
suffix = "way_home.dmm"
name = "Salvation"
description = "In the darkest times, we will find our way home."
+10 -5
View File
@@ -11,8 +11,16 @@
'sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg',\
'sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
// This var is used with the maploader (modules/awaymissions/maploader/reader.dm)
// if this is 1, when used in a map snippet, this will instantiate a unique
// area from any other instances already present (meaning you can have
// separate APCs, and so on)
var/there_can_be_many = 0
/area/New()
..()
icon_state = ""
layer = 10
uid = ++global_uid
@@ -28,14 +36,11 @@
// lighting_state = 4
//has_gravity = 0 // Space has gravity. Because.. because.
if(!requires_power)
if(requires_power != 0)
power_light = 0 //rastaf0
power_equip = 0 //rastaf0
power_environ = 0 //rastaf0
..()
// spawn(15)
power_change() // all machines set to current power level, also updates lighting icon
/area/proc/get_cameras()
@@ -384,4 +389,4 @@
for(var/obj/machinery/door/airlock/temp_airlock in src)
temp_airlock.prison_open()
for(var/obj/machinery/door/window/temp_windoor in src)
temp_windoor.open()
temp_windoor.open()
+15 -2
View File
@@ -23,8 +23,11 @@
/atom/movable/New()
. = ..()
areaMaster = get_area_master(src)
if(auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
initialize()
// If you're wondering what goofery this is, this is for things that need the environment
// around them set up - like `air_update_turf` and the like
if((ticker && ticker.current_state == GAME_STATE_PLAYING))
attempt_init()
/atom/movable/Destroy()
for(var/atom/movable/AM in contents)
@@ -36,6 +39,16 @@
pulledby = null
return ..()
// used to provide a good interface for the init delay system to step in
// and we don't need to call `get_turf` until the game's started
// at which point object creations are a fair toss more seldom
/atom/movable/proc/attempt_init()
var/turf/T = get_turf(src)
if(T && zlevels.is_zlevel_dirty(T.z))
zlevels.postpone_init(T.z, src)
else if(auto_init)
initialize()
/atom/movable/proc/initialize()
return
+1 -2
View File
@@ -186,7 +186,7 @@ var/round_start_time = 0
if(candidate_source.match_tag != current_destination.match_tag)
continue
if (candidate_source.match_width != current_destination.match_width || \
if(candidate_source.match_width != current_destination.match_width || \
candidate_source.match_height != current_destination.match_height)
continue
@@ -479,4 +479,3 @@ var/round_start_time = 0
event_manager.RoundEnd()
return 1
+1
View File
@@ -225,6 +225,7 @@
air_alarm_repository.update_cache(src)
/obj/machinery/alarm/initialize()
..()
set_frequency(frequency)
if(!master_is_operating())
elect_master()
+2 -1
View File
@@ -28,6 +28,7 @@
return ..()
/obj/machinery/meter/initialize()
..()
if(!target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
@@ -153,4 +154,4 @@
<ul>
<li><b>Frequency:</b> <a href="?src=\ref[src];set_freq=-1">[format_frequency(frequency)] GHz</a> (<a href="?src=\ref[src];set_freq=[initial(frequency)]">Reset</a>)</li>
<li>[format_tag("ID Tag","id_tag")]</li>
</ul>"}
</ul>"}
@@ -57,6 +57,10 @@
//Perform the connection
connected_port = new_port
connected_port.connected_device = src
// To avoid a chicken-egg thing where pipes need to
// be initialized before the atmos cans are
if(!connected_port.parent)
connected_port.build_network()
connected_port.parent.reconcile_air()
anchored = 1 //Prevent movement
+2 -2
View File
@@ -48,7 +48,7 @@
src.scanner = findscanner()
releasecloner()
findcloner()
if(!selected_pod)
if(!selected_pod && pods.len)
selected_pod = pods[1]
/obj/machinery/computer/cloning/proc/findscanner()
@@ -450,4 +450,4 @@
return (scanner && scanner.scan_level > 2)
/obj/machinery/computer/cloning/proc/can_brainscan()
return (scanner && scanner.scan_level > 3)
return (scanner && scanner.scan_level > 3)
+2 -1
View File
@@ -63,6 +63,7 @@
efficiency = C
/obj/machinery/atmospherics/unary/cryo_cell/initialize()
..()
if(node) return
for(var/cdir in cardinal)
node = findConnecting(cdir)
@@ -495,4 +496,4 @@
return
/datum/data/function/proc/display()
return
return
+2 -1
View File
@@ -135,6 +135,7 @@ obj/machinery/door/airlock/proc/set_frequency(new_frequency)
obj/machinery/door/airlock/initialize()
..()
if(frequency)
set_frequency(frequency)
@@ -294,4 +295,4 @@ obj/machinery/access_button/airlock_interior
obj/machinery/access_button/airlock_exterior
frequency = 1379
command = "cycle_exterior"
command = "cycle_exterior"
+3 -1
View File
@@ -45,11 +45,13 @@
bound_width = world.icon_size
bound_height = width * world.icon_size
air_update_turf(1)
update_freelook_sight()
airlocks += src
return
/obj/machinery/door/initialize()
air_update_turf(1)
..()
/obj/machinery/door/Destroy()
density = 0
+2 -2
View File
@@ -7,7 +7,7 @@
density = 0
anchored = 1
/obj/structure/spacepoddoor/New()
/obj/structure/spacepoddoor/initialize()
..()
air_update_turf(1)
@@ -21,4 +21,4 @@
/obj/structure/spacepoddoor/CanPass(atom/movable/A, turf/T)
if(istype(A, /obj/spacepod))
return ..()
else return 0
else return 0
+2 -1
View File
@@ -9,6 +9,7 @@
var/dye_color = "#FFFFFF"
/obj/machinery/dye_generator/initialize()
..()
power_change()
/obj/machinery/dye_generator/power_change()
@@ -127,4 +128,4 @@
var/b_skin = hex2num(copytext(dye_color, 6, 8))
if(H.change_skin_color(r_skin, g_skin, b_skin))
H.update_dna()
user.visible_message("<span class='notice'>[user] finishes dying [M]'s [what_to_dye]!</span>", "<span class='notice'>You finish dying [M]'s [what_to_dye]!</span>")
user.visible_message("<span class='notice'>[user] finishes dying [M]'s [what_to_dye]!</span>", "<span class='notice'>You finish dying [M]'s [what_to_dye]!</span>")
@@ -27,8 +27,8 @@
src.updateDialog()
/obj/machinery/embedded_controller/attack_ghost(mob/user as mob)
src.ui_interact(user)
src.ui_interact(user)
/obj/machinery/embedded_controller/attack_ai(mob/user as mob)
src.ui_interact(user)
@@ -55,6 +55,7 @@
unacidable = 1
/obj/machinery/embedded_controller/radio/initialize()
..()
set_frequency(frequency)
/obj/machinery/embedded_controller/radio/update_icon()
@@ -77,4 +78,4 @@
/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency)
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, radio_filter)
radio_connection = radio_controller.add_object(src, frequency, radio_filter)
@@ -313,7 +313,7 @@
/obj/machinery/kitchen_machine/proc/has_extra_item()
for(var/obj/O in contents)
if ( \
if( \
!istype(O,/obj/item/weapon/reagent_containers/food) && \
!istype(O, /obj/item/weapon/grown) \
)
@@ -400,4 +400,4 @@
if("dispose")
dispose()
return
return
+4 -3
View File
@@ -47,7 +47,7 @@ Class Variables:
Currently unused.
Class Procs:
New() 'game/machinery/machine.dm'
initialize() 'game/machinery/machine.dm'
Destroy() 'game/machinery/machine.dm'
@@ -117,9 +117,10 @@ Class Procs:
var/use_log = list()
var/list/settagwhitelist = list()//WHITELIST OF VARIABLES THAT THE set_tag HREF CAN MODIFY, DON'T PUT SHIT YOU DON'T NEED ON HERE, AND IF YOU'RE GONNA USE set_tag (format_tag() proc), ADD TO THIS LIST.
/obj/machinery/New()
/obj/machinery/initialize()
addAtProcessing()
return ..()
. = ..()
power_change()
/obj/machinery/proc/addAtProcessing()
if(use_power)
+4 -1
View File
@@ -13,7 +13,10 @@
/obj/machinery/shield/New()
src.dir = pick(1,2,3,4)
..()
/obj/machinery/shield/initialize()
air_update_turf(1)
..()
/obj/machinery/shield/Destroy()
opacity = 0
@@ -605,4 +608,4 @@
if(istype(mover, /obj/item/projectile))
return prob(10)
else
return !src.density
return !src.density
@@ -145,6 +145,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
listening_level = position.z
/obj/machinery/telecomms/initialize()
..()
if(autolinkers.len)
// Links nearby machines
if(!long_range_link)
@@ -584,10 +585,3 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/name = "data packet (#)"
var/garbage_collector = 1 // if set to 0, will not be garbage collected
var/input_type = "Speech File"
+3
View File
@@ -20,6 +20,7 @@
return
/obj/machinery/computer/teleporter/initialize()
..()
link_power_station()
update_icon()
@@ -294,6 +295,7 @@
RefreshParts()
/obj/machinery/teleport/hub/initialize()
..()
link_power_station()
/obj/machinery/teleport/hub/Destroy()
@@ -472,6 +474,7 @@
link_console_and_hub()
/obj/machinery/teleport/station/initialize()
..()
link_console_and_hub()
/obj/machinery/teleport/station/RefreshParts()
+1
View File
@@ -45,6 +45,7 @@
return ..()
/obj/machinery/turretid/initialize()
..()
if(!control_area)
control_area = get_area(src)
else if(istext(control_area))
+6 -4
View File
@@ -31,11 +31,13 @@
var/resintype = null
smooth = SMOOTH_TRUE
/obj/structure/alien/resin/New(location)
..()
/obj/structure/alien/resin/initialize()
air_update_turf(1)
return
..()
/obj/structure/alien/resin/Destroy()
air_update_turf(1)
return ..()
/obj/structure/alien/resin/Move()
var/turf/T = loc
+1 -1
View File
@@ -1075,7 +1075,7 @@ steam.start() -- spawns the effect
desc = "A lightweight foamed metal wall."
var/metal = MFOAM_ALUMINUM
/obj/structure/foamedmetal/New()
/obj/structure/foamedmetal/initialize()
..()
air_update_turf(1)
+7 -6
View File
@@ -8,7 +8,7 @@
/obj/effect/landmark/New()
..()
tag = text("landmark*[]", name)
set_tag()
invisibility = 101
switch(name) //some of these are probably obsolete
@@ -105,18 +105,19 @@
..()
return QDEL_HINT_HARDDEL_NOW
/obj/effect/landmark/proc/set_tag()
tag = text("landmark*[]", name)
/obj/effect/landmark/start
name = "start"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
anchored = 1.0
/obj/effect/landmark/start/New()
..()
/obj/effect/landmark/start/set_tag()
tag = "start*[name]"
invisibility = 101
return 1
//Costume spawner landmarks
@@ -260,4 +261,4 @@
/obj/effect/landmark/costume/sexymime/New()
new /obj/item/clothing/mask/gas/sexymime(src.loc)
new /obj/item/clothing/under/sexymime(src.loc)
qdel(src)
qdel(src)
@@ -151,6 +151,15 @@
"" = 90
)
/obj/effect/spawner/lootdrop/crate_spawner // for ruins
name = "lootcrate spawner"
lootdoubles = 0
loot = list(
/obj/structure/closet/crate/secure/loot = 20,
"" = 80,
)
/obj/effect/spawner/lootdrop/trade_sol_rare
name = "trader rare item spawner"
lootdoubles = 0
@@ -5,10 +5,15 @@
var/useFull = 0
var/useGrille = 1
var/windowtospawn = /obj/structure/window/basic
anchored = 1 // No sliding out while you prime
/obj/effect/spawner/window/New()
/obj/effect/spawner/window/initialize()
spawn(0)
for(var/obj/structure/grille/G in get_turf(src)) qdel(G) //just in case mappers don't know what they are doing
var/turf/T = get_turf(src)
for(var/obj/structure/grille/G in get_turf(src))
// Complain noisily
log_debug("Extra grille on turf: ([T.x],[T.y],[T.z])")
qdel(G) //just in case mappers don't know what they are doing
if(!useFull)
for(var/cdir in cardinal)
@@ -30,7 +35,8 @@
spawn(10)
qdel(src)
/obj/effect/spawner/window/reinforced
name = "reinforced window spawner"
icon_state = "rwindow_spawner"
windowtospawn = /obj/structure/window/reinforced
windowtospawn = /obj/structure/window/reinforced
+1 -1
View File
@@ -25,7 +25,7 @@
var/health = 50.0
/obj/structure/inflatable/New(location)
/obj/structure/inflatable/initialize(location)
..()
air_update_turf(1)
+133 -130
View File
@@ -16,152 +16,155 @@
var/hardness = 1
var/oreAmount = 7
New(location)
..()
icon_state = mineralType
name = "[mineralType] door"
air_update_turf(1)
/obj/structure/mineral_door/New(location)
..()
icon_state = mineralType
name = "[mineralType] door"
Destroy()
density = 0
air_update_turf(1)
return ..()
/obj/structure/mineral_door/initialize()
..()
air_update_turf(1)
Move()
var/turf/T = loc
..()
move_update_air(T)
/obj/structure/mineral_door/Destroy()
density = 0
air_update_turf(1)
return ..()
Bumped(atom/user)
..()
if(!state)
return TryToSwitchState(user)
return
/obj/structure/mineral_door/Move()
var/turf/T = loc
..()
move_update_air(T)
attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
if(isAI(user)) //so the AI can't open it
return
else if(isrobot(user)) //but cyborgs can
if(get_dist(user,src) <= 1) //not remotely though
return TryToSwitchState(user)
attack_hand(mob/user as mob)
/obj/structure/mineral_door/Bumped(atom/user)
..()
if(!state)
return TryToSwitchState(user)
return
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group) return 0
if(istype(mover, /obj/effect/beam))
return !opacity
return !density
/obj/structure/mineral_door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
if(isAI(user)) //so the AI can't open it
return
else if(isrobot(user)) //but cyborgs can
if(get_dist(user,src) <= 1) //not remotely though
return TryToSwitchState(user)
CanAtmosPass()
return !density
/obj/structure/mineral_door/attack_hand(mob/user as mob)
return TryToSwitchState(user)
proc/TryToSwitchState(atom/user)
if(isSwitchingStates) return
if(ismob(user))
var/mob/M = user
if(world.time - user.last_bumped <= 60) return //NOTE do we really need that?
if(M.client)
if(iscarbon(M))
var/mob/living/carbon/C = M
if(!C.handcuffed)
SwitchState()
else
/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group) return 0
if(istype(mover, /obj/effect/beam))
return !opacity
return !density
/obj/structure/mineral_door/CanAtmosPass()
return !density
/obj/structure/mineral_door/proc/TryToSwitchState(atom/user)
if(isSwitchingStates) return
if(ismob(user))
var/mob/M = user
if(world.time - user.last_bumped <= 60) return //NOTE do we really need that?
if(M.client)
if(iscarbon(M))
var/mob/living/carbon/C = M
if(!C.handcuffed)
SwitchState()
else if(istype(user, /obj/mecha))
SwitchState()
else
SwitchState()
else if(istype(user, /obj/mecha))
SwitchState()
proc/SwitchState()
if(state)
Close()
else
Open()
proc/Open()
isSwitchingStates = 1
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
flick("[mineralType]opening",src)
sleep(10)
density = 0
opacity = 0
state = 1
update_icon()
isSwitchingStates = 0
air_update_turf(1)
proc/Close()
isSwitchingStates = 1
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
flick("[mineralType]closing",src)
sleep(10)
density = 1
opacity = 1
state = 0
update_icon()
isSwitchingStates = 0
air_update_turf(1)
/obj/structure/mineral_door/proc/SwitchState()
if(state)
Close()
else
Open()
/obj/structure/mineral_door/proc/Open()
isSwitchingStates = 1
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
flick("[mineralType]opening",src)
sleep(10)
density = 0
opacity = 0
state = 1
update_icon()
if(state)
icon_state = "[mineralType]open"
else
icon_state = mineralType
isSwitchingStates = 0
air_update_turf(1)
attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/weapon/pickaxe))
var/obj/item/weapon/pickaxe/digTool = W
to_chat(user, "You start digging the [name].")
if(do_after(user,digTool.digspeed*hardness, target = src) && src)
to_chat(user, "You finished digging.")
Dismantle()
else if(istype(W,/obj/item/weapon)) //not sure, can't not just weapons get passed to this proc?
hardness -= W.force/100
to_chat(user, "You hit the [name] with your [W.name]!")
CheckHardness()
else
attack_hand(user)
return
/obj/structure/mineral_door/proc/Close()
isSwitchingStates = 1
playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
flick("[mineralType]closing",src)
sleep(10)
density = 1
opacity = 1
state = 0
update_icon()
isSwitchingStates = 0
air_update_turf(1)
proc/CheckHardness()
if(hardness <= 0)
/obj/structure/mineral_door/update_icon()
if(state)
icon_state = "[mineralType]open"
else
icon_state = mineralType
/obj/structure/mineral_door/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/weapon/pickaxe))
var/obj/item/weapon/pickaxe/digTool = W
to_chat(user, "You start digging the [name].")
if(do_after(user,digTool.digspeed*hardness, target = src) && src)
to_chat(user, "You finished digging.")
Dismantle()
else if(istype(W,/obj/item/weapon)) //not sure, can't not just weapons get passed to this proc?
hardness -= W.force/100
to_chat(user, "You hit the [name] with your [W.name]!")
CheckHardness()
else
attack_hand(user)
return
/obj/structure/mineral_door/proc/CheckHardness()
if(hardness <= 0)
Dismantle(1)
/obj/structure/mineral_door/proc/Dismantle(devastated = 0)
if(!devastated)
if(mineralType == "metal")
var/ore = /obj/item/stack/sheet/metal
for(var/i = 1, i <= oreAmount, i++)
new ore(get_turf(src))
else
var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
for(var/i = 1, i <= oreAmount, i++)
new ore(get_turf(src))
else
if(mineralType == "metal")
var/ore = /obj/item/stack/sheet/metal
for(var/i = 3, i <= oreAmount, i++)
new ore(get_turf(src))
else
var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
for(var/i = 3, i <= oreAmount, i++)
new ore(get_turf(src))
qdel(src)
/obj/structure/mineral_door/ex_act(severity = 1)
switch(severity)
if(1)
Dismantle(1)
proc/Dismantle(devastated = 0)
if(!devastated)
if(mineralType == "metal")
var/ore = /obj/item/stack/sheet/metal
for(var/i = 1, i <= oreAmount, i++)
new ore(get_turf(src))
else
var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
for(var/i = 1, i <= oreAmount, i++)
new ore(get_turf(src))
else
if(mineralType == "metal")
var/ore = /obj/item/stack/sheet/metal
for(var/i = 3, i <= oreAmount, i++)
new ore(get_turf(src))
else
var/ore = text2path("/obj/item/stack/sheet/mineral/[mineralType]")
for(var/i = 3, i <= oreAmount, i++)
new ore(get_turf(src))
qdel(src)
ex_act(severity = 1)
switch(severity)
if(1)
if(2)
if(prob(20))
Dismantle(1)
if(2)
if(prob(20))
Dismantle(1)
else
hardness--
CheckHardness()
if(3)
hardness -= 0.1
else
hardness--
CheckHardness()
return
if(3)
hardness -= 0.1
CheckHardness()
return
/obj/structure/mineral_door/iron
mineralType = "metal"
@@ -285,4 +288,4 @@
CheckHardness()
playsound(loc, 'sound/effects/attackblob.ogg', 100, 1)
..()
..()
+13 -4
View File
@@ -338,10 +338,13 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
ini_dir = dir
if(!color && !istype(src,/obj/structure/window/plasmabasic) && !istype(src,/obj/structure/window/plasmareinforced))
color = color_windows(src)
air_update_turf(1)
update_nearby_icons()
return
/obj/structure/window/initialize()
air_update_turf(1)
return ..()
/obj/structure/window/Destroy()
density = 0
air_update_turf(1)
@@ -402,10 +405,13 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
/obj/structure/window/plasmabasic/New(Loc,re=0)
..()
ini_dir = dir
air_update_turf(1)
update_nearby_icons()
return
/obj/structure/window/plasmabasic/initialize()
..()
air_update_turf(1)
/obj/structure/window/plasmabasic/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > T0C + 32000)
hit(round(exposed_volume / 1000), 0)
@@ -433,10 +439,13 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
/obj/structure/window/plasmareinforced/New(Loc,re=0)
..()
ini_dir = dir
air_update_turf(1)
update_nearby_icons()
return
/obj/structure/window/plasmareinforced/initialize()
..()
air_update_turf(1)
/obj/structure/window/plasmareinforced/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
@@ -516,4 +525,4 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f
toggle_tint()
/obj/machinery/button/windowtint/update_icon()
icon_state = "light[active]"
icon_state = "light[active]"
+5 -4
View File
@@ -129,16 +129,17 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","
/turf/simulated/floor/proc/make_plating()
return ChangeTurf(/turf/simulated/floor/plating)
/turf/simulated/floor/ChangeTurf(turf/simulated/floor/T)
/turf/simulated/floor/ChangeTurf(turf/simulated/floor/T, defer_change = FALSE, keep_icon = TRUE)
if(!istype(src,/turf/simulated/floor)) return ..() //fucking turfs switch the fucking src of the fucking running procs
if(!ispath(T,/turf/simulated/floor)) return ..()
var/old_icon = icon_regular_floor
var/old_plating = icon_plating
var/old_dir = dir
var/turf/simulated/floor/W = ..()
W.icon_regular_floor = old_icon
W.icon_plating = old_plating
W.dir = old_dir
if(keep_icon)
W.icon_regular_floor = old_icon
W.icon_plating = old_plating
W.dir = old_dir
W.update_icon()
return W
+1 -1
View File
@@ -62,4 +62,4 @@
/turf/simulated/shuttle/floor4/vox //Vox skipjack floors
name = "skipjack floor"
oxygen = 0
nitrogen = MOLES_N2STANDARD + MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD + MOLES_O2STANDARD
+21 -12
View File
@@ -156,9 +156,11 @@
qdel(L)
//Creates a new turf
/turf/proc/ChangeTurf(var/path)
if(!path) return
if(path == type) return src
/turf/proc/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE)
if(!path)
return
if(!use_preloader && path == type) // Don't no-op if the map loader requires it to be reconstructed
return src
var/old_opacity = opacity
var/old_dynamic_lighting = dynamic_lighting
var/list/old_affecting_lights = affecting_lights
@@ -167,12 +169,10 @@
if(air_master)
air_master.remove_from_active(src)
var/turf/W = new path(src)
if(!defer_change)
W.AfterChange()
if(istype(W, /turf/simulated))
W:Assimilate_Air()
W.RemoveLattice()
W.blueprint_data = old_blueprint_data
for(var/turf/space/S in range(W,1))
@@ -189,13 +189,22 @@
else
lighting_clear_overlays()
W.levelupdate()
W.CalculateAdjacentTurfs()
return W
if(!can_have_cabling())
// I'm including `ignore_air` because BYOND lacks positional-only arguments
/turf/proc/AfterChange(ignore_air, keep_cabling = FALSE) //called after a turf has been replaced in ChangeTurf()
levelupdate()
CalculateAdjacentTurfs()
if(!keep_cabling && !can_have_cabling())
for(var/obj/structure/cable/C in contents)
qdel(C)
return W
/turf/simulated/AfterChange(ignore_air, keep_cabling = FALSE)
..()
RemoveLattice()
if(!ignore_air)
Assimilate_Air()
//////Assimilate Air//////
/turf/simulated/proc/Assimilate_Air()
@@ -404,4 +413,4 @@
/turf/proc/add_blueprints_preround(atom/movable/AM)
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
add_blueprints(AM)
add_blueprints(AM)
+19 -14
View File
@@ -92,7 +92,7 @@
qdel(I)
/obj/effect/buildmode_line
var/image/I
var/image/I
var/client/cl
/obj/effect/buildmode_line/New(var/client/c, var/atom/atom_a, var/atom/atom_b, var/linename)
@@ -101,13 +101,13 @@
I = image('icons/misc/mark.dmi', src, "line", 19.0)
var/x_offset = ((atom_b.x * 32) + atom_b.pixel_x) - ((atom_a.x * 32) + atom_a.pixel_x)
var/y_offset = ((atom_b.y * 32) + atom_b.pixel_y) - ((atom_a.y * 32) + atom_a.pixel_y)
var/matrix/M = matrix()
M.Translate(0, 16)
M.Scale(1, sqrt((x_offset * x_offset) + (y_offset * y_offset)) / 32)
M.Turn(90 - Atan2(x_offset, y_offset)) // So... You pass coords in order x,y to this version of atan2. It should be called acsc2.
M.Translate(atom_a.pixel_x, atom_a.pixel_y)
transform = M
cl = c
cl.images += I
@@ -242,6 +242,7 @@
if(FILL_BUILDMODE)
to_chat(user, "<span class='notice'>***********************************************************</span>")
to_chat(user, "<span class='notice'>Left Mouse Button on turf/obj/mob = Select corner</span>")
to_chat(user, "<span class='notice'>Left Mouse Button + Alt on turf/obj/mob = Delete region</span>")
to_chat(user, "<span class='notice'>Right Mouse Button on buildmode button = Select object type</span>")
to_chat(user, "<span class='notice'>***********************************************************</span>")
if(LINK_BUILDMODE)
@@ -509,16 +510,20 @@
cornerB = select_tile(get_turf(object))
if(left_click) //rectangular
if(cornerA && cornerB)
if(!objholder)
to_chat(user, "<span class='warning'>Select object type first.</span>")
if(alt_click)
empty_region(block(get_turf(cornerA),get_turf(cornerB)))
deselect_region()
else
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
if(ispath(objholder,/turf))
T.ChangeTurf(objholder)
else
var/obj/A = new objholder(T)
A.dir = build_dir
deselect_region()
if(!objholder)
to_chat(user, "<span class='warning'>Select object type first.</span>")
else
for(var/turf/T in block(get_turf(cornerA),get_turf(cornerB)))
if(ispath(objholder,/turf))
T.ChangeTurf(objholder)
else
var/obj/A = new objholder(T)
A.dir = build_dir
deselect_region()
return
//Something wrong - Reset
@@ -567,13 +572,13 @@
if(P.id_tag && P.id_tag != 1 && alert(holder, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No")
goto(line_jump)
P.id_tag = M.id
line_jump // For the goto
valid_links = 0
for(var/obj/effect/buildmode_line/L in link_lines)
qdel(L)
link_lines -= L
if(istype(link_obj, /obj/machinery/door_control))
var/obj/machinery/door_control/M = link_obj
for(var/obj/machinery/door/airlock/P in range(M.range,M))
@@ -1,10 +1,9 @@
/client/proc/map_template_load()
set category = "Debug"
set name = "Map Template - Place"
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
@@ -16,22 +15,27 @@
if(!T)
return
if(!template.fits_in_map_bounds(T, centered = TRUE))
to_chat(usr, "Map is too large to fit in bounds. Map's dimensions: ([template.width], [template.height])")
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 <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</A>")
var/timer = start_watch()
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has started to place the map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a></span>")
if(template.load(T, centered = TRUE))
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has placed a map template ([template.name]) at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>. Took [stop_watch(timer)]s.</span>")
else
to_chat(usr, "Failed to place map")
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
@@ -39,7 +43,12 @@
to_chat(usr, "Bad map file: [map]")
return
var/timer = start_watch()
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has begun uploading a map template ([map])</span>")
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])")
if(M.preload_size(map))
to_chat(usr, "Map template '[map]' ready to place ([M.width]x[M.height])")
map_templates[M.name] = M
message_admins("<span class='adminnotice'>[key_name_admin(usr)] has uploaded a map template ([map]). Took [stop_watch(timer)]s.</span>")
else
to_chat(usr, "Map template '[map]' failed to load properly")
+10
View File
@@ -7,6 +7,7 @@
/obj/effect/landmark/corpse
name = "Unknown"
var/mobname = "Unknown" //Unused now but it'd fuck up maps to remove it now
var/mob_species = null //Set to make a mob of another race, currently used only in ruins
var/corpseuniform = null //Set this to an object path to have the slot filled with said object on the corpse.
var/corpsesuit = null
var/corpseshoes = null
@@ -37,6 +38,8 @@
M.real_name = src.name
M.death(1) //Kills the new mob
M.timeofdeath = timeofdeath
if(src.mob_species)
M.set_species(src.mob_species)
if(src.corpseuniform)
M.equip_to_slot_or_del(new src.corpseuniform(M), slot_w_uniform)
if(src.corpsesuit)
@@ -285,3 +288,10 @@
corpseid = 1
corpseidjob = "Commander"
corpseidaccess = "Captain"
/obj/effect/landmark/corpse/abductor //Connected to ruins, for some reason?
name = "abductor"
mobname = "???"
mob_species = "abductor"
corpseuniform = /obj/item/clothing/under/color/grey
corpseshoes = /obj/item/clothing/shoes/combat
+22 -9
View File
@@ -9,30 +9,43 @@
var/template_name = null
var/datum/map_template/template = null
var/centered = 1
var/loaded = 0
/obj/effect/landmark/map_loader/New(loc, tname)
/obj/effect/landmark/map_loader/New(turf/loc, tname)
..()
if(tname)
template_name = tname
if(template_name)
template = map_templates[template_name]
/obj/effect/landmark/map_loader/initialize()
..()
if(template)
load(template)
/obj/effect/landmark/map_loader/set_tag()
return
/obj/effect/landmark/map_loader/proc/load(datum/map_template/t)
spawn(1)
if(!t)
return
t.load(get_turf(src), centered = centered)
t.loaded++
qdel(src)
if(!t)
return
if(loaded) // I wanna be super sure this loads only once
return
loaded = 1
var/turf/pos = get_turf(src)
// Hop to nullspace so we don't get re-initialized by the map we're loading
loc = null
t.load(pos, centered = centered)
t.loaded++
qdel(src)
/obj/effect/landmark/map_loader/random
var/template_list = ""
/obj/effect/landmark/map_loader/random/New()
/obj/effect/landmark/map_loader/random/initialize()
..()
if(template_list)
template_name = safepick(splittext(template_list, ";"))
template = map_templates[template_name]
load(template)
load(template)
+245 -125
View File
@@ -2,10 +2,22 @@
//SS13 Optimized Map loader
//////////////////////////////////////////////////////////////
//As of 3.6.2016
//global datum that will preload variables on atoms instanciation
var/global/use_preloader = FALSE
var/global/dmm_suite/preloader/_preloader = new
/dmm_suite
// These regexes are global - meaning that starting the maploader again mid-load will
// reset progress - which means we need to track our index per-map, or we'll
// eternally recurse
// /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g
var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g")
// /^[\s\n]+"?|"?[\s\n]+$|^"|"$/g
var/static/regex/trimQuotesRegex = new/regex({"^\[\\s\n]+"?|"?\[\\s\n]+$|^"|"$"}, "g")
// /^[\s\n]+|[\s\n]+$/
var/static/regex/trimRegex = new/regex("^\[\\s\n]+|\[\\s\n]+$", "g")
var/static/list/modelCache = list()
/**
* Construct the model map and control the loading process
@@ -16,87 +28,156 @@ var/global/dmm_suite/preloader/_preloader = new
* e.g aa = /turf/unsimulated/wall{icon_state = "rock"}
* 2) Read the map line by line, parsing the result (using parse_grid)
*
* If `measureOnly` is set, then no atoms will be created, and all this will do
* is return the bounds after parsing the file
*
* If you need to freeze init while you're working, you can use the spacial allocator's
* "add_dirt" and "remove_dirt" which will put initializations on hold until you say
* the word. This is important for loading large maps such as the cyberiad, where
* atmos will attempt to start before it's ready, causing runtimes galore if init is
* allowed to romp unchecked.
*/
/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
/dmm_suite/load_map(dmm_file as file, x_offset as num, y_offset as num, z_offset as num, cropMap as num, measureOnly as num)
var/tfile = dmm_file//the map file we're creating
var/fname = "Lambda"
if(isfile(tfile))
fname = "[tfile]"
tfile = file2text(tfile)
if(!x_offset)
x_offset = 1
if(!y_offset)
y_offset = 1
if(!z_offset)
z_offset = world.maxz + 1
var/quote = ascii2text(34)
var/tfile = file2text(dmm_file)//the map file we're creating
var/tfile_len = length(tfile)
var/lpos = 1 // the models definition index
///////////////////////////////////////////////////////////////////////////////////////
//first let's map model keys (e.g "aa") to their contents (e.g /turf/space{variables})
///////////////////////////////////////////////////////////////////////////////////////
var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF)
var/list/grid_models = list()
var/key_len = length(copytext(tfile,2,findtext(tfile,quote,2,0)))//the length of the model key (e.g "aa" or "aba")
var/key_len = 0
//proceed line by line
for(lpos=1; lpos<tfile_len; lpos=findtext(tfile,"\n",lpos,0)+1)
var/tline = copytext(tfile,lpos,findtext(tfile,"\n",lpos,0))
if(copytext(tline,1,2) != quote)//we reached the map "layout"
break
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
if(do_sleep)
sleep(-1)
///////////////////////////////////////////////////////////////////////////////////////
//now let's fill the map with turf and objects using the constructed model map
///////////////////////////////////////////////////////////////////////////////////////
//position of the currently processed square
var/zcrd=-1
var/ycrd=y_offset
var/xcrd=x_offset
var/dmm_suite/loaded_map/LM = new
// This try-catch is used as a budget "Finally" clause, as the dirt count
// needs to be reset
var/watch = start_watch()
log_debug("[measureOnly ? "Measuring" : "Loading"] map: [fname]")
try
LM.index = 1
while(dmmRegex.Find(tfile, LM.index))
LM.index = dmmRegex.next
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
// "aa" = (/type{vars=blah})
if(dmmRegex.group[1]) // Model
var/key = dmmRegex.group[1]
if(grid_models[key]) // Duplicate model keys are ignored in DMMs
continue
if(key_len != length(key))
if(!key_len)
key_len = length(key)
else
throw EXCEPTION("Inconsistant key length in DMM")
if(!measureOnly)
grid_models[key] = dmmRegex.group[2]
zcrd++
world.maxz = max(world.maxz, zcrd+z_offset)//create a new z_level if needed
// (1,1,1) = {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
else if(dmmRegex.group[3]) // Coords
if(!key_len)
throw EXCEPTION("Coords before model definition in DMM")
var/zgrid = copytext(tfile,findtext(tfile,quote+"\n",zpos,0)+2,findtext(tfile,"\n"+quote,zpos,0)+1) //copy the whole map grid
var/z_depth = length(zgrid)
var/xcrdStart = text2num(dmmRegex.group[3]) + x_offset - 1
//position of the currently processed square
var/xcrd
var/ycrd = text2num(dmmRegex.group[4]) + y_offset - 1
var/zcrd = text2num(dmmRegex.group[5]) + z_offset - 1
//if exceeding the world max x or y, increase it
var/x_depth = length(copytext(zgrid,1,findtext(zgrid,"\n",2,0)))
var/x_tilecount = x_depth/key_len
if(world.maxx<x_tilecount)
world.maxx=x_tilecount
if(!measureOnly)
if(zcrd > world.maxz)
if(cropMap)
continue
else
zlevels.increase_max_zlevel_to(zcrd) //create a new z_level if needed
var/y_depth = z_depth / (x_depth+1)//x_depth + 1 because we're counting the '\n' characters in z_depth
if(world.maxy<y_depth)
world.maxy=y_depth
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
bounds[MAP_MAXZ] = max(bounds[MAP_MAXZ], zcrd)
//then proceed it line by line, starting from top
ycrd = y_depth
var/list/gridLines = splittext(dmmRegex.group[6], "\n")
for(var/gpos=1;gpos!=0;gpos=findtext(zgrid,"\n",gpos,0)+1)
var/grid_line = copytext(zgrid,gpos,findtext(zgrid,"\n",gpos,0))
var/leadingBlanks = 0
while(leadingBlanks < gridLines.len && gridLines[++leadingBlanks] == "")
if(leadingBlanks > 1)
gridLines.Cut(1, leadingBlanks) // Remove all leading blank lines.
//fill the current square using the model map
xcrd=0
if(!gridLines.len) // Skip it if only blank lines exist.
continue
for(var/mpos in 1 to x_depth step key_len)
xcrd++
var/model_key = copytext(grid_line,mpos,mpos+key_len)
parse_grid(grid_models[model_key], xcrd + x_offset, ycrd + y_offset, zcrd + z_offset, do_sleep)
if(gridLines.len && gridLines[gridLines.len] == "")
gridLines.Cut(gridLines.len) // Remove only one blank line at the end.
//reached end of current map
if(gpos+x_depth+1>z_depth)
break
bounds[MAP_MINY] = min(bounds[MAP_MINY], ycrd)
ycrd += gridLines.len - 1 // Start at the top and work down
ycrd--
if(do_sleep)
sleep(-1)
if(!cropMap && ycrd > world.maxy)
if(!measureOnly)
world.maxy = ycrd // Expand Y here. X is expanded in the loop below
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], ycrd)
else
bounds[MAP_MAXY] = max(bounds[MAP_MAXY], min(ycrd, world.maxy))
//reached End Of File
if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len)
break
if(do_sleep)
sleep(-1)
var/maxx = xcrdStart
if(measureOnly)
for(var/line in gridLines)
maxx = max(maxx, xcrdStart + length(line) / key_len - 1)
else
for(var/line in gridLines)
if(ycrd <= world.maxy && ycrd >= 1)
xcrd = xcrdStart
for(var/tpos = 1 to length(line) - key_len + 1 step key_len)
if(xcrd > world.maxx)
if(cropMap)
break
else
world.maxx = xcrd
if(xcrd >= 1)
var/model_key = copytext(line, tpos, tpos + key_len)
if(!grid_models[model_key])
throw EXCEPTION("Undefined model key in DMM: [model_key]. Map file: [fname].")
parse_grid(grid_models[model_key], xcrd, ycrd, zcrd, LM)
// After this call, it is NOT safe to reference `dmmRegex` without another call to
// "Find" - we might've hit a map loader here and changed its state
CHECK_TICK
maxx = max(maxx, xcrd)
++xcrd
--ycrd
bounds[MAP_MAXX] = max(bounds[MAP_MAXX], cropMap ? min(maxx, world.maxx) : maxx)
CHECK_TICK
catch(var/exception/e)
_preloader.reset()
throw e
_preloader.reset()
log_debug("Loaded map in [stop_watch(watch)]s.")
qdel(LM)
if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item
log_debug("Min x: bounds[MAP_MINX]")
log_debug("Min y: bounds[MAP_MINY]")
log_debug("Min z: bounds[MAP_MINZ]")
log_debug("Max x: bounds[MAP_MAXX]")
log_debug("Max y: bounds[MAP_MAXY]")
log_debug("Max z: bounds[MAP_MAXZ]")
return null
else
if(!measureOnly)
for(var/t in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ])))
var/turf/T = t
//we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs
T.AfterChange(1,keep_cabling = TRUE)
return bounds
/**
* Fill a given tile with its area/turf/objects/mobs
@@ -115,48 +196,60 @@ var/global/dmm_suite/preloader/_preloader = new
* 4) Instanciates the atom with its variables
*
*/
/dmm_suite/proc/parse_grid(model as text, xcrd as num, ycrd as num, zcrd as num, do_sleep = 1)
/dmm_suite/proc/parse_grid(model as text,xcrd as num,ycrd as num,zcrd as num, dmm_suite/loaded_map/LM)
/*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.
*/
var/list/members = list()//will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/explored)
var/list/members_attributes = list()//will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
var/list/members //will contain all members (paths) in model (in our example : /turf/unsimulated/wall and /area/mine/explored)
var/list/members_attributes //will contain lists filled with corresponding variables, if any (in our example : list(icon_state = "rock") and list())
var/list/cached = modelCache[model]
var/index
if(cached)
members = cached[1]
members_attributes = cached[2]
else
/////////////////////////////////////////////////////////
//Constructing members and corresponding variables lists
////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
//Constructing members and corresponding variables lists
////////////////////////////////////////////////////////
members = list()
members_attributes = list()
index = 1
var/index=1
var/old_position = 1
var/dpos
var/old_position = 1
var/dpos
do
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
dpos= find_next_delimiter_position(model,old_position,",","{","}")//find next delimiter (comma here) that's not within {...}
do
//finding next member (e.g /turf/unsimulated/wall{icon_state = "rock"} or /area/mine/explored)
dpos = find_next_delimiter_position(model, old_position, ",", "{", "}") //find next delimiter (comma here) that's not within {...}
var/full_def = copytext(model,old_position,dpos)//full definition, e.g : /obj/foo/bar{variables=derp}
var/atom_def = text2path(copytext(full_def,1,findtext(full_def,"{")))//path definition, e.g /obj/foo/bar
members.Add(atom_def)
old_position = dpos + 1
var/full_def = trim_text(copytext(model, old_position, dpos)) //full definition, e.g : /obj/foo/bar{variables=derp}
var/variables_start = findtext(full_def, "{")
var/atom_def = text2path(trim_text(copytext(full_def, 1, variables_start))) //path definition, e.g /obj/foo/bar
old_position = dpos + 1
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
var/list/fields = list()
if(!atom_def) // Skip the item if the path does not exist. Fix your crap, mappers!
continue
members.Add(atom_def)
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 = readlist(full_def, ";")
//transform the variables in text format into a list (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
var/list/fields = list()
//then fill the members_attributes list with the corresponding variables
members_attributes.len++
members_attributes[index++] = fields
if(variables_start)//if there's any variable
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
fields = readlist(full_def, ";")
if(do_sleep)
sleep(-1)
while(dpos != 0)
//then fill the members_attributes list with the corresponding variables
members_attributes.len++
members_attributes[index++] = fields
CHECK_TICK
while(dpos != 0)
modelCache[model] = list(members, members_attributes)
////////////////
@@ -165,24 +258,25 @@ var/global/dmm_suite/preloader/_preloader = new
//The next part of the code assumes there's ALWAYS an /area AND a /turf on a given tile
//in case of multiples turfs on one tile,
//will contains the images of all underlying turfs, to simulate the DMM multiple tiles piling
var/list/turfs_underlays = list()
//first instance the /area and remove it from the members list
index = members.len
var/turf/crds = locate(xcrd,ycrd,zcrd)
if(members[index] != /area/template_noop)
// We assume `members[index]` is an area path, as above, yes? I will operate
// on that assumption.
if(!ispath(members[index], /area))
throw EXCEPTION("Oh no, I thought this was an area!")
var/atom/instance
_preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation
instance = LM.area_path_to_real_area(members[index])
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
@@ -198,18 +292,20 @@ var/global/dmm_suite/preloader/_preloader = new
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
while(index <= members.len - 1) // Last item is an /area
var/underlay
if(istype(T, /turf)) // I blame this on the stupid clown who coded the BYOND map editor
underlay = T.appearance
T = instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)//instance new turf
if(ispath(members[index],/turf))
T.underlays += underlay
index++
//finally instance all remainings objects/mobs
for(index in 1 to first_turf_index - 1)
for(index in 1 to first_turf_index-1)
instance_atom(members[index],members_attributes[index],xcrd,ycrd,zcrd)
if(do_sleep)
sleep(-1)
CHECK_TICK
////////////////
//Helpers procs
@@ -222,7 +318,13 @@ var/global/dmm_suite/preloader/_preloader = new
var/turf/T = locate(x,y,z)
if(T)
instance = new path (T)//first preloader pass
if(ispath(path, /turf))
T.ChangeTurf(path, 1, 0)
instance = T
else if(ispath(path, /area))
else
instance = new path (T)//first preloader pass
if(use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New()
_preloader.load(instance)
@@ -232,16 +334,11 @@ var/global/dmm_suite/preloader/_preloader = new
//text trimming (both directions) helper proc
//optionally removes quotes before and after the text (for variable name)
/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)))
what=copytext(what,1,length(what))
if(trim_quotes)
while(length(what) && (findtext(what,quote,1,2)))
what=copytext(what,2,0)
while(length(what) && (findtext(what,quote,length(what),0)))
what=copytext(what,1,length(what))
return what
return trimQuotesRegex.Replace(what, "")
else
return trimRegex.Replace(what, "")
//find the position of the next delimiter,skipping whatever is comprised between opening_escape and closing_escape
//returns 0 if reached the last delimiter
@@ -313,14 +410,6 @@ var/global/dmm_suite/preloader/_preloader = new
return to_return
//simulates the DM multiple turfs on one tile underlaying
/dmm_suite/proc/add_underlying_turf(turf/placed,turf/underturf, list/turfs_underlays)
if(underturf.density)
placed.density = 1
if(underturf.opacity)
placed.opacity = 1
placed.underlays += turfs_underlays
//atom creation method that preloads variables at creation
/atom/New()
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
@@ -336,6 +425,7 @@ var/global/dmm_suite/preloader/_preloader = new
//Preloader datum
//////////////////
// This ain't re-entrant, but we had this before the maploader update
/dmm_suite/preloader
parent_type = /datum
var/list/attributes
@@ -349,11 +439,41 @@ var/global/dmm_suite/preloader/_preloader = new
/dmm_suite/preloader/proc/load(atom/what)
for(var/attribute in attributes)
what.vars[attribute] = attributes[attribute]
var/value = attributes[attribute]
if(islist(value))
value = deepCopyList(value)
what.vars[attribute] = value
use_preloader = FALSE
// If the map loader fails, make this safe
/dmm_suite/preloader/proc/reset()
use_preloader = FALSE
attributes = list()
target_path = null
// A datum for use within the context of loading a single map,
// so that one can have separate "unpowered" areas for ruins or whatever,
// yet have a single area type for use of mapping, instead of creating
// a new area type for each new ruin
/dmm_suite/loaded_map
parent_type = /datum
var/list/area_list = list()
var/index = 1 // To store the state of the regex
/dmm_suite/loaded_map/proc/area_path_to_real_area(area/A)
if(!ispath(A, /area))
throw EXCEPTION("Wrong argument to `area_path_to_real_area`")
if(!(A in area_list))
if(initial(A.there_can_be_many))
area_list[A] = new A
else
area_list[A] = locate(A)
return area_list[A]
/area/template_noop
name = "Area Passthrough"
/turf/template_noop
name = "Turf Passthrough"
name = "Turf Passthrough"
@@ -326,7 +326,7 @@ swapmap
x2+=x1-1
y2+=y1-1
z2+=z1-1
world.maxz=max(z2,world.maxz) // stretch z if necessary
zlevels.increase_max_zlevel_to(z2) // stretch z if necessary
if(!ischunk)
swapmaps_loaded[src]=null
swapmaps_byname[id]=src
@@ -373,7 +373,7 @@ swapmap
mz=max(mz,M.z2)
world.maxx=mx
world.maxy=my
world.maxz=mz
zlevels.cut_levels_downto(mz)
// save and delete
proc/Unload()
@@ -54,9 +54,8 @@
name = "space hotel pamphlet"
info = "<h3>Welcome to Deep Space Hotel 419!</h3>Thank you for choosing our hotel. Simply hand your credit or debit card to the concierge and get your room key! To check out, hand your credit card back.<small><h4>Conditions:</h4><ul><li>The hotel is not responsible for any losses due to time or space anomalies.<li>The hotel is not responsible for events that occur outside of the hotel station, including, but not limited to, events that occur inside of dimensional pockets.<li>The hotel is not responsible for overcharging your account.<li>The hotel is not responsible for missing persons.<li>The hotel is not responsible for mind-altering effects due to drugs, magic, demons, or space worms.</ul></small>"
/obj/effect/landmark/map_loader/hotel_room/New()
/obj/effect/landmark/map_loader/hotel_room/initialize()
..()
// load and randomly assign rooms
var/global/list/south_room_templates = list()
var/global/list/north_room_templates = list()
@@ -65,26 +64,27 @@
if(!loaded)
loaded = 1
for(var/map in flist(path))
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
if(copytext(map, 1, 3) == "n_")
north_room_templates += T
else if(copytext(map, 1, 3) == "s_")
south_room_templates += T
else
// omnidirectional rooms are randomly assigned
if(prob(50))
if(cmptext(copytext(map, length(map) - 3), ".dmm"))
var/datum/map_template/T = new(path = "[path][map]", rename = "[map]")
if(copytext(map, 1, 3) == "n_")
north_room_templates += T
else
else if(copytext(map, 1, 3) == "s_")
south_room_templates += T
else
// omnidirectional rooms are randomly assigned
if(prob(50))
north_room_templates += T
else
south_room_templates += T
var/datum/map_template/M = safepick(dir == NORTH ? north_room_templates : south_room_templates)
if(M)
template = M
load(M)
if(dir == NORTH)
north_room_templates -= M
else
south_room_templates -= M
load(M)
// The door to a hotel room, but also metadata for the room itself
/obj/machinery/door/unpowered/hotel_door
@@ -305,4 +305,4 @@
S.retal_target = target
S.retal = 1
#undef CHECKOUT_TIME
#undef CHECKOUT_TIME
+166 -29
View File
@@ -1,14 +1,27 @@
var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away_mission_config.txt")
// Call this before you remove the last dirt on a z level - that way, all objects
// will have proper atmos and other important enviro things
/proc/late_setup_level(turfs, smoothTurfs)
var/total_timer = start_watch()
var/subtimer = start_watch()
if(!smoothTurfs)
smoothTurfs = turfs
log_debug("Setting up atmos")
if(air_master)
air_master.setup_allturfs(turfs)
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
log_debug("Initializing lighting")
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)
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
log_debug("Smoothing tiles")
for(var/turf/T in smoothTurfs)
if(T.smooth)
smooth_icon(T)
@@ -16,20 +29,95 @@
var/atom/A = R
if(A.smooth)
smooth_icon(A)
if(istype(T, /turf/simulated/mineral)) // For the listening post, among other maps
var/turf/simulated/mineral/MT = T
MT.add_edges()
log_debug("\tTook [stop_watch(subtimer)]s")
log_debug("Late setup finished - took [stop_watch(total_timer)]s")
/proc/empty_rect(low_x,low_y, hi_x,hi_y, z)
var/timer = start_watch()
log_debug("Emptying region: ([low_x], [low_y]) to ([hi_x], [hi_y]) on z '[z]'")
empty_region(block(locate(low_x, low_y, z), locate(hi_x, hi_y, z)))
log_debug("Took [stop_watch(timer)]s")
/proc/empty_region(list/turfs)
for(var/thing in turfs)
var/turf/T = thing
for(var/otherthing in T)
qdel(otherthing)
T.ChangeTurf(/turf/space)
/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
if(fexists("config/away_mission_config.txt"))
Lines = file2list("config/away_mission_config.txt")
else
Lines = file2list("config/example/away_mission_config.txt")
if(potentialRandomZlevels && potentialRandomZlevels.len)
var/watch = start_watch()
log_startup_progress("Loading away mission...")
if(!Lines.len) return
var/map = pick(potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
maploader.load_map(file, z_offset = zlev)
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
zlevels.remove_dirt(zlev)
log_to_dd(" Away mission loaded: [map]")
//map_transition_config.Add(AWAY_MISSION_LIST)
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name != "awaystart")
continue
awaydestinations.Add(L)
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
else
log_startup_progress(" No away missions found.")
return
/proc/createALLZlevels()
if(awaydestinations.len) //crude, but it saves another var!
return
if(potentialRandomZlevels && potentialRandomZlevels.len)
var/watch = start_watch()
log_startup_progress("Loading away missions...")
for(var/map in potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
log_startup_progress("Loading away mission: [map]")
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
maploader.load_map(file, z_offset = zlev)
late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev)))
zlevels.remove_dirt(zlev)
log_to_dd(" Away mission loaded: [map]")
//map_transition_config.Add(AWAY_MISSION_LIST)
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name != "awaystart")
continue
awaydestinations.Add(L)
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
watch = start_watch()
else
log_startup_progress(" No away missions found.")
return
/proc/generateMapList(filename)
var/list/potentialMaps = list()
var/list/Lines = file2list(filename)
if(!Lines.len)
return
for(var/t in Lines)
if(!t)
continue
@@ -42,38 +130,87 @@
var/pos = findtext(t, " ")
var/name = null
// var/value = null
if(pos)
name = lowertext(copytext(t, 1, pos))
// value = copytext(t, pos + 1)
else
name = lowertext(t)
if(!name)
continue
potentialRandomZlevels.Add(t)
potentialMaps.Add(t)
return potentialMaps
if(potentialRandomZlevels.len)
var/watch = start_watch()
log_startup_progress("Loading away mission...")
/proc/seedRuins(z_level = 1, budget = 0, whitelist = /area/space, list/potentialRuins = space_ruins_templates)
var/overall_sanity = 100
var/ruins = potentialRuins.Copy()
var/initialbudget = budget
var/watch = start_watch()
var/map = pick(potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
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]")
log_startup_progress("Loading ruins...")
for(var/obj/effect/landmark/L in landmarks_list)
if(L.name != "awaystart")
while(budget > 0 && overall_sanity > 0)
// Pick a ruin
var/datum/map_template/ruin/ruin = ruins[pick(ruins)]
// Can we afford it
if(ruin.cost > budget)
overall_sanity--
continue
// If so, try to place it
var/sanity = 100
// And if we can't fit it anywhere, give up, try again
while(sanity > 0)
sanity--
var/turf/T = locate(rand(25, world.maxx - 25), rand(25, world.maxy - 25), z_level)
var/valid = 1
for(var/turf/check in ruin.get_affected_turfs(T,1))
var/area/new_area = get_area(check)
if(!(istype(new_area, whitelist)))
valid = 0
break
if(!valid)
continue
awaydestinations.Add(L)
log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.")
log_to_dd(" Ruin \"[ruin.name]\" loaded in [stop_watch(watch)]s at ([T.x], [T.y], [T.z]).")
else
log_startup_progress(" No away missions found.")
return
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
R.Load(ruins,ruin)
budget -= ruin.cost
if(!ruin.allow_duplicates)
ruins -= ruin.name
break
to_chat(world, "<span class='danger'> Loaded ruins. Or not.</span>") //So the players don't know if we loaded ruins, but we do have a message
if(initialbudget == budget) //Kill me
log_to_dd(" No ruins loaded.")
/obj/effect/ruin_loader
name = "random ruin"
desc = "If you got lucky enough to see this..."
icon = 'icons/obj/weapons.dmi'
icon_state = "syndballoon"
invisibility = 0
/obj/effect/ruin_loader/proc/Load(list/potentialRuins = space_ruins_templates, datum/map_template/template = null)
var/list/possible_ruins = list()
for(var/A in potentialRuins)
var/datum/map_template/T = potentialRuins[A]
if(!T.loaded)
possible_ruins += T
if(!template && possible_ruins.len)
template = safepick(possible_ruins)
if(!template)
return 0
template.load(get_turf(src),centered = 1)
template.loaded++
qdel(src)
return 1
+7 -2
View File
@@ -21,6 +21,9 @@
/obj/effect/levelref/New()
..()
levels += src
/obj/effect/levelref/initialize()
..()
for(var/obj/effect/levelref/O in levels)
if(id == O.id && O != src)
other = O
@@ -104,7 +107,7 @@
/turf/unsimulated/floor/upperlevel/New()
..()
var/obj/effect/levelref/R = locate() in get_area(src)
if(R)
if(R && R.other)
init(R)
/turf/unsimulated/floor/upperlevel/Destroy()
@@ -159,6 +162,8 @@
..()
portals += src
/obj/effect/view_portal/initialize()
..()
if(id)
for(var/obj/effect/view_portal/O in portals)
if(id == O.id && O != src && can_link(O))
@@ -361,4 +366,4 @@
screen_loc = "CENTER[ox >= 0 ? "+" : ""][ox],CENTER[oy >= 0 ? "+" : ""][oy]"
/obj/effect/view_portal_dummy/attack_ghost(mob/user)
owner.attack_ghost(user)
owner.attack_ghost(user)
+1
View File
@@ -26,6 +26,7 @@
/obj/item/weapon/storage/bible)
/obj/structure/bookcase/initialize()
..()
for(var/obj/item/I in loc)
if(is_type_in_list(I, valid_types))
I.forceMove(src)
+2 -1
View File
@@ -9,6 +9,7 @@
invisibility = INVISIBILITY_LIGHTING
color = "#000000"
icon_state = "light1"
auto_init = 0 // doesn't need special init
var/lum_r
var/lum_g
@@ -104,4 +105,4 @@
if(istype(T))
T.lighting_overlay = null
return ..()
return ..()
@@ -8,6 +8,7 @@
var/on=0
/obj/machinery/media/receiver/boombox/initialize()
..()
if(on)
update_on()
update_icon()
@@ -80,4 +81,4 @@
if(on)
icon_state="wallradio-p"
else
icon_state="wallradio"
icon_state="wallradio"
@@ -19,6 +19,7 @@
var/const/MAX_TEMP=70 // Celsius
/obj/machinery/media/transmitter/broadcast/initialize()
..()
testing("[type]/initialize() called!")
if(autolink && autolink.len)
for(var/obj/machinery/media/source in orange(20, src))
@@ -303,7 +303,7 @@
/mob/living/silicon/robot/drone/Bump(atom/movable/AM as mob|obj, yes)
if (!yes || ( \
if(!yes || ( \
!istype(AM,/obj/machinery/door) && \
!istype(AM,/obj/machinery/recharge_station) && \
!istype(AM,/obj/machinery/disposal/deliveryChute) && \
@@ -135,6 +135,7 @@
var/alerted = 0
var/ore_eaten = 1
var/chase_time = 100
var/will_burrow = 1
/mob/living/simple_animal/hostile/asteroid/goldgrub/New()
..()
@@ -170,7 +171,7 @@
visible_message("<span class='notice'>The ore was swallowed whole!</span>")
/mob/living/simple_animal/hostile/asteroid/goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time
if(!alerted)
if(!alerted && will_burrow)
alerted = 1
spawn(chase_time)
if(alerted)
+22 -7
View File
@@ -99,11 +99,22 @@
var/global/list/status_overlays_lighting
var/global/list/status_overlays_environ
var/indestructible = 0 // If set, prevents aliens from destroying it
var/keep_preset_name = 0
var/report_power_alarm = 1
var/shock_proof = 0 //if set to 1, this APC will not arc bolts of electricity if it's overloaded.
/obj/machinery/power/apc/worn_out
name = "\improper Worn out APC"
keep_preset_name = 1
locked = 0
environ = 0
equipment = 0
lighting = 0
operating = 0
/obj/machinery/power/apc/noalarm
report_power_alarm = 0
@@ -192,15 +203,19 @@
cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
var/area/A = src.loc.loc
var/area/A = get_area(src)
//if area isn't specified use current
if(isarea(A) && src.areastring == null)
src.area = A
if(keep_preset_name)
if(isarea(A))
area = A
// no-op, keep the name
else if(isarea(A) && src.areastring == null)
area = A
name = "\improper [area.name] APC"
else
src.area = get_area_name(areastring)
area = get_area_name(areastring)
name = "\improper [area.name] APC"
area.apc |= src
update_icon()
@@ -623,7 +638,7 @@
else
if(istype(user, /mob/living/silicon))
return src.attack_hand(user)
if (!opened && wiresexposed && \
if(!opened && wiresexposed && \
(istype(W, /obj/item/device/multitool) || \
istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
return src.attack_hand(user)
@@ -853,7 +868,7 @@
if(istype(user, /mob/living/silicon))
var/mob/living/silicon/ai/AI = user
var/mob/living/silicon/robot/robot = user
if ( \
if( \
src.aidisabled || \
malfhack && istype(malfai) && \
( \
@@ -1382,4 +1397,4 @@
else
return 0
#undef APC_UPDATE_ICON_COOLDOWN
#undef APC_UPDATE_ICON_COOLDOWN
+4 -3
View File
@@ -82,6 +82,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
//
/obj/machinery/gravity_generator/main/station/initialize()
..()
setup_parts()
middle.overlays += "activated"
update_list()
@@ -215,17 +216,17 @@ var/const/GRAV_NEEDS_WRENCH = 3
/obj/machinery/gravity_generator/main/attack_hand(mob/user as mob)
if(!..())
return interact(user)
/obj/machinery/gravity_generator/main/attack_ai(mob/user as mob)
return 1
/obj/machinery/gravity_generator/main/attack_ghost(mob/user as mob)
return interact(user)
/obj/machinery/gravity_generator/main/interact(mob/user as mob)
if(stat & BROKEN)
return
var/dat = "Gravity Generator Breaker: "
if(breaker)
dat += "<span class='linkOn'>ON</span> <A href='?src=\ref[src];gentoggle=1'>OFF</A>"
+2 -1
View File
@@ -138,6 +138,7 @@
var/redeem_immediately = 0 // redeem immediately for holding cell
/obj/machinery/treadmill_monitor/initialize()
..()
if(id)
for(var/obj/machinery/power/treadmill/T in machines)
if(T.id == id)
@@ -222,4 +223,4 @@
#undef FONT_SIZE
#undef FONT_COLOR
#undef FONT_STYLE
#undef CHARS_PER_LINE
#undef CHARS_PER_LINE
@@ -146,7 +146,7 @@
return
else
return 1
if ( \
if( \
!isturf(src.loc) || \
!(locate(/obj/structure/table) in src.loc) && \
!(locate(/obj/machinery/optable) in src.loc) && \
@@ -712,6 +712,18 @@
reagents.add_reagent("toxin", 3)
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/lizardmeat
name = "mutant lizard meat"
desc = "Seems to be a slab of meat from some mutant lizard thing?"
icon_state = "xenomeat"
filling_color = "#43DE18"
New()
..()
reagents.add_reagent("protein", 3)
reagents.add_reagent("toxin", 3)
bitesize = 3
/obj/item/weapon/reagent_containers/food/snacks/spiderleg
name = "spider leg"
desc = "A still twitching leg of a giant spider... you don't really want to eat this, do you?"
+49
View File
@@ -0,0 +1,49 @@
//Parent types
/area/ruin/
name = "\improper Unexplored Location"
icon_state = "away"
has_gravity = 1
there_can_be_many = 1
/area/ruin/unpowered
always_unpowered = 0
/area/ruin/unpowered/no_grav
has_gravity = 0
/area/ruin/powered
requires_power = 0
//Areas
/area/ruin/unpowered/no_grav/way_home
name = "\improper Salvation"
icon_state = "away"
/area/ruin/powered/snow_biodome
/area/ruin/powered/golem_ship
name = "Free Golem Ship"
// Ruins of "onehalf" ship
/area/ruin/onehalf/hallway
name = "Hallway"
icon_state = "hallC"
/area/ruin/onehalf/drone_bay
name = "Mining Drone Bay"
icon_state = "engine"
/area/ruin/onehalf/dorms_med
name = "Crew Quarters"
icon_state = "Sleep"
/area/ruin/onehalf/bridge
name = "Bridge"
icon_state = "bridge"
+2 -2
View File
@@ -843,7 +843,7 @@
name = "\improper Airtight plastic flaps"
desc = "Heavy duty, airtight, plastic flaps."
/obj/structure/plasticflaps/mining/New()
/obj/structure/plasticflaps/mining/initialize()
air_update_turf(1)
..()
@@ -857,4 +857,4 @@
#undef ORDER_SCREEN_WIDTH
#undef ORDER_SCREEN_HEIGHT
#undef SUPPLY_SCREEN_WIDTH
#undef SUPPLY_SCREEN_HEIGHT
#undef SUPPLY_SCREEN_HEIGHT
+73
View File
@@ -0,0 +1,73 @@
/datum/zlevel
var/flags = 0
var/dirt_count = 0
var/zpos
var/list/init_list = list()
/datum/zlevel/New(z)
zpos = z
/datum/zlevel/proc/resume_init()
if(dirt_count > 0)
throw EXCEPTION("Init told to resume when z-level still dirty. Z level: '[zpos]'")
log_debug("Releasing freeze on z-level '[zpos]'!")
log_debug("Beginning initialization!")
var/list/our_atoms = init_list // OURS NOW!!! (Keeping this list to ourselves will prevent hijack)
init_list = list()
var/list/late_maps = list()
var/list/pipes = list()
var/list/cables = list()
var/watch = start_watch()
for(var/schmoo in our_atoms)
var/atom/movable/AM = schmoo
if(AM) // to catch stuff like the nuke disk that no longer exists
// This can mess with our state - we leave these for last
if(istype(AM, /obj/effect/landmark/map_loader))
late_maps.Add(AM)
continue
AM.initialize()
if(istype(AM, /obj/machinery/atmospherics))
pipes.Add(AM)
else if(istype(AM, /obj/structure/cable))
cables.Add(AM)
log_debug("Primary initialization finished in [stop_watch(watch)]s.")
our_atoms.Cut()
if(pipes.len)
do_pipes(pipes)
if(cables.len)
do_cables(cables)
if(late_maps.len)
do_late_maps(late_maps)
/datum/zlevel/proc/do_pipes(list/pipes)
var/watch = start_watch()
log_debug("Building pipenets on z-level '[zpos]'!")
for(var/schmoo in pipes)
var/obj/machinery/atmospherics/machine = schmoo
if(machine)
machine.build_network()
pipes.Cut()
log_debug("Took [stop_watch(watch)]s")
/datum/zlevel/proc/do_cables(list/cables)
var/watch = start_watch()
log_debug("Building powernets on z-level '[zpos]'!")
for(var/schmoo in cables)
var/obj/structure/cable/C = schmoo
if(C)
makepowernet_for(C)
cables.Cut()
log_debug("Took [stop_watch(watch)]s")
/datum/zlevel/proc/do_late_maps(list/late_maps)
var/watch = start_watch()
log_debug("Loading map templates on z-level '[zpos]'!")
zlevels.add_dirt(zpos) // Let's not repeatedly resume init for each template
for(var/schmoo in late_maps)
var/obj/effect/landmark/map_loader/ML = schmoo
if(ML)
ML.initialize()
late_maps.Cut()
zlevels.remove_dirt(zpos)
log_debug("Took [stop_watch(watch)]s")
@@ -0,0 +1,89 @@
var/global/datum/zlev_manager/zlevels = new
/datum/zlev_manager
// A list of z-levels
var/list/z_list = list()
// Populate our z level list
/datum/zlev_manager/proc/initialize()
z_list.len = world.maxz
for(var/i = 1, i <= world.maxz, i++)
z_list[i] = new /datum/zlevel(i)
/datum/zlev_manager/proc/get_zlev(z)
if(z < 1)
throw EXCEPTION("Non-positive z level given!")
else if(z > z_list.len)
throw EXCEPTION("Untracked z level: '[z]'")
else
return z_list[z]
// For when you need the z-level to be at a certain point
/datum/zlev_manager/proc/increase_max_zlevel_to(new_maxz)
if(world.maxz>=new_maxz)
return
while(world.maxz<new_maxz)
add_new_zlevel()
// Increments the max z-level by one
// For convenience's sake returns the z-level added
/datum/zlev_manager/proc/add_new_zlevel()
world.maxz++
var/our_z = world.maxz
z_list.len++
z_list[our_z] = new /datum/zlevel(our_z)
return our_z
/datum/zlev_manager/proc/cut_levels_downto(new_maxz)
if(world.maxz <= new_maxz)
return
while(world.maxz>new_maxz)
kill_topmost_zlevel()
// Decrements the max z-level by one
// not normally used, but hey the swapmap loader wanted it
/datum/zlev_manager/proc/kill_topmost_zlevel()
var/our_z = world.maxz
qdel(z_list[our_z])
z_list.len--
world.maxz--
/*
* "Dirt" management
* "Dirt" is used to keep track of whether a z level should automatically have
* stuff on it initialize or not - the map loaders, when set to defer init, place
* a freeze on the z levels they touch so as to prevent atmos from exploding,
* among other things
*/
// Returns whether the given z level has a freeze on initialization
/datum/zlev_manager/proc/is_zlevel_dirty(z)
var/datum/zlevel/our_z = get_zlev(z)
return (our_z.dirt_count > 0)
// Increases the dirt count on a z level
/datum/zlev_manager/proc/add_dirt(z)
var/datum/zlevel/our_z = get_zlev(z)
if(our_z.dirt_count == 0)
log_debug("Placing an init freeze on z-level '[our_z.zpos]'!")
our_z.dirt_count++
// Decreases the dirt count on a z level
/datum/zlev_manager/proc/remove_dirt(z)
var/datum/zlevel/our_z = get_zlev(z)
our_z.dirt_count--
if(our_z.dirt_count == 0)
our_z.resume_init()
if(our_z.dirt_count < 0)
log_debug("WARNING: Imbalanced dirt removal")
our_z.dirt_count = 0
/datum/zlev_manager/proc/postpone_init(z, thing)
var/datum/zlevel/our_z = get_zlev(z)
our_z.init_list.Add(thing)