From 3cc3ad393596275ca200feafca6cbbf524518445 Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:13:19 -0600 Subject: [PATCH] Mining Bluespace Survival Capsule's "Stand back!" alert now actually has meaning (#81193) ## About The Pull Request - Standing in range of a Bluespace Survival Capsule being deployed will now toss you away from the deployed location of the pod, to roughly 2 tiles away. ## Why It's Good For The Game I always found it weird (and a little misleading) that triggering a survival capsule alerts people to "Stand back!", but it's actually harmless to stand on top of it and even smart in some contexts since you phase into it like nothing happened. So I added the missing flavor. This also has some potential shenanigans involving antagging, as you can time it perfectly so that you toss it just in time to throw people away from it. Note: The Luxury Elite pod is so large, that even after being thrown away, you may still end up inside the pod by the time it deploys, but I think that's funny. So. ## Changelog :cl: Melbert add: Shaft Miner's Bluespace Survival Capsules will now throw people away from it when it deploys. Be sure to heed the warning to "Stand back". /:cl: --- code/modules/mining/equipment/survival_pod.dm | 98 ++++++++++++++----- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index c221e78d690..f4463434066 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -37,35 +37,83 @@ . += "This capsule has the [template.name] stored." . += template.description -/obj/item/survivalcapsule/attack_self() +/obj/item/survivalcapsule/interact(mob/user) + . = ..() + if(.) + return . + //Can't grab when capsule is New() because templates aren't loaded then get_template() - if(!used) - loc.visible_message(span_warning("\The [src] begins to shake. Stand back!")) - used = TRUE - sleep(5 SECONDS) - var/turf/deploy_location = get_turf(src) - var/status = template.check_deploy(deploy_location) - switch(status) - if(SHELTER_DEPLOY_BAD_AREA) - src.loc.visible_message(span_warning("\The [src] will not function in this area.")) - if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP) - var/width = template.width - var/height = template.height - src.loc.visible_message(span_warning("\The [src] doesn't have room to deploy! You need to clear a [width]x[height] area!")) - if(status != SHELTER_DEPLOY_ALLOWED) - used = FALSE - return + if(used) + return FALSE - template.load(deploy_location, centered = TRUE) - var/turf/T = deploy_location - if(!is_mining_level(T.z)) //only report capsules away from the mining/lavaland level - message_admins("[ADMIN_LOOKUPFLW(usr)] activated a bluespace capsule away from the mining level! [ADMIN_VERBOSEJMP(T)]") - log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [AREACOORD(T)]") + loc.visible_message(span_warning("[src] begins to shake. Stand back!")) + used = TRUE + addtimer(CALLBACK(src, PROC_REF(expand), user), 5 SECONDS) + return TRUE - playsound(src, 'sound/effects/phasein.ogg', 100, TRUE) - new /obj/effect/particle_effect/fluid/smoke(get_turf(src)) - qdel(src) +/// Expands the capsule into a full shelter, placing the template at the item's location (NOT triggerer's location) +/obj/item/survivalcapsule/proc/expand(mob/triggerer) + if(QDELETED(src)) + return + + var/turf/deploy_location = get_turf(src) + var/status = template.check_deploy(deploy_location) + switch(status) + if(SHELTER_DEPLOY_BAD_AREA) + loc.visible_message(span_warning("[src] will not function in this area.")) + if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP) + loc.visible_message(span_warning("[src] doesn't have room to deploy! You need to clear a [template.width]x[template.height] area!")) + + if(status != SHELTER_DEPLOY_ALLOWED) + used = FALSE + return + + yote_nearby(deploy_location) + template.load(deploy_location, centered = TRUE) + trigger_admin_alert(triggerer, deploy_location) + playsound(src, 'sound/effects/phasein.ogg', 100, TRUE) + new /obj/effect/particle_effect/fluid/smoke(get_turf(src)) + qdel(src) + +/// Throws any mobs near the deployed location away from the item / shelter +/// Does some math to make closer mobs get thrown further +/obj/item/survivalcapsule/proc/yote_nearby(turf/deploy_location) + var/width = template.width + var/height = template.height + var/base_x_throw_distance = ceil(width / 2) + var/base_y_throw_distance = ceil(height / 2) + for(var/mob/living/did_not_stand_back in range(loc, "[width]x[height]")) + var/dir_to_center = get_dir(deploy_location, did_not_stand_back) || pick(GLOB.alldirs) + // Aiming to throw the target just enough to get them out of the range of the shelter + // IE: Stronger if they're closer, weaker if they're further away + var/throw_dist = 0 + var/x_component = abs(did_not_stand_back.x - deploy_location.x) + var/y_component = abs(did_not_stand_back.y - deploy_location.y) + if(ISDIAGONALDIR(dir_to_center)) + throw_dist = ceil(sqrt(base_x_throw_distance ** 2 + base_y_throw_distance ** 2) - (sqrt(x_component ** 2 + y_component ** 2))) + else if(dir_to_center & (NORTH|SOUTH)) + throw_dist = base_y_throw_distance - y_component + 1 + else if(dir_to_center & (EAST|WEST)) + throw_dist = base_x_throw_distance - x_component + 1 + + did_not_stand_back.Paralyze(3 SECONDS) + did_not_stand_back.Knockdown(6 SECONDS) + did_not_stand_back.throw_at( + target = get_edge_target_turf(did_not_stand_back, dir_to_center), + range = throw_dist, + speed = 3, + force = MOVE_FORCE_VERY_STRONG, + ) + +/// Logs if the capsule was triggered, by default only if it happened on non-lavaland +/obj/item/survivalcapsule/proc/trigger_admin_alert(mob/triggerer, turf/trigger_loc) + //only report capsules away from the mining/lavaland level + if(is_mining_level(trigger_loc.z)) + return + + message_admins("[ADMIN_LOOKUPFLW(triggerer)] activated a bluespace capsule away from the mining level! [ADMIN_VERBOSEJMP(trigger_loc)]") + log_admin("[key_name(triggerer)] activated a bluespace capsule away from the mining level at [AREACOORD(trigger_loc)]") //Non-default pods