mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Merge pull request #10598 from phil235/CatchThrownPieFix
Changes to throwing
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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(target_dir, border_only, 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.
|
||||
*/
|
||||
+4
-25
@@ -6,8 +6,6 @@
|
||||
var/list/fingerprintshidden
|
||||
var/fingerprintslast = null
|
||||
var/list/blood_DNA
|
||||
var/last_bumped = 0
|
||||
var/throwpass = 0
|
||||
|
||||
///Chemistry.
|
||||
var/datum/reagents/reagents = null
|
||||
@@ -50,26 +48,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)
|
||||
@@ -280,9 +258,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, 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()
|
||||
|
||||
|
||||
+67
-46
@@ -93,12 +93,12 @@
|
||||
/atom/movable/Crossed(atom/movable/AM)
|
||||
return
|
||||
|
||||
/atom/movable/Bump(var/atom/A as mob|obj|turf|area, yes)
|
||||
if(throwing)
|
||||
throw_impact(A)
|
||||
throwing = 0
|
||||
if ((A && yes))
|
||||
A.last_bumped = world.time
|
||||
/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
|
||||
throw_impact(A)
|
||||
. = 1
|
||||
A.Bumped(src)
|
||||
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
if(!direction)
|
||||
return 1
|
||||
|
||||
|
||||
var/old_dir = dir
|
||||
. = step(src, direction)
|
||||
dir = old_dir
|
||||
@@ -151,70 +150,92 @@
|
||||
/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)
|
||||
return hit_atom.hitby(src)
|
||||
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, var/spin = 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, 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
|
||||
|
||||
src.throwing = 1
|
||||
if(spin) // turns out 1000+ spinning objects being thrown at the singularity creates lag - Iamgoofball
|
||||
throwing = 1
|
||||
if(spin) //if we don't want the /atom/movable to spin.
|
||||
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;
|
||||
var/pure_diagonal = 0
|
||||
if(dist_x == dist_y)
|
||||
pure_diagonal = 1
|
||||
|
||||
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/finalturf = get_turf(target)
|
||||
var/hit = 0
|
||||
|
||||
var/atom/step = get_step(src, (error < 0) ? tdy : tdx)
|
||||
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, 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
|
||||
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) // we hit something during our move
|
||||
hit = 1
|
||||
break
|
||||
dist_travelled++
|
||||
dist_since_sleep++
|
||||
if(dist_since_sleep >= speed)
|
||||
dist_since_sleep = 0
|
||||
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)
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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"
|
||||
@@ -44,13 +33,3 @@
|
||||
density = 1
|
||||
unacidable = 1
|
||||
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
|
||||
@@ -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("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
|
||||
@@ -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("<span class='danger'>[M] is knocked right off \his feet!</span>", 3)
|
||||
@@ -421,7 +422,6 @@
|
||||
icon_state = "hoop"
|
||||
anchored = 1
|
||||
density = 1
|
||||
throwpass = 1
|
||||
|
||||
/obj/structure/holohoop/attackby(obj/item/weapon/W, mob/user, params)
|
||||
if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ var/const/SAFETY_COOLDOWN = 100
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if(!anchored)
|
||||
return
|
||||
if(safety_mode)
|
||||
return
|
||||
|
||||
|
||||
@@ -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("<span class='danger'>[AM] sets off \icon[src] [src]!</span>")
|
||||
triggermine(AM)
|
||||
triggermine(AM)
|
||||
|
||||
/obj/effect/mine/proc/triggermine(mob/victim)
|
||||
if(triggered)
|
||||
return
|
||||
visible_message("<span class='danger'>[victim] sets off \icon[src] [src]!</span>")
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
|
||||
+11
-18
@@ -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
|
||||
@@ -469,26 +471,17 @@ 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)
|
||||
var/itempush = 1
|
||||
if(w_class < 4)
|
||||
itempush = 0 //too light to push anything
|
||||
return A.hitby(src,thrownby, 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("<span class='danger'>\the [name] embeds itself in [H]'s [L.getDisplayName()]!</span>","<span class='userdanger'>\the [name] embeds itself in your [L.getDisplayName()]!</span>")
|
||||
return
|
||||
|
||||
//Reset regardless of if we hit a human.
|
||||
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1)
|
||||
thrownby = thrower
|
||||
. = ..()
|
||||
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)
|
||||
|
||||
@@ -44,41 +44,40 @@
|
||||
|
||||
/obj/item/toy/balloon/afterattack(atom/A as mob|obj, mob/user, proximity)
|
||||
if(!proximity) return
|
||||
if (istype(A, /obj/structure/reagent_dispensers/watertank) && get_dist(src,A) <= 1)
|
||||
A.reagents.trans_to(src, 10)
|
||||
user << "<span class='notice'>You fill the balloon with the contents of [A].</span>"
|
||||
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 << "<span class='warning'>[RD] is empty.</span>"
|
||||
else if(reagents.total_volume >= 10)
|
||||
user << "<span class='warning'>[src] is full.</span>"
|
||||
else
|
||||
A.reagents.trans_to(src, 10)
|
||||
user << "<span class='notice'>You fill the balloon with the contents of [A].</span>"
|
||||
desc = "A translucent balloon with some form of liquid sloshing around in it."
|
||||
update_icon()
|
||||
|
||||
/obj/item/toy/balloon/attackby(obj/O, mob/user, params)
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
if(O.reagents)
|
||||
if(O.reagents.total_volume < 1)
|
||||
user << "<span class='notice'>The [O] is empty.</span>"
|
||||
else if(O.reagents.total_volume >= 1)
|
||||
if(O.reagents.has_reagent("facid", 1))
|
||||
user << "<span class='warning'>The acid chews through the balloon!</span>"
|
||||
O.reagents.reaction(user)
|
||||
qdel(src)
|
||||
else
|
||||
src.desc = "A translucent balloon with some form of liquid sloshing around in it."
|
||||
user << "<span class='notice'>You fill the balloon with the contents of [O].</span>"
|
||||
O.reagents.trans_to(src, 10)
|
||||
src.update_icon()
|
||||
return
|
||||
if(O.reagents.total_volume <= 0)
|
||||
user << "<span class='warning'>[O] is empty.</span>"
|
||||
else if(reagents.total_volume >= 10)
|
||||
user << "<span class='warning'>[src] is full.</span>"
|
||||
else
|
||||
desc = "A translucent balloon with some form of liquid sloshing around in it."
|
||||
user << "<span class='notice'>You fill the balloon with the contents of [O].</span>"
|
||||
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("<span class='danger'>\The [src] bursts!</span>","<span class='italics'>You hear a pop and a splash.</span>")
|
||||
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("<span class='danger'>[src] bursts!</span>","<span class='italics'>You hear a pop and a splash.</span>")
|
||||
reagents.reaction(get_turf(hit_atom))
|
||||
for(var/atom/A in get_turf(hit_atom))
|
||||
reagents.reaction(A)
|
||||
icon_state = "burst"
|
||||
qdel(src)
|
||||
|
||||
/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("<span class='suicide'>The [src.name] explodes!</span>","<span class='italics'>You hear a snap!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(loc)
|
||||
visible_message("<span class='warning'>The [src.name] explodes!</span>","<span class='italics'>You hear a snap!</span>")
|
||||
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
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
/obj/item/weapon/dice/attack_self(mob/user)
|
||||
diceroll(user)
|
||||
|
||||
/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/user)
|
||||
/obj/item/weapon/dice/throw_at(atom/target, range, speed, mob/user, spin=1)
|
||||
if(!..())
|
||||
return
|
||||
diceroll(user)
|
||||
|
||||
@@ -79,15 +79,20 @@
|
||||
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
|
||||
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)
|
||||
step(M, dir)
|
||||
if(throwing)
|
||||
throwing = 0
|
||||
|
||||
/obj/structure/closet/proc/take_contents()
|
||||
|
||||
@@ -100,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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,8 +9,3 @@
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
if(damtype == "brute")
|
||||
hitsound = "swing_hit"
|
||||
|
||||
/obj/item/weapon/Bump(mob/M)
|
||||
spawn(0)
|
||||
..()
|
||||
return
|
||||
@@ -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)
|
||||
@@ -232,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>"
|
||||
|
||||
@@ -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, mob/user, params)
|
||||
if(istype( W, /obj/item/toy/crayon ))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.","<span class='italics'>You hear a smack.</span>")
|
||||
var/turf/T = get_turf(target)
|
||||
new splat(T)
|
||||
visible_message("The [src.name] has been squashed.","<span class='italics'>You hear a smack.</span>")
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/mob/living/carbon/alien/hitby(atom/movable/AM)
|
||||
..(AM, 1)
|
||||
..(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,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, diagonals_first = 1)
|
||||
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,19 @@
|
||||
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("<span class ='danger'>[src] smashes into [A]!</span>", "<span class ='alertalien'>[src] smashes into [A]!</span>")
|
||||
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
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
put_in_active_hand(I)
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>")
|
||||
throw_mode_off()
|
||||
return
|
||||
..()
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
@@ -455,4 +455,18 @@ emp_act
|
||||
else
|
||||
..()
|
||||
|
||||
return
|
||||
/mob/living/carbon/human/hitby(atom/movable/AM)
|
||||
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("<span class='danger'>\the [I.name] embeds itself in [src]'s [L.getDisplayName()]!</span>","<span class='userdanger'>\the [I.name] embeds itself in your [L.getDisplayName()]!</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(..()) //we are thrown onto something
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
if(hit_atom.density)
|
||||
Weaken(1)
|
||||
take_organ_damage(10)
|
||||
|
||||
/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
|
||||
@@ -71,9 +77,11 @@
|
||||
"<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(thrower)
|
||||
add_logs(thrower, src, "hit", I)
|
||||
if(I.thrownby)
|
||||
add_logs(I.thrownby, src, "hit", I)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1)
|
||||
return ..()
|
||||
|
||||
/mob/living/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == "harm")
|
||||
|
||||
@@ -47,4 +47,6 @@
|
||||
|
||||
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/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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
/obj/machinery/field/containment/Crossed(obj/mover)
|
||||
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(master1,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 @@
|
||||
"<span class='italics'>You hear an electrical crack.</span>")
|
||||
|
||||
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()
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -79,8 +79,8 @@
|
||||
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)
|
||||
return
|
||||
@@ -96,12 +96,11 @@
|
||||
R += A.id + " ("
|
||||
R += num2text(A.volume) + "),"
|
||||
|
||||
|
||||
if(thrownby)
|
||||
add_logs(thrownby, M, "splashed", R)
|
||||
reagents.reaction(target, TOUCH)
|
||||
if(thrower)
|
||||
add_logs(thrower, M, "splashed", R)
|
||||
|
||||
else if((!target.density || target.throwpass) && 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
|
||||
|
||||
|
||||
@@ -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("<span class='notice'>[src] fizzles and disappears upon impact!</span>")
|
||||
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("<span class='notice'>[src] fizzles and disappears upon impact!</span>")
|
||||
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.
|
||||
|
||||
|
||||
@@ -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."
|
||||
Reference in New Issue
Block a user