Files
Aurora.3/code/modules/overmap/overmap_shuttle.dm
RustingWithYou 6957bc34f1 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
2024-04-19 21:56:26 +00:00

326 lines
13 KiB
Plaintext

/datum/shuttle/autodock/overmap
warmup_time = 10
var/range = 0 //how many overmap tiles can shuttle go, for picking destinations and returning.
var/fuel_consumption = 0 //Amount of moles of gas consumed per trip; If zero, then shuttle is magic and does not need fuel
var/list/obj/structure/fuel_port/fuel_ports //the fuel ports of the shuttle (but usually just one)
category = /datum/shuttle/autodock/overmap
/datum/shuttle/autodock/overmap/New(var/_name, var/obj/effect/shuttle_landmark/start_waypoint)
..(_name, start_waypoint)
refresh_fuel_ports_list()
for(var/area/A in shuttle_area) //If shuttles initialize after the blueprints, they won't set correctly so we do it here.
var/obj/item/blueprints/shuttle/blueprints = locate() in A
if(blueprints)
blueprints.set_valid_z_levels()
/datum/shuttle/autodock/overmap/proc/refresh_fuel_ports_list() //loop through all
fuel_ports = list()
for(var/area/A in shuttle_area)
for(var/obj/structure/fuel_port/fuel_port_in_area in A)
fuel_port_in_area.parent_shuttle = src
fuel_ports |= fuel_port_in_area
/datum/shuttle/autodock/overmap/fuel_check(var/check_only = FALSE) // "check_only" lets you check the fuel levels without using any.
if(!src.try_consume_fuel(check_only)) //insufficient fuel
for(var/area/A in shuttle_area)
for(var/mob/living/M in A)
M.show_message(SPAN_WARNING("You hear the shuttle engines sputter... perhaps it doesn't have enough fuel?"), 2,
SPAN_WARNING("The shuttle shakes but fails to take off."), 1)
return 0 //failure!
return 1 //sucess, continue with launch
/datum/shuttle/autodock/overmap/proc/can_go()
if(!next_location)
return FALSE
if(moving_status == SHUTTLE_INTRANSIT)
return FALSE //already going somewhere, current_location may be an intransit location instead of in a sector
return get_dist(waypoint_sector(current_location), waypoint_sector(next_location)) <= range
/datum/shuttle/autodock/overmap/can_launch()
return ..() && can_go()
/datum/shuttle/autodock/overmap/can_force()
return ..() && can_go()
/datum/shuttle/autodock/overmap/get_travel_time()
var/distance_mod = get_dist(waypoint_sector(current_location),waypoint_sector(next_location))
return move_time * (1 + distance_mod)
/datum/shuttle/autodock/overmap/proc/set_destination(var/obj/effect/shuttle_landmark/A)
if(A != current_location)
next_location = A
/datum/shuttle/autodock/overmap/proc/get_possible_destinations()
var/list/res = list()
for (var/obj/effect/overmap/visitable/S in range(get_turf(waypoint_sector(current_location)), range))
var/list/waypoints = S.get_waypoints(name)
for(var/obj/effect/shuttle_landmark/LZ in waypoints)
if(LZ.is_valid(src))
res["[waypoints[LZ]] - [LZ.name]"] = LZ
return res
/datum/shuttle/autodock/overmap/get_location_name()
if(moving_status == SHUTTLE_INTRANSIT)
return "In transit"
return "[waypoint_sector(current_location)] - [current_location]"
/datum/shuttle/autodock/overmap/get_destination_name()
if(!next_location)
return "None"
return "[waypoint_sector(next_location)] - [next_location]"
/datum/shuttle/autodock/overmap/proc/try_consume_fuel(var/check_only = FALSE) //returns 1 if sucessful, returns 0 if error (like insufficient fuel)
if(!fuel_consumption)
return 1 //shuttles with zero fuel consumption are magic and can always launch
if(!fuel_ports.len)
return 0 //Nowhere to get fuel from
var/list/obj/item/tank/fuel_tanks = list()
for(var/obj/structure/FP in fuel_ports) //loop through fuel ports and assemble list of all fuel tanks
var/obj/item/tank/FT = locate() in FP
if(FT)
fuel_tanks += FT
if(!fuel_tanks.len)
return 0 //can't launch if you have no fuel TANKS in the ports
var/total_flammable_gas_moles = 0
for(var/obj/item/tank/FT in fuel_tanks)
total_flammable_gas_moles += FT.air_contents.get_by_flag(XGM_GAS_FUEL)
if(total_flammable_gas_moles < fuel_consumption) //not enough fuel
return 0
// We are going to succeed if we got to here, so start consuming that fuel
var/fuel_to_consume = fuel_consumption
for(var/obj/item/tank/FT in fuel_tanks) //loop through tanks, consume their fuel one by one
var/fuel_available = FT.air_contents.get_by_flag(XGM_GAS_FUEL)
if(!fuel_available) // Didn't even have fuel.
continue
if(check_only)
return 1
if(fuel_available >= fuel_to_consume)
FT.remove_air_by_flag(XGM_GAS_FUEL, fuel_to_consume)
return 1 //ALL REQUIRED FUEL HAS BEEN CONSUMED, GO FOR LAUNCH!
else //this tank doesn't have enough to launch shuttle by itself, so remove all its fuel, then continue loop
fuel_to_consume -= fuel_available
FT.remove_air_by_flag(XGM_GAS_FUEL, fuel_available)
/datum/shuttle/autodock/overmap/on_move_interim()
..()
for(var/obj/machinery/computer/shuttle_control/explore/E in shuttle_computers)
var/obj/effect/overmap/visitable/ship/S = E.connected
if(S)
S.halt()
S.unhalt()
#define FUEL_PORT_UNSECURED 0
#define FUEL_PORT_BOLTED 1
#define FUEL_PORT_WELDED 2
/obj/structure/fuel_port //empty
name = "fuel port"
desc = "The fuel input port of the shuttle. Holds one fuel tank. Use a crowbar to open and close it."
desc_info = "The fuel port must be wrenched and welded in place before it can be loaded and used by the shuttle."
icon = 'icons/turf/shuttle.dmi'
icon_state = "fuel_port"
density = 0
anchored = 1
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
var/state = FUEL_PORT_WELDED
var/icon_closed = "fuel_port"
var/icon_empty = "fuel_port_empty"
var/icon_full = "fuel_port_full"
var/opened = 0
var/parent_shuttle
var/port_item_path = /obj/item/fuel_port
/obj/structure/fuel_port/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
. = ..()
switch(state)
if(FUEL_PORT_UNSECURED)
. += SPAN_NOTICE("\The [src] is in place, but not attached to anything.")
if(FUEL_PORT_BOLTED)
. += SPAN_NOTICE("\The [src]'s external reinforcing bolts are deployed and locked.")
if(FUEL_PORT_WELDED)
. += SPAN_NOTICE("\The [src] is bolted and welded in place.")
/obj/structure/fuel_port/Initialize(mapload, var/placement_dir, var/constructed)
. = ..()
switch(placement_dir)
if(NORTH)
pixel_y = 32
if(SOUTH)
pixel_y = -32
if(EAST)
pixel_x = 32
if(WEST)
pixel_x = -32
if(constructed)
state = FUEL_PORT_UNSECURED
update_shuttle()
/obj/structure/fuel_port/New(loc, var/placement_dir, var/constructed = FALSE)
. = ..()
/obj/structure/fuel_port/Destroy()
update_shuttle()
return ..()
/obj/structure/fuel_port/attack_hand(mob/user)
if(state == FUEL_PORT_UNSECURED)
to_chat(user, SPAN_NOTICE("You remove \the [src] from its position."))
var/obj/item/fuel_port/P = new port_item_path(user.loc)
user.put_in_active_hand(P)
qdel(src)
else if(!opened)
to_chat(user, SPAN_WARNING("\The [src] is secured tightly. You'll need to pry it open with a crowbar."))
return
else if(contents.len > 0)
user.put_in_hands(contents[1])
update_icon()
/obj/structure/fuel_port/update_icon()
. = ..()
if(opened)
if(contents.len > 0)
icon_state = icon_full
else
icon_state = icon_empty
else
icon_state = icon_closed
/obj/structure/fuel_port/attackby(obj/item/attacking_item, mob/user)
if(attacking_item.iscrowbar())
if(state != FUEL_PORT_WELDED)
to_chat(user, SPAN_WARNING("\The [src] must be bolted and welded in place before it can be opened!"))
return
else if(opened)
to_chat(user, SPAN_NOTICE("You close \the [src]."))
playsound(src.loc, 'sound/effects/closet_close.ogg', 25, 0, -3)
opened = 0
else
to_chat(user, SPAN_NOTICE("You pry \the [src] open."))
playsound(src.loc, 'sound/effects/closet_open.ogg', 15, 1, -3)
opened = 1
else if(istype(attacking_item, /obj/item/tank))
if(state != FUEL_PORT_WELDED)
to_chat(user, SPAN_WARNING("\The [src] must be welded in place before a new tank can be added!"))
return
if(!opened)
to_chat(user, SPAN_NOTICE("\The [src] isn't open!"))
return
if(contents.len == 0)
user.unEquip(attacking_item, TRUE, src)
else if(attacking_item.iswrench())
switch(state)
if(FUEL_PORT_WELDED)
to_chat(user, SPAN_WARNING("\The [src] is welded in place!"))
return
if(FUEL_PORT_BOLTED)
attacking_item.play_tool_sound(get_turf(src), 75)
user.visible_message(SPAN_NOTICE("\The [user] unsecures \the [src]'s reinforcing bolts from the wall."), \
SPAN_NOTICE("You undo \the [src]'s external reinforcing bolts."), \
SPAN_WARNING("You hear a ratcheting noise."))
state = FUEL_PORT_UNSECURED
if(FUEL_PORT_UNSECURED)
attacking_item.play_tool_sound(get_turf(src), 75)
user.visible_message(SPAN_NOTICE("\The [user] secures \the [src] to the wall."), \
SPAN_NOTICE("You secure \the [src]'s external reinforcing bolts."), \
SPAN_WARNING("You hear a ratcheting noise."))
state = FUEL_PORT_BOLTED
else if(attacking_item.iswelder())
var/obj/item/weldingtool/WT = attacking_item
switch(state)
if(FUEL_PORT_UNSECURED)
to_chat(user, SPAN_WARNING("\The [src]'s external reinforcing bolts must be secured!"))
return
if(FUEL_PORT_BOLTED)
if(WT.use(5, user))
playsound(get_turf(src), 'sound/items/welder_pry.ogg', 50, TRUE)
user.visible_message(SPAN_NOTICE("\The [user] starts to weld \the [src] to the wall."), \
SPAN_NOTICE("You start to weld \the [src] to the wall."), \
SPAN_WARNING("You hear the sound of metal being welded."))
if(attacking_item.use_tool(src, user, 20, volume = 50))
if(!src || !WT.isOn())
return
state = FUEL_PORT_WELDED
to_chat(user, SPAN_NOTICE("You weld \the [src] to the wall."))
else
to_chat(user, SPAN_WARNING("You need more welding fuel to complete this task."))
if(FUEL_PORT_WELDED)
if(contents.len > 0)
to_chat(user, SPAN_WARNING("\The [src] cannot be detached with a tank inside!"))
return
if(WT.use(0, user))
playsound(get_turf(src), 'sound/items/welder_pry.ogg', 50, TRUE)
user.visible_message(SPAN_NOTICE("\The [user] starts to cut \the [src] free from the wall."), \
SPAN_NOTICE("You start to cut \the [src] free from the wall."), \
SPAN_WARNING("You hear the sound of metal being welded."))
if(attacking_item.use_tool(src, user, 20, volume = 50))
if(!src || !WT.isOn())
return
state = FUEL_PORT_BOLTED
to_chat(user, SPAN_NOTICE("You cut \the [src] free from the wall."))
else
to_chat(user, SPAN_WARNING("You need more welding fuel to complete this task."))
update_icon()
/obj/structure/fuel_port/proc/update_shuttle()
var/area/A = get_area(src)
if(A in SSshuttle.shuttle_areas) //Check if we're in a shuttle and refresh its fuel ports
for(var/shuttle_tag in SSshuttle.shuttles)
var/datum/shuttle/autodock/overmap/S = SSshuttle.shuttles[shuttle_tag]
if(istype(S) && (A in S.shuttle_area))
S.refresh_fuel_ports_list()
// Walls hide stuff inside them, but we want to be visible.
/obj/structure/fuel_port/hide()
return
/obj/structure/fuel_port/phoron // The best and most expensive fuel. Likely to be in the hands of corporate forces, though the well-off along with military forces throughout the Spur also have a good chance of using it.
/obj/structure/fuel_port/phoron/scc
icon = 'icons/obj/spaceship/scc/ship_engine.dmi'
/obj/structure/fuel_port/phoron/Initialize()
. = ..()
new /obj/item/tank/phoron/shuttle(src)
/obj/structure/fuel_port/hydrogen // The most common and serviceable fuel for a shuttle. It's not as good as phoron, but it will still get you places. It's also not scarce! Used by practically everyone.
/obj/structure/fuel_port/hydrogen/Initialize()
. = ..()
new /obj/item/tank/hydrogen/shuttle(src)
/obj/item/fuel_port
name = "fuel port"
desc = "The fuel input port of the shuttle. Must be attached to a wall."
icon = 'icons/turf/shuttle.dmi'
icon_state = "fuel_port"
item_state = "fuel_port"
var/port_path = /obj/structure/fuel_port
/obj/item/fuel_port/afterattack(atom/A, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return
if(use_check_and_message(user))
return
if(!iswall(A) || !isturf(user.loc))
to_chat(user, SPAN_WARNING("You can't place this here!"))
return
if(get_area(A) != get_area(user)) //To make sure that we don't get fuel ports attached outside the shuttle area, etc
to_chat(user, SPAN_WARNING("You must be in the same area as the target location to attach \the [src]!"))
return
var/placement_dir = get_dir(user, A)
if (!(placement_dir in GLOB.cardinal))
to_chat(user, SPAN_WARNING("You must stand directly in front of the location you wish to place that on."))
return
user.visible_message(SPAN_NOTICE("\The [user] fastens \the [src] to \the [A]."), SPAN_NOTICE("You fasten \the [src] to \the [A]."))
user.drop_from_inventory(src)
new port_path(user.loc, placement_dir, TRUE)
qdel(src)
#undef FUEL_PORT_UNSECURED
#undef FUEL_PORT_BOLTED
#undef FUEL_PORT_WELDED
#undef waypoint_sector