Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Falling Falcons: Paratroopers Edition #6150

Merged
merged 20 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions code/game/machinery/computer/dropship_weapons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,48 @@

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)
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))
return FALSE
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))
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/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)
Expand Down
7 changes: 5 additions & 2 deletions code/game/machinery/doors/multi_tile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
..()

Expand All @@ -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")
Expand Down
4 changes: 2 additions & 2 deletions code/game/objects/items/misc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
161 changes: 124 additions & 37 deletions code/game/turfs/transit.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -39,14 +41,44 @@
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 ..()

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()
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)) //if we found a fitting place near the landing zone...
var/turf/deploy_turf = pick(valid_turfs)
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)
Expand All @@ -66,54 +98,109 @@
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)
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)

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)

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
/atom/movable/proc/can_paradrop()
return FALSE

/mob/living/carbon/human/can_paradrop()
if(istype(belt, /obj/item/rappel_harness))
return TRUE
..()
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved

/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
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved
var/image/chute = image('icons/obj/structures/droppod_64x64.dmi', src, "chute_static")

chute.pixel_x -= 16
chute.pixel_y += 16

src.overlays += chute
src.pixel_z = 360
src.forceMove(target)
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved
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)

if(!isliving(crosser))
return // don't know how you got here, but you shouldnt be here.
var/mob/living/fallen_mob = crosser
/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/handle_airdrop(turf/target, dropship_name)
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/item/handle_airdrop(turf/target, dropship_name)
Drulikar marked this conversation as resolved.
Show resolved Hide resolved
..()
if(QDELETED(src))
return
if(!indestructible && w_class == SIZE_SMALL) //small items will be lost, good riddance
deconstruct(FALSE)
return
src.explosion_throw(200) // give it a bit of a kick
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved

/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) // 10 seconds
Stun(3) // 3 seconds
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved
// 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)
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved
death(last_damage_data)
status_flags |= PERMANENTLY_DEAD
return
ihatethisengine marked this conversation as resolved.
Show resolved Hide resolved


/turf/open/space/transit/dropship/alamo
shuttle_tag = DROPSHIP_ALAMO
Expand Down
Loading
Loading