From 280dbe20c361dc611e71112834565fd65cfb4bbe Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Mon, 2 Jan 2017 01:08:03 -0800 Subject: [PATCH] [Ready] SSthrowing + callbacks! (#22476) * SSthrowing + callbacks! Throwing is now a subsystem. It's low priority, but is a ticker subsystem so is ran before most other subsystems. To allow for shit to run after the throw finishes, throwing now supports a callback. A callback datum system was created, conversion of addtimer is planned for another PR. Throwing now has a limit of 2048 turfs (was 600) Throwing now ticks every world.tick, and properly converts the speed arg from 1ds to what ever tick_lag is. Throwing now properly accounts for missed ticks. Throwing no longer uses sleep. Throwing should no longer lag since it's not filling the sleep queue up * Smoother tentacles * Some improvements * Missed a spot. * Makes shit quicker. Inlines the thrownthing.tick() proc. Raises missed ticks value Lowers max dist value Inlines the two sister overrides for /atom/movable/Moved() because that just seemed like a waste * >PRs open that use procs i'm removing. * STOP THE PRESSES! * throw_at now runs the first throw tick() immediately This will help some with throwing while running. * Item throwing now imparts the momentum of the user throwing. (ie, running in the direction you are throwing makes you throw faster, running away from the direction you are throwing makes you throw the item slower) * Moves throwing momentum from carbon/throw_item to movable/throw_at. There are other things that cause a mob to "throw" an item, I figured we keep this universal since thrower is already an arg. * Explosions throw shit faster. This was stupid, "Hey, lets set the item's throw_speed to 4 so embedding works, but lets make it throw at the base 2 throw speed for no reason." * Fixes explosion embedding. This also acts as a nice example of how to override a callback in an override of throw_at properly. --- code/__DEFINES/MC.dm | 3 +- code/__DEFINES/callbacks.dm | 3 + code/controllers/subsystem/throwing.dm | 139 ++++++++++++++++ code/datums/callback.dm | 90 ++++++++++ code/datums/martial/wrestling.dm | 4 +- code/game/atoms_movable.dm | 156 ++++++++---------- .../gamemodes/changeling/powers/mutations.dm | 6 +- code/game/machinery/doors/airlock_types.dm | 2 +- code/game/machinery/mass_driver.dm | 2 +- code/game/mecha/equipment/weapons/weapons.dm | 2 +- code/game/objects/explosion.dm | 2 +- code/game/objects/items.dm | 13 +- code/game/objects/items/weapons/dice.dm | 2 +- code/game/objects/items/weapons/handcuffs.dm | 2 +- .../objects/items/weapons/pneumaticCannon.dm | 2 +- code/game/objects/items/weapons/powerfist.dm | 4 +- .../items/weapons/singularityhammer.dm | 2 +- .../objects/items/weapons/storage/storage.dm | 2 +- code/game/objects/items/weapons/twohanded.dm | 2 +- code/game/objects/objs.dm | 2 +- code/modules/clothing/clothing.dm | 2 +- code/modules/clothing/shoes/miscellaneous.dm | 4 +- .../modules/clothing/spacesuits/flightsuit.dm | 6 +- .../kitchen_machinery/gibber.dm | 4 +- code/modules/lighting/lighting_system.dm | 11 -- .../carbon/alien/humanoid/caste/hunter.dm | 10 +- .../living/carbon/alien/special/facehugger.dm | 2 +- code/modules/mob/living/carbon/death.dm | 6 +- code/modules/mob/living/living.dm | 4 +- .../simple_animal/guardian/types/charger.dm | 4 +- .../hostile/megafauna/bubblegum.dm | 5 +- .../simple_animal/hostile/megafauna/dragon.dm | 2 +- .../hostile/megafauna/swarmer.dm | 2 +- code/modules/orbit/orbit.dm | 9 - code/modules/paperwork/paperplane.dm | 4 +- .../projectiles/guns/ballistic/shotgun.dm | 2 +- .../projectiles/guns/grenade_launcher.dm | 2 +- .../modules/projectiles/projectile/special.dm | 6 +- code/modules/reagents/chemistry/recipes.dm | 4 +- code/modules/recycling/disposal-structures.dm | 4 +- code/modules/recycling/disposal-unit.dm | 2 +- code/modules/research/experimentor.dm | 11 +- code/modules/shuttle/special.dm | 2 +- code/modules/spells/spell_types/wizard.dm | 4 +- .../surgery/bodyparts/dismemberment.dm | 2 +- code/modules/surgery/organs/vocal_cords.dm | 2 +- code/modules/vehicles/scooter.dm | 2 +- tgstation.dme | 3 + 48 files changed, 386 insertions(+), 175 deletions(-) create mode 100644 code/__DEFINES/callbacks.dm create mode 100644 code/controllers/subsystem/throwing.dm create mode 100644 code/datums/callback.dm diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index bd980a54b8a..2ea7258816b 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -45,6 +45,5 @@ #define SS_POST_FIRE_TIMING 128 //Timing subsystem -#define GLOBAL_PROC "some_magic_bullshit" #define TIMER_NORMAL "normal" -#define TIMER_UNIQUE "unique" +#define TIMER_UNIQUE "unique" \ No newline at end of file diff --git a/code/__DEFINES/callbacks.dm b/code/__DEFINES/callbacks.dm new file mode 100644 index 00000000000..762e7c38b0f --- /dev/null +++ b/code/__DEFINES/callbacks.dm @@ -0,0 +1,3 @@ +#define GLOBAL_PROC "some_magic_bullshit" + +#define CALLBACK new /datum/callback \ No newline at end of file diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm new file mode 100644 index 00000000000..56d887eb8bc --- /dev/null +++ b/code/controllers/subsystem/throwing.dm @@ -0,0 +1,139 @@ +#define MAX_THROWING_DIST 512 // 2 z-levels on default width +#define MAX_TICKS_TO_MAKE_UP 3 //how many missed ticks will we attempt to make up for this run. +var/datum/subsystem/throwing/SSthrowing + +/datum/subsystem/throwing + name = "Throwing" + priority = 25 + wait = 1 + flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER + + var/list/currentrun + var/list/processing + +/datum/subsystem/throwing/New() + NEW_SS_GLOBAL(SSthrowing) + processing = list() + + +/datum/subsystem/throwing/stat_entry() + ..("P:[processing.len]") + + +/datum/subsystem/throwing/fire(resumed = 0) + if (!resumed) + src.currentrun = processing.Copy() + + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + + while(length(currentrun)) + var/atom/movable/AM = currentrun[currentrun.len] + var/datum/thrownthing/TT = currentrun[AM] + currentrun.len-- + if (!AM || !TT) + processing -= AM + if (MC_TICK_CHECK) + return + continue + + TT.tick() + + if (MC_TICK_CHECK) + return + + currentrun = null + +/datum/thrownthing + var/atom/movable/thrownthing + var/atom/target + var/turf/target_turf + var/init_dir + var/maxrange + var/speed + var/mob/thrower + var/diagonals_first + var/dist_travelled = 0 + var/start_time + var/dist_x + var/dist_y + var/dx + var/dy + var/pure_diagonal + var/diagonal_error + var/datum/callback/callback + +/datum/thrownthing/proc/tick() + var/atom/movable/AM = thrownthing + if (!isturf(AM.loc) || !AM.throwing) + finialize() + return + + if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept + finialize() + return + + var/atom/step + + //calculate how many tiles to move, making up for any missed ticks. + var/tilestomove = round(min(((((world.time+world.tick_lag) - start_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait)) + while (tilestomove-- > 0) + if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc)) + finialize() + return + + if (dist_travelled <= max(dist_x, dist_y)) //if we haven't reached the target yet we home in on it, otherwise we use the initial direction + step = get_step(AM, get_dir(AM, target_turf)) + else + step = get_step(AM, init_dir) + + if (!pure_diagonal && !diagonals_first) // not a purely diagonal trajectory and we don't want all diagonal moves to be done first + if (diagonal_error >= 0 && max(dist_x,dist_y) - dist_travelled != 1) //we do a step forward unless we're right before the target + step = get_step(AM, dx) + diagonal_error += (diagonal_error < 0) ? dist_x/2 : -dist_y + + if (!step) // going off the edge of the map makes get_step return null, don't let things go off the edge + finialize() + return + + AM.Move(step, get_dir(AM, step)) + + if (!AM.throwing) // we hit something during our move + finialize(hit = TRUE) + return + + dist_travelled++ + + if (dist_travelled > MAX_THROWING_DIST) + finialize() + return + +/datum/thrownthing/proc/finialize(hit = FALSE) + set waitfor = 0 + SSthrowing.processing -= thrownthing + //done throwing, either because it hit something or it finished moving + thrownthing.throwing = 0 + 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) + hit = 1 + thrownthing.throw_impact(A) + break + if (!hit) + thrownthing.throw_impact(get_turf(thrownthing)) // we haven't hit something yet and we still must, let's hit the ground. + thrownthing.newtonian_move(init_dir) + else + thrownthing.newtonian_move(init_dir) + if (callback) + callback.Invoke() + +/datum/thrownthing/proc/hitcheck() + for (var/thing in get_turf(thrownthing)) + var/atom/movable/AM = thing + if (AM == thrownthing) + continue + if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags & ON_BORDER)) + thrownthing.throwing = 0 + thrownthing.throw_impact(AM) + return 1 diff --git a/code/datums/callback.dm b/code/datums/callback.dm new file mode 100644 index 00000000000..24d6be6106d --- /dev/null +++ b/code/datums/callback.dm @@ -0,0 +1,90 @@ +/* + USAGE: + + var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn) + var/timerid = addtimer(C, time, timertype) + OR + var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype) + + Note: proc strings can only be given for datum proc calls, global procs must be proc paths + Also proc strings are strongly advised against because they don't compile error if the proc stops existing + See the note on proc typepath shortcuts + + INVOKING THE CALLBACK: + var/result = C.Invoke(args, to, add) //additional args are added after the ones given when the callback was created + OR + var/result = C.InvokeAsync(args, to, add) //Sleeps will not block, returns . on the first sleep (then continues on in the "background" after the sleep/block ends), otherwise operates normally. + + PROC TYPEPATH SHORTCUTS (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...) + + global proc while in another global proc: + .procname + Example: + CALLBACK(GLOBAL_PROC, .some_proc_here) + + proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents: + .procname + Example: + CALLBACK(src, .some_proc_here) + + + when the above doesn't apply: + .proc/procname + Example: + CALLBACK(src, .proc/some_proc_here) + + proc defined on a parent of a some type: + /some/type/.proc/some_proc_here + + + + Other wise you will have to do the full typepath of the proc (/type/of/thing/proc/procname) + +*/ + +/datum/callback + var/datum/object = GLOBAL_PROC + var/delegate + var/list/arguments + +/datum/callback/New(thingtocall, proctocall, ...) + if (thingtocall) + object = thingtocall + delegate = proctocall + if (length(args) > 2) + arguments = args.Copy(3) + + +/datum/callback/proc/Invoke(...) + if (!object) + CRASH("Cannot call null.[delegate]") + + var/list/calling_arguments = arguments + + if (length(args)) + if (length(arguments)) + calling_arguments = calling_arguments + args //not += so that it creates a new list so the arguments list stays clean + else + calling_arguments = args + + if (object == GLOBAL_PROC) + return call(delegate)(arglist(calling_arguments)) + return call(object, delegate)(arglist(calling_arguments)) + +//copy and pasted because fuck proc overhead +/datum/callback/proc/InvokeAsync(...) + set waitfor = 0 + if (!object) + CRASH("Cannot call null.[delegate]") + + var/list/calling_arguments = arguments + + if (length(args)) + if (length(arguments)) + calling_arguments = calling_arguments + args //not += so that it creates a new list so the arguments list stays clean + else + calling_arguments = args + + if (object == GLOBAL_PROC) + return call(delegate)(arglist(calling_arguments)) + return call(object, delegate)(arglist(calling_arguments)) diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 02a044232e4..9b99a2c75d0 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -182,9 +182,7 @@ if (T && isturf(T)) if (!D.stat) D.emote("scream") - D.throw_at(T, 10, 4) - D.Weaken(2) - + D.throw_at(T, 10, 4, callback = CALLBACK(D, /mob/living/carbon/human/.Weaken, 2)) add_logs(A, D, "has thrown with wrestling") return 0 diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index d3b41c25845..c8959a49298 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -3,7 +3,7 @@ var/last_move = null var/anchored = 0 var/throwing = 0 - var/throw_speed = 2 + var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported var/throw_range = 7 var/mob/pulledby = null var/languages_spoken = 0 //For say() and Hear() @@ -81,11 +81,28 @@ //Called after a successful Move(). By this point, we've already moved /atom/movable/proc/Moved(atom/OldLoc, Dir) + //Objects with opacity will trigger nearby lights of the old location to update at next SSlighting fire + if(opacity) + if (isturf(OldLoc)) + OldLoc.UpdateAffectingLights() + if (isturf(loc)) + loc.UpdateAffectingLights() + else + if(light) + light.changed() + if (!inertia_moving) inertia_next_move = world.time + inertia_move_delay newtonian_move(Dir) if (length(client_mobs_in_contents)) update_parallax_contents() + + if (orbiters) + for (var/thing in orbiters) + var/datum/orbit/O = thing + O.Check() + if (orbiting) + orbiting.Check() return 1 /atom/movable/Destroy() @@ -200,109 +217,82 @@ step(src, AM.dir) ..() -/atom/movable/proc/throw_at_fast(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) - set waitfor = 0 - throw_at(target, range, speed, thrower, spin, diagonals_first) +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) + if (!target || (flags & NODROP) || speed <= 0) + return -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) - if(!target || !src || (flags & NODROP)) - return 0 - //use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target - - if(pulledby) + if (pulledby) pulledby.stop_pulling() - throwing = 1 - if(spin) //if we don't want the /atom/movable to spin. - SpinAnimation(5, 1) + //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? + if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) + var/user_momentum = thrower.movement_delay() + if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. + user_momentum = world.tick_lag - var/dist_travelled = 0 - var/next_sleep = 0 + user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses. + + if (get_dir(thrower, target) & last_move) + user_momentum = user_momentum //basically a noop, but needed + else if (get_dir(target, thrower) & last_move) + user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly + else + user_momentum = 0 + + + if (user_momentum) + //first lets add that momentum to range. + range *= (user_momentum / speed) + 1 + //then lets add it to speed + speed += user_momentum + if (speed <= 0) + return //no throw speed, the user was moving too fast. + + var/datum/thrownthing/TT = new() + TT.thrownthing = src + TT.target = target + TT.target_turf = get_turf(target) + TT.init_dir = get_dir(src, target) + TT.maxrange = range + TT.speed = speed + TT.thrower = thrower + TT.diagonals_first = diagonals_first + TT.callback = callback var/dist_x = abs(target.x - src.x) var/dist_y = abs(target.y - src.y) var/dx = (target.x > src.x) ? EAST : WEST var/dy = (target.y > src.y) ? NORTH : SOUTH - var/pure_diagonal = 0 - if(dist_x == dist_y) - pure_diagonal = 1 + if (dist_x == dist_y) + TT.pure_diagonal = 1 - if(dist_x <= dist_y) + else if(dist_x <= dist_y) var/olddist_x = dist_x var/olddx = dx dist_x = dist_y dist_y = olddist_x dx = dy dy = olddx + TT.dist_x = dist_x + TT.dist_y = dist_y + TT.dx = dx + TT.dy = dy + TT.diagonal_error = dist_x/2 - dist_y + TT.start_time = world.time - var/error = dist_x/2 - dist_y //used to decide whether our next move should be forward or diagonal. - var/atom/finalturf = get_turf(target) - var/hit = 0 - var/init_dir = get_dir(src, target) + if(pulledby) + pulledby.stop_pulling() - while(target && ((dist_travelled < range && loc != finalturf) || !has_gravity(src))) //stop if we reached our destination (or max range) and aren't floating - var/slept = 0 - if(!isturf(loc)) - hit = 1 - break + throwing = 1 + if(spin) + SpinAnimation(5, 1) - var/atom/step - if(dist_travelled < max(dist_x, dist_y)) //if we haven't reached the target yet we home in on it, otherwise we use the initial direction - step = get_step(src, get_dir(src, finalturf)) - else - step = get_step(src, init_dir) + SSthrowing.processing[src] = TT + if (SSthrowing.paused && length(SSthrowing.currentrun)) + SSthrowing.currentrun[src] = TT + TT.tick() - if(!pure_diagonal && !diagonals_first) // not a purely diagonal trajectory and we don't want all diagonal moves to be done first - if(error >= 0 && max(dist_x,dist_y) - dist_travelled != 1) //we do a step forward unless we're right before the target - step = get_step(src, dx) - error += (error < 0) ? dist_x/2 : -dist_y - if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge - break - Move(step, get_dir(loc, step)) - if(!throwing) // we hit something during our move - hit = 1 - break - dist_travelled++ - - if(dist_travelled > 600) //safety to prevent infinite while loop. - break - if(dist_travelled >= next_sleep) - slept = 1 - next_sleep += speed - sleep(1) - if(!slept) - var/ticks_slept = TICK_CHECK - if(ticks_slept) - slept = 1 - next_sleep += speed*(ticks_slept*world.tick_lag) //delay the next normal sleep - - if(slept && hitcheck()) //to catch sneaky things moving on our tile while we slept - hit = 1 - break - - - //done throwing, either because it hit something or it finished moving - throwing = 0 - if(!hit) - for(var/atom/A in get_turf(src)) //looking for our target on the turf we land on. - if(A == target) - hit = 1 - throw_impact(A) - return 1 - - throw_impact(get_turf(src)) // we haven't hit something yet and we still must, let's hit the ground. - newtonian_move(init_dir) - return 1 - -/atom/movable/proc/hitcheck() - for(var/atom/movable/AM in get_turf(src)) - if(AM == src) - continue - if(AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags & ON_BORDER)) - throwing = 0 - throw_impact(AM) - return 1 /atom/movable/proc/handle_buckled_mob_movement(newloc,direct) for(var/m in buckled_mobs) diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index f7aa0e75e74..f87b293e534 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -341,15 +341,13 @@ if(INTENT_GRAB) C.visible_message("[L] is grabbed by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") - C.throw_at(get_step_towards(H,C), 8, 2) - addtimer(src, "tentacle_grab", 3, TIMER_NORMAL, H, C) + C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(src, .proc/tentacle_grab, H, C)) return 1 if(INTENT_HARM) C.visible_message("[L] is thrown towards [H] by a tentacle!","A tentacle grabs you and throws you towards [H]!") C.Weaken(3) - C.throw_at(get_step_towards(H,C), 8, 2) - addtimer(src, "tentacle_stab", 3, TIMER_NORMAL, H, C) + C.throw_at(get_step_towards(H,C), 8, 2, callback=CALLBACK(src, .proc/tentacle_stab, H, C)) return 1 else L.visible_message("[L] is pulled by [H]'s tentacle!","A tentacle grabs you and pulls you towards [H]!") diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index aa97b109dc0..847de0fc50a 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -377,7 +377,7 @@ M << pick(sound('sound/hallucinations/turn_around1.ogg',0,1,50), sound('sound/hallucinations/turn_around2.ogg',0,1,50)) flash_color(M, flash_color="#960000", flash_time=20) M.Weaken(2) - M.throw_at_fast(throwtarget, 5, 1,src) + M.throw_at(throwtarget, 5, 1,src) return 0 /obj/machinery/door/airlock/cult/narsie_act() diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index bb77e578741..0b5faa30722 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -26,7 +26,7 @@ audible_message("[src] lets out a screech, it doesn't seem to be able to handle the load.") break use_power(500) - O.throw_at_fast(target, drive_range * power, power) + O.throw_at(target, drive_range * power, power) flick("mass_driver1", src) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 4a3e14cd5d6..49ab002574a 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -290,7 +290,7 @@ log_message("Launched a [O.name] from [name], targeting [target].") projectiles-- proj_init(O) - O.throw_at_fast(target, missile_range, missile_speed, spin = 0) + O.throw_at(target, missile_range, missile_speed, spin = 0) return 1 //used for projectile initilisation (priming flashbang) and additional logging diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index d3ba5840d35..a0b4f066016 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -147,7 +147,7 @@ var/throw_range = rand(throw_dist, max_range) var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range) I.throw_speed = 4 //Temporarily change their throw_speed for embedding purposes (Reset when it finishes throwing, regardless of hitting anything) - I.throw_at_fast(throw_at, throw_range, 2)//Throw it at 2 speed, this is purely visual anyway. + I.throw_at(throw_at, throw_range, I.throw_speed) CHECK_TICK diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a487104dd54..46150235bc4 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -519,7 +519,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s /obj/item/singularity_pull(S, current_size) if(current_size >= STAGE_FOUR) - throw_at_fast(S,14,3, spin=0) + throw_at(S,14,3, spin=0) else ..() /obj/item/throw_impact(atom/A) @@ -528,12 +528,17 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s itempush = 0 //too light to push anything return A.hitby(src, 0, itempush) -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) thrownby = thrower - . = ..() - throw_speed = initial(throw_speed) //explosions change this. + callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own + . = ..(target, range, speed, thrower, spin, diagonals_first, callback) +/obj/item/proc/after_throw(datum/callback/callback) + if (callback) //call the original callback + . = callback.Invoke() + throw_speed = initial(throw_speed) //explosions change this. + /obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/weapon/storage if(!newLoc) return 0 diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index a9fa9d1b45f..86bd732c55f 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -147,7 +147,7 @@ /obj/item/weapon/dice/attack_self(mob/user) diceroll(user) -/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) if(!..()) return diceroll(thrower) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index c1717acbd80..3f87aedd1b9 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -323,7 +323,7 @@ origin_tech = "engineering=3;combat=1" var/weaken = 0 -/obj/item/weapon/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/weapon/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) if(!..()) return playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1) diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index a8701e24cb8..badd8097791 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -110,7 +110,7 @@ loadedWeightClass -= ITD.w_class ITD.throw_speed = pressureSetting * 2 ITD.loc = get_turf(src) - ITD.throw_at_fast(target, pressureSetting * 5, pressureSetting * 2,user) + ITD.throw_at(target, pressureSetting * 5, pressureSetting * 2,user) if(pressureSetting >= 3 && user) user.visible_message("[user] is thrown down by the force of the cannon!", "[src] slams into your shoulder, knocking you down!") user.Weaken(3) diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm index 3353fdda15b..7f78ac53275 100644 --- a/code/game/objects/items/weapons/powerfist.dm +++ b/code/game/objects/items/weapons/powerfist.dm @@ -86,8 +86,8 @@ playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1) var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src))) - spawn(1) - target.throw_at(throw_target, 5 * fisto_setting, 0.2) + + target.throw_at(throw_target, 5 * fisto_setting, 0.2) add_logs(user, target, "power fisted", src) diff --git a/code/game/objects/items/weapons/singularityhammer.dm b/code/game/objects/items/weapons/singularityhammer.dm index 09d6727b58c..2449b8629d6 100644 --- a/code/game/objects/items/weapons/singularityhammer.dm +++ b/code/game/objects/items/weapons/singularityhammer.dm @@ -89,7 +89,7 @@ "You feel a powerful shock course through your body sending you flying!", \ "You hear a heavy electrical crack!") var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src))) - target.throw_at_fast(throw_target, 200, 4) + target.throw_at(throw_target, 200, 4) return /obj/item/weapon/twohanded/mjollnir/attack(mob/living/M, mob/user) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index ea3016f92d0..5da58e012bb 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -122,7 +122,7 @@ is_seeing |= user -/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/weapon/storage/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) close_all() return ..() diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 54b0ebf5d38..e67c9195b19 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -670,7 +670,7 @@ /obj/item/weapon/twohanded/skybulge/update_icon() icon_state = "sky_bulge[wielded]" -/obj/item/weapon/twohanded/skybulge/throw_at() //Throw cooldown and offhand-proofing. +/obj/item/weapon/twohanded/skybulge/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) //Throw cooldown and offhand-proofing. if(throw_cooldown > world.time) var/mob/user = thrownby user.put_in_hands(src) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 7ee61aa2700..24b6924edd3 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -45,7 +45,7 @@ SStgui.close_uis(src) return ..() -/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) ..() if(is_frozen) visible_message("[src] shatters into a million pieces!") diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 3e6a01c213c..0a2912f766f 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -51,7 +51,7 @@ M.put_in_hand(src, H.held_index) add_fingerprint(usr) -/obj/item/clothing/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/clothing/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) if(pockets) pockets.close_all() return ..() diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 326d50942cf..693fec80cb3 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -198,7 +198,9 @@ jumping = TRUE playsound(src.loc, 'sound/effects/stealthoff.ogg', 50, 1, 1) usr.visible_message("[usr] dashes foward into the air!") - usr.throw_at(target,jumpdistance,1, spin=0, diagonals_first = 1) + usr.throw_at(target, jumpdistance, 1, spin=0, diagonals_first = 1, callback = CALLBACK(src, .proc/hop_end)) + +/obj/item/clothing/shoes/bhop/proc/hop_end() jumping = FALSE recharging_time = world.time + recharging_rate diff --git a/code/modules/clothing/spacesuits/flightsuit.dm b/code/modules/clothing/spacesuits/flightsuit.dm index a37bb7c3110..4714eae4e76 100644 --- a/code/modules/clothing/spacesuits/flightsuit.dm +++ b/code/modules/clothing/spacesuits/flightsuit.dm @@ -438,7 +438,7 @@ angle -= 360 dir = angle2dir(angle) var/turf/target = get_edge_target_turf(get_turf(wearer), dir) - wearer.throw_at_fast(target, (speed+density+anchored), 2, wearer) + wearer.throw_at(target, (speed+density+anchored), 2, wearer) wearer.visible_message("[wearer] is knocked flying by the impact!") /obj/item/device/flightpack/proc/flight_impact(atom/unmovablevictim, crashdir) //Yes, victim. @@ -579,7 +579,7 @@ for(var/i in 1 to (knockback-1)) target = get_step(target, throwdir) wearer.visible_message(knockmessage) - victim.throw_at_fast(target, knockback, 1) + victim.throw_at(target, knockback, 1) victim.Weaken(stun) /obj/item/device/flightpack/proc/victimknockback(atom/movable/victim, power, direction) @@ -607,7 +607,7 @@ for(var/i in 1 to knockback/3) target = get_step(target, pick(alldirs)) if(knockback) - victim.throw_at_fast(target, knockback, part_manip.rating) + victim.throw_at(target, knockback, part_manip.rating) if(isobj(victim)) var/obj/O = victim O.take_damage(damage) diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index fa975e12ce9..df2183f3dd4 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -223,11 +223,11 @@ var/list/turf/nearby_turfs = RANGE_TURFS(3,T) - T var/obj/item/skin = allskin skin.loc = src.loc - skin.throw_at_fast(pick(nearby_turfs),meat_produced,3) + skin.throw_at(pick(nearby_turfs),meat_produced,3) for (var/i=1 to meat_produced) var/obj/item/meatslab = allmeat[i] meatslab.loc = src.loc - meatslab.throw_at_fast(pick(nearby_turfs),i,3) + meatslab.throw_at(pick(nearby_turfs),i,3) for (var/turfs=1 to meat_produced) var/turf/gibturf = pick(nearby_turfs) if (!gibturf.density && src in view(gibturf)) diff --git a/code/modules/lighting/lighting_system.dm b/code/modules/lighting/lighting_system.dm index bbb2f282840..03f4a78319e 100644 --- a/code/modules/lighting/lighting_system.dm +++ b/code/modules/lighting/lighting_system.dm @@ -156,17 +156,6 @@ loc.UpdateAffectingLights() return ..() -//Objects with opacity will trigger nearby lights of the old location to update at next SSlighting fire -/atom/movable/Moved(atom/OldLoc, Dir) - if(opacity) - if (isturf(OldLoc)) - OldLoc.UpdateAffectingLights() - if (isturf(loc)) - loc.UpdateAffectingLights() - else - if(light) - light.changed() - return ..() //Sets our luminosity. //If we have no light it will create one. diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 5ffffbd562a..8a52daeb80b 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -54,10 +54,12 @@ leaping = 1 weather_immunities += "lava" update_icons() - throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0, diagonals_first = 1) - leaping = 0 - weather_immunities -= "lava" - update_icons() + throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin=0, diagonals_first = 1, callback = CALLBACK(src, .leap_end)) + +/mob/living/carbon/alien/humanoid/hunter/proc/leap_end() + leaping = 0 + weather_immunities -= "lava" + update_icons() /mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 2ae266e2a73..9098171b8bf 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -101,7 +101,7 @@ var/const/MAX_ACTIVE_TIME = 400 return Attach(AM) return 0 -/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) if(!..()) return if(stat == CONSCIOUS) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 1247c39bd6e..d687dcfd0c7 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -35,7 +35,7 @@ if(org_zone == "chest") O.Remove(src) O.forceMove(get_turf(src)) - O.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) + O.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) else for(var/X in internal_organs) var/obj/item/organ/I = X @@ -44,11 +44,11 @@ continue I.Remove(src) I.forceMove(get_turf(src)) - I.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) + I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) /mob/living/carbon/spread_bodyparts() for(var/X in bodyparts) var/obj/item/bodypart/BP = X BP.drop_limb() - BP.throw_at_fast(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) \ No newline at end of file + BP.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) \ No newline at end of file diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 75a8ed51bd6..af6bed51839 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -664,7 +664,7 @@ /mob/living/singularity_pull(S, current_size) if(current_size >= STAGE_SIX) - throw_at_fast(S,14,3, spin=1) + throw_at(S,14,3, spin=1) else step_towards(src,S) @@ -824,7 +824,7 @@ return 1 return 0 -/mob/living/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/mob/living/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) stop_pulling() . = ..() diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index d9966b41a87..31636ed3c80 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -33,7 +33,9 @@ /mob/living/simple_animal/hostile/guardian/charger/Shoot(atom/targeted_atom) charging = 1 - throw_at(targeted_atom, range, 1, src, 0) + throw_at(targeted_atom, range, 1, src, 0, callback = CALLBACK(src, .proc/charging_end)) + +/mob/living/simple_animal/hostile/guardian/charger/proc/charging_end() charging = 0 /mob/living/simple_animal/hostile/guardian/charger/Move() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 8942dbe394d..ac04e000e6a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -158,7 +158,8 @@ Difficulty: Hard var/obj/effect/overlay/temp/decoy/D = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src)) animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5) sleep(5) - throw_at(T, get_dist(src, T), 1, src, 0) + throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .charge_end)) +/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge_end() charging = 0 try_bloodattack() if(target) @@ -184,7 +185,7 @@ Difficulty: Hard shake_camera(L, 4, 3) shake_camera(src, 2, 3) var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src))) - L.throw_at_fast(throwtarget, 3) + L.throw_at(throwtarget, 3) charging = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm index 59a6cb52106..97a1e388f06 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm @@ -233,7 +233,7 @@ Difficulty: Medium if(L.loc == loc) throw_dir = pick(alldirs) var/throwtarget = get_edge_target_turf(src, throw_dir) - L.throw_at_fast(throwtarget, 3) + L.throw_at(throwtarget, 3) visible_message("[L] is thrown clear of [src]!") for(var/mob/M in range(7, src)) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index 8d620287e61..8909052eeb7 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -147,7 +147,7 @@ var/global/list/AISwarmerCapsByType = list(/mob/living/simple_animal/hostile/swa return FALSE if(istype(newloc, /turf/open/chasm) && !throwing) - throw_at_fast(get_edge_target_turf(src, get_dir(src, newloc)), 7 , 3, spin = FALSE) //my planet needs me + throw_at(get_edge_target_turf(src, get_dir(src, newloc)), 7 , 3, spin = FALSE) //my planet needs me return FALSE return ..() diff --git a/code/modules/orbit/orbit.dm b/code/modules/orbit/orbit.dm index d4e0436aae7..81b80e48b4c 100644 --- a/code/modules/orbit/orbit.dm +++ b/code/modules/orbit/orbit.dm @@ -98,15 +98,6 @@ SpinAnimation(0,0) qdel(orbiting) -/atom/movable/Moved(atom/OldLoc, Dir) - ..() - if (orbiters) - for (var/thing in orbiters) - var/datum/orbit/O = thing - O.Check() - if (orbiting) - orbiting.Check() - /atom/Destroy(force = FALSE) ..() if (orbiters) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 519789649f0..b29e0400933 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -87,8 +87,8 @@ add_fingerprint(user) -/obj/item/weapon/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE) - . = ..(target, range, speed, thrower, FALSE, diagonals_first) +/obj/item/weapon/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback) + . = ..(target, range, speed, thrower, FALSE, diagonals_first, callback) /obj/item/weapon/paperplane/throw_impact(atom/hit_atom) if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index ad4c1a7e51b..f80f2676cc6 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -159,7 +159,7 @@ guns_left = 0 /obj/item/weapon/gun/ballistic/shotgun/boltaction/enchanted/proc/discard_gun(mob/user) - throw_at_fast(pick(oview(7,get_turf(user))),1,1) + throw_at(pick(oview(7,get_turf(user))),1,1) user.visible_message("[user] tosses aside the spent rifle!") /obj/item/weapon/gun/ballistic/shotgun/boltaction/enchanted/arcane_barrage/discard_gun(mob/user) diff --git a/code/modules/projectiles/guns/grenade_launcher.dm b/code/modules/projectiles/guns/grenade_launcher.dm index 2e0a3daa805..6efa9a24336 100644 --- a/code/modules/projectiles/guns/grenade_launcher.dm +++ b/code/modules/projectiles/guns/grenade_launcher.dm @@ -44,7 +44,7 @@ var/obj/item/weapon/grenade/F = grenades[1] //Now with less copypasta! grenades -= F F.loc = user.loc - F.throw_at_fast(target, 30, 2,user) + F.throw_at(target, 30, 2, user) message_admins("[key_name_admin(user)] fired a grenade ([F.name]) from a grenade launcher ([src.name]).") log_game("[key_name(user)] fired a grenade ([F.name]) from a grenade launcher ([src.name]).") F.active = 1 diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 284056b2d74..d2738021640 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -245,7 +245,7 @@ if(A == src || (firer && A == src.firer) || A.anchored) continue var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(A, src))) - A.throw_at_fast(throwtarget,power+1,1) + A.throw_at(throwtarget,power+1,1) for(var/turf/F in range(T,power)) var/obj/effect/overlay/gravfield = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density=0}() F.overlays += gravfield @@ -275,7 +275,7 @@ for(var/atom/movable/A in range(T, power)) if(A == src || (firer && A == src.firer) || A.anchored) continue - A.throw_at_fast(T, power+1, 1) + A.throw_at(T, power+1, 1) for(var/turf/F in range(T,power)) var/obj/effect/overlay/gravfield = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density=0}() F.overlays += gravfield @@ -305,7 +305,7 @@ for(var/atom/movable/A in range(T, power)) if(A == src|| (firer && A == src.firer) || A.anchored) continue - A.throw_at_fast(get_edge_target_turf(A, pick(cardinal)), power+1, 1) + A.throw_at(get_edge_target_turf(A, pick(cardinal)), power+1, 1) for(var/turf/Z in range(T,power)) var/obj/effect/overlay/gravfield = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density=0}() Z.overlays += gravfield diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index ebc98cbf5ef..3de44af126c 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -74,9 +74,9 @@ var/list/chemical_mob_spawn_nicecritters = list() // and possible friendly mobs if(moving_power > 2) //if the vortex is powerful and we're close, we get thrown if(setting_type) var/atom/throw_target = get_edge_target_turf(X, get_dir(X, get_step_away(X, T))) - X.throw_at_fast(throw_target, moving_power, 1) + X.throw_at(throw_target, moving_power, 1) else - X.throw_at_fast(T, moving_power, 1) + X.throw_at(T, moving_power, 1) else spawn(0) //so everything moves at the same time. if(setting_type) diff --git a/code/modules/recycling/disposal-structures.dm b/code/modules/recycling/disposal-structures.dm index 23a14b77df9..681b9b58610 100644 --- a/code/modules/recycling/disposal-structures.dm +++ b/code/modules/recycling/disposal-structures.dm @@ -273,7 +273,7 @@ AM.forceMove(src.loc) AM.pipe_eject(direction) if(target) - AM.throw_at_fast(target, eject_range, 1) + AM.throw_at(target, eject_range, 1) H.vent_gas(T) qdel(H) @@ -683,7 +683,7 @@ for(var/atom/movable/AM in H) AM.forceMove(T) AM.pipe_eject(dir) - AM.throw_at_fast(target, eject_range, 1) + AM.throw_at(target, eject_range, 1) H.vent_gas(T) qdel(H) diff --git a/code/modules/recycling/disposal-unit.dm b/code/modules/recycling/disposal-unit.dm index 40b66555f89..2feb130acb1 100644 --- a/code/modules/recycling/disposal-unit.dm +++ b/code/modules/recycling/disposal-unit.dm @@ -227,7 +227,7 @@ AM.forceMove(T) AM.pipe_eject(0) - AM.throw_at_fast(target, 5, 1) + AM.throw_at(target, 5, 1) H.vent_gas(loc) qdel(H) diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index c7ee3e805e7..b34bc1ef381 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -436,7 +436,7 @@ investigate_log("Experimentor has triggered the 'throw things' reaction.", "experimentor") for(var/atom/movable/AM in oview(7,src)) if(!AM.anchored) - AM.throw_at_fast(src,10,1) + AM.throw_at(src,10,1) else if(prob(EFFECT_PROB_LOW-badThingCoeff)) visible_message("[src]'s crusher goes one level too high, crushing right into space-time!") playsound(src.loc, 'sound/effects/supermatter.ogg', 50, 1, -3) @@ -447,7 +447,7 @@ throwAt.Add(AM) for(var/counter = 1, counter < throwAt.len, ++counter) var/atom/movable/cast = throwAt[counter] - cast.throw_at_fast(pick(throwAt),10,1) + cast.throw_at(pick(throwAt),10,1) ejectItem(TRUE) //////////////////////////////////////////////////////////////////////////////////////////////// if(exp == FAIL) @@ -621,14 +621,13 @@ /obj/item/weapon/relic/proc/throwSmoke(turf/where) var/datum/effect_system/smoke_spread/smoke = new - smoke.set_up(0, where) + smoke.set_up(0, get_turf(where)) smoke.start() /obj/item/weapon/relic/proc/corgicannon(mob/user) playsound(src.loc, "sparks", rand(25,50), 1) var/mob/living/simple_animal/pet/dog/corgi/C = new/mob/living/simple_animal/pet/dog/corgi(get_turf(user)) - C.throw_at(pick(oview(10,user)),10,rand(3,8)) - throwSmoke(get_turf(C)) + C.throw_at(pick(oview(10,user)), 10, rand(3,8), callback = CALLBACK(src, .throwSmoke, C)) warn_admins(user, "Corgi Cannon", 0) /obj/item/weapon/relic/proc/clean(mob/user) @@ -671,7 +670,7 @@ R.realProc = realProc R.revealed = TRUE dupes |= R - R.throw_at_fast(pick(oview(7,get_turf(src))),10,1) + R.throw_at(pick(oview(7,get_turf(src))),10,1) counter = 0 spawn(rand(10,100)) for(counter = 1; counter <= dupes.len; counter++) diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 73d850172f6..62dfad2bb7e 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -197,7 +197,7 @@ var/mob/living/M = AM var/throwtarget = get_edge_target_turf(src, boot_dir) M.Weaken(2) - M.throw_at_fast(throwtarget, 5, 1,src) + M.throw_at(throwtarget, 5, 1,src) M << "No climbing on the bar please." else . = ..() diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 7e2f892ad40..c1707ef8f8c 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -342,7 +342,7 @@ var/mob/living/M = AM M.Weaken(stun_amt) M << "You're thrown back by [user]!" - AM.throw_at_fast(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time. + AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time. /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?! name = "Tail Sweep" @@ -411,7 +411,7 @@ M.electrocute_act(80, src, illusion = 1) qdel(src) -/obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0) +/obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) . = ..() if(ishuman(thrower)) var/mob/living/carbon/human/H = thrower diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 58887e9ac39..4ec5dd2890f 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -38,7 +38,7 @@ target_turf = new_turf if(new_turf.density) break - throw_at_fast(target_turf, throw_range, throw_speed) + throw_at(target_turf, throw_range, throw_speed) return 1 diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index a2e6345456e..08017565e59 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -245,7 +245,7 @@ var/static/regex/multispin_words = regex("like a record baby") for(var/V in listeners) var/mob/living/L = V var/throwtarget = get_edge_target_turf(owner, get_dir(owner, get_step_away(L, owner))) - L.throw_at_fast(throwtarget, 3 * power_multiplier, 1) + L.throw_at(throwtarget, 3 * power_multiplier, 1) next_command = world.time + cooldown_damage //WHO ARE YOU? diff --git a/code/modules/vehicles/scooter.dm b/code/modules/vehicles/scooter.dm index a70a6a495ec..20f6faee418 100644 --- a/code/modules/vehicles/scooter.dm +++ b/code/modules/vehicles/scooter.dm @@ -71,7 +71,7 @@ var/mob/living/carbon/H = buckled_mobs[1] var/atom/throw_target = get_edge_target_turf(H, pick(cardinal)) unbuckle_mob(H) - H.throw_at_fast(throw_target, 4, 3) + H.throw_at(throw_target, 4, 3) H.Weaken(5) H.adjustStaminaLoss(40) visible_message("[src] crashes into [A], sending [H] flying!") diff --git a/tgstation.dme b/tgstation.dme index add4c5d362b..62033852d60 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -24,6 +24,7 @@ #include "code\__DEFINES\admin.dm" #include "code\__DEFINES\atmospherics.dm" #include "code\__DEFINES\atom_hud.dm" +#include "code\__DEFINES\callbacks.dm" #include "code\__DEFINES\clockcult.dm" #include "code\__DEFINES\combat.dm" #include "code\__DEFINES\construction.dm" @@ -174,6 +175,7 @@ #include "code\controllers\subsystem\stickyban.dm" #include "code\controllers\subsystem\sun.dm" #include "code\controllers\subsystem\tgui.dm" +#include "code\controllers\subsystem\throwing.dm" #include "code\controllers\subsystem\ticker.dm" #include "code\controllers\subsystem\timer.dm" #include "code\controllers\subsystem\voting.dm" @@ -186,6 +188,7 @@ #include "code\datums\ai_laws.dm" #include "code\datums\beam.dm" #include "code\datums\browser.dm" +#include "code\datums\callback.dm" #include "code\datums\datacore.dm" #include "code\datums\datumvars.dm" #include "code\datums\dna.dm"