diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 49147dfe4d3..f313acf9ebc 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -110,6 +110,7 @@ // /atom/movable signals #define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" //from base of atom/movable/Moved(): (/atom) + #define COMPONENT_MOVABLE_BLOCK_PRE_MOVE 1 #define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) #define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm new file mode 100644 index 00000000000..4ceba907afd --- /dev/null +++ b/code/datums/components/tether.dm @@ -0,0 +1,37 @@ +/datum/component/tether + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/atom/tether_target + var/max_dist + var/tether_name + +/datum/component/tether/Initialize(atom/tether_target, max_dist = 4, tether_name) + if(!isliving(parent) || !istype(tether_target) || !tether_target.loc) + return COMPONENT_INCOMPATIBLE + src.tether_target = tether_target + src.max_dist = max_dist + if (ispath(tether_name, /atom)) + var/atom/tmp = tether_name + src.tether_name = initial(tmp.name) + else + src.tether_name = tether_name + RegisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE), .proc/checkTether) + +/datum/component/tether/proc/checkTether(mob/mover, newloc) + if (get_dist(mover,newloc) > max_dist) + to_chat(mover, "The [tether_name] runs out of slack and prevents you from moving!") + return COMPONENT_MOVABLE_BLOCK_PRE_MOVE + + var/atom/blocker + :out + for(var/turf/T in getline(tether_target,newloc)) + if (T.density) + blocker = T + break out + for(var/a in T) + var/atom/A = a + if(A.density && A != mover && A != tether_target) + blocker = A + break out + if (blocker) + to_chat(mover, "The [tether_name] catches on [blocker] and prevents you from moving!") + return COMPONENT_MOVABLE_BLOCK_PRE_MOVE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e9c370154cb..bed96e11d9d 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -223,8 +223,10 @@ if(!newloc.Enter(src, src.loc)) return + if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE) + return + // Past this is the point of no return - SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) var/atom/oldloc = loc var/area/oldarea = get_area(oldloc) var/area/newarea = get_area(newloc) diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 2f07a61e9ca..497a0c3310f 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -64,6 +64,7 @@ unsuitable_atmos_damage = 0 faction = list("hostile","vines","plants") var/list/grasping = list() + var/list/tethers = list() var/max_grasps = 4 var/grasp_chance = 20 var/grasp_pull_chance = 85 @@ -75,6 +76,8 @@ var/datum/beam/B = grasping[L] if(B) qdel(B) + for(var/datum/component/tether in tethers) + tether.RemoveComponent() grasping = null return ..() @@ -96,24 +99,31 @@ step(L,get_dir(L,src)) //reel them in L.Paralyze(60) //you can't get away now~ - if(grasping.len < max_grasps) + if(length(grasping) < max_grasps) grasping: for(var/mob/living/L in view(grasp_range, src)) - if(L == src || faction_check_mob(L) || (L in grasping) || L == target) + if(L == src || faction_check_mob(L) || L in grasping || L == target) continue - for(var/t in getline(src,L)) - for(var/a in t) - var/atom/A = a - if(A.density && A != L) + for(var/turf/T in getline(src,L)) + if (T.density) + continue grasping + for(var/obj/O in T) + if(O.density) continue grasping if(prob(grasp_chance)) to_chat(L, "\The [src] has you entangled!") grasping[L] = Beam(L, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine) - + tethers += list(L.AddComponent(/datum/component/tether, src, grasp_range+1, /obj/effect/ebeam/vine), AddComponent(/datum/component/tether, L, grasp_range+1, /obj/effect/ebeam/vine)) break //only take 1 new victim per cycle /mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target) + for(var/turf/T in getline(src,target)) + if (T.density) + return + for(var/obj/O in T) + if(O.density) + return var/dist = get_dist(src,the_target) Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine) the_target.attack_animal(src) diff --git a/tgstation.dme b/tgstation.dme index f32f294e0bd..c8e47347142 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -379,6 +379,7 @@ #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" #include "code\datums\components\swarming.dm" +#include "code\datums\components\tether.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\waddling.dm"