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().
This commit is contained in:
phil235
2015-07-19 21:29:35 +02:00
parent b570af6795
commit 9eced1ac5b
17 changed files with 79 additions and 82 deletions
+6 -5
View File
@@ -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
+5 -15
View File
@@ -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.
*/
+1 -2
View File
@@ -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))
+38 -24
View File
@@ -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
@@ -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
+5 -2
View File
@@ -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.
@@ -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
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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 << "<span class='notice'>[xeno_name] begins climbing into the ventilation system...</span>"
@@ -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.
@@ -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
@@ -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())
@@ -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
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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 @@
"<span class='userdanger'>[src] has been hit by [I].</span>")
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)
+4 -4
View File
@@ -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("<span class='notice'>[src] lands onto the [target.name] without spilling a single drop.</span>")
return