mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 19:22:20 +00:00
## About The Pull Request This PR should fix the problem of small previews in TGUI once and for all (I hope). What was causing it? Because TGUI takes a long time to open, that's why previews were generated broken (small). On Byond 515 this problem was not so noticeable as the interfaces opened faster, but with the release of 516 it became much worse. Previews were generated inside a window that was not yet open, so the scale was broken, sometimes the window would open before the preview was done and sent, usually with small interfaces, or when reopening. I'm not very good at working with signals, and to tell the truth this is my second experience with them, so I hope I did it right. ## Why It's Good For The Game No more small map previews <details> <summary> Video </summary> https://github.com/user-attachments/assets/834f3820-cc6a-4f65-90e5-d6bb2a118bcf </details> ## Changelog 🆑 fix: Fixed small character preview, color matrix preview, mech preview, and other previews with uses ByondUI map /🆑 --------- Co-authored-by: Gaxeer <44334376+Gaxeer@users.noreply.github.com>
456 lines
16 KiB
Plaintext
456 lines
16 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)
|
|
playsound(src, 'sound/machines/gateway/gateway_calibrating.ogg', 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
. = "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, target_gateway.dir)
|
|
|
|
/datum/gateway_destination/gateway/post_transfer(atom/movable/AM)
|
|
. = ..()
|
|
addtimer(CALLBACK(AM, TYPE_PROC_REF(/atom/movable, setDir), target_gateway.dir),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) == gateway?.dir)
|
|
playsound(src, 'sound/machines/gateway/gateway_travel.ogg', 70, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
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
|
|
playsound(src, 'sound/machines/gateway/gateway_close.ogg', 140, TRUE, TRUE, SOUND_RANGE)
|
|
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
|
|
playsound(src, 'sound/machines/gateway/gateway_open.ogg', 140, TRUE, TRUE, SOUND_RANGE)
|
|
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
|
|
playsound(src, 'sound/machines/gateway/gateway_calibrated.ogg', 80, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
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)
|
|
. = ..()
|
|
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)
|
|
ui = new(user, src, "Gateway", name)
|
|
G.portal_visuals.display_to(user, ui.window)
|
|
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, datum/tgui/ui, datum/ui_state/state)
|
|
. = ..()
|
|
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_on_ui_visible(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
|