mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-18 13:04:45 +00:00
## About The Pull Request Adds an arg in huds' screens to add the hud owner in the Initialize, instead of manually setting it every time we need to. This is already done in ``New()`` for lobby screens, which I left intact as lobby screens are used for new players, and are given out before atoms are Initialized. Everything else, however, uses Initialize, so it does not mess with any other args in their own Initializes (like the Escape menu). This also allows us to set the screens' HUDs as a private var, to ensure this won't be messed with in the future. Lastly I replaced instances of ``client`` with ``cannon_client`` to be consistent with a lot of other parts of hud code. ## Why It's Good For The Game Huds are easy to break when they do not have a hud owner, and for something as important as that I believe it should be something you opt-out of when you don't want it, rather than something you opt-into by manually setting hud owner every time. This cuts down on a lot of copy paste in hud code for humans, aliens, etc. ## Changelog 🆑 refactor: Huds now have their hud owner set in Initialize /🆑
451 lines
15 KiB
Plaintext
451 lines
15 KiB
Plaintext
/// Station home gateway
|
|
GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
|
|
/// List of possible gateway destinations.
|
|
GLOBAL_LIST_EMPTY(gateway_destinations)
|
|
|
|
/**
|
|
* Corresponds to single entry in gateway control.
|
|
*
|
|
* Will NOT be added automatically to GLOB.gateway_destinations list.
|
|
*/
|
|
/datum/gateway_destination
|
|
var/name = "Unknown Destination"
|
|
var/wait = 0 /// How long after roundstart this destination becomes active
|
|
var/enabled = TRUE /// If disabled, the destination won't be available
|
|
var/hidden = FALSE /// Will not show on gateway controls at all.
|
|
|
|
/* Can a gateway link to this destination right now. */
|
|
/datum/gateway_destination/proc/is_available()
|
|
return enabled && (world.time - SSticker.round_start_time >= wait)
|
|
|
|
/* Returns user-friendly description why you can't connect to this destination, displayed in UI */
|
|
/datum/gateway_destination/proc/get_available_reason()
|
|
. = "Unreachable"
|
|
if(world.time - SSticker.round_start_time < wait)
|
|
. = "Connection desynchronized. Recalibration in progress."
|
|
|
|
/* Check if the movable is allowed to arrive at this destination (exile implants mostly) */
|
|
/datum/gateway_destination/proc/incoming_pass_check(atom/movable/AM)
|
|
return TRUE
|
|
|
|
/* Get the actual turf we'll arrive at */
|
|
/datum/gateway_destination/proc/get_target_turf()
|
|
CRASH("get target turf not implemented for this destination type")
|
|
|
|
/* Called after moving the movable to target turf */
|
|
/datum/gateway_destination/proc/post_transfer(atom/movable/AM)
|
|
if (ismob(AM))
|
|
var/mob/M = AM
|
|
if (M.client)
|
|
M.client.move_delay = max(world.time + 5, M.client.move_delay)
|
|
|
|
/* Called when gateway activates with this destination. */
|
|
/datum/gateway_destination/proc/activate(obj/machinery/gateway/activated)
|
|
return
|
|
|
|
/* Called when gateway targeting this destination deactivates. */
|
|
/datum/gateway_destination/proc/deactivate(obj/machinery/gateway/deactivated)
|
|
return
|
|
|
|
/* Returns data used by gateway controller ui */
|
|
/datum/gateway_destination/proc/get_ui_data()
|
|
. = list()
|
|
.["ref"] = REF(src)
|
|
.["name"] = name
|
|
.["available"] = is_available()
|
|
.["reason"] = get_available_reason()
|
|
if(wait)
|
|
.["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0)
|
|
|
|
/* Destination is another gateway */
|
|
/datum/gateway_destination/gateway
|
|
/// The gateway this destination points at
|
|
var/obj/machinery/gateway/target_gateway
|
|
|
|
/* We set the target gateway target to activator gateway */
|
|
/datum/gateway_destination/gateway/activate(obj/machinery/gateway/activated)
|
|
if(!target_gateway.target)
|
|
target_gateway.activate(activated)
|
|
|
|
/* We turn off the target gateway if it's linked with us */
|
|
/datum/gateway_destination/gateway/deactivate(obj/machinery/gateway/deactivated)
|
|
if(target_gateway.target == deactivated.destination)
|
|
target_gateway.deactivate()
|
|
|
|
/datum/gateway_destination/gateway/is_available()
|
|
return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered()
|
|
|
|
/datum/gateway_destination/gateway/get_available_reason()
|
|
. = ..()
|
|
if(!target_gateway.calibrated)
|
|
. = "Exit gateway malfunction. Manual recalibration required."
|
|
if(target_gateway.target)
|
|
. = "Exit gateway in use."
|
|
if(!target_gateway.powered())
|
|
. = "Exit gateway unpowered."
|
|
|
|
/datum/gateway_destination/gateway/get_target_turf()
|
|
return get_step(target_gateway.portal,SOUTH)
|
|
|
|
/datum/gateway_destination/gateway/post_transfer(atom/movable/AM)
|
|
. = ..()
|
|
addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, setDir),SOUTH),0)
|
|
|
|
/* Special home destination, so we can check exile implants */
|
|
/datum/gateway_destination/gateway/home
|
|
|
|
/datum/gateway_destination/gateway/home/incoming_pass_check(atom/movable/AM)
|
|
if(isliving(AM))
|
|
if(check_exile_implant(AM))
|
|
return FALSE
|
|
else
|
|
for(var/mob/living/L in AM.contents)
|
|
if(check_exile_implant(L))
|
|
target_gateway.say("Rejecting [AM]: Exile implant detected in contained lifeform.")
|
|
return FALSE
|
|
if(AM.has_buckled_mobs())
|
|
for(var/mob/living/L in AM.buckled_mobs)
|
|
if(check_exile_implant(L))
|
|
target_gateway.say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/datum/gateway_destination/gateway/home/proc/check_exile_implant(mob/living/L)
|
|
for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant
|
|
to_chat(L, span_userdanger("The station gate has detected your exile implant and is blocking your entry."))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
|
|
/* Destination is one ore more turfs - created by landmarks */
|
|
/datum/gateway_destination/point
|
|
var/list/target_turfs = list()
|
|
/// Used by away landmarks
|
|
var/id
|
|
|
|
/datum/gateway_destination/point/get_target_turf()
|
|
return pick(target_turfs)
|
|
|
|
/* Dense invisible object starting the teleportation. Created by gateways on activation. */
|
|
/obj/effect/gateway_portal_bumper
|
|
var/obj/machinery/gateway/gateway
|
|
density = TRUE
|
|
invisibility = INVISIBILITY_ABSTRACT
|
|
|
|
/obj/effect/gateway_portal_bumper/Bumped(atom/movable/AM)
|
|
if(get_dir(src,AM) == SOUTH)
|
|
gateway.Transfer(AM)
|
|
|
|
/obj/effect/gateway_portal_bumper/Destroy(force)
|
|
. = ..()
|
|
gateway = null
|
|
|
|
/obj/machinery/gateway
|
|
name = "gateway"
|
|
desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations."
|
|
icon = 'icons/obj/machines/gateway.dmi'
|
|
icon_state = "portal_frame"
|
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
|
|
|
// 3x2 offset by one row
|
|
pixel_x = -32
|
|
pixel_y = -32
|
|
bound_height = 64
|
|
bound_width = 96
|
|
bound_x = -32
|
|
bound_y = 0
|
|
density = TRUE
|
|
|
|
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 5
|
|
|
|
var/calibrated = TRUE
|
|
/// Type of instanced gateway destination, needs to be subtype of /datum/gateway_destination/gateway
|
|
var/destination_type = /datum/gateway_destination/gateway
|
|
/// Name of the generated destination
|
|
var/destination_name = "Unknown Gateway"
|
|
/// This is our own destination, pointing at this gateway
|
|
var/datum/gateway_destination/gateway/destination
|
|
/// This is current active destination
|
|
var/datum/gateway_destination/target
|
|
/// bumper object, the thing that starts actual teleport
|
|
var/obj/effect/gateway_portal_bumper/portal
|
|
/// Visual object for handling the viscontents
|
|
var/atom/movable/screen/map_view/gateway_port/portal_visuals
|
|
var/teleportion_possible = FALSE
|
|
var/transport_active = FALSE
|
|
|
|
/obj/machinery/gateway/Initialize(mapload)
|
|
generate_destination()
|
|
update_appearance()
|
|
portal_visuals = new
|
|
portal_visuals.generate_view("gateway_popup_[REF(src)]")
|
|
portal_visuals.update_portal_filters()
|
|
return ..()
|
|
|
|
/obj/machinery/gateway/Destroy()
|
|
QDEL_NULL(portal_visuals)
|
|
destination.target_gateway = null
|
|
GLOB.gateway_destinations -= destination
|
|
destination = null
|
|
return ..()
|
|
|
|
/obj/machinery/gateway/proc/generate_destination()
|
|
destination = new destination_type
|
|
destination.name = destination_name
|
|
destination.target_gateway = src
|
|
GLOB.gateway_destinations += destination
|
|
|
|
/obj/machinery/gateway/proc/deactivate()
|
|
var/datum/gateway_destination/dest = target
|
|
target = null
|
|
dest.deactivate(src)
|
|
QDEL_NULL(portal)
|
|
update_use_power(IDLE_POWER_USE)
|
|
transport_active = FALSE
|
|
update_appearance()
|
|
portal_visuals.reset_visuals()
|
|
|
|
/obj/machinery/gateway/process()
|
|
if((machine_stat & (NOPOWER)) && use_power)
|
|
teleportion_possible = FALSE
|
|
if(target)
|
|
deactivate()
|
|
return
|
|
if(teleportion_possible)
|
|
return
|
|
for(var/datum/gateway_destination/possible_destination as anything in GLOB.gateway_destinations)
|
|
if(!valid_destination(possible_destination) || !possible_destination.is_available())
|
|
continue
|
|
teleportion_possible = TRUE
|
|
update_appearance()
|
|
break
|
|
|
|
/obj/machinery/gateway/proc/valid_destination(datum/gateway_destination/possible_destination)
|
|
if(possible_destination == destination)
|
|
return FALSE
|
|
if(istype(possible_destination, /datum/gateway_destination/gateway))
|
|
var/datum/gateway_destination/gateway/gateway_dest = possible_destination
|
|
if(gateway_dest.target_gateway == src)
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/machinery/gateway/proc/show_light_overlays(light_state, toggle)
|
|
if(!toggle)
|
|
return list()
|
|
|
|
var/list/image/to_animate = list()
|
|
to_animate += image('icons/obj/machines/gateway.dmi', light_state)
|
|
var/image/glowing_light = image('icons/obj/machines/gateway.dmi', light_state)
|
|
glowing_light.color = GLOB.emissive_color
|
|
SET_PLANE_EXPLICIT(glowing_light, EMISSIVE_PLANE, src)
|
|
to_animate += glowing_light
|
|
return to_animate
|
|
|
|
/obj/machinery/gateway/update_overlays()
|
|
. = ..()
|
|
. += show_light_overlays("portal_light", teleportion_possible)
|
|
. += show_light_overlays("portal_effect", transport_active)
|
|
|
|
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
|
|
return
|
|
|
|
/obj/machinery/gateway/proc/generate_bumper()
|
|
portal = new(get_turf(src))
|
|
portal.gateway = src
|
|
|
|
/obj/machinery/gateway/proc/activate(datum/gateway_destination/D)
|
|
if(!powered() || target)
|
|
return
|
|
target = D
|
|
target.activate(destination)
|
|
portal_visuals.setup_visuals(target)
|
|
transport_active = TRUE
|
|
generate_bumper()
|
|
update_use_power(ACTIVE_POWER_USE)
|
|
update_appearance()
|
|
|
|
/obj/machinery/gateway/proc/Transfer(atom/movable/AM)
|
|
if(!target || !target.incoming_pass_check(AM))
|
|
return
|
|
AM.forceMove(target.get_target_turf())
|
|
target.post_transfer(AM)
|
|
|
|
/obj/machinery/gateway/attack_ghost(mob/user)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
var/turf/tar_turf = target?.get_target_turf()
|
|
if(isnull(tar_turf))
|
|
to_chat(user, span_warning("There's no active destination for the gateway... or it's broken. Maybe try again later?"))
|
|
return
|
|
if(is_secret_level(tar_turf.z) && !user.client?.holder)
|
|
to_chat(user, span_warning("The gateway destination is secret."))
|
|
return
|
|
Transfer(user)
|
|
|
|
/* Station's primary gateway */
|
|
/obj/machinery/gateway/centerstation
|
|
destination_type = /datum/gateway_destination/gateway/home
|
|
destination_name = "Home Gateway"
|
|
|
|
/obj/machinery/gateway/centerstation/Initialize(mapload)
|
|
. = ..()
|
|
if(!GLOB.the_gateway)
|
|
GLOB.the_gateway = src
|
|
|
|
/obj/machinery/gateway/centerstation/Destroy()
|
|
if(GLOB.the_gateway == src)
|
|
GLOB.the_gateway = null
|
|
return ..()
|
|
|
|
/obj/machinery/gateway/multitool_act(mob/living/user, obj/item/I)
|
|
if(calibrated)
|
|
to_chat(user, span_alert("The gate is already calibrated, there is no work for you to do here."))
|
|
else
|
|
to_chat(user, "[span_boldnotice("Recalibration successful!")]: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.")
|
|
calibrated = TRUE
|
|
return TRUE
|
|
|
|
/* Doesn't need control console or power, always links to home when interacting. */
|
|
/obj/machinery/gateway/away
|
|
density = TRUE
|
|
use_power = NO_POWER_USE
|
|
|
|
/obj/machinery/gateway/away/interact(mob/user, special_state)
|
|
. = ..()
|
|
if(!target)
|
|
if(!GLOB.the_gateway)
|
|
to_chat(user,span_warning("Home gateway is not responding!"))
|
|
if(GLOB.the_gateway.target)
|
|
GLOB.the_gateway.deactivate() //this will turn the home gateway off so that it's free for us to connect to
|
|
activate(GLOB.the_gateway.destination)
|
|
else
|
|
deactivate()
|
|
|
|
/* Gateway control computer */
|
|
/obj/machinery/computer/gateway_control
|
|
name = "Gateway Control"
|
|
desc = "Human friendly interface to the mysterious gate next to it."
|
|
var/obj/machinery/gateway/G
|
|
|
|
/obj/machinery/computer/gateway_control/Initialize(mapload, obj/item/circuitboard/C)
|
|
. = ..()
|
|
try_to_linkup()
|
|
|
|
/obj/machinery/computer/gateway_control/ui_interact(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
G.portal_visuals.display_to(user)
|
|
ui = new(user, src, "Gateway", name)
|
|
ui.open()
|
|
|
|
/obj/machinery/computer/gateway_control/ui_data(mob/user)
|
|
. = ..()
|
|
.["gateway_present"] = G
|
|
.["gateway_status"] = G ? G.powered() : FALSE
|
|
.["current_target"] = G?.target?.get_ui_data()
|
|
.["gateway_mapkey"] = G.portal_visuals.assigned_map
|
|
var/list/destinations = list()
|
|
if(G)
|
|
for(var/datum/gateway_destination/possible_destination in GLOB.gateway_destinations)
|
|
if(!G.valid_destination(possible_destination))
|
|
continue
|
|
destinations += list(possible_destination.get_ui_data())
|
|
.["destinations"] = destinations
|
|
|
|
/obj/machinery/computer/gateway_control/ui_act(action, list/params)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
switch(action)
|
|
if("linkup")
|
|
try_to_linkup()
|
|
return TRUE
|
|
if("activate")
|
|
var/datum/gateway_destination/D = locate(params["destination"]) in GLOB.gateway_destinations
|
|
try_to_connect(D)
|
|
return TRUE
|
|
if("deactivate")
|
|
if(G?.target)
|
|
G.deactivate()
|
|
return TRUE
|
|
|
|
/obj/machinery/computer/gateway_control/ui_close(mob/user)
|
|
. = ..()
|
|
G.portal_visuals.hide_from(user)
|
|
|
|
/obj/machinery/computer/gateway_control/proc/try_to_linkup()
|
|
G = locate(/obj/machinery/gateway) in view(7,get_turf(src))
|
|
|
|
/obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D)
|
|
if(!D || !G)
|
|
return
|
|
if(!D.is_available() || G.target)
|
|
return
|
|
G.activate(D)
|
|
|
|
/obj/item/paper/fluff/gateway
|
|
default_raw_text = "Congratulations,<br><br>Your station has been selected to carry out the Gateway Project.<br><br>The equipment will be shipped to you at the start of the next quarter.<br> You are to prepare a secure location to house the equipment as outlined in the attached documents.<br><br>--Nanotrasen Bluespace Research"
|
|
name = "Confidential Correspondence, Pg 1"
|
|
|
|
/atom/movable/screen/map_view/gateway_port
|
|
var/datum/gateway_destination/our_destination
|
|
/// Handles the background of the portal, ensures the effect well, works properly
|
|
var/atom/movable/screen/background/cam_background
|
|
|
|
/atom/movable/screen/map_view/gateway_port/Initialize(mapload, datum/hud/hud_owner)
|
|
. = ..()
|
|
cam_background = new
|
|
cam_background.del_on_map_removal = FALSE
|
|
// Draw above everything
|
|
cam_background.layer = 200
|
|
cam_background.plane = HIGHEST_EVER_PLANE
|
|
cam_background.blend_mode = BLEND_OVERLAY
|
|
|
|
|
|
/atom/movable/screen/map_view/gateway_port/generate_view(map_key)
|
|
. = ..()
|
|
cam_background.assigned_map = assigned_map
|
|
cam_background.fill_rect(1, 1, 3, 3)
|
|
|
|
/atom/movable/screen/map_view/gateway_port/Destroy()
|
|
QDEL_NULL(cam_background)
|
|
return ..()
|
|
|
|
/atom/movable/screen/map_view/gateway_port/display_to(mob/show_to)
|
|
. = ..()
|
|
show_to.client.register_map_obj(cam_background)
|
|
|
|
/atom/movable/screen/map_view/gateway_port/proc/setup_visuals(datum/gateway_destination/D)
|
|
our_destination = D
|
|
update_portal_filters()
|
|
|
|
/atom/movable/screen/map_view/gateway_port/proc/reset_visuals()
|
|
our_destination = null
|
|
update_portal_filters()
|
|
|
|
/atom/movable/screen/map_view/gateway_port/proc/update_portal_filters()
|
|
cam_background.clear_filters()
|
|
// ok so what this used to do was render the tiles "on the other side" of the gateway onto the gateway mask
|
|
// Unfortunately since I've removed the plane inheriting from /atom vis_flags, this no longer works
|
|
// You could setup gateways to draw onto "lower then everything" z layers, but generating a whole stack of plane masters
|
|
// Just for this one effect is kinda silly. Maybe next time
|
|
// Rather then that, let's just render a little preview port to the console, because for reasons that's trivial
|
|
vis_contents = null
|
|
|
|
var/turf/center_turf = our_destination?.get_target_turf()
|
|
if(!center_turf)
|
|
// Draw static
|
|
cam_background.icon_state = "scanline2"
|
|
cam_background.color = null
|
|
cam_background.alpha = 255
|
|
return
|
|
|
|
cam_background.add_filter("portal_blur", 1, list("type" = "blur", "size" = 0.5))
|
|
|
|
vis_contents += TURF_NEIGHBORS(center_turf)
|
|
cam_background.icon_state = "scanline4"
|
|
cam_background.color = "#adadff"
|
|
cam_background.alpha = 128
|