Fireman Carrying (#12183)

This commit is contained in:
Geeves
2021-07-21 13:58:42 +02:00
committed by GitHub
parent cd6a48502d
commit 225065e3c1
13 changed files with 156 additions and 28 deletions
+4
View File
@@ -25,6 +25,10 @@
#define INCORPOREAL_SHADE 4 // Shady
#define INCORPOREAL_MECH 5 // stripped down bstech
#define MOB_GRAB_NONE 0
#define MOB_GRAB_NORMAL 1
#define MOB_GRAB_FIREMAN 2
// Grab levels.
#define GRAB_PASSIVE 1
#define GRAB_AGGRESSIVE 2
+13 -4
View File
@@ -53,16 +53,25 @@
if(does_teleport)
teleport(user)
/obj/effect/portal/proc/teleport(atom/movable/M)
/obj/effect/portal/proc/teleport(atom/movable/movable)
if(!does_teleport) // just to be safe
return
if(istype(M, /obj/effect)) //sparks don't teleport
if(istype(movable, /obj/effect)) //sparks don't teleport
return
if(!target)
qdel(src)
return
var/has_teleported = FALSE
if(istype(M, /atom/movable))
var/list/things_to_teleport = list(movable)
if(ismob(movable))
var/mob/M = movable
if(M.pulling)
things_to_teleport += M.pulling
if(ishuman(movable))
var/mob/living/carbon/human/H = movable
for(var/obj/item/grab/G in list(H.l_hand, H.r_hand))
things_to_teleport += G.affecting
for(var/atom/movable/M in things_to_teleport)
if(has_failed) //oh dear a problem, put em in deep space
icon_state = "portal1" // only tell people the portal failed after a teleport has been done
desc = "A bluespace tear in space, reaching directly to another point within this region. Definitely unstable."
@@ -72,7 +81,7 @@
if(do_teleport(M, target, precision))
has_teleported = TRUE
if(!has_teleported)
visible_message(SPAN_WARNING("\The [src] oscillates violently as \the [M] comes into contact with it, and collapses! Seems like the rift was unstable..."))
visible_message(SPAN_WARNING("\The [src] oscillates violently as \the [movable] comes into contact with it, and collapses! Seems like the rift was unstable..."))
qdel(src)
/obj/effect/portal/Destroy()
@@ -15,7 +15,7 @@
if (I_GRAB)
if (M == src)
return
var/obj/item/grab/G = new /obj/item/grab( M, src )
var/obj/item/grab/G = new /obj/item/grab(M, M, src)
M.put_in_active_hand(G)
+1 -1
View File
@@ -167,7 +167,7 @@
/mob/living/carbon/swap_hand()
var/obj/item/item_in_hand = src.get_active_hand()
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
if(istype(item_in_hand,/obj/item/material/twohanded) || istype(item_in_hand,/obj/item/gun) || istype(item_in_hand,/obj/item/pickaxe))
if(istype(item_in_hand,/obj/item/material/twohanded) || istype(item_in_hand,/obj/item/gun) || istype(item_in_hand,/obj/item/pickaxe) || istype(item_in_hand, /obj/item/grab))
if(item_in_hand:wielded == 1)
to_chat(usr, SPAN_WARNING("Your other hand is too busy holding the [item_in_hand.name]"))
return
@@ -134,7 +134,7 @@
if(w_uniform)
w_uniform.add_fingerprint(M)
var/obj/item/grab/G = new /obj/item/grab(M, src)
var/obj/item/grab/G = new /obj/item/grab(M, M, src)
if(buckled_to)
to_chat(M, "<span class='notice'>You cannot grab [src], [src.get_pronoun("he")] [get_pronoun("is")] buckled in!</span>")
if(!G) //the grab will delete itself in New if affecting is anchored
@@ -558,7 +558,7 @@ emp_act
if(src.w_uniform)
src.w_uniform.add_fingerprint(src)
var/obj/item/grab/G = new /obj/item/grab(user, src)
var/obj/item/grab/G = new /obj/item/grab(user, user, src)
if(buckled_to)
to_chat(user, "<span class='notice'>You cannot grab [src], [get_pronoun("he")] [get_pronoun("is")] buckled in!</span>")
if(!G) //the grab will delete itself in New if affecting is anchored
@@ -338,7 +338,7 @@
if(I_GRAB)
if(M == src || anchored)
return
var/obj/item/grab/G = new /obj/item/grab(M, src)
var/obj/item/grab/G = new /obj/item/grab(M, M, src)
M.put_in_active_hand(G)
@@ -481,7 +481,7 @@
if (!attempt_grab(M))
return
var/obj/item/grab/G = new /obj/item/grab(M, src)
var/obj/item/grab/G = new /obj/item/grab(M, M, src)
M.put_in_active_hand(G)
+10 -5
View File
@@ -936,11 +936,12 @@
else if(buckled_to)
anchored = 1
canmove = 0
if(buckled_to.buckle_lying != -1)
lying = buckled_to.buckle_lying
if(buckled_to.buckle_movable)
anchored = 0
canmove = 1
if(isobj(buckled_to))
if(buckled_to.buckle_lying != -1)
lying = buckled_to.buckle_lying
if(buckled_to.buckle_movable)
anchored = 0
canmove = 1
else if(captured)
anchored = 1
canmove = 0
@@ -957,6 +958,10 @@
density = initial(density)
for(var/obj/item/grab/G in grabbed_by)
if(G.wielded)
canmove = FALSE
lying = TRUE
break
if(G.state >= GRAB_AGGRESSIVE)
canmove = 0
break
+96 -11
View File
@@ -42,6 +42,9 @@
var/dancing //determines if assailant and affecting keep looking at each other. Basically a wrestling position
var/has_choked = FALSE //Used as a counter for choking people.
var/obj/item/grab/linked_grab
var/wielded = FALSE
layer = SCREEN_LAYER
abstract = 1
item_state = "nothing"
@@ -51,15 +54,13 @@
pickup_sound = null
equip_sound = null
/obj/item/grab/New(mob/user, mob/victim)
..()
loc = user
/obj/item/grab/Initialize(mapload, mob/user, mob/victim)
. = ..()
assailant = user
affecting = victim
if(affecting.anchored || !assailant.Adjacent(victim))
qdel(src)
return
return INITIALIZE_HINT_QDEL
affecting.grabbed_by += src
@@ -81,7 +82,7 @@
//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code.
/obj/item/grab/proc/throw_held()
if(affecting)
if(affecting.buckled_to)
if(affecting.buckled_to && affecting.buckled_to != assailant) // can't throw in fireman carries atm, but future proofing
return null
if(state >= GRAB_AGGRESSIVE)
animate(affecting, pixel_x = affecting.get_standard_pixel_x(), pixel_y = affecting.get_standard_pixel_y(), 4, 1)
@@ -203,13 +204,20 @@
/obj/item/grab/proc/adjust_position()
if(!affecting)
return
if(affecting.buckled_to)
if(affecting.buckled_to && affecting.buckled_to != assailant)
animate(affecting, pixel_x = affecting.get_standard_pixel_x(), pixel_y = affecting.get_standard_pixel_y(), 4, 1, LINEAR_EASING)
return
if(affecting.lying || force_down)
if(affecting.lying || force_down || wielded)
affecting.update_canmove()
animate(affecting, pixel_x = affecting.get_standard_pixel_x(), pixel_y = affecting.get_standard_pixel_y(), 5, 1, LINEAR_EASING)
affecting.set_dir(SOUTH)
var/shift_amount = wielded ? 6 : 0
animate(affecting, pixel_x = affecting.get_standard_pixel_x(), pixel_y = affecting.get_standard_pixel_y() + shift_amount, 5, 1, LINEAR_EASING)
var/set_dir = wielded ? assailant.dir : SOUTH
affecting.set_dir(set_dir)
if(wielded)
if(assailant.dir != NORTH)
affecting.layer = assailant.layer - 0.1
else
affecting.layer = assailant.layer + 0.1
return
var/shift = 0
var/adir = get_dir(assailant, affecting)
@@ -251,6 +259,8 @@
return
if(state == GRAB_UPGRADING)
return
if(wielded)
return
if(!assailant.canClick())
return
if(!assailant.canmove || assailant.lying)
@@ -400,8 +410,18 @@
var/destroying = 0
/obj/item/grab/Destroy()
if(!QDELETED(linked_grab))
qdel(linked_grab)
if(wielded)
if(affecting.buckled_to == assailant)
affecting.buckled_to = null
affecting.update_canmove()
affecting.anchored = FALSE
moved_event.unregister(assailant, src, /obj/item/grab/proc/move_affecting)
animate(affecting, pixel_x = affecting.get_standard_pixel_x(), pixel_y = affecting.get_standard_pixel_y(), 4, 1, LINEAR_EASING)
affecting.layer = 4
affecting.layer = initial(affecting.layer)
if(affecting)
ADD_FALLING_ATOM(affecting) // Makes the grabbee check if they can fall.
affecting.grabbed_by -= src
@@ -414,3 +434,68 @@
hud = null
destroying = 1 // stops us calling qdel(src) on dropped()
return ..()
/obj/item/grab/MouseDrop(mob/living/carbon/human/H)
if(wielded || affecting.buckled_to || !istype(H) || assailant != H || H.get_active_hand() != src)
return
if(!ishuman(affecting))
to_chat(H, SPAN_WARNING("You can only fireman carry humanoids!"))
return
var/mob/living/carbon/human/affected_human = affecting
if(affected_human.species.mob_size > 25)
to_chat(H, SPAN_WARNING("\The [affected_human] is way too big to fireman carry!"))
return
if(state < GRAB_AGGRESSIVE)
to_chat(H, SPAN_WARNING("You need an aggressive grab before you can fireman carry someone!"))
return
if(H.get_inactive_hand())
to_chat(H, SPAN_WARNING("Your other hand must be empty to fireman carry someone!"))
return
H.visible_message("<b>[H]</b> starts lifting \the [affecting] onto their shoulders...", SPAN_NOTICE("You start lifting \the [affecting] onto your shoulders..."))
if(!do_after(H, 3 SECONDS, TRUE))
return
if(affecting.buckled_to)
return
if(H.get_inactive_hand())
to_chat(H, SPAN_WARNING("Your other hand must be empty to fireman carry someone!"))
return
var/obj/item/grab/offhand/OH = new /obj/item/grab/offhand(H, H, affecting, src)
H.put_in_hands(OH)
H.visible_message("<b>[H]</b> lifts \the [affecting] onto their shoulders!", SPAN_NOTICE("You lift \the [affecting] onto your shoulders!"))
affecting.buckled_to = assailant
affecting.forceMove(H.loc)
adjust_position()
moved_event.register(assailant, src, /obj/item/grab/proc/move_affecting)
/obj/item/grab/proc/move_affecting()
if(affecting && assailant.Adjacent(affecting)) // Only move if it's near us.
affecting.forceMove(assailant.loc)
/obj/item/grab/offhand
icon_state = "!reinforce"
/obj/item/grab/offhand/Initialize(mapload, mob/user, mob/victim, var/obj/item/grab/linked)
. = ..()
linked_grab = linked
linked.linked_grab = src
linked_grab.wielded = TRUE
linked_grab.state = GRAB_AGGRESSIVE
icon_state = "!reinforce"
hud.icon_state = "!reinforce"
linked_grab.icon_state = "!reinforce"
linked_grab.hud.icon_state = "!reinforce"
/obj/item/grab/offhand/process()
return
/obj/item/grab/offhand/adjust_position()
return
+16 -1
View File
@@ -1230,4 +1230,19 @@ proc/is_blind(A)
/mob/proc/can_hear_radio(var/list/speaker_coverage = list())
var/turf/ear = get_turf(src)
if(ear && speaker_coverage[ear])
return TRUE
return TRUE
/mob/proc/has_grab()
. = MOB_GRAB_NONE
if(istype(l_hand, /obj/item/grab))
var/obj/item/grab/l_grab = l_hand
if(l_grab.wielded)
. = max(MOB_GRAB_FIREMAN, .)
else
. = max(MOB_GRAB_NORMAL, .)
if(istype(r_hand, /obj/item/grab))
var/obj/item/grab/r_grab = r_hand
if(r_grab.wielded)
. = max(MOB_GRAB_FIREMAN, .)
else
. = max(MOB_GRAB_NORMAL, .)
+4 -1
View File
@@ -334,7 +334,10 @@
//We are now going to move
moving = 1
//Something with pulling things
if (mob_is_human && (istype(mob:l_hand, /obj/item/grab) || istype(mob:r_hand, /obj/item/grab)))
var/grab_level = mob.has_grab()
if(grab_level == MOB_GRAB_FIREMAN)
move_delay++
if (mob_is_human && grab_level == MOB_GRAB_NORMAL)
move_delay = max(move_delay, world.time + 7)
var/list/L = mob.ret_grab()
if(istype(L, /list))
@@ -0,0 +1,7 @@
author: Geeves
delete-after: True
changes:
- rscadd: "It is now possible to fireman carry someone, provided you have an aggressive grab or higher on them. Simply drag the grab in your active hand onto your sprite and wait for a bit. To release, drop the grab."
- rscadd: "Pulling or grabbing someone and dragging them into a portal will now teleport it/them with you."