mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 03:25:49 +01:00
Merge pull request #5254 from Crazylemon64/space_allocation
Updates space transitions and integrates it with the space management module
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 doesn’t Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
|
||||
"Why doesn�t 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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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--
|
||||
|
||||
@@ -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")]!")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 doesn’t Santa have any children?\n\n<i>Because he only comes down the chimney.</i>")
|
||||
"Why doesn�t 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)
|
||||
|
||||
|
||||
@@ -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]"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user