mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 02:09:41 +00:00
[MIRROR] Motion tracker subsystem (#10232)
Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
775c8313f3
commit
dba0bf4304
@@ -270,6 +270,9 @@
|
||||
#define HEARING_SPANS 6
|
||||
#define HEARING_MESSAGE_MODE 7 */
|
||||
|
||||
///from /datum/controller/subsystem/motion_tracker/notice() (/datum/weakref/source_atom,/turf/echo_turf_location)
|
||||
#define COMSIG_MOVABLE_MOTIONTRACKER "move_motiontracker"
|
||||
|
||||
///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
|
||||
#define COMSIG_MOVABLE_DISPOSING "movable_disposing"
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
|
||||
#define FIRE_PRIORITY_NIGHTSHIFT 5
|
||||
#define FIRE_PRIORITY_PLANTS 5
|
||||
#define FIRE_PRIORITY_VIS 5
|
||||
#define FIRE_PRIORITY_MOTIONTRACKER 6
|
||||
#define FIRE_PRIORITY_ORBIT 7
|
||||
#define FIRE_PRIORITY_VOTE 8
|
||||
#define FIRE_PRIORITY_INSTRUMENTS 9
|
||||
|
||||
83
code/controllers/subsystems/motion_tracker.dm
Normal file
83
code/controllers/subsystems/motion_tracker.dm
Normal file
@@ -0,0 +1,83 @@
|
||||
SUBSYSTEM_DEF(motiontracker)
|
||||
name = "Motion Tracker"
|
||||
priority = FIRE_PRIORITY_MOTIONTRACKER
|
||||
wait = 1 SECOND
|
||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||
flags = SS_NO_INIT
|
||||
var/min_range = 2
|
||||
var/max_range = 8
|
||||
var/all_echos_round = 0
|
||||
var/all_pings_round = 0
|
||||
var/list/queued_echo_turfs = list()
|
||||
var/list/currentrun = list()
|
||||
var/list/expended_echos = list()
|
||||
|
||||
/datum/controller/subsystem/motiontracker/stat_entry(msg)
|
||||
var/count = 0
|
||||
if(_listen_lookup)
|
||||
var/list/track_list = _listen_lookup[COMSIG_MOVABLE_MOTIONTRACKER]
|
||||
if(islist(track_list))
|
||||
count = track_list.len
|
||||
else
|
||||
count = 1 // listen_lookup optimizes single entries into just returning the only thing
|
||||
msg = "L: [count] | Q: [queued_echo_turfs.len] | A: [all_echos_round]/[all_pings_round]"
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/motiontracker/fire(resumed = 0)
|
||||
if(!resumed)
|
||||
src.currentrun = queued_echo_turfs.Copy()
|
||||
expended_echos.Cut()
|
||||
while(currentrun.len)
|
||||
var/key = currentrun[1] // Because using an index into an associative array gets the key at that index... I hate you byond.
|
||||
var/list/data = currentrun[key]
|
||||
var/datum/weakref/AF= data[1]
|
||||
var/datum/weakref/RF= data[2]
|
||||
var/count = data[3]
|
||||
var/list/clients = data[4]
|
||||
var/turf/At = AF?.resolve()
|
||||
var/turf/Rt = RF?.resolve()
|
||||
if(Rt && At && count)
|
||||
while(count-- > 0)
|
||||
// Place at root turf offset from signal responder's turf using px offsets. So it will show up over visblocking.
|
||||
var/image/motion_echo/E = new /image/motion_echo('icons/effects/effects.dmi', Rt, "motion_echo", OBFUSCATION_LAYER, SOUTH)
|
||||
E.place_from_root(At)
|
||||
for(var/datum/weakref/C in clients)
|
||||
E.append_client(C)
|
||||
currentrun.Remove(key)
|
||||
expended_echos[key] = data
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
// Removed used keys, incase the current queue grew while we were processing this one
|
||||
queued_echo_turfs -= expended_echos
|
||||
|
||||
// We get this from anything in the world that would cause a motion tracker ping
|
||||
// From sounds to motions, to mob attacks. This then sends a signal to anyone listening.
|
||||
/datum/controller/subsystem/motiontracker/proc/ping(var/atom/source, var/hear_chance = 30)
|
||||
var/turf/T = get_turf(source)
|
||||
if(!isturf(T)) // ONLY call from turfs
|
||||
return
|
||||
if(!prob(hear_chance))
|
||||
return
|
||||
if(hear_chance <= 40)
|
||||
T = get_step(T,pick(cardinal))
|
||||
if(!T) // incase...
|
||||
return
|
||||
// Echo time, we have a turf
|
||||
if(queued_echo_turfs[REF(T)]) // Already echoing
|
||||
return
|
||||
all_pings_round++
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_MOTIONTRACKER, WEAKREF(source), T)
|
||||
|
||||
// We get this back from anything that handles the signal, and queues up a turf to draw the echo on
|
||||
// The logic is in the SIGNAL HANDLER for if it does anything at all with the signal instead of assuming
|
||||
// everything wants effects drawn, for example the motion tracker item just flicks() and doesn't call this.
|
||||
/datum/controller/subsystem/motiontracker/proc/queue_echo(var/turf/Rt,var/turf/At,var/echo_count = 1,var/datum/weakref/client)
|
||||
if(!Rt || !At || !client)
|
||||
return
|
||||
var/rfe = REF(At)
|
||||
if(!queued_echo_turfs[rfe]) // We only care about the final turf, not the root turf for duping
|
||||
queued_echo_turfs[rfe] = list(WEAKREF(At),WEAKREF(Rt),echo_count,list(client))
|
||||
all_echos_round++
|
||||
else
|
||||
var/list/data = queued_echo_turfs[rfe]
|
||||
data[4] += list(client)
|
||||
@@ -1339,6 +1339,8 @@ About the new airlock wires panel:
|
||||
if(T && T.z == get_z(src))
|
||||
M.playsound_local(get_turf(src), sound, volume, 1, null, 0, TRUE, sound(sound), volume_channel = VOLUME_CHANNEL_DOORS)
|
||||
|
||||
SSmotiontracker.ping(src,100)
|
||||
|
||||
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
|
||||
src.closeOther.close()
|
||||
return ..()
|
||||
@@ -1473,6 +1475,9 @@ About the new airlock wires panel:
|
||||
if(distance <= world.view * 2)
|
||||
if(T && T.z == get_z(src))
|
||||
M.playsound_local(get_turf(src), sound, volume, 1, null, 0, TRUE, sound(sound), volume_channel = VOLUME_CHANNEL_DOORS)
|
||||
|
||||
SSmotiontracker.ping(src,100)
|
||||
|
||||
for(var/turf/turf in locs)
|
||||
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
|
||||
if(killthis)
|
||||
|
||||
@@ -141,6 +141,7 @@
|
||||
domutcheck(M,null)
|
||||
M.UpdateAppearance()
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
@@ -158,6 +159,7 @@
|
||||
if(istype(M))
|
||||
M.Stun(30)
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
@@ -173,6 +175,7 @@
|
||||
if(!target.blocks_air)
|
||||
target.assume_gas(GAS_N2O, 30)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
@@ -188,6 +191,7 @@
|
||||
target.assume_gas(GAS_PHORON, 30)
|
||||
target.hotspot_expose(1000, CELL_VOLUME)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
@@ -229,6 +233,7 @@
|
||||
return
|
||||
src.fragmentate(O, 20, 7, list(/obj/item/projectile/bullet/pellet/fragment)) //only 20 weak fragments because you're stepping directly on it
|
||||
visible_message("\The [src.name] detonates!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
@@ -258,6 +263,7 @@
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
visible_message("\The [src.name] flashes violently before disintegrating!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
empulse(loc, 2, 4, 7, 10, 1) // As strong as an EMP grenade
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
@@ -279,6 +285,7 @@
|
||||
M.adjust_fire_stacks(5)
|
||||
M.fire_act()
|
||||
visible_message("\The [src.name] bursts into flames!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
spawn(0)
|
||||
qdel(src)
|
||||
|
||||
@@ -300,6 +307,7 @@
|
||||
else
|
||||
explosion(loc, 0, 0, 2, 2)
|
||||
visible_message("\The [src.name] detonates!")
|
||||
SSmotiontracker.ping(src,100)
|
||||
|
||||
qdel(s)
|
||||
qdel(src)
|
||||
|
||||
27
code/game/objects/effects/motion_echo.dm
Normal file
27
code/game/objects/effects/motion_echo.dm
Normal file
@@ -0,0 +1,27 @@
|
||||
/image/motion_echo
|
||||
plane = PLANE_FULLSCREEN
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
appearance_flags = (RESET_COLOR|PIXEL_SCALE|KEEP_APART)
|
||||
var/list/clients = list()
|
||||
|
||||
/image/motion_echo/New(icon, loc, icon_state, layer, dir)
|
||||
. = ..()
|
||||
QDEL_IN(src, 2 SECONDS)
|
||||
|
||||
/image/motion_echo/proc/place_from_root(var/turf/At)
|
||||
var/rand_limit = 12
|
||||
pixel_x += ((At.x - loc.x) * 32) + rand(-rand_limit,rand_limit)
|
||||
pixel_y += ((At.y - loc.y) * 32) + rand(-rand_limit,rand_limit)
|
||||
|
||||
/image/motion_echo/proc/append_client(var/datum/weakref/C)
|
||||
var/client/CW = C?.resolve()
|
||||
if(CW)
|
||||
CW.images += src
|
||||
clients.Add(C)
|
||||
|
||||
/image/motion_echo/Destroy(force)
|
||||
. = ..()
|
||||
for(var/datum/weakref/C in clients)
|
||||
var/client/CW = C?.resolve()
|
||||
if(CW)
|
||||
CW.images -= src
|
||||
@@ -223,6 +223,7 @@
|
||||
|
||||
if(prob(50))
|
||||
src.visible_message(span_notice("You hear something squeezing through the ventilation ducts."),2)
|
||||
SSmotiontracker.ping(src,10)
|
||||
sleep(travel_time)
|
||||
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
@@ -269,6 +270,7 @@
|
||||
walk_to(src, target_atom, 5)
|
||||
if(prob(25))
|
||||
src.visible_message(span_notice("\The [src] skitters[pick(" away"," around","")]."))
|
||||
SSmotiontracker.ping(src,10)
|
||||
else if(amount_grown < 75 && prob(5))
|
||||
//vent crawl!
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
|
||||
|
||||
49
code/game/objects/items/devices/scanners/motion_tracker.dm
Normal file
49
code/game/objects/items/devices/scanners/motion_tracker.dm
Normal file
@@ -0,0 +1,49 @@
|
||||
/obj/item/motiontracker
|
||||
name = "Motion Tracker"
|
||||
desc = "The \"Vibromaster V1.7\", a handheld motion tracker. Often picks up nearby vibrations as motion however."
|
||||
icon = 'icons/obj/device_alt.dmi'
|
||||
icon_state = "pinoff"
|
||||
item_state = "analyzer"
|
||||
w_class = ITEMSIZE_SMALL
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 5
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
|
||||
matter = list(MAT_STEEL = 30,MAT_GLASS = 20)
|
||||
origin_tech = list(TECH_MAGNET = 1, TECH_DATA = 1)
|
||||
|
||||
pickup_sound = 'sound/items/pickup/device.ogg'
|
||||
drop_sound = 'sound/items/drop/device.ogg'
|
||||
|
||||
/obj/item/motiontracker/Initialize(mapload)
|
||||
RegisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER, PROC_REF(handle_motion_tracking))
|
||||
. = ..()
|
||||
|
||||
/obj/item/motiontracker/Destroy(force, ...)
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.motiontracker_subscribe()
|
||||
UnregisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER)
|
||||
. = ..()
|
||||
|
||||
/obj/item/motiontracker/proc/handle_motion_tracking(mob/source, var/datum/weakref/RW, var/turf/T)
|
||||
SIGNAL_HANDLER
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
PRIVATE_PROC(TRUE)
|
||||
var/atom/echo_source = RW?.resolve()
|
||||
var/atom/scan_pos = src
|
||||
if(!isturf(loc))
|
||||
scan_pos = loc
|
||||
if(!echo_source || get_dist(scan_pos,echo_source) > SSmotiontracker.max_range || scan_pos.z != echo_source.z)
|
||||
return
|
||||
flick("pinondirect",src)
|
||||
|
||||
/obj/item/motiontracker/Moved(atom/old_loc, direction, forced, movetime)
|
||||
. = ..()
|
||||
if(ismob(old_loc))
|
||||
var/mob/M = old_loc
|
||||
M.motiontracker_unsubscribe()
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.motiontracker_subscribe()
|
||||
@@ -87,6 +87,7 @@
|
||||
var/turf/T = get_turf(src)
|
||||
if(T)
|
||||
T.hotspot_expose(700,125)
|
||||
SSmotiontracker.ping(src,100)
|
||||
|
||||
|
||||
/obj/item/grenade/attackby(obj/item/W as obj, mob/user as mob)
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
span_danger("You step on \the [src]!"),
|
||||
span_infoplain(span_bold("You hear a loud metallic snap!"))
|
||||
)
|
||||
SSmotiontracker.ping(src,100) // Clunk!
|
||||
attack_mob(L)
|
||||
if(!has_buckled_mobs())
|
||||
anchored = FALSE
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
if(!ignore_walls && !can_see(turf_source, T, length = maxdistance * 2))
|
||||
continue
|
||||
|
||||
SSmotiontracker.ping(source,vol) // Nearly everything pings this, the quieter the less likely
|
||||
M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, channel, pressure_affected, S, preference, volume_channel)
|
||||
|
||||
/mob/proc/check_sound_preference(list/preference)
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
src.visible_message(span_infoplain(span_bold("\The [src.name]") + " [deathmessage]"))
|
||||
|
||||
set_stat(DEAD)
|
||||
SSmotiontracker.ping(src,80)
|
||||
|
||||
update_canmove()
|
||||
|
||||
|
||||
@@ -195,18 +195,14 @@
|
||||
var/obj/item/clothing/glasses/V = rig.visor.vision.glasses
|
||||
compiled_vis |= V.enables_planes
|
||||
|
||||
//VOREStation Add - NIF Support
|
||||
if(nif)
|
||||
compiled_vis |= nif.planes_visible()
|
||||
//event hud
|
||||
if(vantag_hud)
|
||||
compiled_vis |= VIS_CH_VANTAG
|
||||
//VOREStation Add End
|
||||
|
||||
//Vore Stomach addition start. This goes here.
|
||||
if(stomach_vision)
|
||||
compiled_vis += VIS_CH_STOMACH
|
||||
//Vore Stomach addition end
|
||||
|
||||
//CHOMPAdd Start Soulcatcher
|
||||
if(soulgem?.flag_check(SOULGEM_SEE_SR_SOULS))
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
var/emp_dmg_mod = 1 // Multiplier to all EMP damage sustained by the mob, if it's EMP-sensitive
|
||||
var/emp_stun_mod = 1 // Multiplier to all EMP disorient/etc. sustained by the mob, if it's EMP-sensitive
|
||||
var/vision_flags = SEE_SELF // Same flags as glasses.
|
||||
var/has_vibration_sense = FALSE // Motion tracker subsystem
|
||||
|
||||
// Death vars.
|
||||
var/meat_type = /obj/item/reagent_containers/food/snacks/meat/human
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
base_species = "Xenochimera"
|
||||
selects_bodytype = SELECTS_BODYTYPE_CUSTOM
|
||||
digi_allowed = TRUE
|
||||
has_vibration_sense = TRUE
|
||||
|
||||
num_alternate_languages = 3
|
||||
species_language = null
|
||||
@@ -26,7 +27,7 @@
|
||||
icobase_tail = 1
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/reconstitute_form,
|
||||
/mob/living/carbon/human/proc/sonar_ping,
|
||||
///mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/carbon/human/proc/tie_hair,
|
||||
/mob/living/carbon/human/proc/lick_wounds,
|
||||
/mob/living/carbon/human/proc/shapeshifter_reassemble) //Xenochimera get all the special verbs since they can't select traits.
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
mob_size = MOB_SMALL
|
||||
pass_flags = PASSTABLE
|
||||
holder_type = /obj/item/holder/micro //CHOMPEdit from holder/human to holder/micro
|
||||
// short_sighted = 1 CHOMPEdit: We're fine without near-sightedness for now.
|
||||
// short_sighted = 1
|
||||
has_vibration_sense = TRUE
|
||||
gluttonous = 1
|
||||
blood_volume = 400
|
||||
hunger_factor = 0.2
|
||||
@@ -141,7 +142,7 @@
|
||||
)
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/sonar_ping,
|
||||
///mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/proc/hide
|
||||
)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ End Chomp Edit */
|
||||
vore_belly_default_variant = "T" //Teshari belly sprite
|
||||
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/sonar_ping,
|
||||
///mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/proc/hide,
|
||||
/mob/living/proc/toggle_pass_table
|
||||
)
|
||||
|
||||
@@ -384,3 +384,24 @@
|
||||
is_genetrait = TRUE
|
||||
hidden = FALSE
|
||||
activation_message="Your body feels mundane."
|
||||
|
||||
/datum/trait/positive/vibration_sense
|
||||
name = "Vibration Sense"
|
||||
desc = "Allows you to sense subtle vibrations nearby, even if the source cannot be seen."
|
||||
cost = 2
|
||||
var_changes = list("has_vibration_sense" = TRUE)
|
||||
|
||||
// Traitgenes edit begin - Made into a gene trait
|
||||
is_genetrait = TRUE
|
||||
hidden = FALSE
|
||||
|
||||
activation_message="Your ears ring, and hear everything..."
|
||||
// Traitgenes edit end
|
||||
|
||||
/datum/trait/positive/vibration_sense/apply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
|
||||
. = ..()
|
||||
H.motiontracker_subscribe()
|
||||
|
||||
/datum/trait/positive/vibration_sense/unapply(datum/species/S, mob/living/carbon/human/H, trait_prefs)
|
||||
. = ..()
|
||||
H.motiontracker_unsubscribe()
|
||||
|
||||
@@ -279,6 +279,8 @@ default behaviour is:
|
||||
/mob/living/Moved(var/atom/oldloc, direct, forced, movetime)
|
||||
. = ..()
|
||||
handle_footstep(loc)
|
||||
if(!forced && movetime)
|
||||
SSmotiontracker?.ping(src) // Incase of before init "turf enter gravity" this is ?, unfortunately.
|
||||
// Begin VOREstation edit
|
||||
if(is_shifted)
|
||||
is_shifted = FALSE
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
vore_selected = null // from code/modules/vore/eating/mob_vr
|
||||
focus = null
|
||||
|
||||
motiontracker_unsubscribe(TRUE) // Force unsubscribe
|
||||
|
||||
if(mind)
|
||||
if(mind.current == src)
|
||||
mind.current = null
|
||||
|
||||
@@ -244,3 +244,5 @@
|
||||
var/list/resistances
|
||||
|
||||
var/custom_footstep = FOOTSTEP_MOB_SHOE
|
||||
VAR_PRIVATE/is_motion_tracking = FALSE // Prevent multiple unsubs and resubs, also used to check if the vis layer is enabled, use has_motiontracking() to get externally.
|
||||
VAR_PRIVATE/wants_to_see_motion_echos = TRUE
|
||||
|
||||
48
code/modules/mob/motiontracker.dm
Normal file
48
code/modules/mob/motiontracker.dm
Normal file
@@ -0,0 +1,48 @@
|
||||
/mob/proc/has_motiontracking() // USE THIS
|
||||
return is_motion_tracking
|
||||
|
||||
// Subscribing and unsubscribingto the motion tracker subsystem
|
||||
/mob/proc/motiontracker_subscribe()
|
||||
if(!is_motion_tracking)
|
||||
is_motion_tracking = TRUE
|
||||
wants_to_see_motion_echos = TRUE
|
||||
RegisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER, PROC_REF(handle_motion_tracking))
|
||||
add_verb(src,/mob/proc/toggle_motion_echo_vis)
|
||||
|
||||
/mob/proc/motiontracker_unsubscribe(var/destroying = FALSE)
|
||||
if(is_motion_tracking)
|
||||
is_motion_tracking = FALSE
|
||||
UnregisterSignal(SSmotiontracker, COMSIG_MOVABLE_MOTIONTRACKER)
|
||||
remove_verb(src,/mob/proc/toggle_motion_echo_vis)
|
||||
|
||||
/mob/living/carbon/human/motiontracker_unsubscribe(destroying = FALSE)
|
||||
// Block unsub if our species has vibration senses
|
||||
if(!destroying && species?.has_vibration_sense)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
// For COMSIG_MOVABLE_MOTIONTRACKER
|
||||
/mob/proc/handle_motion_tracking(mob/source, var/datum/weakref/RW, var/turf/T)
|
||||
SIGNAL_HANDLER
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
PRIVATE_PROC(TRUE)
|
||||
if(!client || !wants_to_see_motion_echos || stat || is_deaf())
|
||||
return
|
||||
var/atom/echo_source = RW?.resolve()
|
||||
if(!echo_source || get_dist(src,echo_source) > SSmotiontracker.max_range || src.z != echo_source.z)
|
||||
return
|
||||
// Blind characters see all pings around them. Otherwise remove the closest, or any we can see. Pings behind walls or in the dark are always visible
|
||||
if(!is_blind() && (get_dist(src,echo_source) < SSmotiontracker.min_range || (T.get_lumcount() >= 0.20 && can_see(src, T, 7)) ))
|
||||
return
|
||||
var/echos = 1
|
||||
if(prob(30))
|
||||
echos = rand(1,3)
|
||||
SSmotiontracker.queue_echo(get_turf(src),T,echos,client ? WEAKREF(client) : null)
|
||||
|
||||
/mob/proc/toggle_motion_echo_vis()
|
||||
set name = "Toggle Vibration Senses"
|
||||
set desc = "Toggle the visibility of pings revealed by vibration senses or motion trackers."
|
||||
set category = "Abilities.General"
|
||||
|
||||
wants_to_see_motion_echos = !wants_to_see_motion_echos
|
||||
to_chat(src,"You will [wants_to_see_motion_echos ? "now" : "no longer"] see echos")
|
||||
@@ -186,3 +186,11 @@
|
||||
build_path = /obj/item/juke_remote
|
||||
sort_string = "TCVAE"
|
||||
department = LATHE_ALL | LATHE_SERVICE | LATHE_PUBLIC // CHOMPAdd
|
||||
|
||||
/datum/design/item/general/motion_tracker
|
||||
name = "Motion Tracker"
|
||||
id = "motion_tracker"
|
||||
req_tech = list(TECH_MAGNET = 1, TECH_DATA = 2)
|
||||
build_path = /obj/item/motiontracker
|
||||
sort_string = "TAADC"
|
||||
department = LATHE_ALL | LATHE_SECURITY // CHOMPAdd
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 414 KiB After Width: | Height: | Size: 449 KiB |
@@ -401,6 +401,7 @@
|
||||
#include "code\controllers\subsystems\mapping.dm"
|
||||
#include "code\controllers\subsystems\media_tracks.dm"
|
||||
#include "code\controllers\subsystems\mobs.dm"
|
||||
#include "code\controllers\subsystems\motion_tracker.dm"
|
||||
#include "code\controllers\subsystems\nightshift.dm"
|
||||
#include "code\controllers\subsystems\overlays_ch.dm"
|
||||
#include "code\controllers\subsystems\overmap_renamer_vr.dm"
|
||||
@@ -1329,6 +1330,7 @@
|
||||
#include "code\game\objects\effects\manifest.dm"
|
||||
#include "code\game\objects\effects\mines.dm"
|
||||
#include "code\game\objects\effects\misc.dm"
|
||||
#include "code\game\objects\effects\motion_echo.dm"
|
||||
#include "code\game\objects\effects\overlays.dm"
|
||||
#include "code\game\objects\effects\portals.dm"
|
||||
#include "code\game\objects\effects\semirandom_mobs_vr.dm"
|
||||
@@ -1485,6 +1487,7 @@
|
||||
#include "code\game\objects\items\devices\scanners\halogen.dm"
|
||||
#include "code\game\objects\items\devices\scanners\health.dm"
|
||||
#include "code\game\objects\items\devices\scanners\mass_spectrometer.dm"
|
||||
#include "code\game\objects\items\devices\scanners\motion_tracker.dm"
|
||||
#include "code\game\objects\items\devices\scanners\reagents.dm"
|
||||
#include "code\game\objects\items\devices\scanners\sleevemate.dm"
|
||||
#include "code\game\objects\items\devices\scanners\slime.dm"
|
||||
@@ -3101,6 +3104,7 @@
|
||||
#include "code\modules\mob\mob_planes.dm"
|
||||
#include "code\modules\mob\mob_planes_vr.dm"
|
||||
#include "code\modules\mob\mob_transformation_simple.dm"
|
||||
#include "code\modules\mob\motiontracker.dm"
|
||||
#include "code\modules\mob\say.dm"
|
||||
#include "code\modules\mob\say_old.dm"
|
||||
#include "code\modules\mob\say_vr.dm"
|
||||
|
||||
Reference in New Issue
Block a user