Blueprints Rework (#18947)

Reworks blueprints to use an eye component for area selection and
changing. Blueprints will now work on whichever overmap site they spawn
on if overmap is enabled, though currently they have only been added to
the Horizon.

Adds shuttle-modifying blueprints for altering shuttle areas and
exoplanet outpost blueprints for creating areas on exoplanets. A set of
outpost blueprints and a lockbox containing blueprints for the Horizon's
shuttles have been added to the CE's locker.

Moves eye creation to a component.

Ported from:
https://github.com/NebulaSS13/Nebula/pull/465
https://github.com/NebulaSS13/Nebula/pull/564
https://github.com/NebulaSS13/Nebula/pull/3046
This commit is contained in:
RustingWithYou
2024-04-19 21:56:26 +00:00
committed by GitHub
parent ab23fbdb70
commit 6957bc34f1
29 changed files with 810 additions and 302 deletions
+133 -257
View File
@@ -1,275 +1,151 @@
/obj/item/blueprints
name = "station blueprints"
name = "blueprints"
desc = "Blueprints of the station. There is a \"Classified\" stamp and several coffee stains on it."
icon = 'icons/obj/items.dmi'
icon = 'icons/obj/item/tools/blueprints.dmi'
icon_state = "blueprints"
attack_verb = list("attacked", "bapped", "hit")
var/datum/wires/airlock/blueprint/airlock_wires
var/datum/wires/vending/blueprint/vending_wires
var/const/AREA_ERRNONE = 0
var/const/AREA_STATION = 1
var/const/AREA_SPACE = 2
var/const/AREA_SPECIAL = 3
var/const/BORDER_ERROR = 0
var/const/BORDER_NONE = 1
var/const/BORDER_BETWEEN = 2
var/const/BORDER_2NDTILE = 3
var/const/BORDER_SPACE = 4
var/const/ROOM_ERR_LOLWAT = 0
var/const/ROOM_ERR_SPACE = -1
var/const/ROOM_ERR_TOOLARGE = -2
var/list/active_blueprints
w_class = ITEMSIZE_SMALL
var/list/valid_z_levels = list()
var/area_prefix
/obj/item/blueprints/Initialize(mapload, ...)
. = ..()
airlock_wires = new(src)
vending_wires = new(src)
return INITIALIZE_HINT_LATELOAD
/obj/item/blueprints/LateInitialize()
. = ..()
desc = "Blueprints of the [station_name()]. There is a \"Classified\" stamp and several coffee stains on it."
if(set_valid_z_levels())
create_blueprint_component()
/obj/item/blueprints/attack_self(mob/user)
if(use_check_and_message(user, USE_DISALLOW_SILICONS))
return
add_fingerprint(user)
interact()
/obj/item/blueprints/equipped(var/mob/user, var/slot)
. = ..()
if(slot == slot_l_hand || slot == slot_r_hand)
START_PROCESSING(SSprocessing, src)
LAZYINITLIST(active_blueprints)
/obj/item/blueprints/dropped(mob/user)
. = ..()
STOP_PROCESSING(SSprocessing, src)
if(user.client)
for(var/thing in active_blueprints)
user.client.images -= thing
LAZYCLEARLIST(active_blueprints)
/obj/item/blueprints/process()
var/mob/user = loc
if(!istype(user))
return PROCESS_KILL
var/turf/origin_turf = get_turf(src)
var/list/new_prints = list()
for(var/turf/T as anything in RANGE_TURFS(world.view, origin_turf))
for(var/image/I as anything in T.blueprints)
new_prints += I
var/list/update_remove = active_blueprints - new_prints
active_blueprints = new_prints - update_remove
for(var/thing in update_remove)
user.client.images -= thing
for(var/thing in active_blueprints)
user.client.images += thing
/obj/item/blueprints/Topic(href, href_list)
..()
if(use_check_and_message(usr, USE_DISALLOW_SILICONS) || usr.get_active_hand() != src)
return
if(!href_list["action"])
add_fingerprint(user)
var/datum/component/eye/blueprints = GetComponent(/datum/component/eye)
if(!(user.z in valid_z_levels))
to_chat(user, SPAN_WARNING("The markings on this are entirely irrelevant to your whereabouts!"))
return
switch(href_list["action"])
if ("create_area")
if(get_area_type() != AREA_SPACE)
interact()
return
create_area()
if ("edit_area")
if (get_area_type()!=AREA_STATION)
interact()
return
edit_area()
if("airlock_wires")
airlock_wires.get_wire_diagram(usr)
if("vending_wires")
vending_wires.get_wire_diagram(usr)
if(blueprints)
if(blueprints.look(user, get_look_args())) // Abandon all peripheral vision, ye who enter here.
to_chat(user, SPAN_NOTICE("You start peering closely at \the [src]"))
return
else
to_chat(user, SPAN_WARNING("You couldn't get a good look at \the [src]. Maybe someone else is using it?"))
return
to_chat(user, SPAN_WARNING("The markings on this are useless!"))
/obj/item/blueprints/interact()
var/area/A = get_area(src)
var/text = {"<HTML><head><title>[src]</title></head><BODY>
<h2>[station_name()] blueprints</h2>
<small>Property of [SSatlas.current_map.company_name]. For heads of staff only. Store in high-secure storage.</small><hr>
"}
switch (get_area_type())
if (AREA_SPACE)
text += {"
<p>According the blueprints, you are now in <b>outer space</b>. Hold your breath.</p>
<p><a href='?src=\ref[src];action=create_area'>Mark this place as new area.</a></p>
"}
if (AREA_STATION)
text += {"
<p>According the blueprints, you are now in <b>\"[A.name]\"</b>.</p>
<p>You may <a href='?src=\ref[src];action=edit_area'>
move an amendment</a> to the drawing.</p>
"}
if (AREA_SPECIAL)
text += {"
<p>This place isn't noted on the blueprint.</p>
"}
/obj/item/blueprints/proc/set_valid_z_levels()
if(SSatlas.current_map.use_overmap)
var/obj/effect/overmap/visitable/sector/S = GLOB.map_sectors["[GET_Z(src)]"]
if(!S) //Blueprints are useless now, but keep them around for fluff
desc = "Some dusty old blueprints. The markings are old, and seem entirely irrelevant for your wherabouts."
return FALSE
name += " - [S.name]"
desc = "Blueprints of \the [S.name]. There is a \"Classified\" stamp and several coffee stains on it."
valid_z_levels += S.map_z
area_prefix = S.name
return TRUE
desc = "Blueprints of the [station_name()]. There is a \"Classified\" stamp and several coffee stains on it."
area_prefix = station_name()
valid_z_levels = SSatlas.current_map.station_levels
text += "<br><a href='?src=\ref[src];action=airlock_wires'>View Airlock Wire Schema</a><br>"
text += "<br><a href='?src=\ref[src];action=vending_wires'>View Vending Machine Wire Schema</a><br>"
/obj/item/blueprints/proc/create_blueprint_component() //So that subtypes can override
AddComponent(/datum/component/eye/blueprints)
text += "</BODY></HTML>"
/obj/item/blueprints/proc/get_look_args() // ditto
return list(valid_z_levels, area_prefix)
var/datum/browser/blueprints_win = new(usr, "blueprints", capitalize_first_letters(name))
blueprints_win.set_content(text)
blueprints_win.open()
//Blueprints for building exoplanet outposts
/obj/item/blueprints/outpost
name = "outpost blueprints"
icon_state = "blueprints2"
/obj/item/blueprints/proc/get_area_type(var/area/A = get_area(src))
if(istype(A, /area/space) || istype(A, /area/mine/unexplored))
return AREA_SPACE
var/list/SPECIALS = list(
/area/shuttle,
/area/centcom,
/area/tdome,
/area/antag
/obj/item/blueprints/outpost/attack_self(mob/user)
var/obj/effect/overmap/visitable/sector/S = GLOB.map_sectors["[GET_Z(user)]"]
area_prefix = S.name
. = ..()
/obj/item/blueprints/outpost/set_valid_z_levels()
if(!SSatlas.current_map.use_overmap)
desc = "Some dusty old blueprints. The markings are old, and seem entirely irrelevant for your wherabouts."
return FALSE
desc = "Blueprints for the daring souls wanting to establish a planetary outpost. Has some sketchy looking stains and what appears to be bite holes."
var/area/overmap/map = global.map_overmap
for(var/obj/effect/overmap/visitable/sector/exoplanet/E in map)
valid_z_levels += E.map_z
return TRUE
/obj/item/blueprints/shuttle
desc_info = "These blueprints can be used to modify a shuttle. In order to be used, the shuttle must be located on its \"Open Space\" z-level. Newly-created areas will be automatically added to the shuttle. If all shuttle areas are removed, the shuttle will be destroyed!"
///Name of the blueprints' linked shuttle. Mapped-in versions should have this preset, or be mapped into the shuttle area itself.
var/shuttle_name
///The actual overmap shuttle type, for setting on preset blueprints.
var/obj/effect/overmap/visitable/ship/landable/shuttle_type
/obj/item/blueprints/shuttle/set_valid_z_levels()
if(SSatlas.current_map.use_overmap)
var/area/A = get_area(src)
if(!shuttle_type)
for(var/obj/effect/overmap/visitable/ship/landable/landable in SSshuttle.ships)
var/datum/shuttle/shuttle = SSshuttle.shuttles[landable.shuttle]
if(shuttle && (A in shuttle.shuttle_area))
shuttle_type = landable
break
else
var/obj/effect/overmap/visitable/ship/landable/S = SSshuttle.ship_by_type(shuttle_type)
shuttle_type = S
if(istype(shuttle_type) && !isnull(shuttle_type))
if(isnull(shuttle_name))
shuttle_name = shuttle_type.shuttle
update_linked_name(shuttle_type, null, shuttle_type.name)
RegisterSignal(shuttle_type, COMSIG_QDELETING, PROC_REF(on_shuttle_destroy))
RegisterSignal(shuttle_type, COMSIG_BASENAME_SETNAME, PROC_REF(update_linked_name))
valid_z_levels += shuttle_type.map_z
area_prefix = shuttle_type.name
return TRUE
// The blueprints are useless now, but keep them around for fluff.
desc = "Some dusty old blueprints. The markings are old, and seem entirely irrelevant for your wherabouts."
return FALSE
/obj/item/blueprints/shuttle/proc/update_linked_name(atom/namee, old_name, new_name)
name = "\improper [new_name] blueprints"
desc = "Blueprints of \the [new_name]. There are several coffee stains on it."
area_prefix = new_name
/obj/item/blueprints/shuttle/proc/on_shuttle_destroy(datum/destroyed)
UnregisterSignal(destroyed, COMSIG_QDELETING)
UnregisterSignal(destroyed, COMSIG_BASENAME_SETNAME)
name = initial(name)
desc = "Some dusty old blueprints. The markings are old, and seem entirely irrelevant for your wherabouts."
valid_z_levels = list()
area_prefix = null
/obj/item/blueprints/shuttle/create_blueprint_component()
AddComponent(/datum/component/eye/blueprints/shuttle)
/obj/item/blueprints/shuttle/get_look_args()
return list(valid_z_levels, area_prefix, shuttle_name)
/obj/item/blueprints/shuttle/intrepid
shuttle_name = "Intrepid"
shuttle_type = /obj/effect/overmap/visitable/ship/landable/intrepid
/obj/item/blueprints/shuttle/mining_shuttle
shuttle_name = "Spark"
shuttle_type = /obj/effect/overmap/visitable/ship/landable/mining_shuttle
/obj/item/blueprints/shuttle/canary
shuttle_name = "Canary"
shuttle_type = /obj/effect/overmap/visitable/ship/landable/canary
/obj/item/storage/lockbox/shuttle_blueprints //Blueprints for modifying the Horizon's shuttles.
name = "shuttle blueprints lockbox"
req_access = list(ACCESS_CE)
starts_with = list(
/obj/item/blueprints/shuttle/intrepid = 1,
/obj/item/blueprints/shuttle/mining_shuttle = 1,
/obj/item/blueprints/shuttle/canary = 1
)
for (var/type in SPECIALS)
if ( istype(A,type) )
return AREA_SPECIAL
return AREA_STATION
/obj/item/blueprints/proc/create_area()
var/res = detect_room(get_turf(usr))
if(!istype(res,/list))
switch(res)
if(ROOM_ERR_SPACE)
to_chat(usr, "<span class='warning'>The new area must be completely airtight!</span>")
return
if(ROOM_ERR_TOOLARGE)
to_chat(usr, "<span class='warning'>The new area too large!</span>")
return
else
to_chat(usr, "<span class='warning'>Error! Please notify administration!</span>")
return
var/list/turf/turfs = res
var/str = sanitizeSafe(input("New area name:","Blueprint Editing", ""), MAX_NAME_LEN)
if(!str || !length(str)) //cancel
return
if(length(str) > 50)
to_chat(usr, "<span class='warning'>Name too long.</span>")
return
var/area/A = new
A.name = str
A.power_equip = 0
A.power_light = 0
A.power_environ = 0
A.always_unpowered = 0
move_turfs_to_area(turfs, A)
A.always_unpowered = 0
sorted_add_area(A)
addtimer(CALLBACK(src, PROC_REF(interact)), 5)
return
/obj/item/blueprints/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A)
A.contents.Add(turfs)
//oldarea.contents.Remove(usr.loc) // not needed
//T.forceMove(A) //error: cannot change constant value
/obj/item/blueprints/proc/edit_area()
var/area/A = get_area(src)
var/prevname = "[A.name]"
var/str = sanitizeSafe(input("New area name:","Blueprint Editing", prevname), MAX_NAME_LEN)
if(!str || !length(str) || str==prevname) //cancel
return
if(length(str) > 50)
to_chat(usr, "<span class='warning'>Text too long.</span>")
return
INVOKE_ASYNC(src, PROC_REF(set_area_machinery_title), A, str, prevname)
A.name = str
sortTim(GLOB.all_areas, GLOBAL_PROC_REF(cmp_text_asc))
to_chat(usr, "<span class='notice'>You set the area '[prevname]' title to '[str]'.</span>")
interact()
return
/obj/item/blueprints/proc/set_area_machinery_title(var/area/A,var/title,var/oldtitle)
if (!oldtitle) // or replacetext goes to infinite loop
return
var/static/list/types_to_rename = list(
/obj/machinery/alarm,
/obj/machinery/power/apc,
/obj/machinery/atmospherics/unary/vent_scrubber,
/obj/machinery/atmospherics/unary/vent_pump,
/obj/machinery/door
)
for(var/obj/machinery/M in A)
if (is_type_in_list(M, types_to_rename))
M.name = replacetext(M.name, oldtitle, title)
CHECK_TICK
/obj/item/blueprints/proc/check_tile_is_border(var/turf/T2,var/dir)
if (istype(T2, /turf/space) || istype(T2, /turf/unsimulated/floor/asteroid))
return BORDER_SPACE //omg hull breach we all going to die here
if (get_area_type(T2.loc)!=AREA_SPACE)
return BORDER_BETWEEN
if (istype(T2, /turf/simulated/wall))
return BORDER_2NDTILE
if (!istype(T2, /turf/simulated))
return BORDER_BETWEEN
for (var/obj/structure/window/W in T2)
if(turn(dir,180) == W.dir)
return BORDER_BETWEEN
if (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST))
return BORDER_2NDTILE
for(var/obj/machinery/door/window/D in T2)
if(turn(dir,180) == D.dir)
return BORDER_BETWEEN
if (locate(/obj/machinery/door) in T2)
return BORDER_2NDTILE
return BORDER_NONE
/obj/item/blueprints/proc/detect_room(var/turf/first)
var/list/turf/found = new
var/list/turf/pending = list(first)
while(pending.len)
if (found.len+pending.len > 300)
return ROOM_ERR_TOOLARGE
var/turf/T = pending[1] //why byond havent list::pop()?
pending -= T
for (var/dir in GLOB.cardinal)
var/skip = 0
for (var/obj/structure/window/W in T)
if(dir == W.dir || (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST)))
skip = 1; break
if (skip) continue
for(var/obj/machinery/door/window/D in T)
if(dir == D.dir)
skip = 1; break
if (skip) continue
var/turf/NT = get_step(T,dir)
if (!isturf(NT) || (NT in found) || (NT in pending))
continue
var/tile_is_border = check_tile_is_border(NT,dir)
if(tile_is_border != BORDER_BETWEEN)
switch(tile_is_border)
if(BORDER_NONE)
pending+=NT
if(BORDER_2NDTILE)
found+=NT //tile included to new area, but we dont seek more
if(BORDER_SPACE)
return ROOM_ERR_SPACE
found+=T
return found
@@ -29,6 +29,8 @@
new /obj/item/crowbar/rescue_axe/red(src)
new /obj/item/device/radio/eng/off(src)
new /obj/item/grenade/chem_grenade/antifuel(src)
new /obj/item/storage/lockbox/shuttle_blueprints(src)
new /obj/item/blueprints/outpost(src)
// Chief Engineer - Clothing Satchel
// This satchel is used nowhere except in conjunction with the locker above,