diff --git a/code/game/atoms.dm b/code/game/atoms.dm index d4c15b23e1..05a52137cc 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -22,27 +22,6 @@ //Detective Work, used for the duplicate data points kept in the scanners var/list/original_atom -/atom/proc/throw_impact(atom/hit_atom, var/speed) - if(istype(hit_atom,/mob/living)) - var/mob/living/M = hit_atom - M.hitby(src,speed) - - else if(isobj(hit_atom)) - var/obj/O = hit_atom - if(!O.anchored) - step(O, src.dir) - O.hitby(src,speed) - - else if(isturf(hit_atom)) - var/turf/T = hit_atom - if(T.density) - spawn(2) - step(src, turn(src.dir, 180)) - if(istype(src,/mob/living)) - var/mob/living/M = src - M.turf_collision(T, speed) - - /atom/proc/assume_air(datum/gas_mixture/giver) return null @@ -237,6 +216,8 @@ its easier to just keep the beam vertical. return /atom/proc/hitby(atom/movable/AM as mob|obj) + if (density) + AM.throwing = 0 return /atom/proc/add_hiddenprint(mob/living/M as mob) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 41da5ea7c8..6870d3ab6f 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -25,7 +25,6 @@ /atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes) if(src.throwing) src.throw_impact(A) - src.throwing = 0 spawn( 0 ) if ((A && yes)) @@ -44,6 +43,29 @@ return 1 return 0 +//called when src is thrown into hit_atom +/atom/movable/proc/throw_impact(atom/hit_atom, var/speed) + if(istype(hit_atom,/mob/living)) + var/mob/living/M = hit_atom + M.hitby(src,speed) + + else if(isobj(hit_atom)) + var/obj/O = hit_atom + if(!O.anchored) + step(O, src.dir) + O.hitby(src,speed) + + else if(isturf(hit_atom)) + src.throwing = 0 + var/turf/T = hit_atom + if(T.density) + spawn(2) + step(src, turn(src.dir, 180)) + if(istype(src,/mob/living)) + var/mob/living/M = src + M.turf_collision(T, 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)) @@ -51,12 +73,9 @@ if(istype(A,/mob/living)) if(A:lying) continue src.throw_impact(A,speed) - if(src.throwing == 1) - src.throwing = 0 if(isobj(A)) if(A.density && !A.throwpass) // **TODO: Better behaviour for windows which are dense, but shouldn't always stop movement src.throw_impact(A,speed) - src.throwing = 0 /atom/movable/proc/throw_at(atom/target, range, speed) if(!target || !src) return 0 @@ -149,8 +168,8 @@ a = get_area(src.loc) //done throwing, either because it hit something or it finished moving - src.throwing = 0 if(isobj(src)) src.throw_impact(get_turf(src),speed) + src.throwing = 0 //Overlays diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index e3465c3b7c..0cb89ee683 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -469,6 +469,7 @@ return /obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper + ..() src.log_message("Hit by [A].",1) call((proc_res["dynhitby"]||src), "dynhitby")(A) return diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 4edcbd3dc7..48c16a9983 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -107,6 +107,7 @@ var/const/MAX_ACTIVE_TIME = 400 if(stat == CONSCIOUS) icon_state = "[initial(icon_state)]" Attach(hit_atom) + throwing = 0 /obj/item/clothing/mask/facehugger/proc/Attach(M as mob) if( (!iscorgi(M) && !iscarbon(M)) || isalien(M)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index c3bbfe0728..5f5018e382 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -65,6 +65,7 @@ P.on_hit(src, absorb, def_zone) return absorb +//this proc handles being hit by a thrown atom /mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve if(istype(AM,/obj/)) var/obj/O = AM @@ -73,14 +74,27 @@ if(istype(O,/obj/item/weapon)) var/obj/item/weapon/W = O dtype = W.damtype + var/throw_damage = O.throwforce*(speed/5) - //run to-hit check here + //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(!zone) + visible_message("\blue \The [AM] misses [src] narrowly!") + return + + AM.throwing = 0 //it hit, so stop moving + + if (istype(src, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + if (H.check_shields(throw_damage, "[O]")) + return src.visible_message("\red [src] has been hit by [O].") - var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone].", "Your armor has softened hit to your [zone].") + var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone].", "Your armor has softened the hit to your [zone].") if(armor < 2) - apply_damage(O.throwforce*(speed/5), dtype, zone, armor, is_sharp(O), has_edge(O), O) + apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O) if(!O.fingerprintslast) return @@ -99,7 +113,7 @@ if(speed >= 15) var/obj/item/weapon/W = O var/momentum = speed/2 - var/dir = get_dir(M,src) + var/dir = get_dir(M,src) //TODO: store the location of the thrower and move this out of the fingerprintslast block visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!") src.throw_at(get_edge_target_turf(src,dir),1,momentum) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 314a4026ab..bb7881f0a0 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -147,7 +147,11 @@ proc/hasorgans(A) */ return zone - +// Returns zone with a certain probability. +// If the probability misses, returns "chest" instead. +// If "chest" was passed in as zone, then on a "miss" will return "head", "l_arm", or "r_arm" +// Do not use this if someone is intentionally trying to hit a specific body part. +// Use get_zone_with_miss_chance() for that. /proc/ran_zone(zone, probability) zone = check_zone(zone) if(!probability) probability = 90