diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 0abb637cce..3f74cbd0ea 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -141,7 +141,7 @@ var/const/tk_maxrange = 15
else
apply_focus_overlay()
- focus.throw_at(target, 10, 1)
+ focus.throw_at(target, 10, 1, user)
last_throw = world.time
return
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index 25a5242c07..c7e3df319d 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -303,9 +303,10 @@ var/global/list/PDA_Manifest = list()
throw_speed = 1
throw_range = 20
flags = FPRINT | TABLEPASS | CONDUCT
+
afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
user.drop_item()
- src.throw_at(target, throw_range, throw_speed)
+ src.throw_at(target, throw_range, throw_speed, user)
/obj/effect/stop
var/victim = null
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 6870d3ab6f..de6b84d655 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -7,6 +7,8 @@
var/l_move_time = 1
var/m_flag = 1
var/throwing = 0
+ var/thrower
+ var/turf/throw_source = null
var/throw_speed = 2
var/throw_range = 7
var/moved_recently = 0
@@ -77,11 +79,13 @@
if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement
src.throw_impact(A,speed)
-/atom/movable/proc/throw_at(atom/target, range, speed)
+/atom/movable/proc/throw_at(atom/target, range, speed, thrower)
if(!target || !src) return 0
//use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
src.throwing = 1
+ src.thrower = thrower
+ src.throw_source = get_turf(src) //store the origin turf
if(usr)
if(HULK in usr.mutations)
@@ -170,6 +174,8 @@
//done throwing, either because it hit something or it finished moving
if(isobj(src)) src.throw_impact(get_turf(src),speed)
src.throwing = 0
+ src.thrower = null
+ src.throw_source = null
//Overlays
diff --git a/code/game/machinery/bots/farmbot.dm b/code/game/machinery/bots/farmbot.dm
index 228b525049..1c0bd0875f 100644
--- a/code/game/machinery/bots/farmbot.dm
+++ b/code/game/machinery/bots/farmbot.dm
@@ -394,7 +394,7 @@
if ( emagged ) // Warning, hungry humans detected: throw fertilizer at them
spawn(0)
fert.loc = src.loc
- fert.throw_at(target, 16, 3)
+ fert.throw_at(target, 16, 3, src)
src.visible_message("\red [src] launches [fert.name] at [target.name]!")
flick("farmbot_broke", src)
spawn (FARMBOT_EMAG_DELAY)
diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm
index 4b2fce70cd..b74d3a587a 100644
--- a/code/game/machinery/kitchen/gibber.dm
+++ b/code/game/machinery/kitchen/gibber.dm
@@ -217,7 +217,7 @@
var/obj/item/meatslab = allmeat[i]
var/turf/Tx = locate(src.x - i, src.y, src.z)
meatslab.loc = src.loc
- meatslab.throw_at(Tx,i,3)
+ meatslab.throw_at(Tx,i,3,src)
if (!Tx.density)
new /obj/effect/decal/cleanable/blood/gibs(Tx,i)
src.operating = 0
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index 6242626bc7..8eca8dce3a 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -403,7 +403,7 @@
if(!throw_item)
return 0
spawn(0)
- throw_item.throw_at(target,16,3)
+ throw_item.throw_at(target,16,3,src)
src.visible_message("\red [src] launches [throw_item.name] at [target.name]!")
return 1
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index 5dd31a036e..e69a2b36de 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -552,7 +552,7 @@
if (!throw_item)
return 0
spawn(0)
- throw_item.throw_at(target, 16, 3)
+ throw_item.throw_at(target, 16, 3, src)
src.visible_message("\red [src] launches [throw_item.name] at [target.name]!")
return 1
diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm
index 08cc9a65d0..629e3b9d7d 100644
--- a/code/game/mecha/equipment/tools/tools.dm
+++ b/code/game/mecha/equipment/tools/tools.dm
@@ -464,7 +464,7 @@
return
else if(target!=locked)
if(locked in view(chassis))
- locked.throw_at(target, 14, 1.5)
+ locked.throw_at(target, 14, 1.5, chassis)
locked = null
send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info())
set_ready_state(0)
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index e8a9dc072f..fb1174814d 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -231,7 +231,7 @@
var/missile_range = 30
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc)
- AM.throw_at(target,missile_range, missile_speed)
+ AM.throw_at(target,missile_range, missile_speed, chassis)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive
name = "SRM-8 Missile Rack"
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index 219843e68b..652e51e95c 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -82,16 +82,19 @@
C = usr.buckled
var/obj/B = usr.buckled
var/movementdirection = turn(direction,180)
- if(C) C.propelled = 1
- B.Move(get_step(usr,movementdirection), movementdirection)
- sleep(1)
+ if(C) C.propelled = 4
B.Move(get_step(usr,movementdirection), movementdirection)
sleep(1)
B.Move(get_step(usr,movementdirection), movementdirection)
+ if(C) C.propelled = 3
+ sleep(1)
+ B.Move(get_step(usr,movementdirection), movementdirection)
sleep(1)
B.Move(get_step(usr,movementdirection), movementdirection)
+ if(C) C.propelled = 2
sleep(2)
B.Move(get_step(usr,movementdirection), movementdirection)
+ if(C) C.propelled = 1
sleep(2)
B.Move(get_step(usr,movementdirection), movementdirection)
if(C) C.propelled = 0
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 9982017c6b..115806277c 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -138,7 +138,7 @@
if(propelled)
var/mob/living/occupant = buckled_mob
unbuckle()
- occupant.throw_at(A, 3, 2)
+ occupant.throw_at(A, 3, propelled)
occupant.apply_effect(6, STUN, 0)
occupant.apply_effect(6, WEAKEN, 0)
occupant.apply_effect(6, STUTTER, 0)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index adec836a78..705351acfc 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -136,7 +136,12 @@
if(propelled || (pulling && (pulling.a_intent == "hurt")))
var/mob/living/occupant = buckled_mob
unbuckle()
- occupant.throw_at(A, 3, 2)
+
+ if (pulling && (pulling.a_intent == "hurt"))
+ occupant.throw_at(A, 3, 3, pulling)
+ else if (propelled)
+ occupant.throw_at(A, 3, propelled)
+
occupant.apply_effect(6, STUN, 0)
occupant.apply_effect(6, WEAKEN, 0)
occupant.apply_effect(6, STUTTER, 0)
diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm
index d7ee461161..60adf1e704 100644
--- a/code/modules/games/cards.dm
+++ b/code/modules/games/cards.dm
@@ -116,7 +116,7 @@
H.concealed = 1
H.update_icon()
usr.visible_message("\The [usr] deals a card to \the [M].")
- H.throw_at(get_step(M,M.dir),10,1)
+ H.throw_at(get_step(M,M.dir),10,1,H)
/obj/item/weapon/hand/attackby(obj/O as obj, mob/user as mob)
if(istype(O,/obj/item/weapon/hand))
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index a3c9babd97..c7bf755356 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -330,7 +330,7 @@
*/
- item.throw_at(target, item.throw_range, item.throw_speed)
+ item.throw_at(target, item.throw_range, item.throw_speed, src)
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 45a6647aff..8580099124 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1383,7 +1383,7 @@
status_flags |= LEAPING
src.visible_message("\The [src] leaps at [T]!")
- src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1)
+ src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src)
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
sleep(5)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 5f5018e382..aca29b3e0e 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -69,21 +69,31 @@
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve
if(istype(AM,/obj/))
var/obj/O = AM
- var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
if(istype(O,/obj/item/weapon))
var/obj/item/weapon/W = O
dtype = W.damtype
var/throw_damage = O.throwforce*(speed/5)
+ var/zone
+ if (istype(O.thrower, /mob/living))
+ var/mob/living/L = O.thrower
+ zone = check_zone(L.zone_sel.selecting)
+ else
+ zone = ran_zone("chest",75) //Hits a random part of the body, geared towards the chest
+
//def_zone = get_zone_with_miss_chance(zone, src, 15*AM.throwing_dist_travelled)
- zone = get_zone_with_miss_chance(zone, src) //TODO: store the location of the thrower and adjust miss chance with distance
+ if (O.throw_source)
+ var/distance = get_dist(O.throw_source, loc)
+ zone = get_zone_with_miss_chance(zone, src, min(15*(distance-2), 0))
+ else
+ zone = get_zone_with_miss_chance(zone, src, 15)
if(!zone)
- visible_message("\blue \The [AM] misses [src] narrowly!")
+ visible_message("\blue \The [O] misses [src] narrowly!")
return
- AM.throwing = 0 //it hit, so stop moving
+ O.throwing = 0 //it hit, so stop moving
if (istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
@@ -136,7 +146,7 @@
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
- src.take_organ_damage(speed*4)
+ src.take_organ_damage(speed*5)
/mob/living/proc/near_wall(var/direction,var/distance=1)
var/turf/T = get_step(get_turf(src),direction)
diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm
index f192873090..9ac058bc88 100644
--- a/code/modules/projectiles/guns/alien.dm
+++ b/code/modules/projectiles/guns/alien.dm
@@ -110,7 +110,7 @@
user.visible_message("\red [user] fires [src]!", "\red You fire [src]!")
spike.loc = get_turf(src)
- spike.throw_at(target,10,fire_force)
+ spike.throw_at(target,10,fire_force,user)
spike = null
update_icon()
diff --git a/code/modules/projectiles/guns/projectile/bow.dm b/code/modules/projectiles/guns/projectile/bow.dm
index 912b5f2f1e..7788d35627 100644
--- a/code/modules/projectiles/guns/projectile/bow.dm
+++ b/code/modules/projectiles/guns/projectile/bow.dm
@@ -191,7 +191,7 @@
var/obj/item/weapon/arrow/A = arrow
A.loc = get_turf(user)
- A.throw_at(target,10,tension*release_speed)
+ A.throw_at(target,10,tension*release_speed,user)
arrow = null
tension = 0
icon_state = "crossbow"
diff --git a/code/modules/projectiles/guns/projectile/pneumatic.dm b/code/modules/projectiles/guns/projectile/pneumatic.dm
index 43c1fed24a..7f1de5e43c 100644
--- a/code/modules/projectiles/guns/projectile/pneumatic.dm
+++ b/code/modules/projectiles/guns/projectile/pneumatic.dm
@@ -131,7 +131,7 @@
user.visible_message("[user] fires [src] and launches [object] at [target]!","You fire [src] and launch [object] at [target]!")
src.remove_from_storage(object,user.loc)
- object.throw_at(target,10,speed)
+ object.throw_at(target,10,speed,user)
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
diff --git a/code/modules/projectiles/guns/projectile/rocket.dm b/code/modules/projectiles/guns/projectile/rocket.dm
index a1575b937c..0cf732c9c2 100644
--- a/code/modules/projectiles/guns/projectile/rocket.dm
+++ b/code/modules/projectiles/guns/projectile/rocket.dm
@@ -43,7 +43,7 @@
var/obj/item/missile/M = new projectile(user.loc)
playsound(user.loc, 'sound/effects/bang.ogg', 50, 1)
M.primed = 1
- M.throw_at(target, missile_range, missile_speed)
+ M.throw_at(target, missile_range, missile_speed,user)
message_admins("[key_name_admin(user)] fired a rocket from a rocket launcher ([src.name]).")
log_game("[key_name_admin(user)] used a rocket launcher ([src.name]).")
rockets -= I
diff --git a/code/modules/reagents/grenade_launcher.dm b/code/modules/reagents/grenade_launcher.dm
index 5545883c2f..b69f428410 100644
--- a/code/modules/reagents/grenade_launcher.dm
+++ b/code/modules/reagents/grenade_launcher.dm
@@ -56,7 +56,7 @@
var/obj/item/weapon/grenade/chem_grenade/F = grenades[1] //Now with less copypasta!
grenades -= F
F.loc = user.loc
- F.throw_at(target, 30, 2)
+ 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_admin(user)] used a grenade ([src.name]).")
F.active = 1