diff --git a/code/__DEFINES/equipment.dm b/code/__DEFINES/equipment.dm index b37ae0d59d64..7ed2658bba21 100644 --- a/code/__DEFINES/equipment.dm +++ b/code/__DEFINES/equipment.dm @@ -86,6 +86,8 @@ #define IGNITING_ITEM (1<<13) /// Overrides NODROP in some cases (stripping) #define FORCEDROP_CONDITIONAL (1<<14) +/// Overrides smartgunner not being able to wear backpacks +#define SMARTGUNNER_BACKPACK_OVERRIDE (1<<15) //========================================================================================== diff --git a/code/datums/supply_packs/gear.dm b/code/datums/supply_packs/gear.dm index 54a2ae221c9d..5343b93dabbd 100644 --- a/code/datums/supply_packs/gear.dm +++ b/code/datums/supply_packs/gear.dm @@ -63,3 +63,32 @@ containertype = /obj/structure/closet/crate/ammo containername = "fulton recovery device crate" group = "Gear" + +/datum/supply_packs/parachute + name = "parachute crate (x20)" + contains = list( + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + /obj/item/parachute, + ) + cost = 40 + containertype = /obj/structure/closet/crate/supply + containername = "parachute crate" + group = "Gear" diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm index 017a5f0736ca..5d61ed536618 100644 --- a/code/game/machinery/computer/dropship_weapons.dm +++ b/code/game/machinery/computer/dropship_weapons.dm @@ -453,6 +453,61 @@ initiate_firemission(user, fm_tag, direction, text2num(offset_x_value), text2num(offset_y_value)) return TRUE + if("paradrop-lock") + var/obj/docking_port/mobile/marine_dropship/linked_shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!linked_shuttle) + return FALSE + if(linked_shuttle.mode != SHUTTLE_CALL) + return FALSE + if(linked_shuttle.paradrop_signal) + clear_locked_turf_and_lock_aft() + return TRUE + var/datum/cas_signal/sig = get_cas_signal(camera_target_id) + if(!sig) + to_chat(user, SPAN_WARNING("No signal chosen.")) + return FALSE + 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)) + to_chat(user, SPAN_WARNING("Target is obscured.")) + return FALSE + 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)) + var/obj/structure/dropship_equipment/paradrop_system/paradrop_system = equipment + if(paradrop_system.system_cooldown > world.time) + to_chat(user, SPAN_WARNING("You toggled the system too recently.")) + return + paradrop_system.system_cooldown = world.time + 5 SECONDS + paradrop_system.visible_message(SPAN_NOTICE("[equipment] hums as it locks to a signal.")) + break + linked_shuttle.paradrop_signal = sig + addtimer(CALLBACK(src, PROC_REF(open_aft_for_paradrop)), 2 SECONDS) + 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)) + return TRUE + +/obj/structure/machinery/computer/dropship_weapons/proc/open_aft_for_paradrop() + var/obj/docking_port/mobile/marine_dropship/shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!shuttle || !shuttle.paradrop_signal || shuttle.mode != SHUTTLE_CALL) + return + shuttle.door_control.control_doors("force-unlock", "aft", TRUE) + +/obj/structure/machinery/computer/dropship_weapons/proc/clear_locked_turf_and_lock_aft() + SIGNAL_HANDLER + var/obj/docking_port/mobile/marine_dropship/shuttle = SSshuttle.getShuttle(shuttle_tag) + if(!shuttle) + return + 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/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/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index 6eb5a333ec81..29199ed741fb 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -77,6 +77,7 @@ list("Technician Welder-Satchel", round(scale * 5), /obj/item/storage/backpack/marine/engineerpack/satchel, VENDOR_ITEM_REGULAR), list("IMP Ammo Rack", round(scale * 2), /obj/item/storage/backpack/marine/ammo_rack, VENDOR_ITEM_REGULAR), list("Radio Telephone Pack", round(scale * 2), /obj/item/storage/backpack/marine/satchel/rto, VENDOR_ITEM_REGULAR), + list("Parachute", round(scale * 20), /obj/item/parachute, VENDOR_ITEM_REGULAR), list("BELTS", -1, null, null), list("G8-A General Utility Pouch", round(scale * 2), /obj/item/storage/backpack/general_belt, VENDOR_ITEM_REGULAR), @@ -89,7 +90,6 @@ list("M276 M82F Holster Rig", round(scale * 2), /obj/item/storage/belt/gun/flaregun, VENDOR_ITEM_REGULAR), list("M276 Shotgun Shell Loading Rig", round(scale * 10), /obj/item/storage/belt/shotgun, VENDOR_ITEM_REGULAR), list("M276 Mortar Operator Belt", round(scale * 2), /obj/item/storage/belt/gun/mortarbelt, VENDOR_ITEM_REGULAR), - list("Rappel Harness", round(scale * 20), /obj/item/rappel_harness, VENDOR_ITEM_REGULAR), list("POUCHES", -1, null, null), list("Autoinjector Pouch", round(scale * 1), /obj/item/storage/pouch/autoinjector, VENDOR_ITEM_REGULAR), diff --git a/code/game/objects/items/misc.dm b/code/game/objects/items/misc.dm index a7df88374b29..8c0f88ddb7ca 100644 --- a/code/game/objects/items/misc.dm +++ b/code/game/objects/items/misc.dm @@ -292,11 +292,12 @@ new /obj/item/evidencebag(src) 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." - icon = 'icons/obj/items/clothing/belts.dmi' - icon_state = "rappel_harness" - item_state = "rappel_harness" +/obj/item/parachute + name = "parachute" + desc = "A surprisingly small yet bulky pack with just enough safety straps to make RnD pass health and safety. The label says the pack comes with two parachutes - main and reserve, but you doubt the pack can fit even one." + icon = 'icons/obj/items/clothing/backpacks.dmi' + icon_state = "parachute_pack" + item_state = "parachute_pack" w_class = SIZE_MASSIVE - flags_equip_slot = SLOT_WAIST + flags_equip_slot = SLOT_BACK + flags_item = SMARTGUNNER_BACKPACK_OVERRIDE diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index dd6a8d920f6f..00175ac5e365 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)) @@ -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 @@ -39,14 +41,42 @@ 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) //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/turf as anything in RANGE_TURFS(crosser.get_paradrop_scatter(), location)) + var/area/turf_area = get_area(turf) + if(!turf_area || CEILING_IS_PROTECTED(turf_area.ceiling, CEILING_PROTECTION_TIER_1)) + continue + if(turf.density) + continue + var/found_dense = FALSE + for(var/atom/turf_atom in turf) + if(turf_atom.density && turf_atom.can_block_movement) + found_dense = TRUE + break + if(found_dense) + continue + if(protected_by_pylon(TURF_PROTECTION_MORTAR, turf)) + continue + valid_turfs += turf + var/turf/deploy_turf + if(length(valid_turfs)) //if we found a fitting place near the landing zone... + deploy_turf = pick(valid_turfs) + else //if we somehow did not. Drop them right on the signal then, there is nothing we can do + deploy_turf = location + 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 + + //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) @@ -67,53 +97,141 @@ 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) + 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(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_drop(atom/movable/crosser, turf/target, dropship_name) - if(QDELETED(crosser)) - return - ADD_TRAIT(crosser, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) +/atom/movable/proc/can_paradrop() + return FALSE + +/atom/movable/proc/get_paradrop_scatter() + return 7 + +/mob/living/carbon/human/can_paradrop() + if(istype(back, /obj/item/parachute)) + return TRUE + return ..() + +/obj/structure/closet/crate/can_paradrop() //for now all crates can be paradropped + return TRUE + +/obj/structure/closet/crate/get_paradrop_scatter() //crates land closer to the signal + return 4 - 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) +/obj/structure/largecrate/can_paradrop() + return TRUE - 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 +/obj/structure/largecrate/get_paradrop_scatter() + return 4 + +/atom/movable/proc/handle_paradrop(turf/target, dropship_name) + clear_active_explosives() + 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") + overlays += cables + var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', src, "chute_static") + + chute.pixel_x -= 16 + chute.pixel_y += 16 + + overlays += chute + pixel_z = 360 + forceMove(target) + playsound(src, 'sound/items/fulton.ogg', 30, 1) + 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) + +/mob/living/carbon/handle_paradrop(turf/target, dropship_name) + ..() + if(client) + playsound_client(client, 'sound/items/fulton.ogg', src, 50, 1) //for some reason you don't hear the sound while dropping, maybe because of force move? + +/atom/movable/proc/clear_parachute(image/cables, image/chute) + if(QDELETED(src)) return + 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/clear_active_explosives() + for(var/obj/item/explosive/explosive in contents) + if(!explosive.active) + continue + explosive.deconstruct(FALSE) + +/atom/movable/proc/handle_airdrop(turf/target, dropship_name) + clear_active_explosives() + ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_SOURCE_DROPSHIP_INTERACTION) + pixel_z = 360 + forceMove(target) + 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/structure/closet/handle_airdrop(turf/target, dropship_name) // good idea but no + if(!opened) + for(var/atom/movable/content in src) + INVOKE_ASYNC(content, TYPE_PROC_REF(/atom/movable, handle_airdrop), target, dropship_name) + open() + . = ..() - if(!isliving(crosser)) - return // don't know how you got here, but you shouldnt be here. - var/mob/living/fallen_mob = crosser +/obj/item/handle_airdrop(turf/target, dropship_name) + ..() + if(QDELETED(src)) + return + if(!indestructible && w_class < SIZE_MEDIUM) //tiny and small items will be lost, good riddance + deconstruct(FALSE) + return + explosion_throw(200) // give it a bit of a kick + +/obj/item/explosive/handle_airdrop(turf/target, dropship_name) + if(active) + deconstruct(FALSE) + return + ..() +/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(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) + Stun(3) // 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) + 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.")) + +/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 + /turf/open/space/transit/dropship/alamo shuttle_tag = DROPSHIP_ALAMO diff --git a/code/modules/clothing/suits/marine_armor/smartgunner.dm b/code/modules/clothing/suits/marine_armor/smartgunner.dm index 430942fbbef8..8f39ef83045c 100644 --- a/code/modules/clothing/suits/marine_armor/smartgunner.dm +++ b/code/modules/clothing/suits/marine_armor/smartgunner.dm @@ -32,7 +32,7 @@ /obj/item/clothing/suit/storage/marine/smartgunner/mob_can_equip(mob/equipping_mob, slot, disable_warning = FALSE) . = ..() - if(equipping_mob.back) + if(equipping_mob.back && !(equipping_mob.back.flags_item & SMARTGUNNER_BACKPACK_OVERRIDE)) to_chat(equipping_mob, SPAN_WARNING("You can't equip [src] while wearing a backpack.")) return FALSE @@ -48,6 +48,9 @@ if(slot != WEAR_BACK) return + if(equipping_item.flags_item & SMARTGUNNER_BACKPACK_OVERRIDE) + return + . = COMPONENT_HUMAN_CANCEL_ATTEMPT_EQUIP if(equipping_item.flags_equip_slot == SLOT_BACK) diff --git a/code/modules/cm_marines/dropship_equipment.dm b/code/modules/cm_marines/dropship_equipment.dm index af06f468adcd..1ddee8e85d20 100644 --- a/code/modules/cm_marines/dropship_equipment.dm +++ b/code/modules/cm_marines/dropship_equipment.dm @@ -1290,130 +1290,29 @@ 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 combat_equipment = FALSE + var/system_cooldown - var/harness = /obj/item/rappel_harness +/obj/structure/dropship_equipment/paradrop_system/ui_data(mob/user) + . = list() + .["signal"] = "[linked_shuttle.paradrop_signal]" + .["locked"] = !!linked_shuttle.paradrop_signal -/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 jump to 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 - - 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) - - 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 +/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/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) diff --git a/icons/mob/humans/onmob/back.dmi b/icons/mob/humans/onmob/back.dmi index 42d46bcc9abe..128b05455d6e 100644 Binary files a/icons/mob/humans/onmob/back.dmi and b/icons/mob/humans/onmob/back.dmi differ diff --git a/icons/mob/humans/onmob/items_lefthand_0.dmi b/icons/mob/humans/onmob/items_lefthand_0.dmi index 4e8c1d59a41a..7d887799815b 100644 Binary files a/icons/mob/humans/onmob/items_lefthand_0.dmi and b/icons/mob/humans/onmob/items_lefthand_0.dmi differ diff --git a/icons/mob/humans/onmob/items_righthand_0.dmi b/icons/mob/humans/onmob/items_righthand_0.dmi index b8285acc65ad..184946a13f0b 100644 Binary files a/icons/mob/humans/onmob/items_righthand_0.dmi and b/icons/mob/humans/onmob/items_righthand_0.dmi differ diff --git a/icons/obj/items/clothing/backpacks.dmi b/icons/obj/items/clothing/backpacks.dmi index be2602f76c57..99240596a9da 100644 Binary files a/icons/obj/items/clothing/backpacks.dmi and b/icons/obj/items/clothing/backpacks.dmi differ diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index 40aab722447d..4d84eb26487f 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -7177,11 +7177,11 @@ req_one_access_txt = "3;22;2;19;7" }, /obj/structure/surface/rack, -/obj/item/rappel_harness{ +/obj/item/parachute{ pixel_y = 8 }, -/obj/item/rappel_harness, -/obj/item/rappel_harness{ +/obj/item/parachute, +/obj/item/parachute{ pixel_y = -6 }, /obj/structure/sign/safety/bulkhead_door{ @@ -30245,7 +30245,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 && (