Files
Letter NandGitHub bd9a49dd7e pixel w/z stuff (#7477)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request
byond shenanigans
<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Please note that
maintainers freely reserve the right to remove and add tags should they
deem it appropriate. You can attempt to finagle the system all you want,
but it's best to shoot for clear communication right off the bat. -->

🆑
add: you can now point items inside your inventory
tweak: update fulton
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
2026-01-13 13:38:48 -05:00

261 lines
9.3 KiB
Plaintext

GLOBAL_LIST_EMPTY(total_extraction_beacons)
// todo: this should be included in the air-support module being added later, not just a mining exclusive
/obj/item/extraction_pack
name = "fulton extraction pack"
desc = "A balloon pack that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
icon = 'icons/obj/fulton.dmi'
icon_state = "extraction_pack"
w_class = WEIGHT_CLASS_NORMAL
/// Beacon weakref
var/datum/weakref/beacon_ref
/// List of networks
var/list/beacon_networks = list("station")
/// Number of uses left
var/uses_left = 3
/// Can be used indoors
var/can_use_indoors
/// Can be used on living creatures
var/safe_for_living_creatures = TRUE
var/stuntime = 15
/// Maximum force that can be used to extract
var/max_force_fulton = MOVE_FORCE_STRONG
/obj/item/extraction_pack/wormhole
name = "wormhole fulton extraction pack"
desc = "A balloon pack with integrated wormhole technology and less disruptive movement that can be used to extract equipment or personnel to a Fulton Recovery Beacon. Anything not bolted down can be moved. Link the pack to a beacon by using the pack in hand."
can_use_indoors = TRUE
stuntime = 3
/obj/item/extraction_holdercrate
name = "extraction crate"
desc = "A regular old crate."
icon = 'icons/obj/storage.dmi'
icon_state = "phoroncrate"
/obj/item/extraction_pack/examine()
. = ..()
. += SPAN_INFOPLAIN("It has [uses_left] use\s remaining.")
var/obj/structure/extraction_point/beacon = beacon_ref?.resolve()
if(isnull(beacon))
beacon_ref = null
. += SPAN_INFOPLAIN("It is not linked to a beacon.")
return
. += SPAN_INFOPLAIN("It is linked to [beacon.name].")
/obj/item/extraction_pack/attack_self(mob/user, datum/event_args/actor/actor)
. = ..()
if(.)
return
var/list/possible_beacons = list()
for(var/datum/weakref/point_ref as anything in GLOB.total_extraction_beacons)
var/obj/structure/extraction_point/extraction_point = point_ref.resolve()
if(isnull(extraction_point))
GLOB.total_extraction_beacons.Remove(point_ref)
continue
if(extraction_point.beacon_network in beacon_networks)
possible_beacons += extraction_point
if(!length(possible_beacons))
balloon_alert(user, "no beacons")
return
var/chosen_beacon = tgui_input_list(user, "Beacon to connect to", "Balloon Extraction Pack", sortNames(possible_beacons))
if(isnull(chosen_beacon))
return
beacon_ref = WEAKREF(chosen_beacon)
balloon_alert(user, "linked!")
/obj/item/extraction_pack/afterattack(atom/interacting_with, mob/user, clickchain_flags, list/params)
if(!(clickchain_flags & CLICKCHAIN_HAS_PROXIMITY))
return
if(!ismovable(interacting_with))
return
if(!isturf(interacting_with.loc)) // no extracting stuff inside other stuff
return
var/atom/movable/thing = interacting_with
if(thing.anchored)
return
var/obj/structure/extraction_point/beacon = beacon_ref?.resolve()
if(isnull(beacon))
balloon_alert(user, "not linked!")
beacon_ref = null
return
var/turf/turf = get_turf(thing)
if(!can_use_indoors)
if(!turf?.outdoors)
balloon_alert(user, "not outdoors!")
return
if(!safe_for_living_creatures && check_for_living_mobs(thing))
to_chat(user, SPAN_WARNING("[src] is not safe for use with living creatures, they wouldn't survive the trip back!"))
balloon_alert(user, "not safe!")
return
if(thing.move_resist > max_force_fulton)
balloon_alert(user, "too heavy!")
return
balloon_alert_to_viewers("attaching...")
playsound(thing, 'sound/items/zip.ogg', vol = 50, vary = TRUE)
if(isliving(thing))
var/mob/living/creature = thing
if(creature.mind)
to_chat(thing, SPAN_USERDANGER("You are being extracted! Stand still to proceed."))
if(!do_after(user, 5 SECONDS, target = thing))
return
balloon_alert_to_viewers("extracting!")
// if(loc == user && ishuman(user))
// var/mob/living/carbon/human/human_user = user
// human_user.back?.atom_storage?.attempt_insert(src, user, force = STORAGE_SOFT_LOCKED)
uses_left--
if(uses_left <= 0)
user.transfer_item_to_loc(src, thing, INV_OP_FORCE | INV_OP_SHOULD_NOT_INTERCEPT | INV_OP_SILENT)
if(isliving(thing))
var/mob/living/creature = thing
creature.set_paralyzed(32 SECONDS) // Keep them from moving during the duration of the extraction
if(creature.buckled)
creature.buckled.unbuckle_mob(creature, TRUE) // Unbuckle them to prevent anchoring problems
else
thing.set_anchored(TRUE)
thing.set_density(FALSE)
var/obj/effect/extraction_holder/holder_obj = new(get_turf(thing))
holder_obj.appearance = thing.appearance
thing.forceMove(holder_obj)
var/mutable_appearance/balloon2 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_expand", layer = ABOVE_MOB_LAYER+0.1, appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM | KEEP_APART)
balloon2.pixel_z = 10
holder_obj.add_overlay(balloon2)
addtimer(CALLBACK(src, PROC_REF(create_balloon), thing, user, holder_obj, balloon2), 0.4 SECONDS)
/obj/item/extraction_pack/proc/create_balloon(atom/movable/thing, mob/living/user, obj/effect/extraction_holder/holder_obj, mutable_appearance/balloon2)
var/mutable_appearance/balloon = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_balloon", layer = ABOVE_MOB_LAYER+0.1, appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM | KEEP_APART)
balloon.pixel_z = 10
holder_obj.cut_overlay(balloon2)
holder_obj.add_overlay(balloon)
playsound(holder_obj.loc, 'sound/items/fultext_deploy.ogg', vol = 50, vary = TRUE, extrarange = -3)
animate(holder_obj, pixel_z = 10, time = 2 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = 5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = -5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = 5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = -5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
sleep(6 SECONDS)
playsound(holder_obj.loc, 'sound/items/fultext_launch.ogg', vol = 50, vary = TRUE, extrarange = -3)
animate(holder_obj, pixel_z = 1000, time = 3 SECONDS, flags = ANIMATION_RELATIVE)
if(ishuman(thing))
var/mob/living/carbon/human/creature = thing
creature.set_unconscious(0)
creature.drowsyness = 0
creature.set_sleeping(0)
sleep(3 SECONDS)
var/turf/flooring_near_beacon = list()
var/turf/beacon_turf = get_turf(beacon_ref.resolve())
for(var/turf/floor as anything in RANGE_TURFS(1, beacon_turf))
if(!is_blocked_turf(floor))
flooring_near_beacon += floor
if(!length(flooring_near_beacon))
flooring_near_beacon += beacon_turf
holder_obj.forceMove(pick(flooring_near_beacon))
animate(holder_obj, pixel_z = -990, time = 5 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = 5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
animate(pixel_z = -5, time = 1 SECONDS, flags = ANIMATION_RELATIVE)
sleep(7 SECONDS)
var/mutable_appearance/balloon3 = mutable_appearance('icons/obj/fulton_balloon.dmi', "fulton_retract", layer = ABOVE_MOB_LAYER+0.1, appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM | KEEP_APART)
balloon3.pixel_z = 10
holder_obj.cut_overlay(balloon)
holder_obj.add_overlay(balloon3)
sleep(0.4 SECONDS)
holder_obj.cut_overlay(balloon3)
thing.set_anchored(FALSE) // An item has to be unanchored to be extracted in the first place.
thing.set_density(initial(thing.density))
animate(holder_obj, pixel_z = -10, time = 0.5 SECONDS, flags = ANIMATION_RELATIVE)
sleep(0.5 SECONDS)
thing.forceMove(holder_obj.loc)
qdel(holder_obj)
if(uses_left <= 0)
qdel(src)
/obj/item/fulton_core
name = "extraction beacon assembly kit"
desc = "When built, emits a signal which fulton recovery devices can lock onto. Activate in hand to unfold into a beacon."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "subspace_amplifier"
/obj/item/fulton_core/attack_self(mob/user, datum/event_args/actor/actor)
. = ..()
if(.)
return
if(!do_after(user, 1.5 SECONDS, target = user) || QDELETED(src))
return
new /obj/structure/extraction_point(get_turf(user))
playsound(src, 'sound/items/Deconstruct.ogg', vol = 50, vary = TRUE, extrarange = -5)
qdel(src)
/obj/structure/extraction_point
name = "fulton recovery beacon"
desc = "A beacon for the fulton recovery system. Activate a pack in your hand to link it to a beacon."
icon = 'icons/obj/fulton.dmi'
icon_state = "extraction_point"
anchored = TRUE
density = FALSE
var/beacon_network = "station"
/obj/structure/extraction_point/Initialize(mapload)
. = ..()
name += " ([rand(100,999)]) ([get_area_name(src, TRUE)])"
GLOB.total_extraction_beacons.Add(WEAKREF(src))
/obj/structure/extraction_point/attack_hand(mob/living/user, datum/event_args/actor/clickchain/e_args)
. = ..()
balloon_alert_to_viewers("undeploying...")
if(!do_after(user, 1.5 SECONDS, src))
return
new /obj/item/fulton_core(drop_location())
playsound(src, 'sound/items/Deconstruct.ogg', vol = 50, vary = TRUE, extrarange = -5)
qdel(src)
/obj/effect/extraction_holder
name = "extraction holder"
desc = "you shouldnt see this"
var/atom/movable/stored_obj
/obj/item/extraction_pack/proc/check_for_living_mobs(atom/A)
if(isliving(A))
var/mob/living/L = A
if(L.stat != DEAD)
return TRUE
for(var/thing in A.get_all_contents())
if(isliving(A))
var/mob/living/L = A
if(L.stat != DEAD)
return TRUE
return FALSE
/obj/effect/extraction_holder/singularity_act()
return
/obj/effect/extraction_holder/singularity_pull(atom/singularity, current_size)
return