diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm new file mode 100644 index 0000000000..9b32abf0c9 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_main.dm @@ -0,0 +1,2 @@ +///from base of atom/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) +#define COMSIG_ATOM_HITBY "atom_hitby" diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm new file mode 100644 index 0000000000..3e0e1d2296 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -0,0 +1,2 @@ +/// a person somewhere has thrown something : (mob/living/carbon/carbon_thrower, target) +#define COMSIG_GLOB_CARBON_THROW_THING "!throw_thing" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm new file mode 100644 index 0000000000..e6c3464ff7 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -0,0 +1,2 @@ +/// from mob/proc/dropItemToGround() +#define COMSIG_MOB_DROPPING_ITEM "mob_dropping_item" diff --git a/code/__HELPERS/pronouns.dm b/code/__HELPERS/pronouns.dm index bfe09ba370..fd15c05c64 100644 --- a/code/__HELPERS/pronouns.dm +++ b/code/__HELPERS/pronouns.dm @@ -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) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 9a75660b7a..81cb9d2ba6 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -89,7 +89,7 @@ DelayNextAction(CLICK_CD_HANDCUFFED) return RestrainedClickOn(A) - if(in_throw_mode) + if(throw_mode) throw_item(A) return diff --git a/code/_onclick/right_click.dm b/code/_onclick/right_click.dm index c1613561b4..49bd76516a 100644 --- a/code/_onclick/right_click.dm +++ b/code/_onclick/right_click.dm @@ -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 diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 47efc967ac..8c873d07c4 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -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 diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm index 4b9c25db91..f508f056c3 100644 --- a/code/datums/components/fullauto.dm +++ b/code/datums/components/fullauto.dm @@ -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 diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index a074fe6f5f..49b8f7f7f0 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -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 diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index c336213388..9f448b39a6 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -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)) diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm index 5f57b4fce3..82f42d69b3 100644 --- a/code/datums/elements/mob_holder.dm +++ b/code/datums/elements/mob_holder.dm @@ -61,7 +61,7 @@ return FALSE source.visible_message("[user] starts picking up [source].", \ "[user] starts picking you up!") - if(!do_after(user, 20, target = source) || source.buckled) + if(!do_after(user, 2 SECONDS, target = source) || source.buckled) return FALSE source.visible_message("[user] picks up [source]!", \ @@ -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("[held_mob] escapes from [L]!", "[held_mob] escapes your grip!") 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 diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index d0cdee4937..547a24de0a 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -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("[A] effortlessly swats the projectile aside! They can deflect projectile with their bare hands!", "You deflect the projectile!") playsound(get_turf(A), pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, TRUE) P.firer = A diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 220cd88499..c72b4f7b60 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -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 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 6beb8319ec..6d02c19d23 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -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) diff --git a/code/game/atoms_movement.dm b/code/game/atoms_movement.dm index 9fd007e9ee..7e0a1e6899 100644 --- a/code/game/atoms_movement.dm +++ b/code/game/atoms_movement.dm @@ -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 diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index f17cfde761..5891facfb7 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -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 ..() diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index afc4312779..aae6cbaa5c 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -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) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 7a953089a5..7aab051850 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -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 + /** diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 518772c771..a52bbb75f3 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -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 diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 91aad761d9..ea42fee208 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -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) diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 648a38437c..138472a4c8 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -289,10 +289,11 @@ "[M] has been splashed with something!") 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() diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index 7d84d38624..46e0c66953 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -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) diff --git a/code/game/objects/structures/beds_chairs/alien_nest.dm b/code/game/objects/structures/beds_chairs/alien_nest.dm index eff87d3955..762331c40e 100644 --- a/code/game/objects/structures/beds_chairs/alien_nest.dm +++ b/code/game/objects/structures/beds_chairs/alien_nest.dm @@ -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 diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 998285dd58..d83715a886 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -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 ..() diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index a37797045f..8c2655dd64 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -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) diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index f70510e173..3f1cb5f4c1 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -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)) diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 69206f0d08..c39b3f64b1 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -330,6 +330,17 @@ GLOBAL_LIST_EMPTY(crematoriums) else to_chat(user, "That's not connected to anything!") +/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 diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index b7642f4658..12799b4370 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -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("[user] places [pushed_mob] onto [src].", \ - "[user] places [pushed_mob] onto [src].") - 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) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index e327f62370..9fe612ac07 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -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) diff --git a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm b/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm index 5905862690..cb52944a0a 100644 --- a/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm +++ b/code/modules/antagonists/clockcult/clock_effects/servant_blocker.dm @@ -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 diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm index a7c1f81f06..ac8dc0bffb 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/brass_skewer.dm @@ -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) diff --git a/code/modules/antagonists/devil/true_devil/inventory.dm b/code/modules/antagonists/devil/true_devil/inventory.dm index e98cb5ca72..8856838a34 100644 --- a/code/modules/antagonists/devil/true_devil/inventory.dm +++ b/code/modules/antagonists/devil/true_devil/inventory.dm @@ -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 diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index d32d287800..1a09635e8a 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -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() diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 51659a2904..79a0ccda77 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -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) diff --git a/code/modules/mob/living/carbon/alien/larva/inventory.dm b/code/modules/mob/living/carbon/alien/larva/inventory.dm index b07bd180f6..5b49c3abb0 100644 --- a/code/modules/mob/living/carbon/alien/larva/inventory.dm +++ b/code/modules/mob/living/carbon/alien/larva/inventory.dm @@ -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 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 419a75eff2..13481655df 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -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("[src] crashes into [victim] [extra_speed ? "really hard" : ""], knocking them both over!",\ - "You violently crash into [victim] [extra_speed ? "extra hard" : ""]!") + visible_message("[src] crashes into [victim][extra_speed ? " really hard" : ""], knocking them both over!",\ + "You violently crash into [victim][extra_speed ? " extra hard" : ""]!") 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, "You gently let go of [throwable_mob].") - 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, "You set [I] down gently on the ground.") - 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("[src] throws [thrown_thing][power_throw ? " really hard!" : "."]", \ - "You throw [thrown_thing][power_throw ? " really hard!" : "."]") - 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)) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index a12d6614fa..91481d89b8 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -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("[src] chops [I] out of the air!") + 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("[src] catches [I]!") //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 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 5941efe087..7525cfd216 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -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 There is \a [I] stuck to your [LB.name]!") else to_chat(src, "\t There is \a [I] embedded in your [LB.name]!") - + /mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone) if(damage_type != BRUTE && damage_type != BURN) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 843b47b4a0..c4be0d3948 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -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) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 0c9895c729..2640c642dd 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -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) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 0b71359a1e..cd46072921 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -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("[src] is hit by [I]!", \ - "You're hit by [I]!") - 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) diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index b8d82e8c7a..42bb2f63bc 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -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 diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 9973b6472e..4725ca6225 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -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) ..() diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index 1fd1e623db..4e57aa1562 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -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) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index e9be18f0cb..2463431ad3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -50,7 +50,7 @@ if(!stat) Aggro() if(T.throwforce <= 20) - visible_message("The [T.name] [throw_message] [src.name]!") + visible_message(span_notice("The [T.name] [throw_message] [src.name]!")) return ..() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f226a911d8..151cc70a27 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -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()) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index dc9d6ff6a3..2b267c4d01 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -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) diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 138a3b9662..0b22ae25ec 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -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 diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 8f9a7805c6..be03e8a9c9 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -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)) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index aa871723a3..df794f4842 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -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 @@ "[M] has been splashed with something!") 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("[src] spills its contents all over [target].") reagents.reaction(target, TOUCH) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index bec2f22590..4c6c311a29 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -29,9 +29,10 @@ M.visible_message("[user] splashes the contents of [src] onto [M]!", \ "[user] splashes the contents of [src] onto [M]!") 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) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 8be744cd96..a8835d0cee 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -359,10 +359,10 @@ if(isitem(AM) && AM.CanEnterDisposals()) if(prob(75)) AM.forceMove(src) - visible_message("[AM] lands in [src].") - update_icon() + visible_message(span_notice("[AM] lands in [src].")) + update_appearance() else - visible_message("[AM] bounces off of [src]'s rim!") + visible_message(span_notice("[AM] bounces off of [src]'s rim!")) return ..() else return ..() diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index 78b4c7b441..7208fdaa15 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -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 diff --git a/modular_citadel/code/modules/vectorcrafts/vectorcraft.dm b/modular_citadel/code/modules/vectorcrafts/vectorcraft.dm index 399a1c5f06..f23d4d04fd 100644 --- a/modular_citadel/code/modules/vectorcrafts/vectorcraft.dm +++ b/modular_citadel/code/modules/vectorcrafts/vectorcraft.dm @@ -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) diff --git a/tgstation.dme b/tgstation.dme index 8e6d888970..50ff9eba35 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -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"