Leg actuators for RIGs (#2421)

Preview: https://kama.skullnet.me/index.php/s/GsEdb7q733nO1LK

Okay. These modules allow you to fall from any height without taking damage. As long as your suit is powered and they're enabled, anyways. Secondly, they allow you to leap! Civilian grade allow you to leap 4 tiles, military grade ones (syndicate + ERT commander) allow you to leap 7 tiles and to also grapple people (Vox leap feature).

On top of that, if you middle click on the tile you're on with them selected, you will try to leap upwards. If the tile you're facing above you is a solid (non-open turf, but not dense either), then you will start to climb onto that tile. Civilian grade model isn't powerful enough to jump you there fully, so you gotta spend 4 seconds grappling for your life. Get interrupted in that time, you fall. Military grade models hop you instantly.
This commit is contained in:
skull132
2017-05-29 01:29:35 +03:00
committed by GitHub
parent a5d7d50a69
commit 36dfee27eb
9 changed files with 188 additions and 16 deletions
+1 -1
View File
@@ -38,7 +38,7 @@
for(var/atom/movable/AM as mob|obj in src)
Entered(AM)
turfs += src
if(dynamic_lighting)
@@ -14,6 +14,8 @@
* /obj/item/rig_module/device/paperdispenser
* /obj/item/rig_module/device/pen
* /obj/item/rig_module/device/stamp
* /obj/item/rig_module/actuators
* /obj/item/rig_module/actuators/combat
*/
/obj/item/rig_module/device
@@ -472,3 +474,143 @@
interface_desc = "Eats trash like no one's business."
device_type = /obj/item/weapon/matter_decompiler
/obj/item/rig_module/actuators
name = "leg actuators"
desc = "A set of electromechanical actuators, for safe travesal of multilevelled areas."
icon_state = "generic"
interface_name = "leg actuators"
interface_desc = "Allows you to fall from heights and to jump up onto ledges."
disruptive = 1
use_power_cost = 5
module_cooldown = 25
/*
* TOGGLE - dampens fall, on or off.
* SELECTABLE - Jump forward or up!
*/
toggleable = 1
selectable = 1
usable = 0
engage_string = "Toggle Leg Actuators"
activate_string = "Enable Leg Actuators"
deactivate_string = "Disable Leg Actuators"
var/combatType = 0 // Determines whether or not the actuators can do special combat oriented tasks.
// Such as leaping faster, or grappling targets.
var/leapDistance = 4 // Determines how far the actuators allow you to leap (radius, inclusive).
/obj/item/rig_module/actuators/combat
name = "military grade leg actuators"
desc = "A set of high-powered hydraulic actuators, for improved traversal of multilevelled areas."
interface_name = "combat leg actuators"
combatType = 1
leapDistance = 7
use_power_cost = 10
/obj/item/rig_module/actuators/engage(var/atom/target)
if (!..())
return 0
// This is for when you toggle it on or off. Why do they both run the same
// proc chain ...? :l
if (!target)
return 1
var/mob/living/carbon/human/H = holder.wearer
if (!isturf(H.loc))
to_chat(H, "<span class='warning'>You cannot leap out of your current location!</span>")
return 0
var/turf/T = get_turf(target)
if (!T || T.density)
to_chat(H, "<span class='warning'>You cannot leap at solid walls!</span>")
return 0
// Saved, we need it more than 1 place.
var/dist = max(get_dist(T, get_turf(H)), 0)
if (dist)
for (var/A in T)
var/atom/aa = A
if (combatType && ismob(aa))
continue
if (aa.density)
to_chat(H, "<span class='warning'>You cannot leap at a location with solid objects on it!</span>")
return 0
if (T.z != H.z || dist > leapDistance)
to_chat(H, "<span class='warning'>You cannot leap at such a distant object!</span>")
return 0
// Handle leaping at targets with a combat capable version here.
if (combatType && dist && (ismob(target) || (locate(/mob/living) in T)))
H.leap(target, leapDistance)
return 1
// If dist -> horizontal leap. Otherwise, the user clicked the turf that they're
// currently on. Which means they want to do a vertical leap upwards!
if (dist)
H.visible_message("<span class='warning'>\The [H] leaps horizontally at \the [T]!</span>",
"<span class='warning'>You leap horizontally at \the [T]!</span>",
"<span class='warning'>You hear an electric <i>whirr</i> followed by a weighty thump!</span>")
H.face_atom(T)
H.throw_at(T, leapDistance, 1, src)
return 1
else
var/turf/simulated/open/TA = GetAbove(src)
if (!istype(TA))
to_chat(H, "<span class='warning'>There is a ceiling above you that stop you from leaping upwards!</span>")
return 0
for (var/atom/A in TA)
if (!A.CanPass(src, TA, 1.5, 0))
to_chat(H, "<span class='warning'>\The [A] blocks you!</span>")
return 0
var/turf/leapEnd = get_step(TA, H.dir)
if (!leapEnd || istype(leapEnd, /turf/simulated/open) || istype(leapEnd, /turf/space)\
|| leapEnd.density || leapEnd.contains_dense_objects())
to_chat(H, "<span class='warning'>There is no valid ledge to scale ahead of you!</span>")
return 0
H.visible_message("<span class='notice'>\The [H] leaps up, out of view!</span>",
"<span class='notice'>You leap up!</span>")
// This setting is necessary even for combat type, to stop you from moving onto
// the turf, falling back down, and then getting forcemoved to the final destination.
LAZYADD(TA.climbers, H)
H.forceMove(TA)
// Combat type actuators are better, they allow you to jump instantly onto
// a ledge. Regular actuators make you have to climb the rest of the way.
if (!combatType)
H.visible_message("<span class='notice'>\The [H] starts pulling \himself up onto \the [leapEnd].</span>",
"<span class='notice'>You start pulling yourself up onto \the [leapEnd].</span>")
if (!do_after(H, 4 SECONDS, use_user_turf = TRUE))
H.visible_message("<span class='warning'>\The [H] is interrupted and falls!</span>",
"<span class='danger'>You are interrupted and fall back down!</span>")
LAZYREMOVE(TA.climbers, H)
ADD_FALLING_ATOM(H)
return 1
H.visible_message("<span class='notice'>\The [H] finishes climbing onto \the [leapEnd].</span>",
"<span class='notice'>You finish climbing onto \the [leapEnd].</span>")
else
H.visible_message("<span class='warning'>\The [H] lands on \the [leapEnd] with a heavy slam!</span>",
"<span class='warning'>You land on \the [leapEnd] with a heavy thud!</span>")
LAZYREMOVE(TA.climbers, H)
H.forceMove(leapEnd)
return 1
@@ -97,7 +97,8 @@
/obj/item/rig_module/ai_container,
/obj/item/rig_module/power_sink,
/obj/item/rig_module/datajack,
/obj/item/rig_module/self_destruct
/obj/item/rig_module/self_destruct,
/obj/item/rig_module/actuators/combat
)
..()
@@ -25,12 +25,14 @@
/obj/item/rig_module/power_sink,
/obj/item/rig_module/electrowarfare_suite,
/obj/item/rig_module/chem_dispenser/combat,
/obj/item/rig_module/fabricator/energy_net
/obj/item/rig_module/fabricator/energy_net,
/obj/item/rig_module/actuators/combat
)
//Has most of the modules removed
/obj/item/weapon/rig/merc/empty
initial_modules = list(
/obj/item/rig_module/ai_container,
/obj/item/rig_module/electrowarfare_suite //might as well
/obj/item/rig_module/electrowarfare_suite, //might as well
/obj/item/rig_module/actuators/combat // What the dude above me said.
)
@@ -81,7 +81,8 @@
/obj/item/rig_module/device/drill,
/obj/item/rig_module/device/orescanner,
/obj/item/rig_module/device/rcd,
/obj/item/rig_module/vision/meson
/obj/item/rig_module/vision/meson,
/obj/item/rig_module/actuators
)
/obj/item/weapon/rig/industrial/syndicate
@@ -147,7 +148,8 @@
/obj/item/rig_module/maneuvering_jets,
/obj/item/rig_module/mounted/plasmacutter,
/obj/item/rig_module/device/rcd,
/obj/item/rig_module/vision/meson
/obj/item/rig_module/vision/meson,
/obj/item/rig_module/actuators
)
/obj/item/clothing/gloves/rig/ce
@@ -49,7 +49,7 @@
if ((O.client && !( O.blinded )))
O.show_message(text("<span class='danger'>[] [failed ? "tried to tackle" : "has tackled"] down []!</span>", src, T), 1)
/mob/living/carbon/human/proc/leap()
/mob/living/carbon/human/proc/leap(var/mob/living/T = null, var/max_range = 4)
set category = "Abilities"
set name = "Leap"
set desc = "Leap at a target and grab them aggressively."
@@ -61,17 +61,18 @@
src << "You cannot leap in your current state."
return
var/list/choices = list()
for(var/mob/living/M in view(6,src))
if(!istype(M,/mob/living/silicon))
choices += M
choices -= src
if (!T)
var/list/choices = list()
for(var/mob/living/M in view(6,src))
if(!istype(M,/mob/living/silicon))
choices += M
choices -= src
var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices
T = input(src,"Who do you wish to leap at?") as null|anything in choices
if(!T || !src || src.stat) return
if(get_dist(get_turf(T), get_turf(src)) > 4) return
if(get_dist(get_turf(T), get_turf(src)) > max_range) return
if(last_special > world.time)
return
@@ -85,7 +86,10 @@
src.visible_message("<span class='danger'>\The [src] leaps at [T]!</span>")
src.throw_at(get_step(get_turf(T),get_turf(src)), 4, 1, src)
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
// Only Vox get to shriek. Seriously.
if (isvox(src))
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
sleep(5)
+9 -1
View File
@@ -189,8 +189,12 @@
if(locate(/obj/structure/lattice, dest) || locate(/obj/structure/stairs, dest))
return FALSE
// The var/climbers API is implemented here.
if (LAZYLEN(dest.climbers) && (src in dest.climbers))
return FALSE
// See if something prevents us from falling.
for(var/atom/A in below)
for (var/atom/A in below)
if(!A.CanPass(src, dest))
return FALSE
@@ -212,6 +216,10 @@
// Only things that stop mechas are atoms that, well, stop them.
// Lattices and stairs get crushed in fall_through.
/obj/mecha/can_fall(turf/below, turf/simulated/open/dest = src.loc)
// The var/climbers API is implemented here.
if (LAZYLEN(dest.climbers) && (src in dest.climbers))
return FALSE
// See if something prevents us from falling.
for(var/atom/A in below)
if(!A.CanPass(src, dest))
+7
View File
@@ -42,6 +42,9 @@
var/tmp/depth
var/tmp/list/climbers // A lazy list to contain a list of mobs who are currently scaling
// up this turf. Used in human/can_fall.
// An override of turf/Enter() to make it so that magboots allow you to stop
// falling off the damned rock.
/turf/simulated/open/Enter(mob/living/carbon/human/mover, atom/oldloc)
@@ -66,6 +69,10 @@
above = null
below = null
LAZYCLEARLIST(climbers)
UNSETEMPTY(climbers)
return ..()
/turf/simulated/open/get_smooth_underlay_icon(image/underlay_appearance, turf/asking_turf, adjacency_dir)