From b570af67950d9f2deff675731e5d449c5c8934af Mon Sep 17 00:00:00 2001 From: phil235 Date: Tue, 14 Jul 2015 00:51:19 +0200 Subject: [PATCH 1/4] Fixed catching banana creampie in mid throw (and similar objs). 3824 10536 (hitting a wall now makes the smashed pie effect appear ON the wall) Moved last_bumped var from movable to living. Renamed /obj/machinery/field/proc/bump to bump_field() to avoid confusion with Bump(). Same thing with /obj/effect/mine/Bumped() -> triggermine(). Fixes sprite when hunter leaps into a wall. 10428 Removed some commented code here and there. Remove allow_spin var, throw_at now uses a spin argument for that. Throwpass atom var is no longer used to check whether thrown stuff can pass stuff (now using CanPass() proc like everything else), the var is still used for some adjacency click check. A thrown mob hitting another mob now produces a sound; also thrown mob and target one no longer swap places even on help intent. A thrown mob now is lightly hurt (and weakened) if he hits a wall/mob/dense object. Nerf the damage when thrown mob hit wall.(20 -> 10) Thrown obj/mob no longer bounces off wall unless it's no grav. Heavy thrown items now push an unanchored obj/mob target. Fixes losing all momentum when getting out of a thrown closet. 6569 A lot of work on throw_at, throw_impact, and hitby to make the code more OOP. Thrown items no longer collide with border items on the side. 10479 Fixes the killer crusher. 10507 --- code/game/atoms.dm | 32 +----- code/game/atoms_movable.dm | 103 +++++++++--------- code/game/gamemodes/cult/cult_structures.dm | 15 --- code/game/machinery/bots/ed209bot.dm | 8 -- .../machinery/computer/HolodeckControl.dm | 2 +- code/game/machinery/doors/door.dm | 4 +- code/game/machinery/doors/firedoor.dm | 6 +- code/game/machinery/recycler.dm | 2 + code/game/objects/effects/mines.dm | 13 +-- code/game/objects/items.dm | 28 ++--- code/game/objects/items/toys.dm | 89 +++++++-------- code/game/objects/items/weapons/dice.dm | 2 +- .../structures/crates_lockers/closets.dm | 6 + code/game/objects/structures/mineral_doors.dm | 6 +- code/game/objects/structures/morgue.dm | 9 ++ code/game/objects/weapons.dm | 5 - code/modules/flufftext/Hallucination.dm | 45 +------- code/modules/food&drinks/food/snacks_egg.dm | 9 +- code/modules/food&drinks/food/snacks_pie.dm | 9 +- code/modules/hydroponics/grown.dm | 18 +-- .../mob/living/carbon/alien/alien_defense.dm | 4 +- .../carbon/alien/humanoid/caste/hunter.dm | 49 +-------- .../mob/living/carbon/carbon_defense.dm | 6 +- .../mob/living/carbon/human/human_defense.dm | 16 ++- .../mob/living/carbon/human/human_movement.dm | 2 +- code/modules/mob/living/living.dm | 7 +- code/modules/mob/living/living_defense.dm | 16 ++- code/modules/mob/living/living_defines.dm | 4 +- code/modules/mob/mob_movement.dm | 14 +-- .../power/singularity/containment_field.dm | 8 +- .../power/singularity/field_generator.dm | 2 +- code/modules/power/singularity/singularity.dm | 2 +- code/modules/projectiles/projectile.dm | 2 +- code/modules/reagents/reagent_containers.dm | 4 +- code/modules/telesci/bscrystal.dm | 15 +-- html/changelogs/phil235-CatchThrownPieFix.yml | 8 ++ 36 files changed, 244 insertions(+), 326 deletions(-) create mode 100644 html/changelogs/phil235-CatchThrownPieFix.yml diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 52ac867c334..95c8c95dabf 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -6,7 +6,6 @@ var/list/fingerprintshidden var/fingerprintslast = null var/list/blood_DNA - var/last_bumped = 0 var/throwpass = 0 ///Chemistry. @@ -17,10 +16,6 @@ //HUD images that this atom can provide. var/list/hud_possible - //var/chem_is_open_container = 0 - // replaced by OPENCONTAINER flags and atom/proc/is_open_container() - ///Chemistry. - var/allow_spin = 1 //Value used to increment ex_act() if reactionary_explosions is on var/explosion_block = 0 @@ -55,26 +50,6 @@ return 0 -/atom/proc/throw_impact(atom/hit_atom,mob/thrower) - if(istype(hit_atom,/mob/living)) - var/mob/living/M = hit_atom - M.hitby(src,thrower) - - else if(isobj(hit_atom)) - var/obj/O = hit_atom - if(!O.anchored) - step(O, src.dir) - O.hitby(src) - - 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.take_organ_damage(20) - /atom/proc/attack_hulk(mob/living/carbon/human/hulk, do_attack_animation = 0) if(do_attack_animation) hulk.changeNext_move(CLICK_CD_MELEE) @@ -285,9 +260,10 @@ its easier to just keep the beam vertical. /atom/proc/fire_act() return -/atom/proc/hitby(atom/movable/AM as mob|obj) - return - +/atom/proc/hitby(atom/movable/AM, mob/thrower, skip, var/hitpush) + if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav. + spawn(2) + step(AM, turn(AM.dir, 180)) var/list/blood_splatter_icons = list() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index f24e6bf8e4f..8c20fc83801 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -93,17 +93,13 @@ /atom/movable/Crossed(atom/movable/AM) return -/atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes) - if(src.throwing) - src.throw_impact(A) - src.throwing = 0 - - if ((A && yes)) - A.last_bumped = world.time +/atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). + if((A && yes)) + if(throwing) + throwing = 0 + throw_impact(A) + . = 1 A.Bumped(src) - return - ..() - return /atom/movable/proc/forceMove(atom/destination) if(destination) @@ -146,7 +142,6 @@ if(!direction) return 1 - var/old_dir = dir . = step(src, direction) dir = old_dir @@ -154,57 +149,60 @@ /atom/movable/proc/checkpass(passflag) return pass_flags&passflag -/atom/movable/proc/hit_check(mob/thrower) // todo: this is partly obsolete due to passflags already, add throwing stuff to mob CanPass and finish it - if(src.throwing) - for(var/atom/A in get_turf(src)) - if(A == src) continue - if(istype(A,/mob/living)) - if(A:lying) continue - src.throw_impact(A,thrower) - 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,thrower) - src.throwing = 0 +/atom/movable/proc/throw_impact(atom/hit_atom, mob/thrower) + return hit_atom.hitby(src,thrower) -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower) +/atom/movable/hitby(atom/movable/AM, mob/thrower, skip, var/hitpush = 1) + if(!anchored && hitpush) + step(src, AM.dir) + return ..() + +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=1) 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 - src.throwing = 1 - if(target.allow_spin) // turns out 1000+ spinning objects being thrown at the singularity creates lag - Iamgoofball + throwing = 1 + if(spin) // turns out 1000+ spinning objects being thrown at the singularity creates lag - Iamgoofball SpinAnimation(5, 1) + + var/dist_travelled = 0 + var/dist_since_sleep = 0 + 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/dist_travelled = 0 - var/dist_since_sleep = 0 - - var/tdist_x = dist_x; - var/tdist_y = dist_y; - var/tdx = dx; - var/tdy = dy; if(dist_x <= dist_y) - tdist_x = dist_y; - tdist_y = dist_x; - tdx = dy; - tdy = dx; + var/olddist_x = dist_x + var/olddx = dx + dist_x = dist_y + dist_y = olddist_x + dx = dy + dy = olddx - var/error = tdist_x/2 - tdist_y - while(target && (((((dist_x > dist_y) && ((src.x < target.x && dx == EAST) || (src.x > target.x && dx == WEST))) || ((dist_x <= dist_y) && ((src.y < target.y && dy == NORTH) || (src.y > target.y && dy == SOUTH))) || (src.x > target.x && dx == WEST)) && dist_travelled < range) || !has_gravity(src))) - // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up - if(!src.throwing) break - if(!istype(src.loc, /turf)) break + var/error = dist_x/2 - dist_y - var/atom/step = get_step(src, (error < 0) ? tdy : tdx) + var/throw_range = min(range, dist_x + dist_y) + + var/hit = 0 + while(target && (dist_travelled < throw_range || !has_gravity(src))) + // only stop when we've gone the whole distance (or max throw range) and aren't floating, or hit something, or hit the end of the map, or someone picks it up + if(!throwing) + hit = 1 + break + if(!istype(loc, /turf)) + hit = 1 + break + + var/atom/step = get_step(src, (error < 0) ? dy : dx) + error += (error < 0) ? dist_x : -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 - src.Move(step, get_dir(loc, step)) - hit_check(thrower) - error += (error < 0) ? tdist_x : -tdist_y; + Move(step, get_dir(loc, step)) + if(!throwing) + hit = 1 + break dist_travelled++ dist_since_sleep++ if(dist_since_sleep >= speed) @@ -212,9 +210,14 @@ sleep(1) //done throwing, either because it hit something or it finished moving - src.throwing = 0 - if(isobj(src)) - src.throw_impact(get_turf(src),thrower) + throwing = 0 + 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, thrower) + + if(!hit) // we haven't hit something yet and we still must, let's hit the ground. + throw_impact(get_turf(src),thrower) return 1 diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 01bab649c0c..60cb2429040 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -24,17 +24,6 @@ name = "desk" desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl" icon_state = "tomealtar" -// luminosity = 5 - -//sprites for this no longer exist -Pete -//(they were stolen from another game anyway) -/* -/obj/structure/cult/pillar - name = "Pillar" - desc = "This should not exist" - icon_state = "pillar" - icon = 'magic_pillar.dmi' -*/ /obj/effect/gateway name = "gateway" @@ -46,11 +35,7 @@ anchored = 1.0 /obj/effect/gateway/Bumped(mob/M as mob|obj) - spawn(0) - return return /obj/effect/gateway/Crossed(AM as mob|obj) - spawn(0) - return return \ No newline at end of file diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index c1869318560..bfb6a32506b 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -397,14 +397,6 @@ Auto Patrol[]"}, return 1 return 0 -/* terrible -/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj) - spawn(0) - if (M) - var/turf/T = get_turf(src) - M:loc = T -*/ - /obj/machinery/bot/ed209/explode() walk_to(src,0) visible_message("[src] blows apart!") diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 62427b807e5..c46e84e7bde 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -410,6 +410,7 @@ var/mob/living/carbon/M = hit_atom playsound(src, 'sound/items/dodgeball.ogg', 50, 1) M.apply_damage(10, STAMINA) + loc = get_turf(hit_atom) //drop at the target's feet if(prob(5)) M.Weaken(3) visible_message("[M] is knocked right off \his feet!", 3) @@ -421,7 +422,6 @@ icon_state = "hoop" anchored = 1 density = 1 - throwpass = 1 /obj/structure/holohoop/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index abfb8ff9253..2ee4809f8d8 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -45,8 +45,8 @@ /obj/machinery/door/Bumped(atom/AM) if(operating || emagged) return - if(ismob(AM)) - var/mob/M = AM + if(isliving(AM)) + var/mob/living/M = AM if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent shock spam. M.last_bumped = world.time if(!M.restrained()) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 85f6dac25e8..f15ed458a12 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -16,8 +16,10 @@ closingLayer = 3.11 /obj/machinery/door/firedoor/Bumped(atom/AM) - if(p_open || operating) return - if(!density) return ..() + if(p_open || operating) + return + if(!density) + return ..() return 0 diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index c8a121619cd..d4293072aa4 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -101,6 +101,8 @@ var/const/SAFETY_COOLDOWN = 100 if(stat & (BROKEN|NOPOWER)) return + if(!anchored) + return if(safety_mode) return diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index e1c0f16074a..4c159f7a431 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -15,17 +15,14 @@ if(isanimal(AM)) var/mob/living/simple_animal/SA = AM if(!SA.flying) - Bumped(SA) + triggermine(SA) else - Bumped(AM) - -/obj/effect/mine/Bumped(AM as mob|obj) - - if(triggered) return - visible_message("[AM] sets off \icon[src] [src]!") - triggermine(AM) + triggermine(AM) /obj/effect/mine/proc/triggermine(mob/victim) + if(triggered) + return + visible_message("[victim] sets off \icon[src] [src]!") var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 0ab94fcd813..09147da601f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -431,7 +431,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s /obj/item/singularity_pull(S, current_size) spawn(0) //this is needed or multiple items will be thrown sequentially and not simultaneously if(current_size >= STAGE_FOUR) - throw_at(S,14,3) + throw_at(S,14,3, spin=0) else ..() /obj/item/acid_act(var/acidpwr, var/acid_volume) @@ -465,26 +465,16 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s if(!findtext(desc, "it looks slightly melted...")) //it looks slightly melted... it looks slightly melted... it looks slightly melted... etc. desc += " it looks slightly melted..." //needs a space at the start, formatting +/obj/item/throw_impact(atom/A, mob/thrower) + var/itempush = 1 + if(w_class < 4) + itempush = 0 //too light to push anything + return A.hitby(src,thrower, 0, itempush) - -/obj/item/throw_impact(A) - if(throw_speed >= EMBED_THROWSPEED_THRESHOLD) - if(istype(A, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = A - if(can_embed(src)) - if(prob(embed_chance) && !(PIERCEIMMUNE in H.dna.species.specflags)) - H.throw_alert("embeddedobject") - var/obj/item/organ/limb/L = pick(H.organs) - L.embedded_objects |= src - add_blood(H)//it embedded itself in you, of course it's bloody! - loc = H - L.take_damage(w_class*embedded_impact_pain_multiplier) - H.visible_message("\the [name] embeds itself in [H]'s [L.getDisplayName()]!","\the [name] embeds itself in your [L.getDisplayName()]!") - return - - //Reset regardless of if we hit a human. +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1) + . = ..() 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) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 232aca31cfc..f6f8bfa4745 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -44,41 +44,40 @@ /obj/item/toy/balloon/afterattack(atom/A as mob|obj, mob/user as mob, proximity) if(!proximity) return - if (istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1) - A.reagents.trans_to(src, 10) - user << "You fill the balloon with the contents of [A]." - src.desc = "A translucent balloon with some form of liquid sloshing around in it." - src.update_icon() - return + if (istype(A, /obj/structure/reagent_dispensers)) + var/obj/structure/reagent_dispensers/RD = A + if(RD.reagents.total_volume <= 0) + user << "[RD] is empty." + else if(reagents.total_volume >= 10) + user << "[src] is full." + else + A.reagents.trans_to(src, 10) + user << "You fill the balloon with the contents of [A]." + desc = "A translucent balloon with some form of liquid sloshing around in it." + update_icon() /obj/item/toy/balloon/attackby(obj/O as obj, mob/user as mob, params) if(istype(O, /obj/item/weapon/reagent_containers/glass)) if(O.reagents) - if(O.reagents.total_volume < 1) - user << "The [O] is empty." - else if(O.reagents.total_volume >= 1) - if(O.reagents.has_reagent("facid", 1)) - user << "The acid chews through the balloon!" - O.reagents.reaction(user) - qdel(src) - else - src.desc = "A translucent balloon with some form of liquid sloshing around in it." - user << "You fill the balloon with the contents of [O]." - O.reagents.trans_to(src, 10) - src.update_icon() - return + if(O.reagents.total_volume <= 0) + user << "[O] is empty." + else if(reagents.total_volume >= 10) + user << "[src] is full." + else + desc = "A translucent balloon with some form of liquid sloshing around in it." + user << "You fill the balloon with the contents of [O]." + O.reagents.trans_to(src, 10) + update_icon() /obj/item/toy/balloon/throw_impact(atom/hit_atom) - if(src.reagents.total_volume >= 1) - src.visible_message("\The [src] bursts!","You hear a pop and a splash.") - src.reagents.reaction(get_turf(hit_atom)) - for(var/atom/A in get_turf(hit_atom)) - src.reagents.reaction(A) - src.icon_state = "burst" - spawn(5) - if(src) - qdel(src) - return + if(!..()) //was it caught by a mob? + if(reagents.total_volume >= 1) + visible_message("[src] bursts!","You hear a pop and a splash.") + reagents.reaction(get_turf(hit_atom)) + for(var/atom/A in get_turf(hit_atom)) + reagents.reaction(A) + icon_state = "burst" + del(src) // Not qdel, because it would burst multiple times /obj/item/toy/balloon/update_icon() if(src.reagents.total_volume >= 1) @@ -514,20 +513,24 @@ icon_state = "snappop" w_class = 1 -/obj/item/toy/snappop/fire_act() - throw_impact() - return - -/obj/item/toy/snappop/throw_impact(atom/hit_atom) - ..() +/obj/item/toy/snappop/proc/pop_burst() var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(3, 1, src) s.start() - new /obj/effect/decal/cleanable/ash(src.loc) - src.visible_message("The [src.name] explodes!","You hear a snap!") + new /obj/effect/decal/cleanable/ash(loc) + visible_message("The [src.name] explodes!","You hear a snap!") playsound(src, 'sound/effects/snap.ogg', 50, 1) qdel(src) +/obj/item/toy/snappop/fire_act() + pop_burst() + return + +/obj/item/toy/snappop/throw_impact(atom/hit_atom) + if(!..()) + pop_burst() + + /obj/item/toy/snappop/Crossed(H as mob|obj) if((ishuman(H))) //i guess carp and shit shouldn't set them off var/mob/living/carbon/M = H @@ -1100,12 +1103,12 @@ w_class = 2.0 /obj/item/toy/minimeteor/throw_impact(atom/hit_atom) - ..() - playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) - for(var/mob/M in range(10, src)) - if(!M.stat && !istype(M, /mob/living/silicon/ai))\ - shake_camera(M, 3, 1) - qdel(src) + if(!..()) + playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) + for(var/mob/M in range(10, src)) + if(!M.stat && !istype(M, /mob/living/silicon/ai))\ + shake_camera(M, 3, 1) + qdel(src) /* * Carp plushie diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index 1a85a2e50d6..5e06f31ddb4 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -56,7 +56,7 @@ /obj/item/weapon/dice/attack_self(mob/user as mob) diceroll(user) -/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/user as mob) +/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/user as mob, spin=1) if(!..()) return diceroll(user) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 08ea4e09edd..697f718d095 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -82,12 +82,18 @@ for(var/obj/O in src) O.loc = loc + if(throwing) //you keep some momentum when getting out of a thrown closet + spawn(2) //some time to avoid a collision between the obj and the closet/crate + step(O, dir) for(var/mob/M in src) M.loc = loc if(M.client) M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE + if(throwing) + spawn(2) + step(M, dir) /obj/structure/closet/proc/take_contents() diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 23be1ce7c31..fe14690944a 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -65,9 +65,9 @@ /obj/structure/mineral_door/proc/TryToSwitchState(atom/user) if(isSwitchingStates) return - if(ismob(user)) - var/mob/M = user - if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? + if(isliving(user)) + var/mob/living/M = user + if(world.time - M.last_bumped <= 60) return //NOTE do we really need that? if(M.client) if(iscarbon(M)) var/mob/living/carbon/C = M diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 526e9e3f028..472f46939f1 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -278,3 +278,12 @@ Crematorium Switch desc = "Apply corpse before closing." icon_state = "morguet" +/obj/structure/tray/m_tray/CanPass(atom/movable/mover, turf/target, height=0) + if(height==0) return 1 + + if(istype(mover) && mover.checkpass(PASSTABLE)) + return 1 + if(locate(/obj/structure/table) in get_turf(mover)) + return 1 + else + return 0 \ No newline at end of file diff --git a/code/game/objects/weapons.dm b/code/game/objects/weapons.dm index adca34f56e8..e85375ba5ed 100644 --- a/code/game/objects/weapons.dm +++ b/code/game/objects/weapons.dm @@ -9,8 +9,3 @@ hitsound = 'sound/items/welder.ogg' if(damtype == "brute") hitsound = "swing_hit" - -/obj/item/weapon/Bump(mob/M as mob) - spawn(0) - ..() - return \ No newline at end of file diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 388da344db4..04c1128c9fb 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -22,14 +22,14 @@ Gunshots/explosions/opening doors/less rare audio (done) /mob/living/carbon/proc/handle_hallucinations() if(handling_hal) return - + //Least obvious var/list/minor = list("sounds"=20,"bolts_minor"=10,"whispers"=15,"message"=5) //Something's wrong here var/list/medium = list("hudscrew"=15,"items"=15,"dangerflash"=15,"bolts"=10,"flood"=10,"husks"=10,"battle"=10) //AAAAH var/list/major = list("fake"=10,"death"=5,"xeno"=10,"singulo"=10,"delusion"=10) - + var/grade = 0 var/current = list() var/trip_length = 0 @@ -171,47 +171,6 @@ Gunshots/explosions/opening doors/less rare audio (done) name = "alien hunter ([rand(1, 1000)])" return -/obj/effect/hallucination/simple/xeno/throw_at(atom/target, range, speed) // TODO : Make diagonal trhow into proc/property - if(!target || !src || (flags & NODROP)) return 0 - - src.throwing = 1 - - var/dist_x = abs(target.x - src.x) - var/dist_y = abs(target.y - src.y) - var/dist_travelled = 0 - var/dist_since_sleep = 0 - - var/tdist_x = dist_x; - var/tdist_y = dist_y; - - if(dist_x <= dist_y) - tdist_x = dist_y; - tdist_y = dist_x; - - var/error = tdist_x/2 - tdist_y - while(target && (((((dist_x > dist_y) && ((src.x < target.x) || (src.x > target.x))) || ((dist_x <= dist_y) && ((src.y < target.y) || (src.y > target.y))) || (src.x > target.x)) && dist_travelled < range) || !has_gravity(src))) - - if(!src.throwing) break - if(!istype(src.loc, /turf)) break - - var/atom/step = get_step(src, get_dir(src,target)) - if(!step) - break - src.Move(step, get_dir(src, step)) - hit_check() - error += (error < 0) ? tdist_x : -tdist_y; - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - - - src.throwing = 0 - src.throw_impact(get_turf(src)) - - return 1 - /obj/effect/hallucination/simple/xeno/throw_impact(A) update_icon("alienh_pounce") if(A == target) diff --git a/code/modules/food&drinks/food/snacks_egg.dm b/code/modules/food&drinks/food/snacks_egg.dm index 08e3076e190..c575cd8a57b 100644 --- a/code/modules/food&drinks/food/snacks_egg.dm +++ b/code/modules/food&drinks/food/snacks_egg.dm @@ -18,10 +18,11 @@ filling_color = "#F0E68C" /obj/item/weapon/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom) - ..() - new/obj/effect/decal/cleanable/egg_smudge(src.loc) - reagents.reaction(hit_atom, TOUCH) - del(src) // Not qdel, because it'll hit other mobs then the floor for runtimes. + if(!..()) //was it caught by a mob? + var/turf/T = get_turf(hit_atom) + new/obj/effect/decal/cleanable/egg_smudge(T) + reagents.reaction(hit_atom, TOUCH) + qdel(src) /obj/item/weapon/reagent_containers/food/snacks/egg/attackby(obj/item/weapon/W as obj, mob/user as mob, params) if(istype( W, /obj/item/toy/crayon )) diff --git a/code/modules/food&drinks/food/snacks_pie.dm b/code/modules/food&drinks/food/snacks_pie.dm index e4fe6700f67..6a9be926630 100644 --- a/code/modules/food&drinks/food/snacks_pie.dm +++ b/code/modules/food&drinks/food/snacks_pie.dm @@ -23,10 +23,11 @@ list_reagents = list("nutriment" = 6, "banana" = 5, "vitamin" = 2) /obj/item/weapon/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom) - ..() - new/obj/effect/decal/cleanable/pie_smudge(src.loc) - reagents.reaction(hit_atom, TOUCH) - del(src) // Not qdel, because it'll hit other mobs then the floor for runtimes. + if(!..()) //was it caught by a mob? + var/turf/T = get_turf(hit_atom) + new/obj/effect/decal/cleanable/pie_smudge(T) + reagents.reaction(hit_atom, TOUCH) + qdel(src) /obj/item/weapon/reagent_containers/food/snacks/pie/berryclafoutis diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 8fe33dc7e58..2cfcf77413e 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -806,17 +806,16 @@ obj/item/weapon/reagent_containers/food/snacks/grown/shell/eggy/add_juice() bitesize = 1 + round(reagents.total_volume / 2, 1) /obj/item/weapon/reagent_containers/food/snacks/grown/tomato/proc/squish(atom/target) - new splat(src.loc) - src.visible_message("The [src.name] has been squashed.","You hear a smack.") + var/turf/T = get_turf(target) + new splat(T) + visible_message("The [src.name] has been squashed.","You hear a smack.") for(var/atom/A in get_turf(target)) - src.reagents.reaction(A) + reagents.reaction(A) /obj/item/weapon/reagent_containers/food/snacks/grown/tomato/throw_impact(atom/hit_atom) - ..() - squish(hit_atom) - del(src) // Not qdel, because it'll hit other mobs then the floor for runtimes. - return - + if(!..()) //was it caught by a mob? + squish(hit_atom) + qdel(src) /obj/item/weapon/reagent_containers/food/snacks/grown/tomato/killer seed = /obj/item/seeds/killertomatoseed @@ -906,7 +905,8 @@ obj/item/weapon/reagent_containers/food/snacks/grown/shell/eggy/add_juice() ..() var/teleport_radius = potency / 10 if(isliving(squishee)) - new /obj/effect/decal/cleanable/molten_item(squishee.loc) //Leave a pile of goo behind for dramatic effect... + var/turf/T = get_turf(squishee) + new /obj/effect/decal/cleanable/molten_item(T) //Leave a pile of goo behind for dramatic effect... do_teleport(squishee, get_turf(squishee), teleport_radius) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 51e086ae669..e217683f129 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -1,5 +1,5 @@ -/mob/living/carbon/alien/hitby(atom/movable/AM) - ..(AM, 1) +/mob/living/carbon/alien/hitby(atom/movable/AM, mob/thrower) + ..(AM, thrower, skip = 1) /*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. 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 a34c6337786..e27983fd18d 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -82,11 +82,11 @@ else //Maybe uses plasma in the future, although that wouldn't make any sense... leaping = 1 update_icons() - throw_at(A,MAX_ALIEN_LEAP_DIST,1) + throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0) leaping = 0 update_icons() -/mob/living/carbon/alien/humanoid/hunter/throw_impact(A) +/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) if(!leaping) return ..() @@ -103,60 +103,21 @@ pounce_cooldown = !pounce_cooldown spawn(pounce_cooldown_time) //3s by default pounce_cooldown = !pounce_cooldown - else + else if(A.density && !A.CanPass(src)) visible_message("[src] smashes into [A]!", "[src] smashes into [A]!") weakened = 2 if(leaping) leaping = 0 + update_icons() update_canmove() + /mob/living/carbon/alien/humanoid/float(on) if(leaping) return ..() -//Modified throw_at() that will use diagonal dirs where appropriate -//instead of locking it to cardinal dirs -/mob/living/carbon/alien/humanoid/throw_at(atom/target, range, speed) - if(!target || !src || (flags & NODROP)) return 0 - - src.throwing = 1 - - var/dist_x = abs(target.x - src.x) - var/dist_y = abs(target.y - src.y) - var/dist_travelled = 0 - var/dist_since_sleep = 0 - - var/tdist_x = dist_x; - var/tdist_y = dist_y; - - if(dist_x <= dist_y) - tdist_x = dist_y; - tdist_y = dist_x; - - var/error = tdist_x/2 - tdist_y - while(target && (((((dist_x > dist_y) && ((src.x < target.x) || (src.x > target.x))) || ((dist_x <= dist_y) && ((src.y < target.y) || (src.y > target.y))) || (src.x > target.x)) && dist_travelled < range) || !has_gravity(src))) - - if(!src.throwing) break - if(!istype(src.loc, /turf)) break - - var/atom/step = get_step(src, get_dir(src,target)) - if(!step) - break - src.Move(step, get_dir(src, step)) - hit_check() - error += (error < 0) ? tdist_x : -tdist_y; - dist_travelled++ - dist_since_sleep++ - if(dist_since_sleep >= speed) - dist_since_sleep = 0 - sleep(1) - - - src.throwing = 0 - - return 1 diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 65cdef581b1..24f9192cca3 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/hitby(atom/movable/AM, skip) +/mob/living/carbon/hitby(atom/movable/AM, mob/thrower, skip) if(!skip) //ugly, but easy if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode if(canmove && !restrained()) @@ -8,8 +8,8 @@ put_in_active_hand(I) visible_message("[src] catches [I]!") throw_mode_off() - return - ..() + return 1 + return ..() /mob/living/carbon/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 7feb6af38b3..f1fa58c8509 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -455,4 +455,18 @@ emp_act else ..() - return +/mob/living/carbon/human/hitby(atom/movable/AM, mob/thrower) + if(throw_speed >= EMBED_THROWSPEED_THRESHOLD) + if(istype(AM, /obj/item)) + var/obj/item/I = AM + if(can_embed(I)) + if(prob(I.embed_chance) && !(dna && (PIERCEIMMUNE in dna.species.specflags))) + throw_alert("embeddedobject") + var/obj/item/organ/limb/L = pick(organs) + L.embedded_objects |= I + I.add_blood(src)//it embedded itself in you, of course it's bloody! + I.loc = src + L.take_damage(I.w_class*I.embedded_impact_pain_multiplier) + visible_message("\the [I.name] embeds itself in [src]'s [L.getDisplayName()]!","\the [I.name] embeds itself in your [L.getDisplayName()]!") + return + return ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 5dc30d5535a..113306f12e2 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -45,7 +45,7 @@ return shoes && shoes.negates_gravity() /mob/living/carbon/human/Move(NewLoc, direct) - ..() + . = ..() if(dna) for(var/datum/mutation/human/HM in dna.mutations) HM.on_move(src, NewLoc) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 48b78d3fb65..4e47819cd1a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -52,13 +52,14 @@ Sorry Giacom. Please don't be mad :( //Generic Bump(). Override MobBump() and ObjBump() instead of this. /mob/living/Bump(atom/A, yes) + if(..()) //bumped by a thrown /atom/movable + return if (buckled || !yes || now_pushing) return if(ismob(A)) var/mob/M = A if(MobBump(M)) return - ..() if(isobj(A)) var/obj/O = A if(ObjBump(O)) @@ -68,6 +69,10 @@ Sorry Giacom. Please don't be mad :( if(PushAM(AM)) return +/mob/living/Bumped(atom/movable/AM) + ..() + last_bumped = world.time + //Called when we bump onto a mob /mob/living/proc/MobBump(mob/M) //Even if we don't push/swap places, we "touched" them, so spread fire diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d050141cd8d..05711d54ae1 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -44,7 +44,13 @@ else return 0 -/mob/living/hitby(atom/movable/AM,mob/thrower)//Standardization and logging -Sieve +/mob/living/throw_impact(atom/hit_atom, mob/thrower) + . = ..() + if(hit_atom.density) + Weaken(1) + take_organ_damage(10) + +/mob/living/hitby(atom/movable/AM, mob/thrower) if(istype(AM, /obj/item)) var/obj/item/I = AM var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest @@ -71,9 +77,11 @@ "[src] has been hit by [I].") var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) apply_damage(I.throwforce, dtype, zone, armor, I) - - if(thrower) - add_logs(thrower, src, "hit", object="[I]") + else + playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) + if(thrower) + add_logs(thrower, src, "hit", object="[AM]") + return ..() /mob/living/mech_melee_attack(obj/mecha/M) if(M.occupant.a_intent == "harm") diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index b48f2f21e14..e0247e1d3cd 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -45,4 +45,6 @@ var/list/pipes_shown = list() var/last_played_vent - var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob. \ No newline at end of file + var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob. + + var/last_bumped = 0 \ No newline at end of file diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index f80afc9d4f8..5d992c37117 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -1,18 +1,16 @@ /mob/CanPass(atom/movable/mover, turf/target, height=0) - if(height==0) return 1 - - if(istype(mover) && mover.checkpass(PASSMOB)) + if(height==0) return 1 - if(istype(mover, /obj/item/projectile)) + if(istype(mover, /obj/item/projectile) || mover.throwing) return (!density || lying) + if(mover.checkpass(PASSMOB)) + return 1 if(ismob(mover)) var/mob/moving_mob = mover if ((other_mobs && moving_mob.other_mobs)) return 1 - return (!mover.density || !density || lying) - else - return (!mover.density || !density || lying) - return + return (!mover.density || !density || lying) + /client/Northeast() diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index ad420ffc5e6..33182087e98 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -43,7 +43,7 @@ /obj/machinery/field/containment/Crossed(obj/mover as obj) if(istype(mover, /obj/machinery) || istype(mover, /obj/structure) || istype(mover, /obj/mecha)) - bump(mover) + bump_field(mover) /obj/machinery/field/containment/proc/set_master(var/master1,var/master2) if(!master1 || !master2) @@ -77,7 +77,7 @@ if((istype(mover, /obj/machinery) && !istype(mover, /obj/singularity)) || \ istype(mover, /obj/structure) || \ istype(mover, /obj/mecha)) - bump(mover) + bump_field(mover) return 0 return ..() @@ -106,13 +106,13 @@ "You hear an electrical crack.") user.updatehealth() - bump(user) + bump_field(user) spawn(5) hasShocked = 0 return -/obj/machinery/field/proc/bump(atom/movable/AM as mob|obj) +/obj/machinery/field/proc/bump_field(atom/movable/AM as mob|obj) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread s.set_up(5, 1, AM.loc) s.start() diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 07943676729..45c4a3c4727 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -356,6 +356,6 @@ field_generator power level display if(fields.len) ..() -/obj/machinery/field/generator/bump(atom/movable/AM as mob|obj) +/obj/machinery/field/generator/bump_field(atom/movable/AM as mob|obj) if(fields.len) ..() diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 90c60fc5769..44e06e7d5c2 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -26,7 +26,7 @@ var/last_failed_movement = 0//Will not move in the same dir if it couldnt before, will help with the getting stuck on fields thing var/last_warning var/consumedSupermatter = 0 //If the singularity has eaten a supermatter shard and can go to stage six - allow_spin = 0 + /obj/singularity/New(loc, var/starting_energy = 50, var/temp = 0) //CARN: admin-alert for chuckle-fuckery. admin_investigate_setup() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 8fc1a4622f9..e55eea65f05 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -92,7 +92,7 @@ return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume /obj/item/projectile/Bump(atom/A, yes) - if(!yes) //prevents multi bumps. + if(!yes) //prevents double bumps. return if(A == firer || A == src) loc = A.loc diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 6037ebf02d8..c4c24929e39 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -80,7 +80,7 @@ ..() /obj/item/weapon/reagent_containers/throw_impact(atom/target,mob/thrower) - ..() + . = ..() if(!reagents.total_volume || !spillable) return @@ -100,7 +100,7 @@ add_logs(thrower, M, "splashed", object="[R]") reagents.reaction(target, TOUCH) - else if((!target.density || target.throwpass) && thrower && thrower.mind && thrower.mind.assigned_role == "Bartender") + else if((target.CanPass(src, get_turf(src))) && thrower && thrower.mind && thrower.mind.assigned_role == "Bartender") visible_message("[src] lands onto the [target.name] without spilling a single drop.") return diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm index 74b9807dade..53eba66a1b1 100644 --- a/code/modules/telesci/bscrystal.dm +++ b/code/modules/telesci/bscrystal.dm @@ -28,13 +28,14 @@ do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg') /obj/item/bluespace_crystal/throw_impact(atom/hit_atom) - ..() - visible_message("[src] fizzles and disappears upon impact!") - PoolOrNew(/obj/effect/effect/sparks, loc) - playsound(src.loc, "sparks", 50, 1) - if(isliving(hit_atom)) - blink_mob(hit_atom) - qdel(src) + if(!..()) // not caught in mid-air + visible_message("[src] fizzles and disappears upon impact!") + var/turf/T = get_turf(hit_atom) + PoolOrNew(/obj/effect/effect/sparks, T) + playsound(src.loc, "sparks", 50, 1) + if(isliving(hit_atom)) + blink_mob(hit_atom) + qdel(src) // Artifical bluespace crystal, doesn't give you much research. diff --git a/html/changelogs/phil235-CatchThrownPieFix.yml b/html/changelogs/phil235-CatchThrownPieFix.yml new file mode 100644 index 00000000000..8b8f21081c2 --- /dev/null +++ b/html/changelogs/phil235-CatchThrownPieFix.yml @@ -0,0 +1,8 @@ + +author: phil235 + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +changes: + - tweak: "Thrown things no longer bounces off walls, unless they're in no gravity. Heavy items and mobs thrown can push the mobs and non anchored objects they land on. Throwing a mob onto a mob in no gravity will push each one in opposite direction. Thrown mobs landing on wall, or dense object or mob gets stunned and a bit injured. The damage when mob hit a wall is nerfed. From 9eced1ac5b0da035dc83e4f1203e2e0afa5c6723 Mon Sep 17 00:00:00 2001 From: phil235 Date: Sun, 19 Jul 2015 21:29:35 +0200 Subject: [PATCH 2/4] Fixes thrown closet opening to not use spawn(). Fixes throw_at() to look nicely for xeno leap by adding the diagonals_first argument. Removes useless gateway/Crossed and gateway/Bumped(). Changes throw_at() to use diagonal directions. I replaced the atom variable "throwpass" with the LETPASSTHROW pass_flags I readded hit_check proc to catch things getting on the thrown thing's tile during its sleep(1) (especially needed for mobs running towards the thing), the only other possibility would've been to add throwing checks in atom/movable/Crossed() (called after every move) and I don't think it'd be worth it. I added the item var "thrownby" to be able to continue to log the thrower of the item when it hits a mob. It removes the need for a thrower argument in throw_impact() and hitby(). --- code/__DEFINES/flags.dm | 11 ++-- code/_onclick/adjacent.dm | 20 ++---- code/game/atoms.dm | 3 +- code/game/atoms_movable.dm | 62 ++++++++++++------- code/game/gamemodes/cult/cult_structures.dm | 6 -- code/game/objects/items.dm | 7 ++- .../structures/crates_lockers/closets.dm | 12 ++-- code/game/objects/structures/morgue.dm | 2 +- code/game/objects/structures/tables_racks.dm | 4 +- code/modules/flufftext/Hallucination.dm | 4 +- .../mob/living/carbon/alien/alien_defense.dm | 4 +- .../carbon/alien/humanoid/caste/hunter.dm | 4 +- .../mob/living/carbon/carbon_defense.dm | 2 +- .../mob/living/carbon/human/human_defense.dm | 2 +- code/modules/mob/living/living.dm | 2 +- code/modules/mob/living/living_defense.dm | 8 +-- code/modules/reagents/reagent_containers.dm | 8 +-- 17 files changed, 79 insertions(+), 82 deletions(-) diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 9ddae527eec..0da4f75e1bf 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -42,11 +42,12 @@ the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example) */ //flags for pass_flags -#define PASSTABLE 1 -#define PASSGLASS 2 -#define PASSGRILLE 4 -#define PASSBLOB 8 -#define PASSMOB 16 +#define PASSTABLE 1 +#define PASSGLASS 2 +#define PASSGRILLE 4 +#define PASSBLOB 8 +#define PASSMOB 16 +#define LETPASSTHROW 32 //flags for species diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm index 20aeb967d29..fb06dacb3d0 100644 --- a/code/_onclick/adjacent.dm +++ b/code/_onclick/adjacent.dm @@ -23,7 +23,7 @@ * If you are in the same turf, always true * If you are vertically/horizontally adjacent, ensure there are no border objects * If you are diagonally adjacent, ensure you can pass through at least one of the mutually adjacent square. - * Passing through in this case ignores anything with the throwpass flag, such as tables, racks, and morgue trays. + * Passing through in this case ignores anything with the LETPASSTHROW pass flag, such as tables, racks, and morgue trays. */ /turf/Adjacent(var/atom/neighbor, var/atom/target = null) var/turf/T0 = get_turf(neighbor) @@ -80,28 +80,18 @@ /* This checks if you there is uninterrupted airspace between that turf and this one. - This is defined as any dense ON_BORDER object, or any dense object without throwpass. + This is defined as any dense ON_BORDER object, or any dense object without LETPASSTHROW. The border_only flag allows you to not objects (for source and destination squares) */ /turf/proc/ClickCross(var/target_dir, var/border_only, var/target_atom = null) for(var/obj/O in src) - if( !O.density || O == target_atom || O.throwpass) //check if there's a dense object present on the turf - continue // throwpass is used for anything you can click through (or the firedoor special case, see above) + if( !O.density || O == target_atom || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf + continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above) - if( O.flags&ON_BORDER) // windows have throwpass but are on border, check them first + if( O.flags&ON_BORDER) // windows are on border, check them first if( O.dir & target_dir || O.dir & (O.dir-1) ) // full tile windows are just diagonals mechanically return 0 //O.dir&(O.dir-1) is false for any cardinal direction, but true for diagonal ones else if( !border_only ) // dense, not on border, cannot pass over return 0 return 1 - -/* - Aside: throwpass does not do what I thought it did originally, and is only used for checking whether or not - a thrown object should stop after already successfully entering a square. Currently the throw code involved - only seems to affect hitting mobs, because the checks performed against objects are already performed when - entering or leaving the square. Since throwpass isn't used on mobs, but only on objects, it is effectively - useless. Throwpass may later need to be removed and replaced with a passcheck (bitfield on movable atom passflags). - - Since I don't want to complicate the click code rework by messing with unrelated systems it won't be changed here. -*/ \ No newline at end of file diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 95c8c95dabf..a524b655a7f 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -6,7 +6,6 @@ var/list/fingerprintshidden var/fingerprintslast = null var/list/blood_DNA - var/throwpass = 0 ///Chemistry. var/datum/reagents/reagents = null @@ -260,7 +259,7 @@ its easier to just keep the beam vertical. /atom/proc/fire_act() return -/atom/proc/hitby(atom/movable/AM, mob/thrower, skip, var/hitpush) +/atom/proc/hitby(atom/movable/AM, skip, var/hitpush) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav. spawn(2) step(AM, turn(AM.dir, 180)) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 8c20fc83801..76e6adc3213 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -93,7 +93,7 @@ /atom/movable/Crossed(atom/movable/AM) return -/atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). +/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump(). if((A && yes)) if(throwing) throwing = 0 @@ -149,20 +149,20 @@ /atom/movable/proc/checkpass(passflag) return pass_flags&passflag -/atom/movable/proc/throw_impact(atom/hit_atom, mob/thrower) - return hit_atom.hitby(src,thrower) +/atom/movable/proc/throw_impact(atom/hit_atom) + return hit_atom.hitby(src) -/atom/movable/hitby(atom/movable/AM, mob/thrower, skip, var/hitpush = 1) +/atom/movable/hitby(atom/movable/AM, skip, var/hitpush = 1) if(!anchored && hitpush) step(src, AM.dir) return ..() -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=1) +/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 throwing = 1 - if(spin) // turns out 1000+ spinning objects being thrown at the singularity creates lag - Iamgoofball + if(spin) //if we don't want the /atom/movable to spin. SpinAnimation(5, 1) var/dist_travelled = 0 @@ -173,6 +173,10 @@ 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) var/olddist_x = dist_x var/olddx = dx @@ -182,25 +186,24 @@ dy = olddx var/error = dist_x/2 - dist_y - - var/throw_range = min(range, dist_x + dist_y) - + var/atom/finalturf = get_turf(target) var/hit = 0 - while(target && (dist_travelled < throw_range || !has_gravity(src))) - // only stop when we've gone the whole distance (or max throw range) and aren't floating, or hit something, or hit the end of the map, or someone picks it up - if(!throwing) - hit = 1 - break + + while(target && ((dist_travelled < range && loc != finalturf) || !has_gravity(src))) //stop if we reached our destination (or max range) and aren't floating + if(!istype(loc, /turf)) hit = 1 break - var/atom/step = get_step(src, (error < 0) ? dy : dx) - error += (error < 0) ? dist_x : -dist_y + var/atom/step = get_step(src, get_dir(src, target)) + 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 && get_dist(src, finalturf) > 1) + 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) + if(!throwing) // we hit something during our move hit = 1 break dist_travelled++ @@ -209,18 +212,29 @@ dist_since_sleep = 0 sleep(1) + if(!dist_since_sleep && hitcheck()) //to catch sneaky things moving on our tile during our sleep(1) + hit = 1 + break + //done throwing, either because it hit something or it finished moving throwing = 0 - 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, thrower) - - if(!hit) // we haven't hit something yet and we still must, let's hit the ground. - throw_impact(get_turf(src),thrower) + 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. 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)) + throw_impact(AM) + return 1 //Overlays /atom/movable/overlay diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index 60cb2429040..aaac82f87df 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -33,9 +33,3 @@ density = 1 unacidable = 1 anchored = 1.0 - -/obj/effect/gateway/Bumped(mob/M as mob|obj) - return - -/obj/effect/gateway/Crossed(AM as mob|obj) - return \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 09147da601f..2024cca7d7f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -55,6 +55,8 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s var/suittoggled = 0 var/hooded = 0 + var/mob/thrownby = null + /obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged //So items can have custom embedd values @@ -465,13 +467,14 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s if(!findtext(desc, "it looks slightly melted...")) //it looks slightly melted... it looks slightly melted... it looks slightly melted... etc. desc += " it looks slightly melted..." //needs a space at the start, formatting -/obj/item/throw_impact(atom/A, mob/thrower) +/obj/item/throw_impact(atom/A) var/itempush = 1 if(w_class < 4) itempush = 0 //too light to push anything - return A.hitby(src,thrower, 0, itempush) + return A.hitby(src,thrownby, 0, itempush) /obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1) + thrownby = thrower . = ..() throw_speed = initial(throw_speed) //explosions change this. diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 697f718d095..1f00d290936 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -79,12 +79,10 @@ return 1 /obj/structure/closet/proc/dump_contents() - for(var/obj/O in src) O.loc = loc if(throwing) //you keep some momentum when getting out of a thrown closet - spawn(2) //some time to avoid a collision between the obj and the closet/crate - step(O, dir) + step(O, dir) for(var/mob/M in src) M.loc = loc @@ -92,8 +90,9 @@ M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE if(throwing) - spawn(2) - step(M, dir) + step(M, dir) + if(throwing) + throwing = 0 /obj/structure/closet/proc/take_contents() @@ -106,14 +105,13 @@ return 0 if(!can_open()) return 0 - dump_contents() - opened = 1 if(istype(src, /obj/structure/closet/body_bag)) playsound(loc, 'sound/items/zip.ogg', 15, 1, -3) else playsound(loc, 'sound/machines/click.ogg', 15, 1, -3) density = 0 + dump_contents() update_icon() return 1 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 472f46939f1..87efe8ccffd 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -226,7 +226,7 @@ Crematorium Switch layer = 2.9 var/obj/structure/bodycontainer/connected = null anchored = 1.0 - throwpass = 1 + pass_flags = LETPASSTHROW /obj/structure/tray/Destroy() if(connected) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 02c24df2966..2a61a56a3d5 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -20,7 +20,7 @@ density = 1 anchored = 1.0 layer = 2.8 - throwpass = 1 //You can throw objects over this, despite it's density.") + pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.") var/frame = /obj/structure/table_frame var/framestack = /obj/item/stack/rods var/buildstack = /obj/item/stack/sheet/metal @@ -364,7 +364,7 @@ icon_state = "rack" density = 1 anchored = 1.0 - throwpass = 1 //You can throw objects over this, despite it's density. + pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density. var/health = 5 /obj/structure/rack/ex_act(severity, target) diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 04c1128c9fb..c1a695be39c 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -191,10 +191,10 @@ Gunshots/explosions/opening doors/less rare audio (done) xeno = new(pump.loc,target) sleep(10) xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32) - xeno.throw_at(target,7,1) + xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1) sleep(10) xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32) - xeno.throw_at(pump,7,1) + xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1) sleep(10) var/xeno_name = xeno.name target << "[xeno_name] begins climbing into the ventilation system..." diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index e217683f129..1684d948211 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -1,5 +1,5 @@ -/mob/living/carbon/alien/hitby(atom/movable/AM, mob/thrower) - ..(AM, thrower, skip = 1) +/mob/living/carbon/alien/hitby(atom/movable/AM) + ..(AM, skip = 1) /*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. 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 e27983fd18d..61544e0f8ee 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -82,7 +82,7 @@ else //Maybe uses plasma in the future, although that wouldn't make any sense... leaping = 1 update_icons() - throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0) + throw_at(A,MAX_ALIEN_LEAP_DIST,1, spin=0, diagonals_first = 1) leaping = 0 update_icons() @@ -113,8 +113,6 @@ update_canmove() - - /mob/living/carbon/alien/humanoid/float(on) if(leaping) return diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 24f9192cca3..0af1f998eb7 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/hitby(atom/movable/AM, mob/thrower, skip) +/mob/living/carbon/hitby(atom/movable/AM, skip) if(!skip) //ugly, but easy if(in_throw_mode && !get_active_hand()) //empty active hand and we're in throw mode if(canmove && !restrained()) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index f1fa58c8509..392d741ae41 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -455,7 +455,7 @@ emp_act else ..() -/mob/living/carbon/human/hitby(atom/movable/AM, mob/thrower) +/mob/living/carbon/human/hitby(atom/movable/AM) if(throw_speed >= EMBED_THROWSPEED_THRESHOLD) if(istype(AM, /obj/item)) var/obj/item/I = AM diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4e47819cd1a..2bdfdb8dba2 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -52,7 +52,7 @@ Sorry Giacom. Please don't be mad :( //Generic Bump(). Override MobBump() and ObjBump() instead of this. /mob/living/Bump(atom/A, yes) - if(..()) //bumped by a thrown /atom/movable + if(..()) //we are thrown onto something return if (buckled || !yes || now_pushing) return diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 05711d54ae1..5e219f90060 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -44,13 +44,13 @@ else return 0 -/mob/living/throw_impact(atom/hit_atom, mob/thrower) +/mob/living/throw_impact(atom/hit_atom) . = ..() if(hit_atom.density) Weaken(1) take_organ_damage(10) -/mob/living/hitby(atom/movable/AM, mob/thrower) +/mob/living/hitby(atom/movable/AM) if(istype(AM, /obj/item)) var/obj/item/I = AM var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest @@ -77,10 +77,10 @@ "[src] has been hit by [I].") var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) apply_damage(I.throwforce, dtype, zone, armor, I) + if(I.thrownby) + add_logs(I.thrownby, src, "hit", object="[AM]") else playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) - if(thrower) - add_logs(thrower, src, "hit", object="[AM]") return ..() /mob/living/mech_melee_attack(obj/mecha/M) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index c4c24929e39..b76994178fe 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -79,7 +79,7 @@ reagents.handle_reactions() ..() -/obj/item/weapon/reagent_containers/throw_impact(atom/target,mob/thrower) +/obj/item/weapon/reagent_containers/throw_impact(atom/target) . = ..() if(!reagents.total_volume || !spillable) @@ -96,11 +96,11 @@ R += A.id + " (" R += num2text(A.volume) + ")," - if(thrower) - add_logs(thrower, M, "splashed", object="[R]") + if(thrownby) + add_logs(thrownby, M, "splashed", object="[R]") reagents.reaction(target, TOUCH) - else if((target.CanPass(src, get_turf(src))) && thrower && thrower.mind && thrower.mind.assigned_role == "Bartender") + else if((target.CanPass(src, get_turf(src))) && thrownby && thrownby.mind && thrownby.mind.assigned_role == "Bartender") visible_message("[src] lands onto the [target.name] without spilling a single drop.") return From 1bda2b65193e4ed10ccd005059e95482ac1ba6a6 Mon Sep 17 00:00:00 2001 From: phil235 Date: Sun, 19 Jul 2015 21:57:51 +0200 Subject: [PATCH 3/4] I hate fixing merge conflicts. --- code/modules/mob/living/living_defines.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 9dfe833a9e6..56c0426c5bc 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -45,6 +45,8 @@ var/list/pipes_shown = list() var/last_played_vent + var/smoke_delay = 0 //used to prevent spam with smoke reagent reaction on mob. + var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message" var/last_bumped = 0 From 2833f59f5fe3504ca61f6f7def9756eb2fcb4c81 Mon Sep 17 00:00:00 2001 From: phil235 Date: Sun, 19 Jul 2015 22:16:09 +0200 Subject: [PATCH 4/4] A typo and a forgotten thing to do. --- code/game/objects/items/toys.dm | 2 +- html/changelogs/phil235-CatchThrownPieFix.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 97fe27c8288..a340ca49274 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -77,7 +77,7 @@ for(var/atom/A in get_turf(hit_atom)) reagents.reaction(A) icon_state = "burst" - del(src) // Not qdel, because it would burst multiple times + qdel(src) /obj/item/toy/balloon/update_icon() if(src.reagents.total_volume >= 1) diff --git a/html/changelogs/phil235-CatchThrownPieFix.yml b/html/changelogs/phil235-CatchThrownPieFix.yml index 8b8f21081c2..4f467b01345 100644 --- a/html/changelogs/phil235-CatchThrownPieFix.yml +++ b/html/changelogs/phil235-CatchThrownPieFix.yml @@ -5,4 +5,4 @@ author: phil235 delete-after: True changes: - - tweak: "Thrown things no longer bounces off walls, unless they're in no gravity. Heavy items and mobs thrown can push the mobs and non anchored objects they land on. Throwing a mob onto a mob in no gravity will push each one in opposite direction. Thrown mobs landing on wall, or dense object or mob gets stunned and a bit injured. The damage when mob hit a wall is nerfed. + - tweak: "Thrown things no longer bounces off walls, unless they're in no gravity. Heavy items and mobs thrown can push the mobs and non anchored objects they land on. Throwing a mob onto a mob in no gravity will push each one in opposite direction. Thrown mobs landing on wall, or dense object or mob gets stunned and a bit injured. The damage when mob hit a wall is nerfed."