From 451c1579d0ec1b815aa68136aabebc23594a16a7 Mon Sep 17 00:00:00 2001 From: ihatethisengine Date: Sun, 14 Apr 2024 12:34:43 +0300 Subject: [PATCH 01/18] concept --- code/__DEFINES/mode.dm | 2 +- code/game/machinery/doors/multi_tile.dm | 7 +- code/game/turfs/transit.dm | 63 ++++++++++++++- code/modules/cm_marines/dropship_equipment.dm | 76 +++---------------- code/modules/shuttle/shuttles/dropship.dm | 1 + 5 files changed, 79 insertions(+), 70 deletions(-) diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 28471f3a5ea1..c396beba64ac 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -2,7 +2,7 @@ //Self-destruct, nuke, and evacuation. #define EVACUATION_TIME_LOCK 1 HOURS #define DISTRESS_TIME_LOCK 6 MINUTES -#define SHUTTLE_TIME_LOCK 15 MINUTES +#define SHUTTLE_TIME_LOCK 0 MINUTES #define SHUTTLE_LOCK_COOLDOWN 10 MINUTES #define MONORAIL_LOCK_COOLDOWN 3 MINUTES #define SHUTTLE_LOCK_TIME_LOCK 1 MINUTES diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index 1e7fcbf40155..f95ef09e812f 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -279,8 +279,8 @@ return ..() -/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/unlock() - if(is_reserved_level(z)) +/obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/unlock(forced=FALSE) + if(is_reserved_level(z) && !forced) return // in orbit ..() @@ -294,6 +294,9 @@ if(xeno.action_busy) return + if(is_reserved_level(z)) //no prying in space even though it's funny + return + var/direction switch(id) if("starboard_door") diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index dd6a8d920f6f..df4e8403698f 100644 --- a/code/game/turfs/transit.dm +++ b/code/game/turfs/transit.dm @@ -39,14 +39,39 @@ if(!istype(dropship) || dropship.mode != SHUTTLE_CALL) return ..() - if(dropship.destination.id != DROPSHIP_LZ1 && dropship.destination.id != DROPSHIP_LZ2) - return ..() // we're not heading towards the LZs - // you just jumped out of a dropship heading towards the LZ, have fun living on the way down! var/list/ground_z_levels = SSmapping.levels_by_trait(ZTRAIT_GROUND) if(!length(ground_z_levels)) return ..() + if(dropship.paradrop_signal) + var/list/valid_turfs = list() + var/turf/location = get_turf(dropship.paradrop_signal.signal_loc) + for(var/turf/T as anything in RANGE_TURFS(7, location)) + var/area/t_area = get_area(T) + if(!t_area || CEILING_IS_PROTECTED(t_area.ceiling, CEILING_PROTECTION_TIER_1)) + continue + if(T.density) + continue + var/found_dense = FALSE + for(var/atom/A in T) + if(A.density && A.can_block_movement) + found_dense = TRUE + break + if(found_dense) + continue + if(protected_by_pylon(TURF_PROTECTION_MORTAR, T)) + continue + valid_turfs += T + + if(!length(valid_turfs)) + to_chat(crosser, SPAN_WARNING("You couldn't find a fitting landing spot at desinated zone and had to find another place to land.")) + else + var/turf/deploy_turf = pick(valid_turfs) + INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, deploy_turf, dropship.name) + return + + var/list/area/potential_areas = shuffle(SSmapping.areas_in_z["[ground_z_levels[1]]"]) for(var/area/maybe_this_area in potential_areas) @@ -72,9 +97,41 @@ return ..() // they couldn't be dropped, just delete them +/turf/open/space/transit/dropship/proc/handle_paradrop(atom/movable/crosser, turf/target, dropship_name) + if(QDELETED(crosser)) + return + + ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + ADD_TRAIT(crosser, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + to_chat(world, "test") + var/image/cables = image('icons/obj/structures/droppod_32x64.dmi', crosser, "chute_cables_static") + crosser.overlays += cables + var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', crosser, "chute_static") + + chute.pixel_x -= 16 + chute.pixel_y += 16 + + crosser.overlays += chute + crosser.pixel_z = 360 + crosser.forceMove(target) + animate(crosser, time = 40, pixel_z = 0, flags = ANIMATION_PARALLEL) + sleep(40) + REMOVE_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + REMOVE_TRAIT(crosser, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + crosser.overlays -= chute + crosser.overlays -= cables + /turf/open/space/transit/dropship/proc/handle_drop(atom/movable/crosser, turf/target, dropship_name) if(QDELETED(crosser)) return + if(ishuman(crosser)) + var/mob/living/carbon/human/crossing_human = crosser + if(istype(crossing_human.belt, /obj/item/rappel_harness)) + handle_paradrop(crosser, target, dropship_name) + return + if(isxeno(crosser)) + handle_paradrop(crosser, target, dropship_name) + return ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) crosser.pixel_z = 360 diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index bd40076ea500..b274c04d800e 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -1341,84 +1341,32 @@ var/turf/location = get_turf(LT.signal_loc) var/area/location_area = get_area(location) if(CEILING_IS_PROTECTED(location_area.ceiling, CEILING_PROTECTION_TIER_1)) - to_chat(user, SPAN_WARNING("You cannot jump to the target. It is probably underground.")) + to_chat(user, SPAN_WARNING("You cannot find the target. It is probably underground.")) return - var/list/valid_turfs = list() - for(var/turf/T as anything in RANGE_TURFS(2, location)) - var/area/t_area = get_area(T) - if(!t_area || CEILING_IS_PROTECTED(t_area.ceiling, CEILING_PROTECTION_TIER_1)) - continue - if(T.density) - continue - var/found_dense = FALSE - for(var/atom/A in T) - if(A.density && A.can_block_movement) - found_dense = TRUE - break - if(found_dense) - continue - if(protected_by_pylon(TURF_PROTECTION_MORTAR, T)) - continue - valid_turfs += T - - if(!length(valid_turfs)) - to_chat(user, SPAN_WARNING("There's nowhere safe for you to land, the landing zone is too congested.")) - return - - var/turf/deploy_turf = pick(valid_turfs) - - var/obj/effect/warning/rappel/warning_zone = new(deploy_turf) - flick("rappel_hatch_opening", src) - icon_state = "rappel_hatch_open" - user.forceMove(loc) - user.client?.perspective = EYE_PERSPECTIVE - user.client?.eye = deploy_turf - - if(!do_after(user, 4 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_FRIENDLY, user, INTERRUPT_MOVED) || !can_use(user) || protected_by_pylon(TURF_PROTECTION_MORTAR, deploy_turf)) - qdel(warning_zone) - flick("rappel_hatch_closing", src) - icon_state = "rappel_hatch_closed" - user.client?.perspective = MOB_PERSPECTIVE - user.client?.eye = user - return + linked_shuttle.paradrop_signal = LT + linked_shuttle.door_control.control_doors("force-unlock", "aft", TRUE) + RegisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING, PROC_REF(clear_locked_turf_and_lock_aft)) + RegisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE, PROC_REF(clear_locked_turf_and_lock_aft)) - new /obj/effect/rappel_rope(deploy_turf) - user.forceMove(deploy_turf) - INVOKE_ASYNC(user, TYPE_PROC_REF(/mob/living/carbon/human, animation_rappel)) - user.client?.perspective = MOB_PERSPECTIVE - user.client?.eye = user - deploy_turf.ceiling_debris_check(2) - playsound(deploy_turf, 'sound/items/rappel.ogg', 50, TRUE) +/obj/structure/dropship_equipment/rappel_system/proc/clear_locked_turf_and_lock_aft() + SIGNAL_HANDLER + var/found_dense = FALSE + linked_shuttle.door_control.control_doors("force-lock", "aft", TRUE) + visible_message("[src] displays an alert as it loses the target signal.") + UnregisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) + UnregisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE) - flick("rappel_hatch_closing", src) - icon_state = "rappel_hatch_closed" - qdel(warning_zone) /obj/structure/dropship_equipment/rappel_system/proc/can_use(mob/living/carbon/human/user) if(linked_shuttle.mode != SHUTTLE_CALL) to_chat(user, SPAN_WARNING("\The [src] can only be used while in flight.")) return FALSE - if(!linked_shuttle.in_flyby) - to_chat(user, SPAN_WARNING("\The [src] requires a flyby flight to be used.")) - return FALSE - - if(user.buckled) - to_chat(user, SPAN_WARNING("You cannot rappel while buckled!")) - return FALSE - if(user.is_mob_incapacitated()) to_chat(user, SPAN_WARNING("You are in no state to do that!")) return FALSE - if(!istype(user.belt, harness)) - to_chat(user, SPAN_WARNING("You must have a rappel harness equipped in order to use \the [src]!")) - return FALSE - - if(user.action_busy) - return FALSE - return TRUE // used in the simulation room for cas runs, removed the sound and ammo depletion methods. diff --git a/code/modules/shuttle/shuttles/dropship.dm b/code/modules/shuttle/shuttles/dropship.dm index cb04d9a81ddb..86e869b3361e 100644 --- a/code/modules/shuttle/shuttles/dropship.dm +++ b/code/modules/shuttle/shuttles/dropship.dm @@ -29,6 +29,7 @@ var/automated_lz_id var/automated_delay var/automated_timer + var/datum/cas_signal/paradrop_signal /obj/docking_port/mobile/marine_dropship/Initialize(mapload) From fc07f1f914bb0b9e9ef17337700fcc2af3dee971 Mon Sep 17 00:00:00 2001 From: ihatethisengine Date: Sun, 14 Apr 2024 20:48:13 +0300 Subject: [PATCH 02/18] +++ --- .../machinery/computer/dropship_weapons.dm | 39 ++++++++++ code/game/turfs/transit.dm | 55 +++++++++----- code/modules/cm_marines/dropship_equipment.dm | 7 +- .../interfaces/MfdPanels/ParadropPanel.tsx | 72 +++++++++++++++++++ .../interfaces/MfdPanels/SupportPanel.tsx | 4 ++ .../tgui/interfaces/MfdPanels/types.ts | 5 ++ 6 files changed, 164 insertions(+), 18 deletions(-) create mode 100644 tgui/packages/tgui/interfaces/MfdPanels/ParadropPanel.tsx diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index dce026f4ce33..2b137c3ef742 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -453,6 +453,45 @@ initiate_firemission(user, fm_tag, direction, text2num(offset_x_value), text2num(offset_y_value)) return TRUE + if("paradrop-lock") + to_chat(world, "test12314124") + var/obj/docking_port/mobile/marine_dropship/linked_shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!linked_shuttle) + return FALSE + to_chat(world, "1") + if(linked_shuttle.mode != SHUTTLE_CALL) + return FALSE + to_chat(world, "2") + if(linked_shuttle.paradrop_signal) + clear_locked_turf_and_lock_aft() + return TRUE + to_chat(world, "3 [camera_target_id]") + var/datum/cas_signal/sig = get_cas_signal(camera_target_id) + if(!sig) + return FALSE + to_chat(world, "4 [camera_target_id]") + var/turf/location = get_turf(sig.signal_loc) + var/area/location_area = get_area(location) + if(CEILING_IS_PROTECTED(location_area.ceiling, CEILING_PROTECTION_TIER_1)) + return FALSE + to_chat(world, "5 [camera_target_id]") + linked_shuttle.paradrop_signal = sig + linked_shuttle.door_control.control_doors("force-unlock", "aft", TRUE) + RegisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING, PROC_REF(clear_locked_turf_and_lock_aft)) + RegisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE, PROC_REF(clear_locked_turf_and_lock_aft)) + to_chat(world, "test123141245555555555") + return TRUE + +/obj/structure/machinery/computer/dropship_weapons/proc/clear_locked_turf_and_lock_aft() + SIGNAL_HANDLER + var/obj/docking_port/mobile/marine_dropship/linked_shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!linked_shuttle) + return + linked_shuttle.door_control.control_doors("force-lock", "aft", TRUE) + visible_message("[src] displays an alert as it loses the target signal.") + UnregisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) + UnregisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE) + linked_shuttle.paradrop_signal = null /obj/structure/machinery/computer/dropship_weapons/proc/get_weapon(eqp_tag) var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag) diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index df4e8403698f..9a17d45806fe 100644 --- a/code/game/turfs/transit.dm +++ b/code/game/turfs/transit.dm @@ -11,7 +11,7 @@ if(isobserver(crosser) || crosser.anchored) return - if(!isitem(crosser) && !isliving(crosser)) + if(!isobj(crosser) && !isliving(crosser)) return if(!istype(old_loc, /turf/open/space)) @@ -44,7 +44,16 @@ if(!length(ground_z_levels)) return ..() - if(dropship.paradrop_signal) + var/paradrop = FALSE + + if(ishuman(crosser)) + var/mob/living/carbon/human/crossing_human = crosser + if(istype(crossing_human.belt, /obj/item/rappel_harness)) + paradrop = TRUE + else if(istype(crosser, /obj/structure/closet/crate)) + paradrop = TRUE + + if(dropship.paradrop_signal) //if dropship in paradrop mode, drop them near the signal. Whether they have a parachute or not var/list/valid_turfs = list() var/turf/location = get_turf(dropship.paradrop_signal.signal_loc) for(var/turf/T as anything in RANGE_TURFS(7, location)) @@ -68,10 +77,9 @@ to_chat(crosser, SPAN_WARNING("You couldn't find a fitting landing spot at desinated zone and had to find another place to land.")) else var/turf/deploy_turf = pick(valid_turfs) - INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, deploy_turf, dropship.name) + INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, deploy_turf, dropship.name, paradrop) return - var/list/area/potential_areas = shuffle(SSmapping.areas_in_z["[ground_z_levels[1]]"]) for(var/area/maybe_this_area in potential_areas) @@ -92,9 +100,13 @@ continue // couldnt find one in 10 loops, check another area // we found a good turf, lets drop em - INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, possible_turf, dropship.name) + INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, possible_turf, dropship.name, paradrop) return + //we didn't find a turf to drop them... This shouldn't happen usually + if(paradrop) //don't delete them if they have a parachute + to_chat(crosser, "Your backpack hanged on a string to the dropship, get back inside until it's too late!") + return return ..() // they couldn't be dropped, just delete them /turf/open/space/transit/dropship/proc/handle_paradrop(atom/movable/crosser, turf/target, dropship_name) @@ -115,36 +127,41 @@ crosser.pixel_z = 360 crosser.forceMove(target) animate(crosser, time = 40, pixel_z = 0, flags = ANIMATION_PARALLEL) - sleep(40) + addtimer(CALLBACK(target, PROC_REF(ceiling_debris)), 2 SECONDS) + addtimer(CALLBACK(src, PROC_REF(clear_parachute), crosser, cables, chute), 4 SECONDS) + +/turf/open/space/transit/dropship/proc/clear_parachute(atom/movable/crosser, image/cables, image/chute) + if(QDELETED(crosser)) + return REMOVE_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) REMOVE_TRAIT(crosser, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) - crosser.overlays -= chute crosser.overlays -= cables + crosser.overlays -= chute -/turf/open/space/transit/dropship/proc/handle_drop(atom/movable/crosser, turf/target, dropship_name) - if(QDELETED(crosser)) - return - if(ishuman(crosser)) - var/mob/living/carbon/human/crossing_human = crosser - if(istype(crossing_human.belt, /obj/item/rappel_harness)) - handle_paradrop(crosser, target, dropship_name) - return - if(isxeno(crosser)) +/turf/open/space/transit/dropship/proc/handle_drop(atom/movable/crosser, turf/target, dropship_name, paradrop) + if(paradrop) handle_paradrop(crosser, target, dropship_name) return + if(QDELETED(crosser)) + return ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) crosser.pixel_z = 360 crosser.forceMove(target) crosser.visible_message(SPAN_WARNING("[crosser] falls out of the sky."), SPAN_HIGHDANGER("As you fall out of the [dropship_name], you plummet towards the ground.")) animate(crosser, time = 6, pixel_z = 0, flags = ANIMATION_PARALLEL) - + target.ceiling_debris() REMOVE_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) if(isitem(crosser)) var/obj/item/item = crosser item.explosion_throw(200) // give it a bit of a kick return + if(isobj(crosser)) + var/obj/obj = crosser + obj.ex_act(500) + return + if(!isliving(crosser)) return // don't know how you got here, but you shouldnt be here. var/mob/living/fallen_mob = crosser @@ -157,6 +174,10 @@ fallen_mob.KnockDown(10) // 10 seconds fallen_mob.Stun(3) // 3 seconds + // if(isxeno(fallen_mob)) + // var/mob/living/carbon/xenomorph/xeno = fallen_mob + // xeno.gib(create_cause_data("falling from [dropship_name]", xeno)) + // return if(ishuman(fallen_mob)) var/mob/living/carbon/human/human = fallen_mob diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index b274c04d800e..911d27e787cb 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -1306,6 +1306,11 @@ var/harness = /obj/item/rappel_harness +/obj/structure/dropship_equipment/rappel_system/ui_data(mob/user) + . = list() + .["signal"] = (linked_shuttle.paradrop_signal != null ? linked_shuttle.paradrop_signal : null) + .["locked"] = (linked_shuttle.paradrop_signal != null) + /obj/structure/dropship_equipment/rappel_system/update_equipment() if(ship_base) icon_state = "rappel_hatch_closed" @@ -1351,11 +1356,11 @@ /obj/structure/dropship_equipment/rappel_system/proc/clear_locked_turf_and_lock_aft() SIGNAL_HANDLER - var/found_dense = FALSE linked_shuttle.door_control.control_doors("force-lock", "aft", TRUE) visible_message("[src] displays an alert as it loses the target signal.") UnregisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) UnregisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE) + linked_shuttle.paradrop_signal = null /obj/structure/dropship_equipment/rappel_system/proc/can_use(mob/living/carbon/human/user) diff --git a/tgui/packages/tgui/interfaces/MfdPanels/ParadropPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/ParadropPanel.tsx new file mode 100644 index 000000000000..1f0219774caa --- /dev/null +++ b/tgui/packages/tgui/interfaces/MfdPanels/ParadropPanel.tsx @@ -0,0 +1,72 @@ +import { MfdPanel, MfdProps } from './MultifunctionDisplay'; +import { Box, Stack } from '../../components'; +import { DropshipEquipment } from '../DropshipWeaponsConsole'; +import { useBackend } from '../../backend'; +import { mfdState, useEquipmentState } from './stateManagers'; +import { EquipmentContext, ParadropSpec } from './types'; + +const ParadropPanel = (props: DropshipEquipment) => { + const paradropData = props.data as ParadropSpec; + return ( + + + + + + + +

Paradrop System

+
+ {paradropData.signal && ( + +

Locked to: {paradropData.signal}

+

Paradrop available.

+
+ )} + {!paradropData.signal && ( + +

No signal locked, paradrop system unavailable.

+
+ )} +
+
+ + + +
+ ); +}; + +export const ParadropMfdPanel = (props: MfdProps) => { + const { act, data } = useBackend(); + const { setPanelState } = mfdState(props.panelStateId); + const { equipmentState } = useEquipmentState(props.panelStateId); + const paradrop = data.equipment_data.find( + (x) => x.mount_point === equipmentState + ); + const deployLabel = (paradrop?.data?.locked ?? 0) === 1 ? 'CLEAR' : 'LOCK'; + + return ( + setPanelState('equipment') }, + ]} + leftButtons={[ + { + children: deployLabel, + onClick: () => act('paradrop-lock'), + }, + ]} + bottomButtons={[ + { + children: 'EXIT', + onClick: () => setPanelState(''), + }, + ]}> + + {paradrop && } + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx b/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx index 6c224dc7ad63..04d11ad39b6c 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx +++ b/tgui/packages/tgui/interfaces/MfdPanels/SupportPanel.tsx @@ -4,6 +4,7 @@ import { MedevacMfdPanel } from './MedevacPanel'; import { FultonMfdPanel } from './FultonPanel'; import { Box, Stack } from '../../components'; import { SentryMfdPanel } from './SentryPanel'; +import { ParadropMfdPanel } from './ParadropPanel'; import { MgMfdPanel } from './MGPanel'; import { SpotlightMfdPanel } from './SpotlightPanel'; import { EquipmentContext } from './types'; @@ -27,6 +28,9 @@ export const SupportMfdPanel = (props: MfdProps) => { if (result?.shorthand === 'Sentry') { return ; } + if (result?.shorthand === 'Rappel') { + return ; + } if (result?.shorthand === 'MG') { return ; } diff --git a/tgui/packages/tgui/interfaces/MfdPanels/types.ts b/tgui/packages/tgui/interfaces/MfdPanels/types.ts index 0e4f6f392ba4..239c121a1c3e 100644 --- a/tgui/packages/tgui/interfaces/MfdPanels/types.ts +++ b/tgui/packages/tgui/interfaces/MfdPanels/types.ts @@ -73,6 +73,11 @@ export type SpotlightSpec = { name: string; }; +export type ParadropSpec = { + signal: string | null; + locked: 0 | 1; +}; + export type MGSpec = { name: string; health: number; From ecb04cc0ed8bbbb5cf4ca08508f5115ae9508b76 Mon Sep 17 00:00:00 2001 From: ihatethisengine Date: Mon, 15 Apr 2024 09:07:15 +0300 Subject: [PATCH 03/18] init --- code/__DEFINES/mode.dm | 2 +- .../machinery/computer/dropship_weapons.dm | 31 ++-- code/game/objects/items/misc.dm | 4 +- code/game/turfs/transit.dm | 172 +++++++++--------- code/modules/cm_marines/dropship_equipment.dm | 67 +------ maps/map_files/USS_Almayer/USS_Almayer.dmm | 2 +- .../tgui/interfaces/DropshipFlightControl.tsx | 5 +- .../interfaces/MfdPanels/ParadropPanel.tsx | 30 +-- .../interfaces/MfdPanels/SupportPanel.tsx | 2 +- 9 files changed, 139 insertions(+), 176 deletions(-) diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index c396beba64ac..28471f3a5ea1 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -2,7 +2,7 @@ //Self-destruct, nuke, and evacuation. #define EVACUATION_TIME_LOCK 1 HOURS #define DISTRESS_TIME_LOCK 6 MINUTES -#define SHUTTLE_TIME_LOCK 0 MINUTES +#define SHUTTLE_TIME_LOCK 15 MINUTES #define SHUTTLE_LOCK_COOLDOWN 10 MINUTES #define MONORAIL_LOCK_COOLDOWN 3 MINUTES #define SHUTTLE_LOCK_TIME_LOCK 1 MINUTES diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index 2b137c3ef742..c49ba4b31ee0 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -454,44 +454,47 @@ initiate_firemission(user, fm_tag, direction, text2num(offset_x_value), text2num(offset_y_value)) return TRUE if("paradrop-lock") - to_chat(world, "test12314124") var/obj/docking_port/mobile/marine_dropship/linked_shuttle = SSshuttle.getShuttle(shuttle_tag) if(!linked_shuttle) return FALSE - to_chat(world, "1") if(linked_shuttle.mode != SHUTTLE_CALL) return FALSE - to_chat(world, "2") if(linked_shuttle.paradrop_signal) clear_locked_turf_and_lock_aft() return TRUE - to_chat(world, "3 [camera_target_id]") var/datum/cas_signal/sig = get_cas_signal(camera_target_id) if(!sig) return FALSE - to_chat(world, "4 [camera_target_id]") var/turf/location = get_turf(sig.signal_loc) var/area/location_area = get_area(location) if(CEILING_IS_PROTECTED(location_area.ceiling, CEILING_PROTECTION_TIER_1)) return FALSE - to_chat(world, "5 [camera_target_id]") linked_shuttle.paradrop_signal = sig linked_shuttle.door_control.control_doors("force-unlock", "aft", TRUE) RegisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING, PROC_REF(clear_locked_turf_and_lock_aft)) RegisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE, PROC_REF(clear_locked_turf_and_lock_aft)) - to_chat(world, "test123141245555555555") + var/equipment_tag = params["equipment_id"] + for(var/obj/structure/dropship_equipment/equipment as anything in shuttle.equipments) + var/mount_point = equipment.ship_base.attach_id + if(mount_point != equipment_tag) + continue + if(istype(equipment, /obj/structure/dropship_equipment/paradrop_system)) + equipment.visible_message(SPAN_NOTICE("[equipment] hums as it locks to a signal.")) + break return TRUE /obj/structure/machinery/computer/dropship_weapons/proc/clear_locked_turf_and_lock_aft() SIGNAL_HANDLER - var/obj/docking_port/mobile/marine_dropship/linked_shuttle = SSshuttle.getShuttle(shuttle_tag) - if(!linked_shuttle) + var/obj/docking_port/mobile/marine_dropship/shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!shuttle) return - linked_shuttle.door_control.control_doors("force-lock", "aft", TRUE) - visible_message("[src] displays an alert as it loses the target signal.") - UnregisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) - UnregisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE) - linked_shuttle.paradrop_signal = null + shuttle.door_control.control_doors("force-lock", "aft", TRUE) + visible_message(SPAN_WARNING("[src] displays an alert as it loses the paradrop target.")) + for(var/obj/structure/dropship_equipment/paradrop_system/parad in shuttle.equipments) + parad.visible_message(SPAN_WARNING("[parad] displays an alert as it loses the paradrop target.")) + UnregisterSignal(shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) + UnregisterSignal(shuttle, COMSIG_SHUTTLE_SETMODE) + shuttle.paradrop_signal = null /obj/structure/machinery/computer/dropship_weapons/proc/get_weapon(eqp_tag) var/obj/docking_port/mobile/marine_dropship/dropship = SSshuttle.getShuttle(shuttle_tag) diff --git a/code/game/objects/items/misc.dm b/code/game/objects/items/misc.dm index 1699cb24ef39..8ce4ddc83abe 100644 --- a/code/game/objects/items/misc.dm +++ b/code/game/objects/items/misc.dm @@ -293,8 +293,8 @@ new /obj/item/evidencebag(src) /obj/item/rappel_harness - name = "rappel harness" - desc = "A simple, uncomfortable rappel harness with just enough safety straps to make RnD pass health and safety. It comes with an in-built descender, but has no pouches for ammunition." + name = "paradrop harness" + desc = "A simple, uncomfortable harness with just enough safety straps to make RnD pass health and safety. It comes with an in-built descender, but has no pouches for ammunition. You won't be able to paradrop without this thing." icon = 'icons/obj/items/clothing/belts.dmi' icon_state = "rappel_harness" item_state = "rappel_harness" diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index 9a17d45806fe..a1a24890a9b4 100644 --- a/code/game/turfs/transit.dm +++ b/code/game/turfs/transit.dm @@ -24,6 +24,8 @@ /turf/open/space/transit/proc/handle_crosser(atom/movable/crosser) if(QDELETED(crosser)) return + if(crosser.can_paradrop()) //let's not delete people who arent meant to be deleted... This shouldn't happen normally, but if it does, congratulations, you gamed the system + return qdel(crosser) /turf/open/space/transit/dropship @@ -44,14 +46,7 @@ if(!length(ground_z_levels)) return ..() - var/paradrop = FALSE - - if(ishuman(crosser)) - var/mob/living/carbon/human/crossing_human = crosser - if(istype(crossing_human.belt, /obj/item/rappel_harness)) - paradrop = TRUE - else if(istype(crosser, /obj/structure/closet/crate)) - paradrop = TRUE + var/failed_drop = FALSE if(dropship.paradrop_signal) //if dropship in paradrop mode, drop them near the signal. Whether they have a parachute or not var/list/valid_turfs = list() @@ -73,13 +68,17 @@ continue valid_turfs += T - if(!length(valid_turfs)) - to_chat(crosser, SPAN_WARNING("You couldn't find a fitting landing spot at desinated zone and had to find another place to land.")) - else + if(length(valid_turfs)) //if we found a fitting place near the landing zone... var/turf/deploy_turf = pick(valid_turfs) - INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, deploy_turf, dropship.name, paradrop) + if(crosser.can_paradrop()) + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, handle_paradrop), deploy_turf, dropship.name) + return + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, handle_airdrop), deploy_turf, dropship.name) return + failed_drop = TRUE //If we don't (which hopefully won't happen) we will try to just drop them somewhere else, emergency gameplay? + + //find a random spot to drop them var/list/area/potential_areas = shuffle(SSmapping.areas_in_z["[ground_z_levels[1]]"]) for(var/area/maybe_this_area in potential_areas) @@ -99,99 +98,106 @@ if(!istype(possible_turf) || is_blocked_turf(possible_turf) || istype(possible_turf, /turf/open/space)) continue // couldnt find one in 10 loops, check another area + if(failed_drop) + to_chat(crosser, SPAN_BOLDWARNING("You got carried away from the dropping zone by the wind!")) + // we found a good turf, lets drop em - INVOKE_ASYNC(src, PROC_REF(handle_drop), crosser, possible_turf, dropship.name, paradrop) + if(crosser.can_paradrop()) + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, handle_paradrop), possible_turf, dropship.name) + return + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, handle_airdrop), possible_turf, dropship.name) return //we didn't find a turf to drop them... This shouldn't happen usually - if(paradrop) //don't delete them if they have a parachute - to_chat(crosser, "Your backpack hanged on a string to the dropship, get back inside until it's too late!") + if(crosser.can_paradrop()) //don't delete them if they were supposed to paradrop + to_chat(crosser, SPAN_BOLDWARNING("Your harness got stuck and you got thrown back in the dropship.")) + var/turf/projected = get_ranged_target_turf(crosser.loc, turn(dir, 180), 15) + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE) return return ..() // they couldn't be dropped, just delete them -/turf/open/space/transit/dropship/proc/handle_paradrop(atom/movable/crosser, turf/target, dropship_name) - if(QDELETED(crosser)) - return - ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) - ADD_TRAIT(crosser, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) - to_chat(world, "test") - var/image/cables = image('icons/obj/structures/droppod_32x64.dmi', crosser, "chute_cables_static") - crosser.overlays += cables - var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', crosser, "chute_static") + +/atom/movable/proc/can_paradrop() + return FALSE + +/mob/living/carbon/human/can_paradrop() + if(istype(belt, /obj/item/rappel_harness)) + return TRUE + ..() + +/obj/structure/closet/crate/can_paradrop() //for now all crates can be paradropped + return TRUE + +/atom/movable/proc/handle_paradrop(turf/target, dropship_name) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + ADD_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + var/image/cables = image('icons/obj/structures/droppod_32x64.dmi', src, "chute_cables_static") + src.overlays += cables + var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', src, "chute_static") chute.pixel_x -= 16 chute.pixel_y += 16 - crosser.overlays += chute - crosser.pixel_z = 360 - crosser.forceMove(target) - animate(crosser, time = 40, pixel_z = 0, flags = ANIMATION_PARALLEL) - addtimer(CALLBACK(target, PROC_REF(ceiling_debris)), 2 SECONDS) - addtimer(CALLBACK(src, PROC_REF(clear_parachute), crosser, cables, chute), 4 SECONDS) + src.overlays += chute + src.pixel_z = 360 + src.forceMove(target) + animate(src, time = 3.5 SECONDS, pixel_z = 0, flags = ANIMATION_PARALLEL) + addtimer(CALLBACK(target, TYPE_PROC_REF(/turf, ceiling_debris)), 2 SECONDS) + addtimer(CALLBACK(src, PROC_REF(clear_parachute), cables, chute), 3.5 SECONDS) -/turf/open/space/transit/dropship/proc/clear_parachute(atom/movable/crosser, image/cables, image/chute) - if(QDELETED(crosser)) - return - REMOVE_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) - REMOVE_TRAIT(crosser, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) - crosser.overlays -= cables - crosser.overlays -= chute - -/turf/open/space/transit/dropship/proc/handle_drop(atom/movable/crosser, turf/target, dropship_name, paradrop) - if(paradrop) - handle_paradrop(crosser, target, dropship_name) - return - if(QDELETED(crosser)) +/atom/movable/proc/clear_parachute(image/cables, image/chute) + if(QDELETED(src)) return - ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) - - crosser.pixel_z = 360 - crosser.forceMove(target) - crosser.visible_message(SPAN_WARNING("[crosser] falls out of the sky."), SPAN_HIGHDANGER("As you fall out of the [dropship_name], you plummet towards the ground.")) - animate(crosser, time = 6, pixel_z = 0, flags = ANIMATION_PARALLEL) - target.ceiling_debris() - REMOVE_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) - if(isitem(crosser)) - var/obj/item/item = crosser - item.explosion_throw(200) // give it a bit of a kick + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + REMOVE_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_DROPSHIP_INTERACTION) + overlays -= cables + overlays -= chute + +/atom/movable/proc/handle_airdrop(turf/target, dropship_name) + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + pixel_z = 360 + forceMove(target) + visible_message(SPAN_WARNING("[src] falls out of the sky."), SPAN_HIGHDANGER("As you fall out of the [dropship_name], you plummet towards the ground.")) + animate(src, time = 6, pixel_z = 0, flags = ANIMATION_PARALLEL) + INVOKE_ASYNC(target, TYPE_PROC_REF(/turf, ceiling_debris)) + REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + +/obj/handle_airdrop(turf/target, dropship_name) + ..() + if(!indestructible && prob(30)) // throwing objects from the air is not always a good idea + deconstruct(FALSE) + +/obj/item/handle_airdrop(turf/target, dropship_name) + ..() + if(QDELETED(src)) return + src.explosion_throw(200) // give it a bit of a kick - if(isobj(crosser)) - var/obj/obj = crosser - obj.ex_act(500) - return - - if(!isliving(crosser)) - return // don't know how you got here, but you shouldnt be here. - var/mob/living/fallen_mob = crosser - +/mob/living/handle_airdrop(turf/target, dropship_name) + ..() playsound(target, "punch", rand(20, 70), TRUE) playsound(target, "punch", rand(20, 70), TRUE) playsound(target, "bone_break", rand(20, 70), TRUE) playsound(target, "bone_break", rand(20, 70), TRUE) - fallen_mob.KnockDown(10) // 10 seconds - fallen_mob.Stun(3) // 3 seconds - - // if(isxeno(fallen_mob)) - // var/mob/living/carbon/xenomorph/xeno = fallen_mob - // xeno.gib(create_cause_data("falling from [dropship_name]", xeno)) - // return - - if(ishuman(fallen_mob)) - var/mob/living/carbon/human/human = fallen_mob - human.last_damage_data = create_cause_data("falling from [dropship_name]", human) - // I'd say falling from space is pretty much like getting hit by an explosion - human.take_overall_armored_damage(300, ARMOR_BOMB, limb_damage_chance = 100) - // but just in case, you will still take a ton of damage. - human.take_overall_damage(200, used_weapon = "falling", limb_damage_chance = 100) - if(human.stat != DEAD) - human.death(human.last_damage_data) - fallen_mob.status_flags |= PERMANENTLY_DEAD - return + KnockDown(10) // 10 seconds + Stun(3) // 3 seconds // take a little bit more damage otherwise - fallen_mob.take_overall_damage(400, used_weapon = "falling", limb_damage_chance = 100) + take_overall_damage(400, used_weapon = "falling", limb_damage_chance = 100) + +/mob/living/carbon/human/handle_airdrop(turf/target, dropship_name) + ..() + last_damage_data = create_cause_data("falling from [dropship_name]", src) + // I'd say falling from space is pretty much like getting hit by an explosion + take_overall_armored_damage(300, ARMOR_BOMB, limb_damage_chance = 100) + // but just in case, you will still take a ton of damage. + take_overall_damage(200, used_weapon = "falling", limb_damage_chance = 100) + if(stat != DEAD) + death(last_damage_data) + status_flags |= PERMANENTLY_DEAD + return + /turf/open/space/transit/dropship/alamo shuttle_tag = DROPSHIP_ALAMO diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index 911d27e787cb..64778a9ddb25 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -1296,9 +1296,9 @@ fulton_cooldown = world.time + 50 // Rappel deployment system -/obj/structure/dropship_equipment/rappel_system - name = "\improper HPU-1 Rappel Deployment System" - shorthand = "Rappel" +/obj/structure/dropship_equipment/paradrop_system + name = "\improper HPU-1 Paradrop Deployment System" + shorthand = "PDS" equip_categories = list(DROPSHIP_CREW_WEAPON) icon_state = "rappel_module_packaged" point_cost = 50 @@ -1306,73 +1306,20 @@ var/harness = /obj/item/rappel_harness -/obj/structure/dropship_equipment/rappel_system/ui_data(mob/user) +/obj/structure/dropship_equipment/paradrop_system/ui_data(mob/user) . = list() .["signal"] = (linked_shuttle.paradrop_signal != null ? linked_shuttle.paradrop_signal : null) .["locked"] = (linked_shuttle.paradrop_signal != null) -/obj/structure/dropship_equipment/rappel_system/update_equipment() +/obj/structure/dropship_equipment/paradrop_system/update_equipment() if(ship_base) icon_state = "rappel_hatch_closed" density = FALSE else icon_state = "rappel_module_packaged" -/obj/effect/warning/rappel - color = "#17d17a" - -/obj/structure/dropship_equipment/rappel_system/attack_hand(mob/living/carbon/human/user) - var/datum/cas_iff_group/cas_group = GLOB.cas_groups[FACTION_MARINE] - var/list/targets = cas_group.cas_signals - - if(!LAZYLEN(targets)) - to_chat(user, SPAN_NOTICE("No CAS signals found.")) - return - - if(!can_use(user)) - return - - var/user_input = tgui_input_list(user, "Choose a target to jump to.", name, targets) - if(!user_input) - return - - if(!can_use(user)) - return - - var/datum/cas_signal/LT = user_input - if(!istype(LT) || !LT.valid_signal()) - return - - var/turf/location = get_turf(LT.signal_loc) - var/area/location_area = get_area(location) - if(CEILING_IS_PROTECTED(location_area.ceiling, CEILING_PROTECTION_TIER_1)) - to_chat(user, SPAN_WARNING("You cannot find the target. It is probably underground.")) - return - - linked_shuttle.paradrop_signal = LT - linked_shuttle.door_control.control_doors("force-unlock", "aft", TRUE) - RegisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING, PROC_REF(clear_locked_turf_and_lock_aft)) - RegisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE, PROC_REF(clear_locked_turf_and_lock_aft)) - -/obj/structure/dropship_equipment/rappel_system/proc/clear_locked_turf_and_lock_aft() - SIGNAL_HANDLER - linked_shuttle.door_control.control_doors("force-lock", "aft", TRUE) - visible_message("[src] displays an alert as it loses the target signal.") - UnregisterSignal(linked_shuttle.paradrop_signal, COMSIG_PARENT_QDELETING) - UnregisterSignal(linked_shuttle, COMSIG_SHUTTLE_SETMODE) - linked_shuttle.paradrop_signal = null - - -/obj/structure/dropship_equipment/rappel_system/proc/can_use(mob/living/carbon/human/user) - if(linked_shuttle.mode != SHUTTLE_CALL) - to_chat(user, SPAN_WARNING("\The [src] can only be used while in flight.")) - return FALSE - - if(user.is_mob_incapacitated()) - to_chat(user, SPAN_WARNING("You are in no state to do that!")) - return FALSE - - return TRUE +/obj/structure/dropship_equipment/paradrop_system/attack_hand(mob/living/carbon/human/user) + return // used in the simulation room for cas runs, removed the sound and ammo depletion methods. // copying code is definitely bad, but adding an unnecessary sim or not sim boolean check in the open_fire_firemission just doesn't seem right. diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 8ccad6d6cca2..0322a3fc2ef6 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -30249,7 +30249,7 @@ }, /area/almayer/engineering/upper_engineering/starboard) "gpi" = ( -/obj/structure/dropship_equipment/rappel_system, +/obj/structure/dropship_equipment/paradrop_system, /turf/open/floor/almayer{ icon_state = "test_floor4" }, diff --git a/tgui/packages/tgui/interfaces/DropshipFlightControl.tsx b/tgui/packages/tgui/interfaces/DropshipFlightControl.tsx index 679b78efe843..7466942aa141 100644 --- a/tgui/packages/tgui/interfaces/DropshipFlightControl.tsx +++ b/tgui/packages/tgui/interfaces/DropshipFlightControl.tsx @@ -86,10 +86,13 @@ const DropshipDoorControl = () => { <> {x.value === DoorStatusEnum.SHUTTLE_DOOR_BROKEN && ( - + )} {x.value === DoorStatusEnum.SHUTTLE_DOOR_UNLOCKED && (