mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
193 lines
6.8 KiB
Plaintext
193 lines
6.8 KiB
Plaintext
/datum/tether
|
|
var/atom/movable/master //Used only to reference the actual, original master
|
|
var/atom/movable/effective_master //Used to reference either the actual master or its holder at turf level
|
|
var/atom/movable/slave //Used only to reference the actual, original slave
|
|
var/atom/movable/effective_slave //Used to reference either the actual slave or its holder at turf level
|
|
var/tether_distance //On a master-slave tether, how far apart the two can be before the slave is either prohibited from moving or pulled by the master.
|
|
//On an equal tether, how far apart the two can be before whichever one that moves pulls the other.
|
|
/datum/tether/proc/break_tether()
|
|
master.on_tether_broken(slave)
|
|
slave.on_tether_broken(master)
|
|
qdel(src)
|
|
|
|
/datum/tether/proc/make_tether(atom/movable/M, atom/movable/S, var/distance)
|
|
tether_distance = distance
|
|
master = M
|
|
effective_master = master
|
|
slave = S
|
|
effective_slave = slave
|
|
master.register_event(/event/moved, src, .proc/master_moved)
|
|
master.register_event(/event/moved, src, .proc/slave_moved)
|
|
if(!master.current_tethers)
|
|
master.current_tethers = list()
|
|
master.current_tethers.Add(src)
|
|
if(!slave.current_tethers)
|
|
slave.current_tethers = list()
|
|
slave.current_tethers.Add(src)
|
|
|
|
/datum/tether/Destroy()
|
|
if(effective_master != master)
|
|
effective_master.unregister_event(/event/moved, src, .proc/master_moved)
|
|
effective_master.current_tethers.Remove(src)
|
|
effective_master = null
|
|
master.unregister_event(/event/moved, src, .proc/master_moved)
|
|
master.current_tethers.Remove(src)
|
|
master = null
|
|
if(effective_slave != slave)
|
|
effective_slave.unregister_event(/event/moved, src, .proc/slave_moved)
|
|
effective_slave.current_tethers.Remove(src)
|
|
effective_slave = null
|
|
slave.unregister_event(/event/moved, src, .proc/slave_moved)
|
|
slave.current_tethers.Remove(src)
|
|
slave = null
|
|
..()
|
|
|
|
/datum/tether/proc/check_distance()
|
|
if(get_exact_dist(effective_master, effective_slave) > tether_distance)
|
|
return 0
|
|
return 1
|
|
|
|
/datum/tether/proc/check_breakage_distance()
|
|
if(get_exact_dist(effective_master, effective_slave) > tether_distance+5) //A small buffer is added to account for the master moving before the slave catches up and such.
|
|
return 0
|
|
return 1
|
|
|
|
/datum/tether/proc/master_moved()
|
|
if(effective_master != master)
|
|
if(!isturf(effective_master.loc) || isturf(master.loc))
|
|
effective_master.unregister_event(/event/moved, src, .proc/master_moved)
|
|
effective_master.current_tethers.Remove(src)
|
|
effective_master = master
|
|
if(!isturf(master.loc) && effective_master == master)
|
|
effective_master = get_holder_at_turf_level(master)
|
|
effective_master.register_event(/event/moved, src, .proc/master_moved)
|
|
if(!effective_master.current_tethers)
|
|
effective_master.current_tethers = list()
|
|
effective_master.current_tethers.Add(src)
|
|
if(!check_breakage_distance())
|
|
break_tether()
|
|
|
|
rein_in_slave()
|
|
|
|
/datum/tether/proc/slave_moved()
|
|
if(effective_slave != slave)
|
|
if(!isturf(effective_slave.loc) || isturf(slave.loc))
|
|
effective_slave.unregister_event(/event/moved, src, .proc/slave_moved)
|
|
effective_slave.current_tethers.Remove(src)
|
|
effective_slave = slave
|
|
if(!isturf(slave.loc) && effective_slave == slave)
|
|
effective_slave = get_holder_at_turf_level(slave)
|
|
effective_slave.register_event(/event/moved, src, .proc/slave_moved)
|
|
if(!effective_slave.current_tethers)
|
|
effective_slave.current_tethers = list()
|
|
effective_slave.current_tethers.Add(src)
|
|
if(!check_breakage_distance())
|
|
break_tether()
|
|
|
|
/datum/tether/proc/rein_in_slave()
|
|
while(!check_distance())
|
|
if(!step_to(effective_slave,effective_master))
|
|
break_tether()
|
|
break
|
|
|
|
/datum/tether/master_slave/make_tether(atom/movable/M, atom/movable/S, var/distance) //With a master-slave tether, the slave is incapable of moving or being moved farther from its master than the tether allows.
|
|
S.tether_master = M //If its master moves out of range, the slave is pulled along.
|
|
if(!M.tether_slaves)
|
|
M.tether_slaves = list()
|
|
M.tether_slaves.Add(S)
|
|
..()
|
|
|
|
/datum/tether/master_slave/Destroy()
|
|
slave.tether_master = null
|
|
master.tether_slaves.Remove(slave)
|
|
..()
|
|
|
|
/datum/tether/equal/make_tether(atom/movable/M, atom/movable/S, var/distance) //An equal tether functions like a master-slave tether, however both the master and slave are capable of pulling each other.
|
|
M.tether_master = S
|
|
S.tether_master = M
|
|
..()
|
|
|
|
/datum/tether/equal/slave_moved()
|
|
..()
|
|
rein_in_master()
|
|
|
|
/datum/tether/equal/proc/rein_in_master()
|
|
while(!check_distance())
|
|
if(!step_to(effective_master,effective_slave))
|
|
break_tether()
|
|
break
|
|
|
|
/datum/tether/equal/Destroy()
|
|
master.tether_master = null
|
|
slave.tether_master = null
|
|
..()
|
|
|
|
/datum/tether/equal/restrictive //A restrictive equal tether disallows pulling from either side. If either the master or slave attempts to exceed the tether's distance, they simply fail.
|
|
|
|
/proc/tether_equal(atom/movable/first, atom/movable/second, var/distance, var/restrictive = FALSE)
|
|
if(!istype(first) || !istype(second) || !distance)
|
|
return FALSE
|
|
if(first.tether_master || second.tether_master) //an atom can only have a single master or equal tether
|
|
return FALSE
|
|
var/datum/tether/equal/E
|
|
if(restrictive)
|
|
E = new /datum/tether/equal/restrictive()
|
|
else
|
|
E = new()
|
|
E.make_tether(first,second,distance)
|
|
return TRUE
|
|
|
|
/proc/tether_equal_restrictive(atom/movable/first, atom/movable/second, var/distance)
|
|
return tether_equal(first, second, distance, TRUE)
|
|
|
|
/proc/tether_master_slave(atom/movable/M, atom/movable/S, var/distance)
|
|
if(!istype(M) || !istype(S) || !distance)
|
|
return FALSE
|
|
if(S.tether_master) //an atom can only have a single master or equal tether
|
|
return FALSE
|
|
var/datum/tether/master_slave/T = new()
|
|
T.make_tether(M,S,distance)
|
|
return TRUE
|
|
|
|
//Uncomment for easy testing of tethers.
|
|
/*
|
|
/obj/item/tether_maker
|
|
name = "tether maker"
|
|
icon_state = "spacecash20"
|
|
var/mode = 0
|
|
|
|
/obj/item/tether_maker/attack_self(mob/user)
|
|
mode++
|
|
if(mode > 4)
|
|
mode = 0
|
|
if(mode == 0)
|
|
to_chat(user, "Will now break tethers.")
|
|
if(mode == 1)
|
|
to_chat(user, "Will now create equal tethers.")
|
|
if(mode == 2)
|
|
to_chat(user, "Will now create restrictive equal tethers.")
|
|
if(mode == 3)
|
|
to_chat(user, "Will now create master-slave tethers.")
|
|
if(mode == 4)
|
|
to_chat(user, "Will now create slave-master tethers.")
|
|
|
|
/obj/item/tether_maker/afterattack(atom/movable/A, mob/living/user)
|
|
if(!istype(A))
|
|
return
|
|
if(mode == 0)
|
|
A.break_all_tethers()
|
|
to_chat(user, "All \the [A]'s tethers are now broken.")
|
|
if(mode == 1)
|
|
tether_equal(user, A, 7)
|
|
to_chat(user, "You and \the [A] are now tethered.")
|
|
if(mode == 2)
|
|
tether_equal_restrictive(user, A, 7)
|
|
to_chat(user, "You and \the [A] are now restrictively tethered.")
|
|
if(mode == 3)
|
|
tether_master_slave(user, A, 7)
|
|
to_chat(user, "\The [A] is now tethered to you.")
|
|
if(mode == 4)
|
|
tether_master_slave(A, user, 7)
|
|
to_chat(user, "You are now tethered to \the [A].")
|
|
*/
|