From 441ee14971573d7461dfcd3970d447746a3368b6 Mon Sep 17 00:00:00 2001 From: CHOMPStation2StaffMirrorBot <94713762+CHOMPStation2StaffMirrorBot@users.noreply.github.com> Date: Thu, 8 Jan 2026 14:45:27 -0700 Subject: [PATCH] [MIRROR] initial throw fixing (#12231) Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com> Co-authored-by: C.L. --- .../signals/signals_mob/signals_mob_living.dm | 4 + code/__defines/dcs/signals/signals_vore.dm | 2 +- code/__defines/subsystems.dm | 1 + code/controllers/subsystems/throwing.dm | 100 ++++++++++++++---- code/datums/elements/vore/spontaneous_vore.dm | 16 ++- code/game/atom/_atom.dm | 4 +- code/game/atoms_movable.dm | 49 +++------ code/game/machinery/camera/camera.dm | 2 +- code/game/machinery/doors/door.dm | 3 +- code/game/mecha/mecha.dm | 2 +- code/game/objects/items.dm | 3 +- .../objects/items/weapons/capture_crystal.dm | 6 +- code/game/objects/structures/alien/alien.dm | 2 +- code/game/objects/structures/gargoyle.dm | 6 +- code/game/objects/structures/low_wall.dm | 3 +- code/game/objects/structures/window.dm | 2 +- code/game/turfs/simulated/lava.dm | 2 +- code/game/turfs/simulated/walls.dm | 3 +- code/game/turfs/turf.dm | 4 +- code/game/turfs/unsimulated/sky_vr.dm | 2 +- code/modules/assembly/mousetrap.dm | 2 +- code/modules/awaymissions/redgate.dm | 2 +- code/modules/food/food/drinks/bottle.dm | 2 +- .../kitchen/smartfridge/smartfridge_vr.dm | 9 +- .../maint_recycler/code/maint_recycler.dm | 2 +- code/modules/mining/kinetic_crusher.dm | 4 +- .../mob/living/carbon/human/human_defense.dm | 83 +++++++-------- code/modules/mob/living/living.dm | 1 - code/modules/mob/living/living_defense.dm | 22 ++-- .../subtypes/animal/alien animals/stardog.dm | 7 +- code/modules/mob/mob.dm | 1 + code/modules/multiz/turf.dm | 2 +- code/modules/projectiles/guns/lasertag.dm | 4 +- .../projectiles/guns/launcher/syringe_gun.dm | 8 +- code/modules/projectiles/projectile/beams.dm | 2 +- .../projectiles/projectile/explosive.dm | 4 +- code/modules/recycling/disposal_machines.dm | 2 +- code/modules/recycling/sortingmachinery.dm | 2 +- code/modules/shieldgen/emergency_shield.dm | 2 +- code/modules/tgs_commands/vorestation.dm | 2 +- code/modules/vore/resizing/holder_vr.dm | 1 - .../code/game/turfs/simulated/shuttlewalls.dm | 3 +- .../simple_mob/subtypes/bullet_heck/base.dm | 6 +- 43 files changed, 219 insertions(+), 170 deletions(-) diff --git a/code/__defines/dcs/signals/signals_mob/signals_mob_living.dm b/code/__defines/dcs/signals/signals_mob/signals_mob_living.dm index 6e84d3e320..07685f0b6a 100644 --- a/code/__defines/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__defines/dcs/signals/signals_mob/signals_mob_living.dm @@ -449,3 +449,7 @@ #define COMSIG_VENT_CRAWLER_ENTERED "ventcrawl_entered_vent" ///called when a ventcrawling mob leaves a vent : (mob/exiting_mob) #define COMSIG_VENT_CRAWLER_EXITED "ventcrawl_exit_vent" + +///called when a living mob collides with a dense turf : /mob/living/proc/turf_collision(var/turf/T, var/speed) +#define COMSIG_LIVING_TURF_COLLISION "living_turf_collision" + #define COMPONENT_LIVING_BLOCK_TURF_COLLISION (1<<0) diff --git a/code/__defines/dcs/signals/signals_vore.dm b/code/__defines/dcs/signals/signals_vore.dm index 6c0eb35fce..746ce3fb88 100644 --- a/code/__defines/dcs/signals/signals_vore.dm +++ b/code/__defines/dcs/signals/signals_vore.dm @@ -12,7 +12,7 @@ #define COMSIG_LIVING_FALLING_DOWN "living_falling_down" //Special handling. Cancel the fall chain. #define COMSIG_CANCEL_FALL (1<<0) -///from /mob/living/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR) +///from /mob/living/hitby(atom/movable/source, datum/thrownthing/throwingdatum). #define COMSIG_LIVING_HIT_BY_THROWN_ENTITY "hit_by_thrown_entity" //Special handling. Cancel the hitby proc. #define COMSIG_CANCEL_HITBY (1<<0) diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index d5ad6ab640..c29c93af6c 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -133,6 +133,7 @@ #define FIRE_PRIORITY_AIR 35 #define FIRE_PRIORITY_OBJ 40 #define FIRE_PRIORITY_PROCESS 45 +#define FIRE_PRIORITY_THROWING 45 #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_TICKER 60 #define FIRE_PRIORITY_PLANETS 75 diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm index 037970ef93..33e30895e0 100644 --- a/code/controllers/subsystems/throwing.dm +++ b/code/controllers/subsystems/throwing.dm @@ -3,14 +3,16 @@ SUBSYSTEM_DEF(throwing) name = "Throwing" + priority = FIRE_PRIORITY_THROWING wait = 1 - flags = SS_NO_INIT|SS_KEEP_TIMING + flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME var/list/currentrun var/list/processing = list() /datum/controller/subsystem/throwing/stat_entry(msg) - msg = "P:[processing.len]" + msg = "P:[length(processing)]" return ..() /datum/controller/subsystem/throwing/fire(resumed = 0) @@ -38,36 +40,76 @@ 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 + ///The turf that we were thrown from. + var/turf/starting_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 its target. var/maxrange + ///Turfs to travel per tick var/speed - var/mob/thrower - var/start_time - var/dist_travelled = 0 - var/dist_x - var/dist_y - var/dx - var/dy - var/diagonal_error + ///If a mob is the one who has thrown the object, then it's moved here. This can be null and must be null checked before trying to use it. + var/datum/weakref/thrower + ///A variable that helps in describing objects thrown at an angle, if it should be moved diagonally first or last. + var/diagonals_first + ///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 = 1 + ///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 + /// If our thrownthing has been blocked + var/blocked = FALSE -/datum/thrownthing/New(var/atom/movable/thrownthing, var/atom/target, var/range, var/speed, var/mob/thrower, var/datum/callback/callback) +/datum/thrownthing/New(atom/movable/thrownthing, atom/target, init_dir, maxrange, speed, mob/thrower, diagonals_first, force, gentle, callback, target_zone) + . = ..() src.thrownthing = thrownthing - src.target = target + RegisterSignal(thrownthing, COMSIG_QDELETING, PROC_REF(on_thrownthing_qdel)) + RegisterSignal(thrownthing, COMSIG_LIVING_TURF_COLLISION, PROC_REF(hit_atom)) + src.starting_turf = get_turf(thrownthing) src.target_turf = get_turf(target) - src.init_dir = get_dir(thrownthing, target) - src.maxrange = range + if(target_turf != target) + src.initial_target = WEAKREF(target) + src.init_dir = init_dir + src.maxrange = maxrange src.speed = speed - src.thrower = thrower + if(thrower) + src.thrower = WEAKREF(thrower) + src.diagonals_first = diagonals_first + src.force = force + src.gentle = gentle src.callback = callback + src.target_zone = target_zone if(!QDELETED(thrower) && ismob(thrower)) src.target_zone = thrower.zone_sel ? thrower.zone_sel.selecting : null @@ -92,14 +134,29 @@ SUBSYSTEM_DEF(throwing) start_time = world.time /datum/thrownthing/Destroy() + UnregisterSignal(thrownthing, COMSIG_QDELETING) + UnregisterSignal(thrownthing, COMSIG_LIVING_TURF_COLLISION) SSthrowing.processing -= thrownthing + SSthrowing.currentrun -= thrownthing thrownthing.throwing = null thrownthing = null - target = null thrower = null + initial_target = null callback = null return ..() +///Defines the datum behavior on the thrownthing's qdeletion event. +/datum/thrownthing/proc/on_thrownthing_qdel(atom/movable/source, force) + SIGNAL_HANDLER + + qdel(src) + +/// Returns the thrower, or null +/datum/thrownthing/proc/get_thrower() + . = thrower?.resolve() + if(isnull(.)) + thrower = null + /datum/thrownthing/proc/tick() var/atom/movable/AM = thrownthing if (!isturf(AM.loc) || !AM.throwing) @@ -168,21 +225,22 @@ SUBSYSTEM_DEF(throwing) return thrownthing.throwing = null if (!hit) + var/atom/movable/actual_target = initial_target?.resolve() for (var/thing in get_turf(thrownthing)) //looking for our target on the turf we land on. var/atom/A = thing - if (A == target) + if (A == actual_target) hit = TRUE - thrownthing.throw_impact(A, speed) + thrownthing.throw_impact(A, src) break if (!hit) - thrownthing.throw_impact(get_turf(thrownthing), speed) // we haven't hit something yet and we still must, let's hit the ground. + thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. if(ismob(thrownthing)) var/mob/M = thrownthing M.inertia_dir = init_dir if(t_target && !QDELETED(thrownthing)) - thrownthing.throw_impact(t_target, speed) + thrownthing.throw_impact(t_target, src) if (callback) callback.Invoke() diff --git a/code/datums/elements/vore/spontaneous_vore.dm b/code/datums/elements/vore/spontaneous_vore.dm index f83ddbe9c4..2f3059264d 100644 --- a/code/datums/elements/vore/spontaneous_vore.dm +++ b/code/datums/elements/vore/spontaneous_vore.dm @@ -68,7 +68,7 @@ source.visible_message(span_vdanger("\The [drop_mob] falls right into \the [source]!")) return COMSIG_CANCEL_FALL -/datum/element/spontaneous_vore/proc/handle_hitby(mob/living/source, atom/movable/hitby, speed) +/datum/element/spontaneous_vore/proc/handle_hitby(mob/living/source, atom/movable/hitby, mob/thrower, speed) SIGNAL_HANDLER //Handle object throw vore @@ -80,7 +80,6 @@ if(source.stat != DEAD && source.trash_catching) if(source.adminbus_trash || is_type_in_list(O, GLOB.edible_trash) && O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist)) source.visible_message(span_vwarning("[O] is thrown directly into [source]'s [lowertext(destination_belly.name)]!")) - O.throwing = 0 destination_belly.nom_atom(O) return COMSIG_CANCEL_HITBY @@ -105,7 +104,11 @@ destination_belly.nom_atom(thrown_mob) //Eat them!!! source.visible_message(span_vwarning("[thrown_mob] is thrown right into [source]'s [lowertext(destination_belly.name)]!")) source.on_throw_vore_special(TRUE, thrown_mob) - add_attack_logs(thrown_mob.thrower,source,"Devoured [thrown_mob.name] via throw vore.") + + if(thrower) + add_attack_logs(thrower,source,"Devoured [thrown_mob.name] via throw vore.") + else + log_vore("[source] devoured [thrown_mob.name] via throw vore.") return COMSIG_CANCEL_HITBY //We can stop here. We don't need to calculate damage or anything else. They're eaten. // PERSON BEING HIT: CAN BE DROP PREY, ALLOWS THROW VORE, AND IS DEVOURABLE. @@ -116,7 +119,12 @@ return source.visible_message(span_vwarning("[source] suddenly slips inside of [thrown_mob]'s [lowertext(destination_belly.name)] as [thrown_mob] flies into them!")) destination_belly.nom_atom(source) //Eat them!!! - add_attack_logs(thrown_mob.LAssailant,source,"Was Devoured by [thrown_mob.name] via throw vore.") + if(source.loc != thrown_mob.vore_selected) + source.forceMove(thrown_mob.vore_selected) //Double check. Should never happen but...Weirder things have happened! + if(thrower) + add_attack_logs(thrower,source,"Was Devoured by [thrown_mob.name] via throw vore.") + else + log_vore("[source] Was Devoured by [thrown_mob.name] via throw vore.") return COMSIG_CANCEL_HITBY //source = person standing up diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 4e75659198..38d7091349 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -298,10 +298,8 @@ return -/atom/proc/hitby(atom/movable/source) +/atom/proc/hitby(atom/movable/source, datum/thrownthing/throwingdatum) SEND_SIGNAL(src, COMSIG_ATOM_HITBY, source) - if (density) - source.throwing = 0 return //returns 1 if made bloody, returns 0 otherwise diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 6a6162f404..4e36a8164c 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -9,8 +9,7 @@ var/moving_diagonally var/move_speed = 10 var/l_move_time = 1 - var/throwing = 0 - var/thrower + var/datum/thrownthing/throwing var/turf/throw_source = null var/throw_speed = 2 var/throw_range = 7 @@ -93,6 +92,7 @@ if(orbiting) stop_orbit() + throw_source = null QDEL_NULL(riding_datum) set_listening(NON_LISTENING_ATOM) @@ -291,8 +291,7 @@ CRASH("Bump was called with no argument.") . = ..() if(throwing) - throw_impact(A) - throwing = 0 + throw_impact(A, throwing) if(QDELETED(A)) return @@ -412,49 +411,22 @@ ///////////////////////////////////////////////////////////////// //called when src is thrown into hit_atom -/atom/movable/proc/throw_impact(atom/hit_atom, var/speed) +/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(isliving(hit_atom)) var/mob/living/M = hit_atom if(M.buckled == src) return // Don't hit the thing we're buckled to. - M.hitby(src,speed) + M.hitby(src, throwingdatum) else if(isobj(hit_atom)) var/obj/O = hit_atom if(!O.anchored) step(O, src.last_move) - O.hitby(src,speed) + O.hitby(src, throwingdatum) else if(isturf(hit_atom)) - src.throwing = 0 var/turf/T = hit_atom - T.hitby(src,speed) - -//decided whether a movable atom being thrown can pass through the turf it is in. -/atom/movable/proc/hit_check(var/speed) - if(src.throwing) - for(var/atom/A in get_turf(src)) - if(A == src) - continue - if(A.is_incorporeal()) - continue - if(isliving(A)) - var/mob/living/M = A - if(M.lying) - continue - src.throw_impact(A,speed) - if(isobj(A)) - if(!A.density || A.throwpass) - continue - // Special handling of windows, which are dense but block only from some directions - if(istype(A, /obj/structure/window)) - var/obj/structure/window/W = A - if (!W.is_fulltile() && !(turn(src.last_move, 180) & A.dir)) - continue - // Same thing for (closed) windoors, which have the same problem - else if(istype(A, /obj/machinery/door/window) && !(turn(src.last_move, 180) & A.dir)) - continue - src.throw_impact(A,speed) + T.hitby(src, throwingdatum) /atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, datum/callback/callback) //If this returns FALSE then callback will not be called. . = TRUE @@ -464,7 +436,12 @@ if (pulledby) pulledby.stop_pulling() - var/datum/thrownthing/TT = new(src, target, range, speed, thrower, callback) + var/real_force = 0 + if(isitem(src)) + var/obj/item/thrown_item = src + real_force = thrown_item.throwforce + + var/datum/thrownthing/TT = new(src, target, dir, range, speed, thrower, FALSE, real_force, FALSE, callback) throwing = TT pixel_z = 0 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 84f22e0479..f28bb5905b 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -121,7 +121,7 @@ return destroy() -/obj/machinery/camera/hitby(atom/movable/source) +/obj/machinery/camera/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() if (!isobj(source)) return diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 24d920b21a..7840f4a104 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -220,9 +220,10 @@ -/obj/machinery/door/hitby(atom/movable/source, var/speed=5) +/obj/machinery/door/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() visible_message(span_danger("[name] was hit by [source].")) + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR var/tforce = 0 if(ismob(source)) tforce = 15 * (speed/THROWFORCE_SPEED_DIVISOR) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 8ebca35b60..d48ee1101c 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1119,7 +1119,7 @@ src.log_append_to_last("Armor saved.") return -/obj/mecha/hitby(atom/movable/source) //wrapper +/obj/mecha/hitby(atom/movable/source, datum/thrownthing/throwingdatum) //wrapper ..() src.mecha_log_message("Hit by [source].",1) call((proc_res["dynhitby"]||src), "dynhitby")(source) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 74a4bfe188..ee1475380a 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -355,7 +355,6 @@ return src.pickup(user) - src.throwing = 0 if (src.loc == user) if(!user.unEquip(src)) return @@ -415,7 +414,7 @@ else return 0 -/obj/item/throw_impact(atom/hit_atom, var/speed) +/obj/item/throw_impact(atom/hit_atom) ..() if(isliving(hit_atom) && !hit_atom.is_incorporeal()) //Living mobs handle hit sounds differently. var/volume = get_volume_by_throwforce_and_or_w_class() diff --git a/code/game/objects/items/weapons/capture_crystal.dm b/code/game/objects/items/weapons/capture_crystal.dm index c03bb417f4..b9b31998c5 100644 --- a/code/game/objects/items/weapons/capture_crystal.dm +++ b/code/game/objects/items/weapons/capture_crystal.dm @@ -364,7 +364,7 @@ //If the crystal hasn't been set up, it does this /obj/item/capture_crystal/proc/activate(mob/living/user, target) if(!cooldown_check()) //Are we ready to do things yet? - to_chat(thrower, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) + to_chat(user, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1) return if(spawn_mob_type && !bound_mob) //We don't already have a mob, but we know what kind of mob we want @@ -424,7 +424,7 @@ //We're using the crystal, but what will it do? /obj/item/capture_crystal/proc/determine_action(mob/living/U, T) if(!cooldown_check()) //Are we ready yet? - to_chat(thrower, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) + to_chat(U, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1) return //No if(bound_mob in contents) //Do we have our mob? @@ -917,7 +917,7 @@ /obj/item/capture_crystal/cheap/activate(mob/living/user, target) if(!cooldown_check()) //Are we ready to do things yet? - to_chat(thrower, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) + to_chat(user, span_notice("\The [src] clicks unsatisfyingly... It is not ready yet.")) playsound(src, 'sound/effects/capture-crystal-negative.ogg', 75, 1, -1) return if(spawn_mob_type && !bound_mob) //We don't already have a mob, but we know what kind of mob we want diff --git a/code/game/objects/structures/alien/alien.dm b/code/game/objects/structures/alien/alien.dm index 970e7b67d0..8e2a476ca0 100644 --- a/code/game/objects/structures/alien/alien.dm +++ b/code/game/objects/structures/alien/alien.dm @@ -33,7 +33,7 @@ healthcheck() return -/obj/structure/alien/hitby(atom/movable/source) +/obj/structure/alien/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() visible_message(span_danger("\The [src] was hit by \the [source].")) var/tforce diff --git a/code/game/objects/structures/gargoyle.dm b/code/game/objects/structures/gargoyle.dm index f677a47def..8314d8f58c 100644 --- a/code/game/objects/structures/gargoyle.dm +++ b/code/game/objects/structures/gargoyle.dm @@ -285,14 +285,14 @@ tail_image.layer = BODY_LAYER + ((dir in tail_lower_dirs) ? TAIL_LOWER_LAYER : tail_layering) add_overlay(tail_image) -/obj/structure/gargoyle/hitby(atom/movable/source ,var/speed = THROWFORCE_SPEED_DIVISOR) +/obj/structure/gargoyle/hitby(atom/movable/source, datum/thrownthing/throwingdatum) var/mob/living/carbon/human/gargoyle = WR_gargoyle.resolve() if(!gargoyle) return if(isitem(source) && gargoyle.vore_selected && gargoyle.trash_catching) var/obj/item/I = source if(gargoyle.adminbus_trash || is_type_in_list(I, GLOB.edible_trash) && I.trash_eatable && !is_type_in_list(I, GLOB.item_vore_blacklist)) - gargoyle.hitby(source, speed) + gargoyle.hitby(source, throwingdatum) return else if(isliving(source)) var/mob/living/L = source @@ -301,7 +301,7 @@ if(gargoyle.can_be_drop_prey) drop_prey_temp = TRUE gargoyle.can_be_drop_prey = FALSE //Making sure the original gargoyle body is not the one getting throwvored instead. - gargoyle.hitby(L, speed) + gargoyle.hitby(L, throwingdatum) if(drop_prey_temp) gargoyle.can_be_drop_prey = TRUE return diff --git a/code/game/objects/structures/low_wall.dm b/code/game/objects/structures/low_wall.dm index 47df2f8cc9..d3ea0aaa99 100644 --- a/code/game/objects/structures/low_wall.dm +++ b/code/game/objects/structures/low_wall.dm @@ -257,9 +257,10 @@ take_damage(damage) return -/obj/structure/low_wall/hitby(atom/movable/source, var/speed) +/obj/structure/low_wall/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() var/tforce = 0 + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR if(ismob(source)) // All mobs have a multiplier and a size according to mob_defines.dm var/mob/I = source tforce = I.mob_size * (speed/THROWFORCE_SPEED_DIVISOR) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index da513b3850..daddfa4973 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -165,7 +165,7 @@ return !anchored // If it's anchored, it'll block air. return TRUE // Don't stop airflow from the other sides. -/obj/structure/window/hitby(atom/movable/source) +/obj/structure/window/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() visible_message(span_danger("[src] was hit by [source].")) var/tforce = 0 diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 2a94f78c62..200d596308 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -61,7 +61,7 @@ if(burn_stuff(AM)) START_PROCESSING(SSturfs, src) -/turf/simulated/floor/lava/hitby(atom/movable/source) +/turf/simulated/floor/lava/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(burn_stuff(source)) START_PROCESSING(SSturfs, src) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 9600c3fc26..55edd14398 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -96,13 +96,14 @@ take_damage(damage) return -/turf/simulated/wall/hitby(atom/movable/source, var/speed=THROWFORCE_SPEED_DIVISOR) +/turf/simulated/wall/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() if(ismob(source)) return var/tforce = 0 if(isobj(source)) var/obj/object = source + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR if(isitem(object)) var/obj/item/our_item = object tforce = our_item.throwforce * (speed/THROWFORCE_SPEED_DIVISOR) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index cac9bae268..873b77f70f 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -347,7 +347,7 @@ return // Called when turf is hit by a thrown object -/turf/hitby(atom/movable/source, var/speed) +/turf/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(!density) return @@ -356,7 +356,7 @@ step(source, turn(source.last_move, 180)) //This makes it float away after hitting a wall in 0G if(isliving(source)) var/mob/living/M = source - M.turf_collision(src, speed) + M.turf_collision(src, throwingdatum?.speed) /turf/AllowDrop() return TRUE diff --git a/code/game/turfs/unsimulated/sky_vr.dm b/code/game/turfs/unsimulated/sky_vr.dm index 6127168178..1ef473acdf 100644 --- a/code/game/turfs/unsimulated/sky_vr.dm +++ b/code/game/turfs/unsimulated/sky_vr.dm @@ -41,7 +41,7 @@ do_fall(AM) -/turf/unsimulated/floor/sky/hitby(var/atom/movable/source, var/speed) +/turf/unsimulated/floor/sky/hitby(var/atom/movable/source, datum/thrownthing/throwingdatum) . = ..() if(!does_skyfall) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 12358b20b3..aa3b2483a9 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -105,7 +105,7 @@ return 1 //end the search! return 0 -/obj/item/assembly/mousetrap/hitby(var/atom/movable/source) +/obj/item/assembly/mousetrap/hitby(var/atom/movable/source, datum/thrownthing/throwingdatum) if(!armed) return ..() visible_message(span_warning("[src] is triggered by [source].")) diff --git a/code/modules/awaymissions/redgate.dm b/code/modules/awaymissions/redgate.dm index ea85d5a1de..3de12a5a08 100644 --- a/code/modules/awaymissions/redgate.dm +++ b/code/modules/awaymissions/redgate.dm @@ -1759,7 +1759,7 @@ ball.item_state = "[initial(ball.item_state)]" ball.update_icon() -/obj/structure/hyperball_goal/hitby(atom/movable/source) +/obj/structure/hyperball_goal/hitby(atom/movable/source, datum/thrownthing/throwingdatum) . = ..() if(!istype(source, /obj/item/laserdome_hyperball)) return diff --git a/code/modules/food/food/drinks/bottle.dm b/code/modules/food/food/drinks/bottle.dm index b86ef2fd81..57c95b9561 100644 --- a/code/modules/food/food/drinks/bottle.dm +++ b/code/modules/food/food/drinks/bottle.dm @@ -41,7 +41,7 @@ violent_throw = TRUE throw_source = get_turf(thrower) -/obj/item/reagent_containers/food/drinks/bottle/throw_impact(atom/hit_atom, var/speed) +/obj/item/reagent_containers/food/drinks/bottle/throw_impact(atom/hit_atom) ..() if(isGlass && violent_throw) diff --git a/code/modules/food/kitchen/smartfridge/smartfridge_vr.dm b/code/modules/food/kitchen/smartfridge/smartfridge_vr.dm index 1708bf97fe..d9416d4ae5 100644 --- a/code/modules/food/kitchen/smartfridge/smartfridge_vr.dm +++ b/code/modules/food/kitchen/smartfridge/smartfridge_vr.dm @@ -19,13 +19,14 @@ /* * Allow thrown items into smartfridges */ -/obj/machinery/smartfridge/hitby(var/atom/movable/source, speed) +/obj/machinery/smartfridge/hitby(var/atom/movable/source, datum/thrownthing/throwingdatum) . = ..() - if(accept_check(source) && source.thrower) + var/mob/thrower = throwingdatum?.get_thrower() + if(accept_check(source) && thrower) //Try to find what job they are via ID var/obj/item/card/id/thrower_id - if(ismob(source.thrower)) - var/mob/T = source.thrower + if(ismob(thrower)) + var/mob/T = thrower thrower_id = T.GetIdCard() //98% chance the expert makes it diff --git a/code/modules/maint_recycler/code/maint_recycler.dm b/code/modules/maint_recycler/code/maint_recycler.dm index 54bafdb839..12482254c1 100644 --- a/code/modules/maint_recycler/code/maint_recycler.dm +++ b/code/modules/maint_recycler/code/maint_recycler.dm @@ -244,7 +244,7 @@ -/obj/machinery/maint_recycler/hitby(atom/movable/source) +/obj/machinery/maint_recycler/hitby(atom/movable/source, datum/thrownthing/throwingdatum) . = ..() if(!isitem(source) || istype(source, /obj/item/projectile)) //no mob throwing. return diff --git a/code/modules/mining/kinetic_crusher.dm b/code/modules/mining/kinetic_crusher.dm index 08e428f5b6..ed4ff4ac5d 100644 --- a/code/modules/mining/kinetic_crusher.dm +++ b/code/modules/mining/kinetic_crusher.dm @@ -136,13 +136,13 @@ else L.apply_damage(detonation_damage + thrown_bonus, BRUTE, blocked = def_check) -/obj/item/kinetic_crusher/throw_impact(atom/hit_atom, speed) +/obj/item/kinetic_crusher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatumd) . = ..() if(!isliving(hit_atom)) return var/mob/living/L = hit_atom if(L.has_modifier_of_type(/datum/modifier/crusher_mark)) - detonate(L, thrower, TRUE) + detonate(L, throwingdatumd?.get_thrower(), TRUE) /obj/item/kinetic_crusher/proc/Recharge() if(!charged) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index bc8938441c..8307b5c765 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -344,116 +344,109 @@ emp_act return 1 //this proc handles being hit by a thrown atom -/mob/living/carbon/human/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR) +/mob/living/carbon/human/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(src.is_incorporeal()) return // if(buckled && buckled == AM) // return // Don't get hit by the thing we're buckled to. - if(isliving(source)) - if(SEND_SIGNAL(src, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, source, speed) & COMSIG_CANCEL_HITBY) - return + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR + var/mob/living/thrower = throwingdatum?.get_thrower() + if(SEND_SIGNAL(src, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, source, thrower, speed) & COMSIG_CANCEL_HITBY) + return if(isitem(source)) - var/obj/item/O = source - if(stat != DEAD && trash_catching && vore_selected) - if(adminbus_trash || is_type_in_list(O, GLOB.edible_trash) && O.trash_eatable && !is_type_in_list(O, GLOB.item_vore_blacklist)) - visible_message(span_vwarning("[O] is thrown directly into [src]'s [lowertext(vore_selected.name)]!")) - O.throwing = 0 - vore_selected.nom_atom(O) - return + var/obj/item/thrown_object = source if(in_throw_mode && speed <= THROWFORCE_SPEED_DIVISOR) //empty active hand and we're in throw mode if(canmove && !restrained() && !src.is_incorporeal()) - if(isturf(O.loc) && can_catch(O)) + if(isturf(thrown_object.loc) && can_catch(thrown_object)) if(!SEND_SIGNAL(src, COMSIG_HUMAN_ON_CATCH_THROW, source, speed)) - put_in_active_hand(O) - visible_message(span_warning("[src] catches [O]!")) + put_in_active_hand(thrown_object) + visible_message(span_warning("[src] catches [thrown_object]!")) throw_mode_off() return - var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR) + var/throw_damage = thrown_object.throwforce*(speed/THROWFORCE_SPEED_DIVISOR) if(species && species.throwforce_absorb_threshold >= throw_damage) - visible_message(span_infoplain(span_bold("\The [O]") + " simply bounces off of [src]'s body!")) + visible_message(span_infoplain(span_bold("\The [thrown_object]") + " simply bounces off of [src]'s body!")) return var/zone - if (isliving(O.thrower)) - var/mob/living/L = O.thrower + if (isliving(thrower)) + var/mob/living/L = thrower zone = check_zone(L.zone_sel.selecting) else zone = ran_zone(BP_TORSO,75) //Hits a random part of the body, geared towards the chest //check if we hit var/miss_chance = 15 - if (O.throw_source) - var/distance = get_dist(O.throw_source, loc) + if (thrown_object.throw_source) + var/distance = get_dist(thrown_object.throw_source, loc) miss_chance = max(15*(distance-2), 0) - zone = get_zone_with_miss_chance(zone, src, miss_chance, ranged_attack=1, attacker = O.thrower) + zone = get_zone_with_miss_chance(zone, src, miss_chance, ranged_attack=1, attacker = thrower) - if(zone && O.thrower != src) - var/shield_check = check_shields(throw_damage, O, thrower, zone, "[O]") + if(zone && thrower != src) + var/shield_check = check_shields(throw_damage, thrown_object, thrower, zone, "[thrown_object]") if(shield_check == PROJECTILE_FORCE_MISS) zone = null else if(shield_check) return if(!zone) - visible_message(span_infoplain(span_bold("\The [O]") + " misses [src] narrowly!")) + visible_message(span_infoplain(span_bold("\The [thrown_object]") + " misses [src] narrowly!")) return - O.throwing = 0 //it hit, so stop moving - var/obj/item/organ/external/affecting = get_organ(zone) var/hit_area = affecting.name - src.visible_message(span_filter_warning("[span_red("[src] has been hit in the [hit_area] by [O].")]")) + src.visible_message(span_filter_warning("[span_red("[src] has been hit in the [hit_area] by [thrown_object].")]")) - if(ismob(O.thrower)) - add_attack_logs(O.thrower,src,"Hit with thrown [O.name]") + if(ismob(thrower)) + add_attack_logs(thrower,src,"Hit with thrown [thrown_object.name]") - var/armor = run_armor_check(affecting, "melee", O.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here + var/armor = run_armor_check(affecting, "melee", thrown_object.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here if(armor < 100) - apply_damage(throw_damage, O.damtype, zone, armor, is_sharp(O), has_edge(O), O) + apply_damage(throw_damage, thrown_object.damtype, zone, armor, is_sharp(thrown_object), has_edge(thrown_object), thrown_object) //thrown weapon embedded object code. - if(O.damtype == BRUTE) - if (!is_robot_module(O)) - var/sharp = is_sharp(O) + if(thrown_object.damtype == BRUTE) + if (!is_robot_module(thrown_object)) + var/sharp = is_sharp(thrown_object) var/damage = throw_damage if(armor) damage /= armor+1 //blunt objects should really not be embedding in things unless a huge amount of force is involved - var/embed_chance = sharp? damage/O.w_class : damage/(O.w_class*3) - var/embed_threshold = sharp? 5*O.w_class : 15*O.w_class + var/embed_chance = sharp? damage/thrown_object.w_class : damage/(thrown_object.w_class*3) + var/embed_threshold = sharp? 5*thrown_object.w_class : 15*thrown_object.w_class //Sharp objects will always embed if they do enough damage. //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold - if((sharp && prob(damage/(10*O.w_class)*100)) || (damage > embed_threshold && prob(embed_chance))) - affecting.embed(O) + if((sharp && prob(damage/(10*thrown_object.w_class)*100)) || (damage > embed_threshold && prob(embed_chance))) + affecting.embed(thrown_object) // Begin BS12 momentum-transfer code. - var/mass = O.w_class/THROWNOBJ_KNOCKBACK_DIVISOR + var/mass = thrown_object.w_class/THROWNOBJ_KNOCKBACK_DIVISOR var/momentum = speed*mass - if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED && !buckled) - var/dir = get_dir(O.throw_source, src) + if(thrown_object.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED && !buckled) + var/dir = get_dir(thrown_object.throw_source, src) visible_message(span_filter_warning("[span_red("[src] staggers under the impact!")]"),span_filter_warning("[span_red("You stagger under the impact!")]")) src.throw_at(get_edge_target_turf(src,dir),1,momentum) - if(!O || !src) return + if(!thrown_object || !src) return - if(O.loc == src && O.sharp) //Projectile is embedded and suitable for pinning. + if(thrown_object.loc == src && thrown_object.sharp) //Projectile is embedded and suitable for pinning. var/turf/T = near_wall(dir,2) if(T) src.loc = T - visible_message(span_warning("[src] is pinned to the wall by [O]!"),span_warning("You are pinned to the wall by [O]!")) + visible_message(span_warning("[src] is pinned to the wall by [thrown_object]!"),span_warning("You are pinned to the wall by [thrown_object]!")) src.anchored = TRUE - src.pinned += O + src.pinned += thrown_object // This does a prob check to catch the thing flying at you, with a minimum of 1% /mob/living/carbon/human/proc/can_catch(var/obj/item/O) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index a359302608..ef5f72b8a0 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1325,7 +1325,6 @@ src.inertia_dir = get_dir(target, src) step(src, inertia_dir) item.throw_at(target, throw_range, item.throw_speed, src) - item.throwing = 1 //Small edit so thrown interactions actually work! return TRUE else return FALSE diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 90652af125..9ebc4961ec 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -243,11 +243,16 @@ return 1 //this proc handles being hit by a thrown atom -/mob/living/hitby(atom/movable/source, var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve +/mob/living/hitby(atom/movable/source, datum/thrownthing/throwingdatum)//Standardization and logging -Sieve if(is_incorporeal()) return - if(SEND_SIGNAL(src, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, source, speed) & COMSIG_CANCEL_HITBY) + + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR + var/mob/living/thrower = throwingdatum?.get_thrower() + + if(SEND_SIGNAL(src, COMSIG_LIVING_HIT_BY_THROWN_ENTITY, source, thrower, speed) & COMSIG_CANCEL_HITBY) return + if(isitem(source)) var/obj/item/O = source var/dtype = O.damtype @@ -268,15 +273,12 @@ apply_damage(throw_damage, dtype, null, armor, is_sharp(O), has_edge(O), O) - O.throwing = 0 //it hit, so stop moving - - if(ismob(O.thrower)) - var/mob/M = O.thrower - var/client/assailant = M.client + if(ismob(thrower)) + var/client/assailant = thrower.client if(assailant) - add_attack_logs(M,src,"Hit by thrown [O.name]") + add_attack_logs(thrower, src, "Hit by thrown [O.name]") if(ai_holder) - ai_holder.react_to_attack(O.thrower) + ai_holder.react_to_attack(thrower) // Begin BS12 momentum-transfer code. var/mass = O.w_class/THROWNOBJ_KNOCKBACK_DIVISOR @@ -314,6 +316,8 @@ //This is called when the mob is thrown into a dense turf /mob/living/proc/turf_collision(var/turf/T, var/speed) + if(SEND_SIGNAL(src, COMSIG_LIVING_TURF_COLLISION, T, speed) & COMPONENT_LIVING_BLOCK_TURF_COLLISION) + return src.take_organ_damage(speed * 5) // used to be 5 * speed. That's a default of 25 and I dont see anything ever changing the "speed" value. //CHOMPEdit, no. We keep the damage values, no reduction to 12 //src.Weaken(3) // That is absurdly high so im just setting it to a flat 12 with a bit of stun ontop. //Stun is too dangerous playsound(src, get_sfx("punch"), 50) //ouch sound diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm index 5baf514cab..1c49a26d3b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm @@ -1364,7 +1364,8 @@ playsound(src, teleport_sound, vol = 100, vary = 1, preference = /datum/preference/toggle/eating_noises, volume_channel = VOLUME_CHANNEL_VORE) visible_message(span_warning("The dog gobbles up \the [I]!")) if(dog.client) - to_chat(dog, span_notice("[I.thrower ? "\The [I.thrower]" : "Someone"] feeds \the [I] to you!")) + var/mob/thrower = I.throwing?.get_thrower() + to_chat(dog, span_notice("[thrower ? "\The [thrower]" : "Someone"] feeds \the [I] to you!")) qdel(I) GLOB.items_digested_roundstat++ @@ -1436,7 +1437,7 @@ START_PROCESSING(SSturfs, src) we_process = TRUE -/turf/simulated/floor/water/digestive_enzymes/hitby(atom/movable/source) +/turf/simulated/floor/water/digestive_enzymes/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(digest_stuff(source) && !we_process) START_PROCESSING(SSturfs, src) we_process = TRUE @@ -1566,7 +1567,7 @@ if(!we_process) START_PROCESSING(SSturfs, src) -/turf/simulated/floor/flesh/mover/hitby(atom/movable/source) +/turf/simulated/floor/flesh/mover/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(!we_process) START_PROCESSING(SSturfs, src) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8e0ca19544..fae7b0eee9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -43,6 +43,7 @@ previewing_belly = null // from code/modules/vore/eating/mob_ch.dm vore_selected = null // from code/modules/vore/eating/mob_vr focus = null + LAssailant = null motiontracker_unsubscribe(TRUE) // Force unsubscribe diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 67c41c1649..1e09515f85 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -84,7 +84,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr A.fall() // Called when thrown object lands on this turf. -/turf/simulated/open/hitby(var/atom/movable/source, var/speed) +/turf/simulated/open/hitby(var/atom/movable/source, datum/thrownthing/throwingdatum) . = ..() source.fall() diff --git a/code/modules/projectiles/guns/lasertag.dm b/code/modules/projectiles/guns/lasertag.dm index 5e8ec95219..338a6bce54 100644 --- a/code/modules/projectiles/guns/lasertag.dm +++ b/code/modules/projectiles/guns/lasertag.dm @@ -144,9 +144,9 @@ return TRUE ///go my hack -/obj/item/lasertagknife/throw_impact(atom/hit_atom, var/speed) +/obj/item/lasertagknife/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(ismob(hit_atom)) //So, attacker should ALWAYS be true, but there's a problem. The code doesn't actually set 'thrower' which we used for thrown laser knives. //Instead of this PR getting massively out of scope and refactoring throwing code, we're just going to have thrown knives do vest override. - return handle_lasertag_attack(hit_atom, thrower, tag_damage, TRUE, required_vest, allowed_suits) + return handle_lasertag_attack(hit_atom, throwingdatum?.get_thrower(), tag_damage, TRUE, required_vest, allowed_suits) ..() diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm index a4acc83582..4be7a18ef2 100644 --- a/code/modules/projectiles/guns/launcher/syringe_gun.dm +++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm @@ -45,18 +45,20 @@ icon_state = icon_flight underlays.Cut() -/obj/item/syringe_cartridge/throw_impact(atom/hit_atom, var/speed) +/obj/item/syringe_cartridge/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() //handles embedding for us. Should have a decent chance if thrown fast enough if(syringe) //check speed to see if we hit hard enough to trigger the rapid injection //incidentally, this means syringe_cartridges can be used with the pneumatic launcher - if(speed >= 10 && isliving(hit_atom)) + if(throwingdatum?.speed >= 10 && isliving(hit_atom)) var/mob/living/L = hit_atom //unfortuately we don't know where the dart will actually hit, since that's done by the parent. if(L.can_inject() && syringe.reagents) var/contained = syringe.reagents.get_reagents() var/trans = syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD) - add_attack_logs(thrower,L,"Shot with [src.name] containing [contained], trasferred [trans] units") + var/mob/thrower = throwingdatum?.get_thrower() + if(thrower) + add_attack_logs(thrower,L,"Shot with [src.name] containing [contained], trasferred [trans] units") syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null) syringe.update_icon() diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 84bd369141..801b530526 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -529,7 +529,7 @@ /obj/item/projectile/beam/energy_net/proc/do_net(var/mob/M) var/obj/item/energy_net/net = new net_type(get_turf(M)) - net.throw_impact(M) + net.throw_impact(M, throwing) // // Shrinking Energy Net diff --git a/code/modules/projectiles/projectile/explosive.dm b/code/modules/projectiles/projectile/explosive.dm index 76da8f3e3a..c14d017a99 100644 --- a/code/modules/projectiles/projectile/explosive.dm +++ b/code/modules/projectiles/projectile/explosive.dm @@ -17,7 +17,7 @@ explosion(target, 0, 0, 2, 4) return 1 -/obj/item/projectile/bullet/srmrocket/throw_impact(atom/target, var/speed) +/obj/item/projectile/bullet/srmrocket/throw_impact(atom/target) if(!isliving(target)) //if the target isn't alive, so is a wall or something explosion(target, 0, 1, 2, 4) else @@ -32,7 +32,7 @@ explosion(target, 0, 0, 2, 4)//No need to have a question. return 1 -/obj/item/projectile/bullet/srmrocket/weak/throw_impact(atom/target, var/speed) +/obj/item/projectile/bullet/srmrocket/weak/throw_impact(atom/target) explosion(target, 0, 0, 2, 4)//No need to have a question. qdel(src) diff --git a/code/modules/recycling/disposal_machines.dm b/code/modules/recycling/disposal_machines.dm index 1b21c25da7..350beac682 100644 --- a/code/modules/recycling/disposal_machines.dm +++ b/code/modules/recycling/disposal_machines.dm @@ -507,7 +507,7 @@ update() // update icon return -/obj/machinery/disposal/hitby(atom/movable/source) +/obj/machinery/disposal/hitby(atom/movable/source, datum/thrownthing/throwingdatum) . = ..() if(isitem(source) && !istype(source, /obj/item/projectile)) if(prob(75)) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index f73dd14de9..024bc0b433 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -28,7 +28,7 @@ AM.forceMove(src) flush() -/obj/machinery/disposal/deliveryChute/hitby(atom/movable/source) +/obj/machinery/disposal/deliveryChute/hitby(atom/movable/source, datum/thrownthing/throwingdatum) if(!QDELETED(source) || (isitem(source) || isliving(source)) && !istype(source, /obj/item/projectile)) switch(dir) if(NORTH) diff --git a/code/modules/shieldgen/emergency_shield.dm b/code/modules/shieldgen/emergency_shield.dm index b6b4ee95ef..f6fdcf6823 100644 --- a/code/modules/shieldgen/emergency_shield.dm +++ b/code/modules/shieldgen/emergency_shield.dm @@ -91,7 +91,7 @@ qdel(src) -/obj/machinery/shield/hitby(atom/movable/source) +/obj/machinery/shield/hitby(atom/movable/source, datum/thrownthing/throwingdatum) //Let everyone know we've been hit! visible_message(span_danger("\The [src] was hit by [source].")) diff --git a/code/modules/tgs_commands/vorestation.dm b/code/modules/tgs_commands/vorestation.dm index 1117e7771c..2576fc63a6 100644 --- a/code/modules/tgs_commands/vorestation.dm +++ b/code/modules/tgs_commands/vorestation.dm @@ -410,7 +410,7 @@ GLOBAL_LIST_EMPTY(pending_discord_registrations) for(var/datum/job/our_job in job_master.occupations) if(our_job.whitelist_only) whitelist_jobs += our_job.title - message.text = "The following jobs and species have a whitelist:\nJobs: [english_list(whitelist_jobs)]]\nSpecies: [english_list(GLOB.whitelisted_species)]" + message.text = "The following jobs and species have a whitelist:\nJobs: [english_list(whitelist_jobs)]\nSpecies: [english_list(GLOB.whitelisted_species)]" return message message_as_list.Cut(1, 2) diff --git a/code/modules/vore/resizing/holder_vr.dm b/code/modules/vore/resizing/holder_vr.dm index 43eaee1393..8e66d3e21b 100644 --- a/code/modules/vore/resizing/holder_vr.dm +++ b/code/modules/vore/resizing/holder_vr.dm @@ -31,7 +31,6 @@ return src.pickup(user) - src.throwing = 0 if (src.loc == user) if(!mob_can_unequip(user, user.get_inventory_slot(src))) //VOREStation Edit return diff --git a/modular_chomp/code/game/turfs/simulated/shuttlewalls.dm b/modular_chomp/code/game/turfs/simulated/shuttlewalls.dm index 25b6fa6855..7c385f6dbe 100644 --- a/modular_chomp/code/game/turfs/simulated/shuttlewalls.dm +++ b/modular_chomp/code/game/turfs/simulated/shuttlewalls.dm @@ -90,12 +90,13 @@ take_damage(damage) return -/turf/simulated/shuttlewalls/hitby(atom/movable/source, var/speed=THROWFORCE_SPEED_DIVISOR) +/turf/simulated/shuttlewalls/hitby(atom/movable/source, datum/thrownthing/throwingdatum) ..() if(ismob(source)) return var/tforce = 0 + var/speed = throwingdatum?.speed || THROWFORCE_SPEED_DIVISOR if(isitem(source)) var/obj/item/O = source tforce = O.throwforce * (speed/THROWFORCE_SPEED_DIVISOR) diff --git a/modular_chomp/code/modules/mob/living/simple_mob/subtypes/bullet_heck/base.dm b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/bullet_heck/base.dm index fbeb3e2ad4..89b56bd353 100644 --- a/modular_chomp/code/modules/mob/living/simple_mob/subtypes/bullet_heck/base.dm +++ b/modular_chomp/code/modules/mob/living/simple_mob/subtypes/bullet_heck/base.dm @@ -22,10 +22,10 @@ /mob/living/simple_mob/mechanical/mecha/eclipse/do_special_attack(atom/A) bullet_heck(A, 3, 3) -/mob/living/simple_mob/mechanical/mecha/eclipse/hitby(obj/item/projectile/P) //removal of E net cheese - if(P == /obj/item/projectile/beam/energy_net) +/mob/living/simple_mob/mechanical/mecha/eclipse/hitby(atom/movable/source, datum/thrownthing/throwingdatum) //removal of E net cheese + if(source == /obj/item/projectile/beam/energy_net) return - ..() + ..(source, throwingdatum) /datum/ai_holder/simple_mob/intentional/three_phases use_astar = TRUE