Merge pull request #16016 from SandPoot/throwing-update
[TESTMERGE] Updates firemanning, throwing stuff
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
///from base of atom/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
#define COMSIG_ATOM_HITBY "atom_hitby"
|
||||
2
code/__DEFINES/dcs/signals/signals_global.dm
Normal file
2
code/__DEFINES/dcs/signals/signals_global.dm
Normal file
@@ -0,0 +1,2 @@
|
||||
/// a person somewhere has thrown something : (mob/living/carbon/carbon_thrower, target)
|
||||
#define COMSIG_GLOB_CARBON_THROW_THING "!throw_thing"
|
||||
@@ -0,0 +1,2 @@
|
||||
/// from mob/proc/dropItemToGround()
|
||||
#define COMSIG_MOB_DROPPING_ITEM "mob_dropping_item"
|
||||
@@ -39,6 +39,21 @@
|
||||
/datum/proc/p_es(temp_gender)
|
||||
. = "es"
|
||||
|
||||
/datum/proc/plural_s(pluralize)
|
||||
switch(copytext_char(pluralize, -2))
|
||||
if ("ss")
|
||||
return "es"
|
||||
if ("sh")
|
||||
return "es"
|
||||
if ("ch")
|
||||
return "es"
|
||||
else
|
||||
switch(copytext_char(pluralize, -1))
|
||||
if("s", "x", "z")
|
||||
return "es"
|
||||
else
|
||||
return "s"
|
||||
|
||||
//like clients, which do have gender.
|
||||
/client/p_they(capitalized, temp_gender)
|
||||
if(!temp_gender)
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
DelayNextAction(CLICK_CD_HANDCUFFED)
|
||||
return RestrainedClickOn(A)
|
||||
|
||||
if(in_throw_mode)
|
||||
if(throw_mode)
|
||||
throw_item(A)
|
||||
return
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
DelayNextAction(CLICK_CD_HANDCUFFED)
|
||||
return RestrainedClickOn(A)
|
||||
|
||||
if(in_throw_mode)
|
||||
if(throw_mode)
|
||||
throw_item(A)//todo: make it plausible to lightly toss items via right-click
|
||||
return
|
||||
|
||||
|
||||
@@ -41,37 +41,61 @@ SUBSYSTEM_DEF(throwing)
|
||||
currentrun = null
|
||||
|
||||
/datum/thrownthing
|
||||
///Defines the atom that has been thrown (Objects and Mobs, mostly.)
|
||||
var/atom/movable/thrownthing
|
||||
var/atom/target
|
||||
///Weakref to the original intended target of the throw, to prevent hardDels
|
||||
var/datum/weakref/initial_target
|
||||
///The turf that the target was on, if it's not a turf itself.
|
||||
var/turf/target_turf
|
||||
///If the target happens to be a carbon and that carbon has a body zone aimed at, this is carried on here.
|
||||
var/target_zone
|
||||
///The initial direction of the thrower of the thrownthing for building the trajectory of the throw.
|
||||
var/init_dir
|
||||
///The maximum number of turfs that the thrownthing will travel to reach it's target.
|
||||
var/maxrange
|
||||
///The speed of the projectile thrownthing being thrown.
|
||||
var/speed
|
||||
///If a mob is the one who has thrown the object, then it's moved here.
|
||||
var/mob/thrower
|
||||
///A variable that helps in describing objects thrown at an angle, if it should be moved diagonally first or last.
|
||||
var/diagonals_first
|
||||
var/dist_travelled = 0
|
||||
var/start_time
|
||||
var/dist_x
|
||||
var/dist_y
|
||||
var/dx
|
||||
var/dy
|
||||
var/force = MOVE_FORCE_DEFAULT
|
||||
var/gentle = FALSE
|
||||
///Set to TRUE if the throw is exclusively diagonal (45 Degree angle throws for example)
|
||||
var/pure_diagonal
|
||||
///Tracks how far a thrownthing has traveled mid-throw for the purposes of maxrange
|
||||
var/dist_travelled = 0
|
||||
///The start_time obtained via world.time for the purposes of tiles moved/tick.
|
||||
var/start_time
|
||||
///Distance to travel in the X axis/direction.
|
||||
var/dist_x
|
||||
///Distance to travel in the y axis/direction.
|
||||
var/dist_y
|
||||
///The Horizontal direction we're traveling (EAST or WEST)
|
||||
var/dx
|
||||
///The VERTICAL direction we're traveling (NORTH or SOUTH)
|
||||
var/dy
|
||||
///The movement force provided to a given object in transit. More info on these in move_force.dm
|
||||
var/force = MOVE_FORCE_DEFAULT
|
||||
///If the throw is gentle, then the thrownthing is harmless on impact.
|
||||
var/gentle = FALSE
|
||||
///How many tiles that need to be moved in order to travel to the target.
|
||||
var/diagonal_error
|
||||
///If a thrown thing has a callback, it can be invoked here within thrownthing.
|
||||
var/datum/callback/callback
|
||||
///Mainly exists for things that would freeze a thrown object in place, like a timestop'd tile. Or a Tractor Beam.
|
||||
var/paused = FALSE
|
||||
///How long an object has been paused for, to be added to the travel time.
|
||||
var/delayed_time = 0
|
||||
///The last world.time value stored when the thrownthing was moving.
|
||||
var/last_move = 0
|
||||
|
||||
|
||||
/datum/thrownthing/New(thrownthing, target, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
|
||||
/datum/thrownthing/New(thrownthing, target, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
|
||||
. = ..()
|
||||
src.thrownthing = thrownthing
|
||||
RegisterSignal(thrownthing, COMSIG_PARENT_QDELETING, .proc/on_thrownthing_qdel)
|
||||
src.target = target
|
||||
src.target_turf = target_turf
|
||||
src.target_turf = get_turf(target)
|
||||
if(target_turf != target)
|
||||
src.initial_target = WEAKREF(target)
|
||||
src.init_dir = init_dir
|
||||
src.maxrange = maxrange
|
||||
src.speed = speed
|
||||
@@ -90,8 +114,8 @@ SUBSYSTEM_DEF(throwing)
|
||||
SSthrowing.currentrun -= thrownthing
|
||||
thrownthing.throwing = null
|
||||
thrownthing = null
|
||||
target = null
|
||||
thrower = null
|
||||
initial_target = null
|
||||
if(callback)
|
||||
QDEL_NULL(callback) //It stores a reference to the thrownthing, its source. Let's clean that.
|
||||
return ..()
|
||||
@@ -114,9 +138,17 @@ SUBSYSTEM_DEF(throwing)
|
||||
delayed_time += world.time - last_move
|
||||
return
|
||||
|
||||
if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept
|
||||
finalize()
|
||||
return
|
||||
var/atom/movable/actual_target = initial_target?.resolve()
|
||||
|
||||
if(dist_travelled) //to catch sneaky things moving on our tile while we slept
|
||||
for(var/atom/movable/obstacle as anything in get_turf(thrownthing))
|
||||
if (obstacle == thrownthing || (obstacle == thrower && !ismob(thrownthing)))
|
||||
continue
|
||||
if(obstacle.pass_flags_self & LETPASSTHROW)
|
||||
continue
|
||||
if (obstacle == actual_target || (obstacle.density && !(obstacle.flags_1 & ON_BORDER_1)))
|
||||
finalize(TRUE, obstacle)
|
||||
return
|
||||
|
||||
var/atom/step
|
||||
|
||||
@@ -143,14 +175,17 @@ SUBSYSTEM_DEF(throwing)
|
||||
finalize()
|
||||
return
|
||||
|
||||
AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed))
|
||||
|
||||
if (!AM.throwing) // we hit something during our move
|
||||
finalize(hit = TRUE)
|
||||
if(!AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed))) // we hit something during our move...
|
||||
if(AM.throwing) // ...but finalize() wasn't called on Bump() because of a higher level definition that doesn't always call parent.
|
||||
finalize()
|
||||
return
|
||||
|
||||
dist_travelled++
|
||||
|
||||
if(actual_target && !(actual_target.pass_flags_self & LETPASSTHROW) && actual_target.loc == AM.loc) // we crossed a movable with no density (e.g. a mouse or APC) we intend to hit anyway.
|
||||
finalize(TRUE, actual_target)
|
||||
return
|
||||
|
||||
if (dist_travelled > MAX_THROWING_DIST)
|
||||
finalize()
|
||||
return
|
||||
@@ -162,11 +197,10 @@ SUBSYSTEM_DEF(throwing)
|
||||
return
|
||||
thrownthing.throwing = null
|
||||
if (!hit)
|
||||
for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on.
|
||||
var/atom/A = thing
|
||||
if (A == target)
|
||||
for (var/atom/movable/obstacle as anything in get_turf(thrownthing)) //looking for our target on the turf we land on.
|
||||
if (obstacle == target)
|
||||
hit = TRUE
|
||||
thrownthing.throw_impact(A, src)
|
||||
thrownthing.throw_impact(obstacle, src)
|
||||
if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
|
||||
return //deletion should already be handled by on_thrownthing_qdel()
|
||||
break
|
||||
@@ -192,15 +226,3 @@ SUBSYSTEM_DEF(throwing)
|
||||
T.zFall(thrownthing)
|
||||
|
||||
qdel(src)
|
||||
|
||||
/datum/thrownthing/proc/hit_atom(atom/A)
|
||||
finalize(hit=TRUE, target=A)
|
||||
|
||||
/datum/thrownthing/proc/hitcheck()
|
||||
for (var/thing in get_turf(thrownthing))
|
||||
var/atom/movable/AM = thing
|
||||
if (AM == thrownthing || (AM == thrower && !ismob(thrownthing)))
|
||||
continue
|
||||
if (AM.density && !(AM.pass_flags_self & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
|
||||
finalize(hit=TRUE, target=AM)
|
||||
return TRUE
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
return
|
||||
if(LAZYACCESS(modifiers, ALT_CLICK))
|
||||
return
|
||||
if(source.mob.in_throw_mode)
|
||||
if(source.mob.throw_mode)
|
||||
return
|
||||
if(!isturf(source.mob.loc)) //No firing inside lockers and stuff.
|
||||
return
|
||||
|
||||
@@ -392,3 +392,12 @@
|
||||
if(rider in AM.buckled_mobs)
|
||||
AM.unbuckle_mob(rider)
|
||||
. = ..()
|
||||
|
||||
/obj/item/riding_offhand/on_thrown(mob/living/carbon/user, atom/target)
|
||||
if(rider == user)
|
||||
return //Piggyback user.
|
||||
user.unbuckle_mob(rider)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, span_notice("You gently let go of [rider]."))
|
||||
return
|
||||
return rider
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
///See if we can tackle or not. If we can, leap!
|
||||
/datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/A, params)
|
||||
if(!user.in_throw_mode || user.get_active_held_item() || user.pulling || user.buckling)
|
||||
if(!user.throw_mode || user.get_active_held_item() || user.pulling || user.buckling)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_HULK))
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
return FALSE
|
||||
source.visible_message("<span class='warning'>[user] starts picking up [source].</span>", \
|
||||
"<span class='userdanger'>[user] starts picking you up!</span>")
|
||||
if(!do_after(user, 20, target = source) || source.buckled)
|
||||
if(!do_after(user, 2 SECONDS, target = source) || source.buckled)
|
||||
return FALSE
|
||||
|
||||
source.visible_message("<span class='warning'>[user] picks up [source]!</span>", \
|
||||
@@ -95,6 +95,7 @@
|
||||
dynamic_hair_suffix = ""
|
||||
var/mob/living/held_mob
|
||||
var/escape_on_find
|
||||
var/destroying = FALSE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE)
|
||||
. = ..()
|
||||
@@ -134,45 +135,54 @@
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Destroy()
|
||||
destroying = TRUE
|
||||
if(held_mob)
|
||||
release()
|
||||
release(FALSE)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/examine(mob/user)
|
||||
return held_mob?.examine(user) || ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
if(AM == held_mob)
|
||||
held_mob.reset_perspective()
|
||||
held_mob = null
|
||||
QDEL_IN(src, 1) //To avoid a qdel loop.
|
||||
/obj/item/clothing/head/mob_holder/on_thrown(mob/living/carbon/user, atom/target)
|
||||
if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP))
|
||||
return
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, span_notice("You set [src] down gently on the ground."))
|
||||
release()
|
||||
return
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
if(AM != held_mob)
|
||||
var/destination = loc
|
||||
if(isliving(loc)) //the mob is held or worn, drop things on the floor
|
||||
destination = get_turf(loc)
|
||||
AM.forceMove(destination)
|
||||
var/mob/living/throw_mob = held_mob
|
||||
release()
|
||||
return throw_mob
|
||||
|
||||
/obj/item/clothing/head/mob_holder/dropped(mob/user)
|
||||
. = ..()
|
||||
if(held_mob && !ismob(loc) && !istype(loc,/obj/item/storage))//don't release on soft-drops
|
||||
if(held_mob && isturf(loc))
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/proc/release()
|
||||
if(held_mob)
|
||||
var/mob/living/L = held_mob
|
||||
held_mob = null
|
||||
L.forceMove(get_turf(L))
|
||||
L.reset_perspective()
|
||||
L.setDir(SOUTH)
|
||||
if(!QDELETED(src))
|
||||
/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE, display_messages = TRUE)
|
||||
if(!held_mob)
|
||||
if(del_on_release && !destroying)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
var/mob/living/released_mob = held_mob
|
||||
held_mob = null // stops the held mob from being release()'d twice.
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
if(display_messages)
|
||||
to_chat(L, span_warning("[released_mob] wriggles free!"))
|
||||
L.dropItemToGround(src)
|
||||
released_mob.forceMove(drop_location())
|
||||
released_mob.reset_perspective()
|
||||
released_mob.setDir(SOUTH)
|
||||
if(display_messages)
|
||||
released_mob.visible_message(span_warning("[released_mob] uncurls!"))
|
||||
if(del_on_release && !destroying)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
|
||||
return
|
||||
/obj/item/clothing/head/mob_holder/relaymove(mob/living/user, direction)
|
||||
container_resist()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/container_resist()
|
||||
if(isliving(loc))
|
||||
@@ -180,6 +190,11 @@
|
||||
L.visible_message("<span class='warning'>[held_mob] escapes from [L]!</span>", "<span class='warning'>[held_mob] escapes your grip!</span>")
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(held_mob && held_mob == gone)
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(M == held_mob || !ishuman(M)) //monkeys holding monkeys holding monkeys...
|
||||
return FALSE
|
||||
@@ -232,7 +247,9 @@
|
||||
return location.transfer_air(taker, ratio)
|
||||
|
||||
// escape when found if applicable
|
||||
/obj/item/clothing/head/mob_holder/on_found(mob/living/finder)
|
||||
/obj/item/clothing/head/mob_holder/on_found(mob/finder)
|
||||
if(escape_on_find)
|
||||
finder.visible_message("[finder] accidentally releases the [held_mob]!")
|
||||
release()
|
||||
to_chat(finder, span_warning("\A [held_mob.name] pops out! "))
|
||||
finder.visible_message(span_warning("\A [held_mob.name] pops out of the container [finder] is opening!"), ignored_mobs = finder)
|
||||
release(TRUE, FALSE)
|
||||
return
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
return BULLET_ACT_HIT
|
||||
if(!isturf(A.loc)) //NO MOTHERFLIPPIN MECHS!
|
||||
return BULLET_ACT_HIT
|
||||
if(A.in_throw_mode)
|
||||
if(A.throw_mode)
|
||||
A.visible_message("<span class='danger'>[A] effortlessly swats the projectile aside! They can deflect projectile with their bare hands!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
|
||||
playsound(get_turf(A), pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE)
|
||||
P.firer = A
|
||||
|
||||
@@ -686,13 +686,29 @@
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...).
|
||||
addtimer(CALLBACK(src, .proc/hitby_react, AM), 2)
|
||||
/**
|
||||
* React to being hit by a thrown object
|
||||
*
|
||||
* Default behaviour is to call [hitby_react][/atom/proc/hitby_react] on ourselves after 2 seconds if we are dense
|
||||
* and under normal gravity.
|
||||
*
|
||||
* Im not sure why this the case, maybe to prevent lots of hitby's if the thrown object is
|
||||
* deleted shortly after hitting something (during explosions or other massive events that
|
||||
* throw lots of items around - singularity being a notable example)
|
||||
*/
|
||||
/atom/proc/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HITBY, hitting_atom, skipcatch, hitpush, blocked, throwingdatum)
|
||||
if(density && !has_gravity(hitting_atom)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...).
|
||||
addtimer(CALLBACK(src, .proc/hitby_react, hitting_atom), 2)
|
||||
|
||||
/atom/proc/hitby_react(atom/movable/AM)
|
||||
if(AM && isturf(AM.loc))
|
||||
step(AM, turn(AM.dir, 180))
|
||||
/**
|
||||
* We have have actually hit the passed in atom
|
||||
*
|
||||
* Default behaviour is to move back from the item that hit us
|
||||
*/
|
||||
/atom/proc/hitby_react(atom/movable/harmed_atom)
|
||||
if(harmed_atom && isturf(harmed_atom.loc))
|
||||
step(harmed_atom, turn(harmed_atom.dir, 180))
|
||||
|
||||
/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
|
||||
return
|
||||
|
||||
@@ -383,9 +383,9 @@
|
||||
if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit
|
||||
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)
|
||||
|
||||
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
|
||||
/atom/movable/hitby(atom/movable/hitting_atom, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
|
||||
if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO))))
|
||||
step(src, AM.dir)
|
||||
step(src, hitting_atom.dir)
|
||||
..()
|
||||
|
||||
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
|
||||
@@ -441,7 +441,7 @@
|
||||
else
|
||||
target_zone = thrower.zone_selected
|
||||
|
||||
var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
|
||||
var/datum/thrownthing/TT = new(src, target, get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
|
||||
|
||||
var/dist_x = abs(target.x - src.x)
|
||||
var/dist_y = abs(target.y - src.y)
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
|
||||
. = ..()
|
||||
if(!QDELETED(throwing))
|
||||
throwing.hit_atom(A)
|
||||
throwing.finalize(hit = TRUE, target = A)
|
||||
. = TRUE
|
||||
if(QDELETED(A))
|
||||
return
|
||||
|
||||
@@ -151,8 +151,9 @@
|
||||
slipper.lube_flags |= FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING
|
||||
slipper.Slip(src, hit_atom)
|
||||
slipper.lube_flags &= ~(FLYING_DOESNT_HELP|SLIP_WHEN_CRAWLING)
|
||||
if(thrownby && !caught)
|
||||
throw_at(thrownby, throw_range+2, throw_speed, null, 1)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(thrown_by && !caught)
|
||||
throw_at(thrown_by, throw_range+2, throw_speed, null, 1)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -25,11 +25,32 @@
|
||||
if(user_unbuckle_mob(buckled_mobs[1],user))
|
||||
return 1
|
||||
|
||||
/atom/movable/attackby(obj/item/attacking_item, mob/user, params)
|
||||
if(!can_buckle || !istype(attacking_item, /obj/item/riding_offhand) || !user.Adjacent(src))
|
||||
return ..()
|
||||
|
||||
var/obj/item/riding_offhand/riding_item = attacking_item
|
||||
var/mob/living/carried_mob = riding_item.rider
|
||||
if(carried_mob == user) //Piggyback user.
|
||||
return
|
||||
user.unbuckle_mob(carried_mob)
|
||||
carried_mob.forceMove(get_turf(src))
|
||||
return mouse_buckle_handling(carried_mob, user)
|
||||
|
||||
/atom/movable/MouseDrop_T(mob/living/M, mob/living/user)
|
||||
. = ..()
|
||||
return mouse_buckle_handling(M, user)
|
||||
|
||||
/**
|
||||
* Does some typechecks and then calls user_buckle_mob
|
||||
*
|
||||
* Arguments:
|
||||
* M - The mob being buckled to src
|
||||
* user - The mob buckling M to src
|
||||
*/
|
||||
/atom/movable/proc/mouse_buckle_handling(mob/living/M, mob/living/user)
|
||||
if(can_buckle && istype(M) && istype(user))
|
||||
if(user_buckle_mob(M, user))
|
||||
return 1
|
||||
return user_buckle_mob(M, user, check_loc = FALSE)
|
||||
|
||||
/atom/movable/proc/has_buckled_mobs()
|
||||
if(!buckled_mobs)
|
||||
|
||||
@@ -112,7 +112,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
|
||||
var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
|
||||
|
||||
var/mob/thrownby = null
|
||||
///A weakref to the mob who threw the item
|
||||
var/datum/weakref/thrownby = null //I cannot verbally describe how much I hate this var
|
||||
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
|
||||
|
||||
@@ -177,6 +178,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
|
||||
var/canMouseDown = FALSE
|
||||
|
||||
/// Used if we want to have a custom verb text for throwing. "John Spaceman flicks the ciggerate" for example.
|
||||
var/throw_verb
|
||||
|
||||
/obj/item/Initialize(mapload)
|
||||
|
||||
@@ -737,7 +740,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
|
||||
|
||||
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
|
||||
thrownby = thrower
|
||||
thrownby = WEAKREF(thrower)
|
||||
callback = CALLBACK(src, .proc/after_throw, callback, (spin && messy_throw)) //replace their callback with our own
|
||||
. = ..(target, range, speed, thrower, spin, diagonals_first, callback, force)
|
||||
|
||||
@@ -831,9 +834,6 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
else
|
||||
. = ""
|
||||
|
||||
/obj/item/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return
|
||||
|
||||
/obj/item/attack_hulk(mob/living/carbon/human/user)
|
||||
return 0
|
||||
|
||||
@@ -1116,6 +1116,16 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
QDEL_NULL(src)
|
||||
return TRUE
|
||||
|
||||
///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else.
|
||||
/obj/item/proc/on_thrown(mob/living/carbon/user, atom/target)
|
||||
if((item_flags & ABSTRACT) || HAS_TRAIT(src, TRAIT_NODROP))
|
||||
return
|
||||
user.dropItemToGround(src, silent = TRUE)
|
||||
if(throwforce && HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, span_notice("You set [src] down gently on the ground."))
|
||||
return
|
||||
return src
|
||||
|
||||
/**
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
body_parts_covered = null
|
||||
grind_results = list()
|
||||
throw_verb = "flick"
|
||||
var/lit = FALSE
|
||||
var/starts_lit = FALSE
|
||||
var/icon_on = "cigon" //Note - these are in masks.dmi not in cigarette.dmi
|
||||
|
||||
@@ -168,7 +168,9 @@
|
||||
diceroll(user)
|
||||
|
||||
/obj/item/dice/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
diceroll(thrownby)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(thrown_by)
|
||||
diceroll(thrown_by)
|
||||
. = ..()
|
||||
|
||||
/obj/item/dice/proc/diceroll(mob/user)
|
||||
|
||||
@@ -289,10 +289,11 @@
|
||||
"<span class='userdanger'>[M] has been splashed with something!</span>")
|
||||
var/turf/TT = get_turf(hit_atom)
|
||||
var/throwerstring
|
||||
if(thrownby)
|
||||
log_combat(thrownby, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrownby)
|
||||
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(thrown_by)
|
||||
log_combat(thrown_by, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrown_by)
|
||||
throwerstring = " THROWN BY [key_name(thrown_by)] at [AT] (AREACOORD(AT)]"
|
||||
log_reagent("SPLASH: [src] mob throw_impact() onto [key_name(hit_atom)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
|
||||
reagents.reaction(hit_atom, TOUCH)
|
||||
reagents.clear_reagents()
|
||||
|
||||
@@ -61,9 +61,10 @@
|
||||
|
||||
/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
..()
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
//Only mob/living types have stun handling
|
||||
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom) && thrownby)
|
||||
baton_stun(hit_atom, thrownby, shoving = TRUE)
|
||||
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom) && thrown_by)
|
||||
baton_stun(hit_atom, thrown_by, shoving = TRUE)
|
||||
|
||||
/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
|
||||
preload_cell_type = /obj/item/stock_parts/cell/high/plus
|
||||
@@ -387,8 +388,9 @@
|
||||
/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(turned_on)
|
||||
var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
|
||||
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance) && thrownby)//if they are a carbon and they didn't catch it
|
||||
baton_stun(hit_atom, thrownby, shoving = TRUE)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance) && thrown_by)//if they are a carbon and they didn't catch it
|
||||
baton_stun(hit_atom, thrown_by, shoving = TRUE)
|
||||
if(thrownby && !caught)
|
||||
throw_back()
|
||||
else
|
||||
@@ -397,8 +399,9 @@
|
||||
/obj/item/melee/baton/boomerang/proc/throw_back()
|
||||
set waitfor = FALSE
|
||||
sleep(1)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(!QDELETED(src))
|
||||
throw_at(thrownby, throw_range+2, throw_speed, null, TRUE)
|
||||
throw_at(thrown_by, throw_range+2, throw_speed, null, TRUE)
|
||||
|
||||
/obj/item/melee/baton/boomerang/update_icon()
|
||||
if(turned_on)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
unbuckle_mob(M)
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/carbon/user)
|
||||
/obj/structure/bed/nest/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc)
|
||||
if ( !ismob(M) || (get_dist(src, user) > 1) || (M.loc != src.loc) || !user.cuff_resist_check() || M.buckled )
|
||||
return
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/cable/C = T.get_cable_node()
|
||||
if(C)
|
||||
playsound(src, 'sound/magic/lightningshock.ogg', 100, 1, extrarange = 5)
|
||||
playsound(src, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
|
||||
tesla_zap(src, 3, C.newavail() * 0.01, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN | ZAP_ALLOW_DUPLICATES) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
|
||||
C.add_delayedload(C.newavail() * 0.0375) // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
|
||||
return ..()
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
|
||||
|
||||
/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking
|
||||
/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user, check_loc) //Don't want them getting put on the rack other than by spiking
|
||||
return
|
||||
|
||||
/obj/structure/kitchenspike/user_unbuckle_mob(mob/living/buckled_mob, mob/living/carbon/human/user)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
. = ..()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user)
|
||||
/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc)
|
||||
if(user.incapacitated() || !istype(user))
|
||||
return
|
||||
M.forceMove(get_turf(src))
|
||||
|
||||
@@ -330,6 +330,17 @@ GLOBAL_LIST_EMPTY(crematoriums)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>That's not connected to anything!</span>")
|
||||
|
||||
/obj/structure/tray/attackby(obj/P, mob/user, params)
|
||||
if(!istype(P, /obj/item/riding_offhand))
|
||||
return ..()
|
||||
|
||||
var/obj/item/riding_offhand/riding_item = P
|
||||
var/mob/living/carried_mob = riding_item.rider
|
||||
if(carried_mob == user) //Piggyback user.
|
||||
return
|
||||
user.unbuckle_mob(carried_mob)
|
||||
MouseDrop_T(carried_mob, user)
|
||||
|
||||
/obj/structure/tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user)
|
||||
if(!ismovable(O) || O.anchored || !Adjacent(user) || !user.Adjacent(O) || O.loc == user)
|
||||
return
|
||||
|
||||
@@ -124,11 +124,11 @@
|
||||
. = . || (caller.pass_flags & PASSTABLE)
|
||||
|
||||
/obj/structure/table/proc/tableplace(mob/living/user, mob/living/pushed_mob)
|
||||
pushed_mob.forceMove(src.loc)
|
||||
pushed_mob.set_resting(TRUE, FALSE)
|
||||
pushed_mob.visible_message("<span class='notice'>[user] places [pushed_mob] onto [src].</span>", \
|
||||
"<span class='notice'>[user] places [pushed_mob] onto [src].</span>")
|
||||
log_combat(user, pushed_mob, "placed")
|
||||
pushed_mob.forceMove(loc)
|
||||
pushed_mob.set_resting(TRUE, TRUE)
|
||||
pushed_mob.visible_message(span_notice("[user] places [pushed_mob] onto [src]."), \
|
||||
span_notice("[user] places [pushed_mob] onto [src]."))
|
||||
log_combat(user, pushed_mob, "places", null, "onto [src]")
|
||||
|
||||
/obj/structure/table/proc/tablepush(mob/living/user, mob/living/pushed_mob)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
@@ -205,6 +205,30 @@
|
||||
return
|
||||
// If the tray IS empty, continue on (tray will be placed on the table like other items)
|
||||
|
||||
if(istype(I, /obj/item/riding_offhand))
|
||||
var/obj/item/riding_offhand/riding_item = I
|
||||
var/mob/living/carried_mob = riding_item.rider
|
||||
if(carried_mob == user) //Piggyback user.
|
||||
return
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
user.unbuckle_mob(carried_mob)
|
||||
tablelimbsmash(user, carried_mob)
|
||||
else
|
||||
var/tableplace_delay = 3.5 SECONDS
|
||||
var/skills_space = ""
|
||||
if(HAS_TRAIT(user, TRAIT_QUICKER_CARRY))
|
||||
tableplace_delay = 2 SECONDS
|
||||
skills_space = " expertly"
|
||||
else if(HAS_TRAIT(user, TRAIT_QUICK_CARRY))
|
||||
tableplace_delay = 2.75 SECONDS
|
||||
skills_space = " quickly"
|
||||
carried_mob.visible_message(span_notice("[user] begins to[skills_space] place [carried_mob] onto [src]..."),
|
||||
span_userdanger("[user] begins to[skills_space] place [carried_mob] onto [src]..."))
|
||||
if(do_after(user, tableplace_delay, target = carried_mob))
|
||||
user.unbuckle_mob(carried_mob)
|
||||
tableplace(user, carried_mob)
|
||||
return TRUE
|
||||
|
||||
if(user.a_intent != INTENT_HARM && !(I.item_flags & ABSTRACT))
|
||||
if(user.transferItemToLoc(I, drop_location()))
|
||||
var/list/click_params = params2list(params)
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
..()
|
||||
|
||||
/obj/item/projectile/tentacle/proc/reset_throw(mob/living/carbon/human/H)
|
||||
if(H.in_throw_mode)
|
||||
if(H.throw_mode)
|
||||
H.throw_mode_off() //Don't annoy the changeling if he doesn't catch the item
|
||||
|
||||
/obj/item/projectile/tentacle/proc/tentacle_grab(mob/living/carbon/human/H, mob/living/carbon/C)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
return
|
||||
if(isitem(M))
|
||||
var/obj/item/I = M
|
||||
if(is_servant_of_ratvar(I.thrownby)) //nice try!
|
||||
if(is_servant_of_ratvar(I.thrownby?.resolve())) //nice try!
|
||||
return
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
density = TRUE //Skewers are one-use only
|
||||
desc = "A vicious brass spike protruding from the ground like a stala[pick("gm", "ct")]ite. It makes you sick to look at." //is stalagmite the ground one? or the ceiling one? who can ever remember?
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob()
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/user_buckle_mob(check_loc)
|
||||
return
|
||||
|
||||
/obj/structure/destructible/clockwork/trap/brass_skewer/post_buckle_mob(mob/living/L)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, silent = FALSE)
|
||||
/mob/living/carbon/true_devil/doUnEquip(obj/item/I, force, invdrop, silent = FALSE)
|
||||
if(..())
|
||||
update_inv_hands()
|
||||
return 1
|
||||
|
||||
@@ -425,9 +425,10 @@
|
||||
for(var/datum/reagent/A in reagents.reagent_list)
|
||||
R += A.type + " ("
|
||||
R += num2text(A.volume) + "),"
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
reagents.reaction(M, TOUCH)
|
||||
log_combat(user, M, "splashed", R)
|
||||
reagents.clear_reagents()
|
||||
|
||||
@@ -292,10 +292,18 @@
|
||||
|
||||
//The following functions are the same save for one small difference
|
||||
|
||||
//for when you want the item to end up on the ground
|
||||
//will force move the item to the ground and call the turf's Entered
|
||||
/mob/proc/dropItemToGround(obj/item/I, force = FALSE)
|
||||
return doUnEquip(I, force, drop_location(), FALSE)
|
||||
/**
|
||||
* Used to drop an item (if it exists) to the ground.
|
||||
* * Will pass as TRUE is successfully dropped, or if there is no item to drop.
|
||||
* * Will pass FALSE if the item can not be dropped due to TRAIT_NODROP via doUnEquip()
|
||||
* If the item can be dropped, it will be forceMove()'d to the ground and the turf's Entered() will be called.
|
||||
*/
|
||||
/mob/proc/dropItemToGround(obj/item/I, force = FALSE, silent = FALSE, invdrop = TRUE)
|
||||
if (isnull(I))
|
||||
return TRUE
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_DROPPING_ITEM)
|
||||
. = doUnEquip(I, force, drop_location(), FALSE, invdrop = invdrop, silent = silent)
|
||||
|
||||
//for when the item will be immediately placed in a loc other than the ground
|
||||
/mob/proc/transferItemToLoc(obj/item/I, newloc = null, force = FALSE, silent = TRUE)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
//can't unequip since it can't equip anything
|
||||
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, silent = FALSE)
|
||||
/mob/living/carbon/alien/larva/doUnEquip(obj/item/W, invdrop, silent = FALSE)
|
||||
return
|
||||
|
||||
@@ -125,8 +125,8 @@
|
||||
take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5)
|
||||
victim.DefaultCombatKnockdown(20)
|
||||
DefaultCombatKnockdown(20)
|
||||
visible_message("<span class='danger'>[src] crashes into [victim] [extra_speed ? "really hard" : ""], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim] [extra_speed ? "extra hard" : ""]!</span>")
|
||||
visible_message("<span class='danger'>[src] crashes into [victim][extra_speed ? " really hard" : ""], knocking them both over!</span>",\
|
||||
"<span class='userdanger'>You violently crash into [victim][extra_speed ? " extra hard" : ""]!</span>")
|
||||
playsound(src,'sound/weapons/punch1.ogg',50,1)
|
||||
|
||||
|
||||
@@ -134,33 +134,35 @@
|
||||
/mob/living/carbon/proc/toggle_throw_mode()
|
||||
if(stat)
|
||||
return
|
||||
if(in_throw_mode)
|
||||
if(throw_mode)
|
||||
throw_mode_off()
|
||||
else
|
||||
throw_mode_on()
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_off()
|
||||
in_throw_mode = 0
|
||||
throw_mode = FALSE
|
||||
if(client && hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_off"
|
||||
|
||||
|
||||
/mob/living/carbon/proc/throw_mode_on()
|
||||
in_throw_mode = 1
|
||||
throw_mode = TRUE
|
||||
if(client && hud_used)
|
||||
hud_used.throw_icon.icon_state = "act_throw_on"
|
||||
|
||||
/mob/proc/throw_item(atom/target)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_THROW, target)
|
||||
return
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_CARBON_THROW_THING, src, target)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/throw_item(atom/target)
|
||||
. = ..()
|
||||
throw_mode_off()
|
||||
if(!target || !isturf(loc))
|
||||
return
|
||||
return FALSE
|
||||
if(istype(target, /atom/movable/screen))
|
||||
return
|
||||
return FALSE
|
||||
|
||||
//CIT CHANGES - makes it impossible to throw while in stamina softcrit
|
||||
if(IS_STAMCRIT(src))
|
||||
@@ -170,59 +172,56 @@
|
||||
var/random_turn = a_intent == INTENT_HARM
|
||||
//END OF CIT CHANGES
|
||||
|
||||
var/obj/item/I = get_active_held_item()
|
||||
|
||||
var/atom/movable/thrown_thing
|
||||
var/mob/living/throwable_mob
|
||||
var/obj/item/held_item = get_active_held_item()
|
||||
var/verb_text = pick("throw", "toss", "hurl", "chuck", "fling")
|
||||
if(prob(0.5))
|
||||
verb_text = "yeet"
|
||||
|
||||
if(istype(I, /obj/item/clothing/head/mob_holder))
|
||||
var/obj/item/clothing/head/mob_holder/holder = I
|
||||
if(holder.held_mob)
|
||||
throwable_mob = holder.held_mob
|
||||
holder.release()
|
||||
|
||||
if(!I || throwable_mob)
|
||||
if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
throwable_mob = pulling
|
||||
|
||||
if(throwable_mob && !throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(pulling)
|
||||
var/neckgrab_throw = FALSE
|
||||
if(!held_item)
|
||||
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
|
||||
var/mob/living/throwable_mob = pulling
|
||||
if(!throwable_mob.buckled)
|
||||
thrown_thing = throwable_mob
|
||||
if(grab_state >= GRAB_NECK)
|
||||
neckgrab_throw = TRUE
|
||||
stop_pulling()
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
|
||||
return
|
||||
if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE))
|
||||
return
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
|
||||
else if(!(I.item_flags & ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
|
||||
thrown_thing = I
|
||||
dropItemToGround(I)
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM) && I.throwforce)
|
||||
to_chat(src, "<span class='notice'>You set [I] down gently on the ground.</span>")
|
||||
return
|
||||
|
||||
if(!UseStaminaBuffer(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST), warn = TRUE))
|
||||
return
|
||||
|
||||
if(thrown_thing)
|
||||
var/power_throw = 0
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(pulling && grab_state >= GRAB_NECK)
|
||||
power_throw++
|
||||
visible_message("<span class='danger'>[src] throws [thrown_thing][power_throw ? " really hard!" : "."]</span>", \
|
||||
"<span class='danger'>You throw [thrown_thing][power_throw ? " really hard!" : "."]</span>")
|
||||
log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK)
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
|
||||
newtonian_move(get_dir(target, src))
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn)
|
||||
if(HAS_TRAIT(src, TRAIT_PACIFISM))
|
||||
to_chat(src, span_notice("You gently let go of [throwable_mob]."))
|
||||
return FALSE
|
||||
if(!UseStaminaBuffer(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2), TRUE))
|
||||
return FALSE
|
||||
else
|
||||
thrown_thing = held_item.on_thrown(src, target)
|
||||
if(!thrown_thing)
|
||||
return FALSE
|
||||
if(isliving(thrown_thing))
|
||||
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
|
||||
var/turf/end_T = get_turf(target)
|
||||
if(start_T && end_T)
|
||||
log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
|
||||
var/power_throw = 0
|
||||
if(HAS_TRAIT(src, TRAIT_HULK))
|
||||
power_throw++
|
||||
if(HAS_TRAIT(src, TRAIT_DWARF))
|
||||
power_throw--
|
||||
if(HAS_TRAIT(thrown_thing, TRAIT_DWARF))
|
||||
power_throw++
|
||||
if(neckgrab_throw)
|
||||
power_throw++
|
||||
if(isitem(thrown_thing))
|
||||
var/obj/item/thrown_item = thrown_thing
|
||||
if(thrown_item.throw_verb)
|
||||
verb_text = thrown_item.throw_verb
|
||||
visible_message(span_danger("[src] [verb_text][plural_s(verb_text)] [thrown_thing][power_throw ? " really hard!" : "."]"), \
|
||||
span_danger("You [verb_text] [thrown_thing][power_throw ? " really hard!" : "."]"))
|
||||
log_message("has thrown [thrown_thing] [power_throw > 0 ? "really hard" : ""]", LOG_ATTACK)
|
||||
do_attack_animation(target, no_effect = 1)
|
||||
var/extra_throw_range = 0 // HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
|
||||
newtonian_move(get_dir(target, src))
|
||||
thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force, random_turn)
|
||||
|
||||
/mob/living/carbon/restrained(ignore_grab)
|
||||
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
|
||||
|
||||
@@ -48,22 +48,30 @@
|
||||
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
affecting.dismember(P.damtype)
|
||||
|
||||
/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
. = ..()
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
|
||||
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
|
||||
. = FALSE
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !throw_mode)
|
||||
return
|
||||
if(incapacitated())
|
||||
if(get_active_held_item())
|
||||
return
|
||||
if (get_active_held_item())
|
||||
if (HAS_TRAIT_FROM(src, TRAIT_AUTO_CATCH_ITEM,RISING_BASS_TRAIT))
|
||||
visible_message("<span class='warning'>[src] chops [I] out of the air!</span>")
|
||||
if(HAS_TRAIT(src, TRAIT_HANDS_BLOCKED))
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(!skipcatch && can_catch_item() && isitem(AM) && isturf(AM.loc))
|
||||
var/obj/item/I = AM
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message(span_warning("[src] catches [I]!"), \
|
||||
span_userdanger("You catch [I] in mid-air!"))
|
||||
throw_mode_off()
|
||||
return TRUE
|
||||
return
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
if(isitem(AM) && HAS_TRAIT_FROM(src, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT))
|
||||
visible_message(span_warning("[src] chops [AM] out of the air!"), \
|
||||
span_userdanger("You chop [AM] out of the air!"))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1)
|
||||
var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier
|
||||
|
||||
@@ -68,12 +68,16 @@
|
||||
|
||||
/mob/living/carbon/human/proc/check_martial_melee_block()
|
||||
if(mind)
|
||||
if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE))
|
||||
if(mind.martial_art && prob(mind.martial_art.block_chance) && mind.martial_art.can_use(src) && throw_mode && !incapacitated(FALSE, TRUE))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
return dna?.species?.spec_hitby(AM, src) || ..()
|
||||
if(dna?.species)
|
||||
var/spec_return = dna.species.spec_hitby(AM, src)
|
||||
if(spec_return)
|
||||
return spec_return
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling))
|
||||
@@ -817,7 +821,7 @@
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
|
||||
if(damage_type != BRUTE && damage_type != BURN)
|
||||
|
||||
@@ -419,7 +419,8 @@
|
||||
var/obj/item/I
|
||||
if(istype(AM, /obj/item))
|
||||
I = AM
|
||||
if(I.thrownby == H) //No throwing stuff at yourself to trigger the teleport
|
||||
var/mob/thrown_by = I.thrownby?.resolve()
|
||||
if(thrown_by == H) //No throwing stuff at yourself to trigger the teleport
|
||||
return 0
|
||||
else
|
||||
reactive_teleport(H)
|
||||
|
||||
@@ -396,12 +396,13 @@
|
||||
retaliate(Proj.firer)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
/mob/living/carbon/monkey/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
/mob/living/carbon/monkey/Crossed(atom/movable/AM)
|
||||
|
||||
@@ -106,48 +106,51 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
// Throwingdatum can be null if someone had an accident() while slipping with an item in hand.
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(isitem(AM))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
var/impacting_zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
var/list/block_return = list()
|
||||
var/total_damage = AM.throwforce
|
||||
if(mob_run_block(AM, throwpower, "\the [AM.name]", ATTACK_TYPE_THROWN, 0, throwingdatum?.thrower, impacting_zone, block_return) & BLOCK_SUCCESS)
|
||||
if(!isitem(AM))
|
||||
// Filled with made up numbers for non-items.
|
||||
if(mob_run_block(AM, 30, "\the [AM.name]", ATTACK_TYPE_PROJECTILE, 0, throwingdatum.thrower, throwingdatum.thrower.zone_selected, list()))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) //Item sounds are handled in the item itself
|
||||
return ..()
|
||||
|
||||
var/obj/item/thrown_item = AM
|
||||
if(thrown_item.thrownby == WEAKREF(src)) //No throwing stuff at yourself to trigger hit reactions
|
||||
return ..()
|
||||
|
||||
if(mob_run_block(AM, thrown_item.throwforce, "\the [thrown_item.name]", ATTACK_TYPE_PROJECTILE, 0, throwingdatum.thrower, throwingdatum.thrower.zone_selected, list()))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
total_damage = block_calculate_resultant_damage(total_damage, block_return)
|
||||
if(I)
|
||||
var/nosell_hit = SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone, throwingdatum, FALSE, blocked)
|
||||
if(nosell_hit)
|
||||
skipcatch = TRUE
|
||||
hitpush = FALSE
|
||||
if(!skipcatch && isturf(I.loc) && catch_item(I))
|
||||
return TRUE
|
||||
var/dtype = BRUTE
|
||||
|
||||
dtype = I.damtype
|
||||
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
var/nosell_hit = SEND_SIGNAL(thrown_item, COMSIG_MOVABLE_IMPACT_ZONE, src, zone, blocked, throwingdatum) // TODO: find a better way to handle hitpush and skipcatch for humans
|
||||
if(nosell_hit)
|
||||
skipcatch = TRUE
|
||||
hitpush = FALSE
|
||||
|
||||
if(!blocked)
|
||||
if(!nosell_hit)
|
||||
visible_message("<span class='danger'>[src] is hit by [I]!</span>", \
|
||||
"<span class='userdanger'>You're hit by [I]!</span>")
|
||||
if(!I.throwforce)
|
||||
return
|
||||
var/armor = run_armor_check(impacting_zone, MELEE, "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration)
|
||||
apply_damage(I.throwforce, dtype, impacting_zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND))
|
||||
else
|
||||
return 1
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
|
||||
..()
|
||||
if(blocked)
|
||||
return TRUE
|
||||
|
||||
var/mob/thrown_by = thrown_item.thrownby?.resolve()
|
||||
if(thrown_by)
|
||||
log_combat(thrown_by, src, "threw and hit", thrown_item)
|
||||
if(nosell_hit)
|
||||
return ..()
|
||||
visible_message(span_danger("[src] is hit by [thrown_item]!"), \
|
||||
span_userdanger("You're hit by [thrown_item]!"))
|
||||
if(!thrown_item.throwforce)
|
||||
return
|
||||
var/armor = run_armor_check(zone, MELEE, "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", thrown_item.armour_penetration, "", FALSE)
|
||||
apply_damage(thrown_item.throwforce, thrown_item.damtype, zone, armor, sharpness = thrown_item.get_sharpness(), wound_bonus = (nosell_hit * CANT_WOUND))
|
||||
if(QDELETED(src)) //Damage can delete the mob.
|
||||
return
|
||||
if(lying) // physics says it's significantly harder to push someone by constantly chucking random furniture at them if they are down on the floor.
|
||||
hitpush = FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/fire_act()
|
||||
adjust_fire_stacks(3)
|
||||
|
||||
@@ -138,13 +138,14 @@
|
||||
bike_horn(A)
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
playsound(src, honksound, 50, TRUE, -1)
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
|
||||
|
||||
@@ -351,12 +351,13 @@
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby))
|
||||
var/mob/living/carbon/human/H = I.thrownby
|
||||
retaliate(H)
|
||||
/mob/living/simple_animal/bot/secbot/hitby(atom/movable/hitting_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)
|
||||
if(istype(hitting_atom, /obj/item))
|
||||
var/obj/item/item_hitby = hitting_atom
|
||||
var/mob/thrown_by = item_hitby.thrownby?.resolve()
|
||||
if(item_hitby.throwforce < src.health && thrown_by && ishuman(thrown_by))
|
||||
var/mob/living/carbon/human/human_throwee = thrown_by
|
||||
retaliate(human_throwee)
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
..() //lose items, then return
|
||||
|
||||
//SLOT HANDLING BULLSHIT FOR INTERNAL STORAGE
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, silent = FALSE)
|
||||
/mob/living/simple_animal/hostile/guardian/dextrous/doUnEquip(obj/item/I, force, invdrop, silent = FALSE)
|
||||
if(..())
|
||||
update_inv_hands()
|
||||
if(I == internal_storage)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
if(!stat)
|
||||
Aggro()
|
||||
if(T.throwforce <= 20)
|
||||
visible_message("<span class='notice'>The [T.name] [throw_message] [src.name]!</span>")
|
||||
visible_message(span_notice("The [T.name] [throw_message] [src.name]!"))
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -587,7 +587,7 @@
|
||||
|
||||
//ANIMAL RIDING
|
||||
|
||||
/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user)
|
||||
/mob/living/simple_animal/user_buckle_mob(mob/living/M, mob/user, check_loc)
|
||||
var/datum/component/riding/riding_datum = GetComponent(/datum/component/riding)
|
||||
if(riding_datum)
|
||||
if(user.incapacitated())
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
Feedon(Food)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/slime/doUnEquip(obj/item/W, silent = FALSE)
|
||||
/mob/living/simple_animal/slime/doUnEquip(obj/item/W, invdrop, silent = FALSE)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
|
||||
|
||||
var/in_throw_mode = 0
|
||||
var/throw_mode = 0
|
||||
|
||||
var/job = null//Living
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
auto.Remove(buckled_mob)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user)
|
||||
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user, check_loc)
|
||||
if(user.incapacitated() || !istype(user))
|
||||
return
|
||||
for(var/atom/movable/A in get_turf(src))
|
||||
|
||||
@@ -106,9 +106,10 @@
|
||||
/obj/item/reagent_containers/proc/bartender_check(atom/target)
|
||||
. = FALSE
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T || !target.CanPass(src, T) || !thrownby || !thrownby.actions)
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(!T || !target.CanPass(src, T) || !thrown_by || !thrown_by.actions)
|
||||
return
|
||||
var/datum/action/innate/D = get_action_of_type(thrownby, /datum/action/innate/drink_fling)
|
||||
var/datum/action/innate/D = get_action_of_type(thrown_by, /datum/action/innate/drink_fling)
|
||||
if(D?.active)
|
||||
return TRUE
|
||||
|
||||
@@ -118,6 +119,7 @@
|
||||
/obj/item/reagent_containers/proc/SplashReagents(atom/target, thrown = FALSE)
|
||||
if(!reagents || !reagents.total_volume || !spillable)
|
||||
return
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
|
||||
if(ismob(target) && target.reagents)
|
||||
if(thrown)
|
||||
@@ -128,10 +130,10 @@
|
||||
"<span class='userdanger'>[M] has been splashed with something!</span>")
|
||||
var/turf/TT = get_turf(target)
|
||||
var/throwerstring
|
||||
if(thrownby && thrown)
|
||||
log_combat(thrownby, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrownby)
|
||||
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]"
|
||||
if(thrown_by && thrown)
|
||||
log_combat(thrown_by, M, "splashed", R)
|
||||
var/turf/AT = get_turf(thrown_by)
|
||||
throwerstring = " THROWN BY [key_name(thrown_by)] at [AT] (AREACOORD(AT)]"
|
||||
log_reagent("SPLASH: [src] mob SplashReagents() onto [key_name(target)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]")
|
||||
reagents.reaction(target, TOUCH)
|
||||
reagents.clear_reagents()
|
||||
@@ -142,15 +144,15 @@
|
||||
addtimer(CALLBACK(src, .proc/ForceResetRotation), 1)
|
||||
|
||||
else
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
|
||||
log_game("[key_name(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
|
||||
var/turf/T = get_turf(target)
|
||||
var/throwerstring
|
||||
if(thrownby && thrown)
|
||||
var/turf/AT = get_turf(thrownby)
|
||||
throwerstring = " THROWN BY [key_name(thrownby)] at [AT] ([AREACOORD(AT)])"
|
||||
if(thrown_by && thrown)
|
||||
var/turf/AT = get_turf(thrown_by)
|
||||
throwerstring = " THROWN BY [key_name(thrown_by)] at [AT] ([AREACOORD(AT)])"
|
||||
log_reagent("SPLASH - [src] object SplashReagents() onto [target] at [T] ([AREACOORD(T)])[throwerstring] - [reagents.log_list()]")
|
||||
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
|
||||
reagents.reaction(target, TOUCH)
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
M.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [M]!</span>", \
|
||||
"<span class='userdanger'>[user] splashes the contents of [src] onto [M]!</span>")
|
||||
var/R = reagents?.log_list()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
var/mob/thrown_by = thrownby?.resolve()
|
||||
if(isturf(target) && reagents.reagent_list.len && thrown_by)
|
||||
log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
reagents.reaction(M, TOUCH)
|
||||
log_combat(user, M, "splashed", R)
|
||||
var/turf/UT = get_turf(user)
|
||||
|
||||
@@ -359,10 +359,10 @@
|
||||
if(isitem(AM) && AM.CanEnterDisposals())
|
||||
if(prob(75))
|
||||
AM.forceMove(src)
|
||||
visible_message("<span class='notice'>[AM] lands in [src].</span>")
|
||||
update_icon()
|
||||
visible_message(span_notice("[AM] lands in [src]."))
|
||||
update_appearance()
|
||||
else
|
||||
visible_message("<span class='notice'>[AM] bounces off of [src]'s rim!</span>")
|
||||
visible_message(span_notice("[AM] bounces off of [src]'s rim!"))
|
||||
return ..()
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
/obj/vehicle/sealed/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper
|
||||
log_message("Hit by [AM].", LOG_MECHA, color="red")
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/sealed/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
|
||||
if(!enclosed && LAZYLEN(occupants) && !(mecha_flags & SILICON_PILOT) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit the pilot of open-canopy mechs
|
||||
|
||||
@@ -133,10 +133,10 @@
|
||||
check_boost()
|
||||
if(driver.m_intent == MOVE_INTENT_WALK)
|
||||
var/deceleration = max_deceleration
|
||||
if(driver.in_throw_mode)
|
||||
if(driver.throw_mode)
|
||||
deceleration *= 1.5
|
||||
friction(deceleration, TRUE)
|
||||
else if(driver.in_throw_mode)
|
||||
else if(driver.throw_mode)
|
||||
friction(max_deceleration*1.2, TRUE)
|
||||
friction(max_deceleration/4)
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
#include "code\__DEFINES\dcs\flags.dm"
|
||||
#include "code\__DEFINES\dcs\helpers.dm"
|
||||
#include "code\__DEFINES\dcs\signals.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_global.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_hud.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_medical.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mod.dm"
|
||||
@@ -167,8 +168,10 @@
|
||||
#include "code\__DEFINES\dcs\signals\signals_reagent.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_screentips.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_main.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_main.dm"
|
||||
#include "code\__DEFINES\mapping\maploader.dm"
|
||||
#include "code\__DEFINES\material\worth.dm"
|
||||
#include "code\__DEFINES\mobs\innate_abilities.dm"
|
||||
|
||||
Reference in New Issue
Block a user