Merge pull request #5254 from Crazylemon64/space_allocation

Updates space transitions and integrates it with the space management module
This commit is contained in:
Fox McCloud
2016-07-31 12:18:19 -04:00
committed by GitHub
122 changed files with 1035 additions and 465 deletions
+3
View File
@@ -1979,6 +1979,7 @@
return
else
for(var/obj/machinery/photocopier/faxmachine/F in allfaxes)
// TODO: Tie into space manager
if((F.z in config.station_levels))
spawn(0)
if(!F.receivefax(P))
@@ -2326,6 +2327,7 @@
for(var/mob/living/carbon/human/H in mob_list)
var/turf/loc = find_loc(H)
var/security = 0
// TODO: Tie into space manager
if(!(loc.z in config.station_levels) || prisonwarped.Find(H))
//don't warp them if they aren't ready or are already there
@@ -2563,6 +2565,7 @@
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","EgL")
for(var/obj/machinery/door/airlock/W in world)
// TODO: Tie into space manager
if((W.z in config.station_levels) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
+1
View File
@@ -373,6 +373,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
for(var/I in singularities)
var/obj/singularity/S = I
// TODO: Tie into space manager
if(S.z == ZLEVEL_CENTCOMM || S.z >= MAX_Z)
continue
qdel(S)
+3 -1
View File
@@ -139,7 +139,9 @@ var/list/admin_verbs_show_debug_verbs = list(
/client/proc/print_jobban_old_filter,
/client/proc/forceEvent,
/client/proc/nanomapgen_DumpImage,
/client/proc/reload_nanoui_resources
/client/proc/reload_nanoui_resources,
/client/proc/admin_redo_space_transitions,
/client/proc/make_turf_space_map
)
/client/proc/enable_debug_verbs()
+1
View File
@@ -81,6 +81,7 @@ var/list/sounds_cache = list()
for(var/O in global_intercoms)
var/obj/item/device/radio/intercom/I = O
// TODO: Tie into space manager
if(I.z != ZLEVEL_STATION && !ignore_z)
continue
if(!I.on && !ignore_power)
@@ -0,0 +1,41 @@
/client/proc/admin_redo_space_transitions()
set name = "Remake Space Transitions"
set desc = "Re-assigns all space transitions"
set category = "Debug"
if(!check_rights(R_ADMIN|R_DEBUG))
return
var/choice = alert("Do you want to rebuild space transitions?",,"Yes", "No")
if(choice == "No")
return
message_admins("[key_name_admin(usr)] re-assigned all space transitions")
space_manager.do_transition_setup()
log_admin("[key_name(usr)] re-assigned all space transitions")
feedback_add_details("admin_verb","SPCRST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/make_turf_space_map()
set name = "Make Space Map"
set desc = "Create a map of the space levels as turfs at your feet"
set category = "Debug"
if(!check_rights(R_ADMIN|R_DEBUG))
return
var/choice = alert("Are you sure you want to make a space map out of turfs?",,"Yes","No")
if(choice == "No")
return
message_admins("[key_name_admin(usr)] made a space map")
space_manager.map_as_turfs(get_turf(usr))
log_admin("[key_name(usr)] made a space map")
@@ -96,7 +96,7 @@ var/global/dmm_suite/preloader/_preloader = new
if(cropMap)
continue
else
zlevels.increase_max_zlevel_to(zcrd) //create a new z_level if needed
space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed
bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart)
bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd)
@@ -326,7 +326,7 @@ swapmap
x2+=x1-1
y2+=y1-1
z2+=z1-1
zlevels.increase_max_zlevel_to(z2) // stretch z if necessary
space_manager.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
zlevels.cut_levels_downto(mz)
space_manager.cut_levels_downto(mz)
// save and delete
proc/Unload()
+6 -11
View File
@@ -59,15 +59,13 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/map = pick(potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
var/zlev = space_manager.add_new_zlevel(AWAY_MISSION, linkage = UNAFFECTED)
space_manager.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)
space_manager.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
@@ -91,11 +89,11 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/file = file(map)
if(isfile(file))
log_startup_progress("Loading away mission: [map]")
var/zlev = zlevels.add_new_zlevel()
zlevels.add_dirt(zlev)
var/zlev = space_manager.add_new_zlevel()
space_manager.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)
space_manager.remove_dirt(zlev)
log_to_dd(" Away mission loaded: [map]")
//map_transition_config.Add(AWAY_MISSION_LIST)
@@ -151,8 +149,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
var/initialbudget = budget
var/watch = start_watch()
log_startup_progress("Loading ruins...")
while(budget > 0 && overall_sanity > 0)
// Pick a ruin
var/datum/map_template/ruin/ruin = ruins[pick(ruins)]
@@ -187,7 +183,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
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.")
@@ -115,6 +115,7 @@
to_chat(H, "<span class='warning'>You cannot teleport into solid walls.</span>")
return 0*///Who the fuck cares? Ninjas in walls are cool.
// TODO: Tie into space manager
if(T.z in config.admin_levels)
to_chat(H, "<span class='warning'>You cannot use your teleporter on this Z-level.</span>")
return 0
+2 -1
View File
@@ -181,7 +181,8 @@
//proc/camera_list(var/datum/file/camnet_key/key)
get_machines(var/datum/file/camnet_key/key)
if(!computer || computer.z > 6)
// TODO: Tie into space manager
if(!computer || computer.z > ZLEVEL_DERELICT)
return null
var/list/L = list()
@@ -59,6 +59,7 @@
Topic(var/href, var/list/href_list)
if(!interactable() || !computer.radio || ..(href,href_list) )
return
// TODO: Tie into space manager
if(!(computer.z in config.station_levels))
to_chat(usr, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
+2 -1
View File
@@ -24,7 +24,8 @@
attackby(obj/item/weapon/aiModule/module as obj, mob/user as mob, params)
if(user.z > 6)
// TODO: Tie into space manager
if(user.z > ZLEVEL_DERELICT)
to_chat(user, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
if(istype(module, /obj/item/weapon/aiModule))
+2 -1
View File
@@ -49,7 +49,8 @@
scan = computer.cardslot.reader
if(!interactable())
return
if(computer.z > 6)
// TODO: Tie into space manager
if(computer.z > ZLEVEL_DERELICT)
to_chat(usr, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
var/dat
+1 -2
View File
@@ -43,6 +43,7 @@
if(!T.implanted) continue
var/loc_display = "Unknown"
var/mob/living/carbon/M = T.imp_in
// TODO: Tie into space manager
if(M.z == ZLEVEL_STATION && !istype(M.loc, /turf/space))
var/turf/mob_loc = get_turf(M)
loc_display = mob_loc.loc
@@ -98,5 +99,3 @@
interact()
return
+2 -4
View File
@@ -31,7 +31,8 @@
interact()
if(!interactable() || computer.z > 6)
// TODO: Tie into space manager
if(!interactable() || computer.z > ZLEVEL_DERELICT)
return
var/dat
if(src.temp)
@@ -206,6 +207,3 @@
interact()
return
+2 -1
View File
@@ -57,7 +57,8 @@
if(!interactable())
return
if(computer.z > 6)
// TODO: Tie into space manager
if(computer.z > ZLEVEL_DERELICT)
to_chat(usr, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
var/dat
+1 -1
View File
@@ -105,6 +105,7 @@
for(var/obj/O in radio_connection.devices)
if(istype(O,typekey))
T = get_turf(O)
// TODO: Tie into space manager
if(istype(O) && (subspace || (O.z == z_level))) // radio does not work across z-levels
result |= O
return result
@@ -232,4 +233,3 @@
if(C.d1 == 0 && (C.powernet == P))
return 1
return 0
+1 -1
View File
@@ -17,6 +17,7 @@
/datum/event/alien_infestation/start()
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
// TODO: Tie into space manager
if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
@@ -34,4 +35,3 @@
spawncount--
successSpawn = 1
+1
View File
@@ -19,6 +19,7 @@
var/obj/item/device/radio/beacon/chosen
var/list/possible = list()
for(var/obj/item/device/radio/beacon/W in world)
// TODO: Tie into space manager
if(!(W.z in config.station_levels))
continue
possible += W
+3 -2
View File
@@ -18,7 +18,8 @@
/datum/event/brand_intelligence/start()
for(var/obj/machinery/vending/V in machines)
if(V.z != 1) continue
// TODO: Tie into space manager
if(V.z != ZLEVEL_STATION) continue
vendingMachines.Add(V)
if(!vendingMachines.len)
@@ -62,4 +63,4 @@
rebel.shoot_inventory = 1
if(IsMultiple(activeFor, 8))
originMachine.speak(pick(rampant_speeches))
originMachine.speak(pick(rampant_speeches))
+3 -2
View File
@@ -21,7 +21,8 @@
var/turf/T = get_turf(H)
if(!T)
continue
if(T.z != 1)
// TODO: Tie into space manager
if(T.z != ZLEVEL_STATION)
continue
var/foundAlready = 0 // don't infect someone that already has the virus
for(var/datum/disease/D in H.viruses)
@@ -34,4 +35,4 @@
D = new virus_type()
D.carrier = 1
H.AddDisease(D)
break
break
+1 -1
View File
@@ -62,7 +62,7 @@
goal = locate(endx, endy, 1)
src.x = startx
src.y = starty
src.z = 1
src.z = ZLEVEL_STATION
spawn(0)
walk_towards(src, goal, 1)
return
+6 -2
View File
@@ -22,6 +22,7 @@
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
// TODO: Tie into space manager
if(current_area.type in skipped_areas || !(S.z in config.station_levels))
continue
S.last_charge = S.charge
@@ -35,6 +36,7 @@
for(var/obj/machinery/power/apc/C in world)
var/area/current_area = get_area(C)
// TODO: Tie into space manager
if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels))
continue
if(C.cell)
@@ -48,12 +50,14 @@
command_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
for(var/obj/machinery/power/apc/C in machines)
var/area/current_area = get_area(C)
// TODO: Tie into space manager
if(current_area.type in skipped_areas_apc || !(C.z in config.station_levels))
continue
if(C.cell)
C.cell.charge = C.cell.maxcharge
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
// TODO: Tie into space manager
if(current_area.type in skipped_areas || !(S.z in config.station_levels))
continue
S.charge = S.last_charge
@@ -66,7 +70,8 @@
if(announce)
command_announcement.Announce("All SMESs on [station_name()] have been recharged. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
for(var/obj/machinery/power/smes/S in machines)
if(S.z != 1)
// TODO: Tie into space manager
if(S.z != ZLEVEL_STATION)
continue
S.charge = S.capacity
S.output_level = S.output_level_max
@@ -74,4 +79,3 @@
S.input_attempt = 1
S.update_icon()
S.power_change()
+2 -2
View File
@@ -1,5 +1,6 @@
/proc/Christmas_Game_Start()
for(var/obj/structure/flora/tree/pine/xmas in world)
// TODO: Tie into space manager
if(!(xmas.z in config.station_levels)) continue
for(var/turf/simulated/floor/T in orange(1,xmas))
for(var/i=1,i<=rand(1,5),i++)
@@ -40,7 +41,7 @@
"What do you get from eating tree decorations?\n\n<i>Tinsilitis!</i>",
"What do snowmen wear on their heads?\n\n<i>Ice caps!</i>",
"Why is Christmas just like life on ss13?\n\n<i>You do all the work and the fat guy gets all the credit.</i>",
"Why doesnt Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
"Why doesnt Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
new /obj/item/clothing/head/festive(target.loc)
user.update_icons()
cracked = 1
@@ -59,4 +60,3 @@
desc = "A crappy paper hat that you are REQUIRED to wear."
flags_inv = 0
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
+3
View File
@@ -24,6 +24,7 @@
command_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
for(var/area/A in world)
// TODO: Tie into space manager
if(!(A.z in config.station_levels) || is_safe_zone(A))
continue
A.radiation_alert()
@@ -42,6 +43,7 @@
var/turf/T = get_turf(H)
if(!T)
continue
// TODO: Tie into space manager
if(!(T.z in config.station_levels) || is_safe_zone(T.loc))
continue
@@ -61,6 +63,7 @@
command_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
for(var/area/A in world)
// TODO: Tie into space manager
if(!(A.z in config.station_levels) || is_safe_zone(A))
continue
A.reset_radiation_alert()
+1 -1
View File
@@ -41,7 +41,7 @@
var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread()
sparks.set_up(3, 0, D.loc)
sparks.start()
D.z = 2
D.z = ZLEVEL_CENTCOMM
D.has_loot = 0
qdel(D)
+2 -1
View File
@@ -16,6 +16,7 @@
var/list/vents = list()
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
// TODO: Tie into space manager
if((temp_vent.loc.z in config.station_levels) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
@@ -26,4 +27,4 @@
if(prob(66))
S.grow_as = /mob/living/simple_animal/hostile/poison/giant_spider/nurse
vents -= vent
spawncount--
spawncount--
+3 -2
View File
@@ -2,13 +2,14 @@
var/spawn_prob = 10
startWhen = 2
announceWhen = 3
/datum/event/undead/start()
var/datum/event/electrical_storm/RS = new
RS.lightsoutAmount = pick(2,2,3)
RS.start()
RS.kill()
for(var/area/A)
// TODO: Tie into space manager
if(!(A.z in config.station_levels)) continue //Spook on main station only.
if(A.luminosity) continue
// if(A.lighting_space) continue
@@ -34,7 +35,7 @@
80;/mob/living/simple_animal/hostile/retaliate/zombie,
60;/mob/living/simple_animal/hostile/retaliate/ghost)
new undeadtype(T)
/datum/event/undead/announce()
for(var/mob/living/M in player_list)
to_chat(M, "You feel [pick("a chill","a deathly chill","the undead","dirty", "creeped out","afraid","fear")]!")
+1
View File
@@ -11,6 +11,7 @@
/datum/event/vent_clog/setup()
endWhen = rand(25, 100)
for(var/obj/machinery/atmospherics/unary/vent_scrubber/temp_vent in machines)
// TODO: Tie into space manager
if((temp_vent.loc.z in config.station_levels))
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
+2 -1
View File
@@ -13,6 +13,7 @@
/datum/event/wormholes/start()
for(var/turf/simulated/floor/T in world)
// TODO: Tie into space manager
if((T.z in config.station_levels))
pick_turfs += T
@@ -62,4 +63,4 @@
if(P && isturf(P.loc))
target = P.loc
if(!target) return
do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon
do_teleport(M, target, 1, 1, 0, 0) ///You will appear adjacent to the beacon
+2 -2
View File
@@ -1,5 +1,6 @@
/datum/holiday/xmas/celebrate()
for(var/obj/structure/flora/tree/pine/xmas in world)
// TODO: Tie into space manager
if(!(xmas.z in config.station_levels)) continue
for(var/turf/simulated/floor/T in orange(1,xmas))
for(var/i=1,i<=rand(1,5),i++)
@@ -43,7 +44,7 @@
"What do you get from eating tree decorations?\n\n<i>Tinsilitis!</i>",
"What do snowmen wear on their heads?\n\n<i>Ice caps!</i>",
"Why is Christmas just like life on ss13?\n\n<i>You do all the work and the fat guy gets all the credit.</i>",
"Why doesnt Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
"Why doesnt Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
new /obj/item/clothing/head/festive(target.loc)
user.update_icons()
cracked = 1
@@ -62,4 +63,3 @@
desc = "A crappy paper hat that you are REQUIRED to wear."
flags_inv = 0
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+2 -1
View File
@@ -376,6 +376,7 @@
// Bluespace tomato code copied over from grown.dm.
if(get_trait(TRAIT_TELEPORTING))
// TODO: Tie into space manager
if(target.z in config.admin_levels)
return 1
@@ -828,4 +829,4 @@
display_name = "modified [base_name]"
if(2) //Enhanced
seed_name = "enhanced [base_name]"
display_name = "enhanced [base_name]"
display_name = "enhanced [base_name]"
+3 -1
View File
@@ -528,7 +528,8 @@
/obj/item/device/wormhole_jaunter/attack_self(mob/user as mob)
var/turf/device_turf = get_turf(user)
if(!device_turf||device_turf.z==2||device_turf.z>=7)
// TODO: Tie into space manager
if(!device_turf||device_turf.z==ZLEVEL_CENTCOMM||device_turf.z>=ZLEVEL_EMPTY)
to_chat(user, "<span class='notice'>You're having difficulties getting the [src.name] to work.</span>")
return
else
@@ -536,6 +537,7 @@
var/list/L = list()
for(var/obj/item/device/radio/beacon/B in world)
var/turf/T = get_turf(B)
// TODO: Tie into space manager
if(T.z == ZLEVEL_STATION)
L += B
if(!L.len)
+1
View File
@@ -240,6 +240,7 @@
/obj/item/weapon/ore/New()
pixel_x = rand(0,16)-8
pixel_y = rand(0,8)-8
// TODO: Tie into space manager
if(src.z == ZLEVEL_ASTEROID)
score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining asteroid (No Clown Planet)
+1
View File
@@ -18,6 +18,7 @@
var/turf/T = get_turf(src)
if(!T)
return 0
// TODO: Tie into space manager
if(T.z == ZLEVEL_CENTCOMM) //dont detect mobs on centcomm
return 0
if(T.z >= MAX_Z)
+2 -1
View File
@@ -640,13 +640,14 @@ var/list/ai_verbs_default = list(
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
var/ai_allowed_Zlevel = list(1,3,5)
var/ai_allowed_Zlevel = list(ZLEVEL_STATION,ZLEVEL_TELECOMMS,ZLEVEL_ASTEROID)
var/d
var/area/bot_area
d += "<A HREF=?src=\ref[src];botrefresh=\ref[Bot]>Query network status</A><br>"
d += "<table width='100%'><tr><td width='40%'><h3>Name</h3></td><td width='20%'><h3>Status</h3></td><td width='30%'><h3>Location</h3></td><td width='10%'><h3>Control</h3></td></tr>"
for(var/mob/living/simple_animal/bot/Bot in simple_animal_list)
// TODO: Tie into space manager
if((Bot.z in ai_allowed_Zlevel) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected!
bot_area = get_area(Bot)
d += "<tr><td width='30%'>[Bot.hacked ? "<span class='bad'>(!) </span>[Bot.name]" : Bot.name] ([Bot.model])</td>"
@@ -499,6 +499,7 @@
/mob/living/silicon/pai/proc/hackloop()
var/turf/T = get_turf_or_move(src.loc)
for(var/mob/living/silicon/ai/AI in player_list)
// TODO: Tie into space manager
if(!T || !(T.z in config.contact_levels))
break
if(T.loc)
+2 -1
View File
@@ -41,6 +41,7 @@
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
// TODO: Tie into space manager
if(!T || !(z == T.z || (T.z in config.player_levels)))
return STATUS_CLOSE
@@ -102,4 +103,4 @@
. = shared_nano_interaction(src_object)
if(. != STATUS_CLOSE)
if(!(src_object in contents))
. = STATUS_CLOSE
. = STATUS_CLOSE
+2 -2
View File
@@ -2,9 +2,10 @@
name = "Crew monitor"
/datum/nano_module/crew_monitor/Topic(href, href_list)
if(..())
if(..())
return 1
var/turf/T = get_turf(nano_host())
// TODO: Tie into space manager
if(!T || !(T.z in config.player_levels))
to_chat(usr, "<span class='warning'>Unable to establish a connection<span>: You're too far away from the station!")
return 0
@@ -38,4 +39,3 @@
// should make the UI auto-update; doesn't seem to?
ui.set_auto_update(1)
+2 -1
View File
@@ -316,6 +316,7 @@
if(shuttle_master.supply.mode == SHUTTLE_CALL)
supplyData["shuttle_moving"] = 1
// TODO: Tie into space manager
if(shuttle_master.supply.z != ZLEVEL_STATION)
supplyData["shuttle_loc"] = "station"
else
@@ -418,4 +419,4 @@
JaniData["buckets"] = BucketData
JaniData["cleanbots"] = CbotData
JaniData["carts"] = CartData
data["janitor"] = JaniData
data["janitor"] = JaniData
+2 -1
View File
@@ -158,6 +158,7 @@
if(signal.data["done"])
useTC = 1
var/turf/pos = get_turf(P)
// TODO: Tie into space manager
if(pos.z in signal.data["level"])
useTC = 2
//Let's make this barely readable
@@ -211,4 +212,4 @@
return plist
/datum/data/pda/app/messenger/proc/can_receive()
return pda.owner && !toff && !hidden
return pda.owner && !toff && !hidden
+6
View File
@@ -170,6 +170,7 @@
apcs -= src
if(malfai && operating)
if(ticker.mode.config_tag == "malfunction")
// TODO: Tie into space manager
if(src.z == ZLEVEL_STATION)
ticker.mode:apcs--
area.power_light = 0
@@ -995,6 +996,7 @@
malfai.malfhacking = 0
locked = 1
if(ticker.mode.config_tag == "malfunction")
// TODO: Tie into space manager
if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs++
if(usr:parent)
@@ -1027,6 +1029,7 @@
if(malfai)
if(ticker.mode.config_tag == "malfunction")
// TODO: Tie into space manager
if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas))
operating ? ticker.mode:apcs++ : ticker.mode:apcs--
@@ -1042,6 +1045,7 @@
if(!malf.can_shunt)
to_chat(malf, "<span class='warning'>You cannot shunt.</span>")
return
// TODO: Tie into space manager
if(!(src.z in config.station_levels))
return
src.occupier = new /mob/living/silicon/ai(src,malf.laws,null,1)
@@ -1091,6 +1095,7 @@
/obj/machinery/power/apc/proc/ion_act()
//intended to be exactly the same as an AI malf attack
// TODO: Tie into space manager
if(!src.malfhack && (src.z in config.station_levels))
if(prob(3))
src.locked = 1
@@ -1366,6 +1371,7 @@
/obj/machinery/power/apc/proc/set_broken()
if(malfai && operating)
if(ticker.mode.config_tag == "malfunction")
// TODO: Tie into space manager
if((src.z in config.station_levels)) //if(is_type_in_list(get_area(src), the_station_areas))
ticker.mode:apcs--
stat |= BROKEN
+5
View File
@@ -124,6 +124,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
O.main_part = null
qdel(O)
for(var/area/A in world)
// TODO: Tie into space manager
if(!(A.z in config.station_levels)) continue
A.gravitychange(0,A)
shake_everyone()
@@ -301,6 +302,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
message_admins("The gravity generator was brought online. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
for(var/area/A in world)
// TODO: Tie into space manager
if(!(A.z in config.station_levels)) continue
A.gravitychange(1,A)
else
@@ -309,6 +311,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
message_admins("The gravity generator was brought offline with no backup generator. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
for(var/area/A in world)
// TODO: Tie into space manager
if(!(A.z in config.station_levels)) continue
A.gravitychange(0,A)
@@ -377,6 +380,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
shake_camera(M, 15, 1)
M.playsound_local(our_turf, 'sound/effects/alert.ogg', 100, 1, 0.5)
// TODO: Tie into space manager
/obj/machinery/gravity_generator/main/proc/gravity_in_level()
var/turf/T = get_turf(src)
if(!T)
@@ -385,6 +389,7 @@ var/const/GRAV_NEEDS_WRENCH = 3
return length(gravity_generators["[T.z]"])
return 0
// TODO: Tie into space manager
/obj/machinery/gravity_generator/main/proc/update_list()
var/turf/T = get_turf(src.loc)
if(T)
+1
View File
@@ -433,6 +433,7 @@
return 1
/obj/machinery/power/smes/proc/ion_act()
// TODO: Tie into space manager
if(src.z in config.station_levels)
if(prob(1)) //explosion
for(var/mob/M in viewers(src))
@@ -23,7 +23,8 @@
var/turf/T = get_turf(R)
if(!T)
continue
if((T.z in config.admin_levels) || T.z > 7)
// TODO: Tie into space manager
if((T.z in config.admin_levels) || T.z > ZLEVEL_EMPTY)
continue
if(R.syndicate == 1)
continue
@@ -37,6 +37,7 @@
CC.post_status("alert", "outline")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
@@ -53,6 +54,7 @@
CC.post_status("alert", "outline")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
@@ -65,6 +67,7 @@
security_level = SEC_LEVEL_RED
var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
// TODO: Tie into space manager
if(R && (R.z in config.station_levels))
R.locked = 0
R.update_icon()
@@ -74,6 +77,7 @@
CC.post_status("alert", "redalert")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
@@ -86,11 +90,13 @@
if(security_level < SEC_LEVEL_RED)
for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
// TODO: Tie into space manager
if((R.z in config.station_levels))
R.locked = 0
R.update_icon()
for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
// TODO: Tie into space manager
if((H.z in config.station_levels))
H.locked = 0
H.update_icon()
@@ -100,6 +106,7 @@
CC.post_status("alert", "gammaalert")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
@@ -114,6 +121,7 @@
CC.post_status("alert", "epsilonalert")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
@@ -127,6 +135,7 @@
CC.post_status("alert", "deltaalert")
for(var/obj/machinery/firealarm/FA in world)
// TODO: Tie into space manager
if((FA.z in config.contact_levels))
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
@@ -189,4 +198,4 @@
set_security_level(2)
/mob/verb/set_thing3()
set_security_level(3)
*/
*/
+1
View File
@@ -6,6 +6,7 @@
height = 7
/obj/docking_port/mobile/assault_pod/request()
// TODO: Tie into space manager
if(z == initial(src.z)) //No launching pods that have already launched
return ..()
+1
View File
@@ -202,6 +202,7 @@
if(time_left <= 0 && !shuttle_master.emergencyNoEscape)
//move each escape pod to its corresponding transit dock
for(var/obj/docking_port/mobile/pod/M in shuttle_master.mobile)
// TODO: Tie into space manager
if(M.z == ZLEVEL_STATION) //Will not launch from the mine/planet
M.enterTransit()
//now move the actual emergency shuttle to its transit dock
@@ -0,0 +1,15 @@
// This represents a level we can carve up as we please, and hand out
// chunks of to whatever requests it
/datum/space_level/heap
var/datum/space_chunk/top
linkage = UNAFFECTED
/datum/space_level/heap/New()
..()
top = new
/datum/space_level/heap/proc/request(width, height)
return 1 // All are welcome! At least until I add code for this
/datum/zlevel/heap/proc/allocate(width, height)
return
@@ -0,0 +1,24 @@
/datum/space_chunk
var/x
var/y
var/width
var/height
var/zpos
/datum/space_chunk/New(w, h, z, new_x, new_y)
x = new_x
y = new_y
zpos = z
width = w
height = h
/datum/space_chunk/proc/check_sanity()
var/i_am_sane = 1
i_am_sane |= (x > 0)
i_am_sane |= (y > 0)
i_am_sane |= (x <= world.maxx)
i_am_sane |= (y <= world.maxy)
return i_am_sane
/datum/space_chunk/proc/return_turfs()
return
@@ -0,0 +1,125 @@
/datum/space_level
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
var/zpos = 1
var/flags = 0 // We'll use this to keep track of whether you can teleport/etc
// Map transition stuff
var/list/neighbors = list()
// # How this level connects with others. See __MAP_DEFINES.dm for defines
var/linkage = SELFLOOPING
// # imaginary placements on the grid - these reflect the point it is linked to
var/xi
var/yi
var/list/transit_north = list()
var/list/transit_south = list()
var/list/transit_east = list()
var/list/transit_west = list()
// Init deferral stuff
var/dirt_count = 0
var/list/init_list = list()
/datum/space_level/New(z, name, transition_type = SELFLOOPING)
zpos = z
set_linkage(transition_type)
build_space_destination_arrays()
/datum/space_level/proc/build_space_destination_arrays()
var/timer = start_watch()
log_debug("Starting to build space destination arrays for z level '[zpos]'...")
for(var/turf/space/S in get_turfs())
// Bottom border
if(S.y <= TRANSITIONEDGE)
transit_south |= S
continue
// Top border
if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
transit_north |= S
continue
// Left border
if(S.x <= TRANSITIONEDGE)
transit_west |= S
continue
// Right border
if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
transit_east |= S
continue
log_debug("Building space destination arrays complete, took [stop_watch(timer)]s.")
/datum/space_level/proc/get_turfs()
return block(locate(1, 1, zpos), locate(world.maxx, world.maxy, zpos))
/datum/space_level/proc/set_linkage(transition_type)
linkage = transition_type
if(transition_type == SELFLOOPING)
link_to_self() // `link_to_self` is defined in space_transitions.dm
/datum/space_level/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/space_level/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/space_level/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/space_level/proc/do_late_maps(list/late_maps)
var/watch = start_watch()
log_debug("Loading map templates on z-level '[zpos]'!")
space_manager.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()
space_manager.remove_dirt(zpos)
log_debug("Took [stop_watch(watch)]s")
@@ -0,0 +1,412 @@
//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube
#define Z_LEVEL_NORTH "1"
#define Z_LEVEL_SOUTH "2"
#define Z_LEVEL_EAST "4"
#define Z_LEVEL_WEST "8"
/proc/get_opposite_direction(direction)
switch(direction)
if(Z_LEVEL_NORTH)
return Z_LEVEL_SOUTH
if(Z_LEVEL_SOUTH)
return Z_LEVEL_NORTH
if(Z_LEVEL_EAST)
return Z_LEVEL_WEST
if(Z_LEVEL_WEST)
return Z_LEVEL_EAST
/datum/space_level
var/list/direction_cache = list()
/datum/space_level/proc/link_to_self()
neighbors = list()
var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST)
for(var/A in L)
neighbors[A] = src
// This proc takes another space level, and establishes a connection between the
// two depending on how the `xi` and the `yi` values compare
/datum/space_level/proc/link_levels(datum/space_level/S)
if(S.xi == xi)
if(S.yi == yi+1)
add_connection(S, Z_LEVEL_NORTH)
else if(S.yi == yi-1)
add_connection(S, Z_LEVEL_SOUTH)
else if(S.yi == yi)
if(S.xi == xi+1)
add_connection(S, Z_LEVEL_EAST)
else if(S.xi == xi-1)
add_connection(S, Z_LEVEL_WEST)
else // yell about evil wizards, this shouldn't happen
log_debug("Two z levels attempted to link, but were not adjacent! Our z:([xi],[yi]). Other z:([S.xi],[S.yi])")
// Do this before setting up new connections, or the old ones will haunt you
/datum/space_level/proc/reset_connections()
neighbors.Cut()
direction_cache.Cut()
// `direction` here is the direction from `src` to `S`
/datum/space_level/proc/add_connection(datum/space_level/S, direction)
var/oppose = get_opposite_direction(direction)
neighbors[direction] = S
S.neighbors[oppose] = src
// The "direction cache" will need updating if a
/datum/space_level/proc/get_connection(direction)
if(direction in neighbors)
return neighbors[direction]
var/use_direction_cache = 0
if(use_direction_cache)
if(direction in direction_cache)
return direction_cache[direction]
// It's in a direction that loops - so we step as far in the opposite direction to get where to wrap to
var/datum/space_level/S = src
var/oppose = get_opposite_direction(direction)
// Loop all the way in the other direction that we can
while(S.neighbors[oppose])
if(S.neighbors[oppose] == src) // we've got a tesseract, boys
CRASH("Tesseract formed when routing connections between z levels. Culprit: z level '[S.zpos]' to '[src.zpos]', direction [oppose]")
S = S.neighbors[oppose]
if(use_direction_cache)
direction_cache[direction] = S
return S
/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else
var/list/neighbors = list()
var/x
var/y
var/datum/space_level/spl
/datum/point/New(nx, ny)
x = nx
y = ny
/datum/point/proc/hash()
return "([x],[y])"
// This is called only on `filled_nodes` - meaning we have a guarantee that
// it is already surrounded on all sides
/datum/point/proc/set_neighbors(datum/spacewalk_grid/SW)
neighbors.Cut()
neighbors |= SW.get(x+1, y, allow_empty = 1)
neighbors |= SW.get(x-1, y, allow_empty = 1)
neighbors |= SW.get(x, y+1, allow_empty = 1)
neighbors |= SW.get(x, y-1, allow_empty = 1)
// Updates variables of the space level
/datum/point/proc/set_space_level(datum/space_level/S)
spl = S
S.xi = x
S.yi = y
for(var/datum/point/P in neighbors)
if(istype(P.spl))
// Since each time this proc is called, it is the first time
// that the z level is added to the grid, we know for certain
// that no other z level has this as its neighbor
spl.link_levels(P.spl)
// Returns a list of all neighbors that don't have a space level yet
// If a node doesn't exist yet, it will create it
// This is only called for nodes within the `available_nodes` list
/datum/point/proc/get_empty_neighbors(datum/spacewalk_grid/SW)
var/list/result
var/datum/point/up = SW.get(x, y+1, allow_empty = 1)
var/datum/point/down = SW.get(x, y-1, allow_empty = 1)
var/datum/point/left = SW.get(x-1, y, allow_empty = 1)
var/datum/point/right = SW.get(x+1, y, allow_empty = 1)
if(isnull(up))
up = new(x, y+1)
SW.add_available_node(up)
if(isnull(down))
down = new(x, y-1)
SW.add_available_node(down)
if(isnull(left))
left = new(x-1, y)
SW.add_available_node(left)
if(isnull(right))
right = new(x+1, y)
SW.add_available_node(right)
// Nodes with a space datum are not empty
result = list(up, down, left, right)
for(var/datum/point/thing in result)
if(!isnull(thing.spl))
result -= thing
return result
// This looks around itself to see if it has any active nodes within the cardinal directions
/datum/point/proc/has_no_neighbors(datum/spacewalk_grid/SW)
var/result = 1
if(spl)
return 1
if(!isnull(SW.get(x+1,y)))
result = 0
if(!isnull(SW.get(x-1,y)))
result = 0
if(!isnull(SW.get(x,y+1)))
result = 0
if(!isnull(SW.get(x,y-1)))
result = 0
return result
/datum/point/proc/deactivate()
if(!spl)
throw EXCEPTION("Attempted to deactivate inactive point")
for(var/direction in spl.neighbors)
var/datum/space_level/S = spl.neighbors[direction]
var/oppose = get_opposite_direction(direction)
S.neighbors.Remove(oppose)
spl.reset_connections()
spl = initial(spl)
// This is like the old algorithm, except this one
// can expand indefinitely and add new points on the fly
// The algorithm is: Start in the center, and add all adjacent points to a list of things to select
// Then repeatedly do the cycle of choosing a node next to any previously-selected node, then
// add all points next to your chosen node to the list of things to select
/datum/spacewalk_grid
// This is a list of fully initialized nodes - these have their neighbors
// assigned, and are surrounded
var/list/filled_nodes = list()
// These nodes are not fully initialized - their neighbors field is empty,
// and they do not correspond to a space level
var/list/available_nodes = list()
var/list/all_nodes = list() // filled_nodes | available_nodes
var/min_x = 0
var/min_y = 0
var/max_x = 0
var/max_y = 0
/datum/spacewalk_grid/New()
var/datum/point/P = new(0,0)
add_available_node(P)
/datum/spacewalk_grid/proc/add_available_node(datum/point/P)
var/hash = P.hash()
if(hash in all_nodes)
log_debug("Hash overlap! [hash]")
all_nodes[P.hash()] = P
available_nodes |= P
// We call this to flag a node as in use - all required variables will be
// ready after this is called
/datum/spacewalk_grid/proc/consume_node(datum/point/P)
filled_nodes |= P
available_nodes -= P
// This proc adds any new neighbors to the list of available nodes
P.get_empty_neighbors(src)
if(min_x > P.x)
min_x = P.x
else if(max_x < P.x)
max_x = P.x
if(min_y > P.y)
min_y = P.y
else if(max_y < P.y)
max_y = P.y
P.set_neighbors(src)
// You can call this with an active point, to remove it from the grid -
// this is important if you want to separate a z level from the network
/datum/spacewalk_grid/proc/release_node(datum/point/P)
filled_nodes -= P
available_nodes |= P
// Go through each neighbor node, and delete it if it's not
// next to any other active nodes
for(var/datum/point/P2 in P.neighbors)
var/isolated = P2.has_no_neighbors(src)
if(isolated)
available_nodes -= P2
all_nodes -= P2.hash()
qdel(P)
P.deactivate()
P.neighbors.Cut()
// Now that we've cleaned out inactive nodes, we will update the bounds
var/datum/point/outer_bound
if(P.x == max_x)
for(var/i = min_y, i <= max_y, i++)
outer_bound = get(P.x, i)
if(!isnull(outer_bound)) // There is still an active node in this column
break
if(isnull(outer_bound))
max_x--
if(P.x == min_x)
for(var/i = min_y, i <= max_y, i++)
outer_bound = get(P.x, i)
if(!isnull(outer_bound)) // There is still an active node in this column
break
if(isnull(outer_bound))
min_x++
if(P.y == max_y)
for(var/i = min_x, i <= max_x, i++)
outer_bound = get(i, P.y)
if(!isnull(outer_bound)) // There is still an active node in this column
break
if(isnull(outer_bound))
max_y--
if(P.y == min_y)
for(var/i = min_x, i <= max_x, i++)
outer_bound = get(i, P.y)
if(!isnull(outer_bound)) // There is still an active node in this column
break
if(isnull(outer_bound))
min_y++
// If the node isn't in the grid, this will return null
/datum/spacewalk_grid/proc/get(x,y, allow_empty = 0)
var/datum/point/P = all_nodes["([x],[y])"]
if(!allow_empty && !(P in filled_nodes))
P = null // active nodes only
return P
/datum/spacewalk_grid/proc/get_width()
return 1 + max_x - min_x
/datum/spacewalk_grid/proc/get_height()
return 1 + max_y - min_y
// This function is called repeatedly to build the map
/datum/spacewalk_grid/proc/get_empty_node()
var/datum/point/P = pick(available_nodes)
if(isnull(P))
throw EXCEPTION("The `available_nodes` list was either empty or contained a null entry")
consume_node(P)
return P
// This proc substantiates the grid of points used to determine routes between levels
// Separating this from initialization gives us time in which we can add more crosslink z levels
// before we bake in all our connections
/datum/zlev_manager/proc/route_linkage()
var/list/crosslinks = list()
var/datum/space_level/D
for(var/A in z_list)
D = z_list[A]
if(D.linkage == CROSSLINKED)
crosslinks.Add(D)
D.reset_connections()
// We create an imaginary, square, grid, with dimensions that are
// twice the number of z levels, plus one, per side
// This is big enough to hold a straight line from the center to any side
// `point_grid` is indexed as a 2 way matrix of these points
// `grid` is a flat list of these same above points
// Each point represents a possible z level position
var/datum/spacewalk_grid/point_grid = new
// We do this so we can display the way the levels connect later
linkage_map = point_grid
var/datum/point/P
// Now, we pop entries in a random order from our list of space levels
// and assign its connections based on the grid
while(crosslinks.len)
D = pick(crosslinks)
crosslinks.Remove(D)
// We now choose a point in our imaginary grid adjacent to our current location
P = point_grid.get_empty_node()
// Let our z level know where in the imaginary grid it is
// This will also handle establishing neighborship with other z levels
P.set_space_level(D)
// A heavy proc - loops through all space turfs and sets its destination
// based on its space level's linkage
// Takes 0.6 seconds per call on my machine - could have each z level
// have its own space turf cache, but I don't want to complicate this more
// than is necessary
/datum/zlev_manager/proc/setup_space_destinations()
var/timer = start_watch()
log_debug("Assigning space turf destinations...")
var/datum/space_level/D
var/datum/space_level/E
var/turf/space/S
for(var/A in z_list) //Define the transistions of the z levels
D = z_list[A]
if(!D.neighbors.len)
continue
// Left border
for(var/B in D.transit_west)
S = B
E = D.get_connection(Z_LEVEL_WEST)
S.destination_z = E.zpos
S.destination_x = world.maxx - TRANSITIONEDGE - 2
S.destination_y = S.y
// Right border
for(var/B in D.transit_east)
S = B
E = D.get_connection(Z_LEVEL_EAST)
S.destination_x = TRANSITIONEDGE + 2
S.destination_y = S.y
S.destination_z = E.zpos
// Bottom border
for(var/B in D.transit_south)
S = B
E = D.get_connection(Z_LEVEL_SOUTH)
S.destination_x = S.x
S.destination_y = world.maxy - TRANSITIONEDGE - 2
S.destination_z = E.zpos
// Top border
for(var/B in D.transit_north)
S = B
E = D.get_connection(Z_LEVEL_NORTH)
S.destination_x = S.x
S.destination_y = TRANSITIONEDGE + 2
S.destination_z = E.zpos
log_debug("Assigning space turf destinations complete. Took [stop_watch(timer)]s.")
// Nothing fancy, just does it all at once
/datum/zlev_manager/proc/do_transition_setup()
route_linkage()
setup_space_destinations()
// A debugging proc that expresses the map's shape as a bunch of turfs
/datum/zlev_manager/proc/map_as_turfs(turf/center)
// size is odd
// -1, /2 to get distance from the center
// center - radius = bottom left coordinate
var/datum/point/P
var/turf/our_spot
var/grid_desc = ""
for(var/i = linkage_map.min_x, i <= linkage_map.max_x, i++)
for(var/j = linkage_map.min_y, j <= linkage_map.max_y, j++)
P = linkage_map.get(i, j)
our_spot = locate(center.x + i, center.y + j, center.z)
grid_desc = "([i],[j])"
if(!isnull(P))
our_spot = our_spot.ChangeTurf(/turf/simulated/floor/plating/snow)
grid_desc += ": Z level [P.spl.zpos]. "
var/datum/space_level/up = P.spl.get_connection(Z_LEVEL_NORTH)
var/datum/space_level/down = P.spl.get_connection(Z_LEVEL_SOUTH)
var/datum/space_level/right = P.spl.get_connection(Z_LEVEL_EAST)
var/datum/space_level/left = P.spl.get_connection(Z_LEVEL_WEST)
grid_desc += "Up: [up.zpos], "
grid_desc += "Down: [down.zpos], "
grid_desc += "Right: [right.zpos], "
grid_desc += "Left: [left.zpos]"
else
our_spot = our_spot.ChangeTurf(/turf/simulated/floor/fakespace)
our_spot.desc = grid_desc
#undef Z_LEVEL_NORTH
#undef Z_LEVEL_SOUTH
#undef Z_LEVEL_EAST
#undef Z_LEVEL_WEST
@@ -0,0 +1,131 @@
var/global/datum/zlev_manager/space_manager = new
/datum/zlev_manager
// A list of z-levels
var/list/z_list = list()
var/list/heaps = list()
var/datum/spacewalk_grid/linkage_map
// Populate our space level list
// and prepare space transitions
/datum/zlev_manager/proc/initialize()
var/num_official_z_levels = map_transition_config.len
var/k = 1
// First take care of "Official" z levels, without visiting levels outside of the list
for(var/A in map_transition_config)
// `A` is the name
// `map_transition_config[A]` is the transition type
z_list["[k]"] = new /datum/space_level(k, A, transition_type = map_transition_config[A])
if(k > world.maxz)
CRASH("More map transitions defined than existent z levels - [num_official_z_levels]")
k++
// Then, we take care of unmanaged z levels
// They get the default linkage of SELFLOOPING
for(var/i = k, i <= world.maxz, i++)
z_list["[i]"] = new /datum/space_level(i)
/datum/zlev_manager/proc/get_zlev(z)
if(!("[z]" in z_list))
throw EXCEPTION("Unmanaged z level: '[z]'")
else
return z_list["[z]"]
/*
* "Dirt" management
* "Dirt" is used to keep track of whether a z level should automatically have
* stuff on it initialize or not - If you're loading a map, place
* a freeze on the z levels it touches 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/space_level/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/space_level/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/space_level/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/space_level/our_z = get_zlev(z)
our_z.init_list.Add(thing)
/**
*
* SPACE ALLOCATION
*
*/
// 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("Anonymous Z level [world.maxz]")
// Increments the max z-level by one
// For convenience's sake returns the z-level added
/datum/zlev_manager/proc/add_new_zlevel(name, linkage = SELFLOOPING)
world.maxz++
var/our_z = world.maxz
z_list["[our_z]"] = new /datum/space_level(our_z,name, transition_type = linkage)
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
var/datum/space_level/S = get_zlev(our_z)
z_list.Remove(S)
qdel(S)
world.maxz--
// An internally-used proc used for heap-zlevel management
/datum/zlev_manager/proc/add_new_heap()
world.maxz++
var/our_z = world.maxz
var/datum/space_level/yup = new /datum/space_level/heap(our_z)
z_list["[our_z]"] = yup
return yup
// This is what you can call to allocate a section of space
// Later, I'll add an argument to let you define the flags on the region
/datum/zlev_manager/proc/allocate_space(width, height)
if(!heaps.len)
heaps.len++
heaps[heaps.len] = add_new_heap()
var/datum/space_level/heap/our_heap
for(our_heap in heaps)
var/weve_got_vacancy = our_heap.request(width, height)
if(weve_got_vacancy)
break // We're sticking with the present value of `our_heap` - it's got room
@@ -1,187 +0,0 @@
//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube
#define Z_LEVEL_NORTH "1"
#define Z_LEVEL_SOUTH "2"
#define Z_LEVEL_EAST "4"
#define Z_LEVEL_WEST "8"
var/list/z_levels_list = list()
/datum/space_level
var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
var/list/neigbours
var/z_value = 1 //actual z placement
var/linked = 1
var/xi
var/yi //imaginary placements on the grid
/datum/space_level/New()
neigbours = list()
var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST)
for(var/A in L)
neigbours[A] = src
/datum/space_level/proc/set_neigbours(list/L)
for(var/datum/point/P in L)
if(P.x == xi)
if(P.y == yi+1)
neigbours[Z_LEVEL_NORTH] = P.spl
P.spl.neigbours[Z_LEVEL_SOUTH] = src
else if(P.y == yi-1)
neigbours[Z_LEVEL_SOUTH] = P.spl
P.spl.neigbours[Z_LEVEL_NORTH] = src
else if(P.y == yi)
if(P.x == xi+1)
neigbours[Z_LEVEL_EAST] = P.spl
P.spl.neigbours[Z_LEVEL_WEST] = src
else if(P.x == xi-1)
neigbours[Z_LEVEL_WEST] = P.spl
P.spl.neigbours[Z_LEVEL_EAST] = src
/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else
var/list/neigbours = list()
var/x
var/y
var/datum/space_level/spl
/datum/point/New(nx, ny, list/point_grid)
if(!point_grid)
qdel(src)
return
var/list/L = point_grid[1]
if(nx > point_grid.len || ny > L.len)
qdel(src)
return
x = nx
y = ny
if(point_grid[x][y])
return
point_grid[x][y] = src
/datum/point/proc/set_neigbours(list/grid)
var/max_X = grid.len
var/list/max_Y = grid[1]
max_Y = max_Y.len
neigbours.Cut()
if(x+1 <= max_X)
neigbours |= grid[x+1][y]
if(x-1 >= 1)
neigbours |= grid[x-1][y]
if(y+1 <= max_Y)
neigbours |= grid[x][y+1]
if(y-1 >= 1)
neigbours |= grid[x][y-1]
//config/space_levels.txt is where you define your zlevel datum names, their connection to actual z levels and if you want them connected to one another or not
//Grammar: Name;z value;linked/unlinked
//Name is the name of the datum, just for the sake of it
//z value is to what actual map z level this datum is pointing
//linked/unlinked decide if you want the z level in the general map or not, for example centcomm is not reachable
//Each entry must be separated with a single empty line, no spaces outside the name
//No comments in the file allowed
/proc/setup_map_transitions() //listamania
var/list/SLS = file2list("config/space_levels.txt", "\n\n")
var/datum/space_level/D
var/list/config_settings[SLS.len][]
for(var/A in SLS)
config_settings[SLS.Find(A)] = splittext(A, ";")
var/conf_set_len = SLS.len
SLS.Cut()
for(var/A in config_settings)
D = new()
D.name = A[1]
D.z_value = text2num(A[2])
if(A[3] != "linked")
D.linked = 0
z_levels_list["[D.z_value]"] = D
else
SLS.Add(D)
var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1]
var/list/grid = list()
var/datum/point/P
for(var/i = 1, i<=conf_set_len*2+1, i++)
for(var/j = 1, j<=conf_set_len*2+1, j++)
P = new/datum/point(i,j, point_grid)
point_grid[i][j] = P
grid.Add(P)
for(var/datum/point/pnt in grid)
pnt.set_neigbours(point_grid)
P = point_grid[conf_set_len][conf_set_len]
var/list/possible_points = list()
var/list/used_points = list()
grid.Cut()
while(SLS.len)
D = pick(SLS)
SLS.Remove(D)
D.xi = P.x
D.yi = P.y
P.spl = D
possible_points |= P.neigbours
used_points |= P
possible_points.Remove(used_points)
D.set_neigbours(used_points)
P = pick(possible_points)
grid["[D.z_value]"] = D
for(var/A in z_levels_list)
grid[A] = z_levels_list[A]
for(var/turf/space/S in world) //Define the transistions of the z levels
if(S.x <= TRANSITIONEDGE)
D = grid["[S.z]"]
if(D.neigbours[Z_LEVEL_WEST] != D)
D = D.neigbours[Z_LEVEL_WEST]
S.destination_z = D.z_value
else
while(D.neigbours[Z_LEVEL_EAST] != D)
D = D.neigbours[Z_LEVEL_EAST]
S.destination_z = D.z_value
S.destination_x = world.maxx - TRANSITIONEDGE - 2
S.destination_y = S.y
if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
D = grid["[S.z]"]
if(D.neigbours[Z_LEVEL_EAST] != D)
D = D.neigbours[Z_LEVEL_EAST]
S.destination_z = D.z_value
else
while(D.neigbours[Z_LEVEL_WEST] != D)
D = D.neigbours[Z_LEVEL_WEST]
S.destination_z = D.z_value
S.destination_x = TRANSITIONEDGE + 2
S.destination_y = S.y
if(S.y <= TRANSITIONEDGE)
D = grid["[S.z]"]
if(D.neigbours[Z_LEVEL_SOUTH] != D)
D = D.neigbours[Z_LEVEL_SOUTH]
S.destination_z = D.z_value
else
while(D.neigbours[Z_LEVEL_NORTH] != D)
D = D.neigbours[Z_LEVEL_NORTH]
S.destination_z = D.z_value
S.destination_x = S.x
S.destination_y = world.maxy - TRANSITIONEDGE - 2
if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
D = grid["[S.z]"]
if(D.neigbours[Z_LEVEL_NORTH] != D)
D = D.neigbours[Z_LEVEL_NORTH]
S.destination_z = D.z_value
else
while(D.neigbours[Z_LEVEL_SOUTH] != D)
D = D.neigbours[Z_LEVEL_SOUTH]
S.destination_z = D.z_value
S.destination_x = S.x
S.destination_y = TRANSITIONEDGE + 2
for(var/A in grid)
z_levels_list[A] = grid[A]
#undef Z_LEVEL_NORTH
#undef Z_LEVEL_SOUTH
#undef Z_LEVEL_EAST
#undef Z_LEVEL_WEST
-73
View File
@@ -1,73 +0,0 @@
/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")
@@ -1,89 +0,0 @@
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)
+2 -1
View File
@@ -48,6 +48,7 @@ var/global/datum/store/centcomm_store=new
/datum/store/proc/reconnect_database()
for(var/obj/machinery/computer/account_database/DB in world)
// TODO: Tie into space manager
if((DB.z in config.station_levels))
linked_db = DB
break
@@ -62,4 +63,4 @@ var/global/datum/store/centcomm_store=new
return 0
// Give them the item.
item.deliver(usr)
return 1
return 1
+2 -1
View File
@@ -22,6 +22,7 @@
qdel(src)
/obj/item/weapon/ore/bluespace_crystal/proc/blink_mob(var/mob/living/L)
// TODO: Tie into space manager
if(L.z in config.admin_levels)
src.visible_message("<span class=warning>[src]'s fragments begin rapidly vibrating and blink out of existence.<span>")
qdel(src)
@@ -59,4 +60,4 @@ var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/st
..()
recipes = bluespace_crystal_recipes
pixel_x = rand(0,4)-4
pixel_y = rand(0,4)-4
pixel_y = rand(0,4)-4