Pinpointer refactor (#19156)

* Pinpointer refactor

* Gives operatives the proper pinpointers

* Improves operative and AI tracking a bit

* Bashing people over minor mistakes is the new thing

* Replaces some more strings with defines

* Makes operative tracking actually functional

* Improves operative tracking

* Conflicts I

* Conflicts III

* Conflicts I

* Conflicts III

* Adds two new tracking modes

* Fixes a grammar error
This commit is contained in:
Xhuis
2016-07-12 20:03:36 -04:00
committed by oranges
parent 10ad8df67d
commit 82e2e8a844
11 changed files with 150 additions and 272 deletions

View File

@@ -0,0 +1,7 @@
//I would rather have these in pinpointer.dm, but Malf_Modules.dm is loaded before that file so they need to be here.
#define TRACK_NUKE_DISK 1 //We track the nuclear authentication disk, either to protect it or steal it
#define TRACK_MALF_AI 2 //We track the malfunctioning AI, so we can prevent it from blowing us all up
#define TRACK_INFILTRATOR 3 //We track the Syndicate infiltrator, so we can get back to ship when the nuke's armed
#define TRACK_OPERATIVES 4 //We track the closest operative, so we can regroup when we need to
#define TRACK_ATOM 5 //We track a specified atom, so admins can make us function for events
#define TRACK_COORDINATES 6 //We point towards the specified coordinates on our z-level, so we can navigate

View File

@@ -40,10 +40,8 @@
doomsday_device = DOOM doomsday_device = DOOM
doomsday_device.start() doomsday_device.start()
verbs -= /mob/living/silicon/ai/proc/nuke_station verbs -= /mob/living/silicon/ai/proc/nuke_station
for(var/obj/item/weapon/pinpointer/point in pinpointer_list) for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
for(var/mob/living/silicon/ai/A in ai_list) P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes
if((A.stat != DEAD) && A.nuking)
point.the_disk = A //The pinpointer now tracks the AI core
/obj/machinery/doomsday_device /obj/machinery/doomsday_device
icon = 'icons/obj/machines/nuke_terminal.dmi' icon = 'icons/obj/machines/nuke_terminal.dmi'

View File

@@ -296,7 +296,7 @@
gloves = /obj/item/clothing/gloves/combat gloves = /obj/item/clothing/gloves/combat
back = /obj/item/weapon/storage/backpack back = /obj/item/weapon/storage/backpack
ears = /obj/item/device/radio/headset/syndicate/alt ears = /obj/item/device/radio/headset/syndicate/alt
l_pocket = /obj/item/weapon/pinpointer/nukeop l_pocket = /obj/item/weapon/pinpointer/syndicate
id = /obj/item/weapon/card/id/syndicate id = /obj/item/weapon/card/id/syndicate
belt = /obj/item/weapon/gun/projectile/automatic/pistol belt = /obj/item/weapon/gun/projectile/automatic/pistol
backpack_contents = list(/obj/item/weapon/storage/box/syndie=1) backpack_contents = list(/obj/item/weapon/storage/box/syndie=1)

View File

@@ -358,6 +358,9 @@ var/bomb_set
if(safety) if(safety)
if(timing) if(timing)
set_security_level(previous_level) set_security_level(previous_level)
for(var/obj/item/weapon/pinpointer/syndicate/S in pinpointer_list)
S.switch_mode_to(initial(S.mode))
S.nuke_warning = FALSE
timing = FALSE timing = FALSE
bomb_set = TRUE bomb_set = TRUE
detonation_timer = null detonation_timer = null
@@ -374,6 +377,8 @@ var/bomb_set
bomb_set = TRUE bomb_set = TRUE
set_security_level("delta") set_security_level("delta")
detonation_timer = world.time + (timer_set * 10) detonation_timer = world.time + (timer_set * 10)
for(var/obj/item/weapon/pinpointer/syndicate/S in pinpointer_list)
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start() countdown.start()
else else
bomb_set = FALSE bomb_set = FALSE

View File

@@ -1,5 +1,7 @@
//Pinpointers are used to track atoms from a distance as long as they're on the same z-level. The captain and nuke ops have ones that track the nuclear authentication disk.
/obj/item/weapon/pinpointer /obj/item/weapon/pinpointer
name = "pinpointer" name = "pinpointer"
desc = "A handheld tracking device that locks onto certain signals."
icon = 'icons/obj/device.dmi' icon = 'icons/obj/device.dmi'
icon_state = "pinoff" icon_state = "pinoff"
flags = CONDUCT flags = CONDUCT
@@ -8,290 +10,162 @@
item_state = "electronic" item_state = "electronic"
throw_speed = 3 throw_speed = 3
throw_range = 7 throw_range = 7
materials = list(MAT_METAL=500) materials = list(MAT_METAL = 500, MAT_GLASS = 250)
var/obj/item/weapon/disk/nuclear/the_disk = null var/active = FALSE
var/active = 0 var/atom/movable/target = null //The thing we're searching for
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
var/target_x = 0 //The target coordinates if we're tracking those
var/target_y = 0
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
var/mode = TRACK_NUKE_DISK //What are we looking for?
/obj/item/weapon/pinpointer/New() /obj/item/weapon/pinpointer/New()
..() ..()
pinpointer_list += src pinpointer_list += src
/obj/item/weapon/pinpointer/Destroy() /obj/item/weapon/pinpointer/Destroy()
active = 0 STOP_PROCESSING(SSfastprocess, src)
pinpointer_list -= src
return ..() return ..()
/obj/item/weapon/pinpointer/attack_self() /obj/item/weapon/pinpointer/attack_self(mob/living/user)
if(!active) active = !active
active = 1 user.visible_message("<span class='notice'>[user] [active ? "" : "de"]activates their pinpointer.</span>", "<span class='notice'>You [active ? "" : "de"]activate your pinpointer.</span>")
workdisk() playsound(user, 'sound/items/Screwdriver2.ogg', 50, 1)
usr << "<span class='notice'>You activate the pinpointer.</span>" icon_state = "pin[active ? "onnull" : "off"]"
if(active)
START_PROCESSING(SSfastprocess, src)
else else
active = 0 target = null //Restarting the pinpointer forces a target reset
icon_state = "pinoff" STOP_PROCESSING(SSfastprocess, src)
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
/obj/item/weapon/pinpointer/proc/scandisk() /obj/item/weapon/pinpointer/attackby(obj/item/I, mob/living/user, params)
if(!the_disk) if(mode != TRACK_ATOM)
the_disk = locate() return ..()
user.visible_message("<span class='notice'>[user] tunes [src] to [I].</span>", "<span class='notice'>You fine-tune [src]'s tracking to track [I].</span>")
/obj/item/weapon/pinpointer/proc/point_at(atom/target, spawnself = 1) playsound(src, 'sound/machines/click.ogg', 50, 1)
if(!active) constant_target = I
return
if(!target)
icon_state = "pinonnull"
return
var/turf/T = get_turf(target)
var/turf/L = get_turf(src)
if(T.z != L.z)
icon_state = "pinonnull"
else
setDir(get_dir(L, T))
switch(get_dist(L, T))
if(-1)
icon_state = "pinondirect"
if(1 to 8)
icon_state = "pinonclose"
if(9 to 16)
icon_state = "pinonmedium"
if(16 to INFINITY)
icon_state = "pinonfar"
if(spawnself)
spawn(5)
.()
/obj/item/weapon/pinpointer/proc/workdisk()
scandisk()
point_at(the_disk, 0)
spawn(5)
.()
/obj/item/weapon/pinpointer/examine(mob/user) /obj/item/weapon/pinpointer/examine(mob/user)
..() ..()
var/msg = "Its tracking indicator reads "
switch(mode)
if(TRACK_NUKE_DISK)
msg += "\"nuclear_disk\"."
if(TRACK_MALF_AI)
msg += "\"01000001 01001001\"."
if(TRACK_INFILTRATOR)
msg += "\"vasvygengbefuvc\"."
if(TRACK_OPERATIVES)
msg += "\"[target ? "Operative [target]" : "friends"]\"."
if(TRACK_ATOM)
msg += "\"[initial(constant_target.name)]\"."
if(TRACK_COORDINATES)
msg += "\"([target_x], [target_y])\"."
else
msg = "Its tracking indicator is blank."
user << msg
for(var/obj/machinery/nuclearbomb/bomb in machines) for(var/obj/machinery/nuclearbomb/bomb in machines)
if(bomb.timing) if(bomb.timing)
user << "Extreme danger. Arming signal detected. Time remaining: [bomb.get_time_left()]" user << "Extreme danger. Arming signal detected. Time remaining: [bomb.get_time_left()]"
/obj/item/weapon/pinpointer/process()
/obj/item/weapon/pinpointer/advpinpointer
name = "advanced pinpointer"
icon = 'icons/obj/device.dmi'
desc = "A larger version of the normal pinpointer, this unit features a helpful quantum entanglement detection system to locate various objects that do not broadcast a locator signal."
var/mode = 0 // Mode 0 locates disk, mode 1 locates coordinates.
var/turf/location = null
var/obj/target = null
/obj/item/weapon/pinpointer/advpinpointer/attack_self()
if(!active) if(!active)
active = 1 STOP_PROCESSING(SSfastprocess, src)
if(mode == 0)
workdisk()
if(mode == 1)
point_at(location)
if(mode == 2)
point_at(target)
usr << "<span class='notice'>You activate the pinpointer.</span>"
else
active = 0
icon_state = "pinoff"
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode()
set category = "Object"
set name = "Toggle Pinpointer Mode"
set src in view(1)
if(usr.stat || usr.restrained() || !usr.canmove)
return return
scan_for_target()
point_to_target()
my_god_jc_a_bomb()
addtimer(src, "refresh_target", 50, TRUE)
active = 0 /obj/item/weapon/pinpointer/proc/scan_for_target() //Looks for whatever it's tracking
icon_state = "pinoff" if(target)
target=null if(isliving(target))
location = null var/mob/living/L = target
if(L.stat == DEAD)
switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature")) target = null
if("Location")
mode = 1
var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num
if(!locationx || !(usr in view(1,src)))
return
var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num
if(!locationy || !(usr in view(1,src)))
return
var/turf/Z = get_turf(src)
location = locate(locationx,locationy,Z.z)
usr << "<span class='notice'>You set the pinpointer to locate [locationx],[locationy]</span>"
return attack_self()
if("Disk Recovery")
mode = 0
return attack_self()
if("Other Signature")
mode = 2
switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA"))
if("Item")
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in possible_items
if(!targetitem)
return
target=locate(possible_items[targetitem])
if(!target)
usr << "<span class='warning'>Failed to locate [targetitem]!</span>"
return
usr << "<span class='notice'>You set the pinpointer to locate [targetitem].</span>"
if("DNA")
var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "")
if(!DNAstring)
return
for(var/mob/living/carbon/C in mob_list)
if(!C.dna)
continue
if(C.dna.unique_enzymes == DNAstring)
target = C
break
return attack_self()
///////////////////////
//nuke op pinpointers//
///////////////////////
/obj/item/weapon/pinpointer/nukeop
var/mode = 0 //Mode 0 locates disk, mode 1 locates the shuttle
var/obj/docking_port/mobile/home
/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user)
if(!active)
active = 1
var/mode_text = "Authentication Disk Locator mode"
if(!mode)
workdisk()
else
mode_text = "Shuttle Locator mode"
worklocation()
user << "<span class='notice'>You activate the pinpointer([mode_text]).</span>"
else
active = 0
icon_state = "pinoff"
user << "<span class='notice'>You deactivate the pinpointer.</span>"
/obj/item/weapon/pinpointer/nukeop/workdisk()
if(!active) return
if(mode) //Check in case the mode changes while operating
worklocation()
return return
if(bomb_set) //If the bomb is set, lead to the shuttle switch(mode)
mode = 1 //Ensures worklocation() continues to work if(TRACK_NUKE_DISK)
worklocation() var/obj/item/weapon/disk/nuclear/N = locate()
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep target = N
visible_message("Shuttle Locator mode actived.") //Lets the mob holding it know that the mode has changed if(TRACK_MALF_AI)
return //Get outta here for(var/V in ai_list)
scandisk() var/mob/living/silicon/ai/A = V
if(!the_disk) if(A.nuking)
icon_state = "pinonnull" target = A
return for(var/V in apcs_list)
setDir(get_dir(src, the_disk)) var/obj/machinery/power/apc/A = V
switch(get_dist(src, the_disk)) if(A.malfhack && A.occupier)
if(0) target = A
icon_state = "pinondirect" if(TRACK_INFILTRATOR)
if(1 to 8) target = SSshuttle.getShuttle("syndicate")
icon_state = "pinonclose" if(TRACK_OPERATIVES)
if(9 to 16) var/list/possible_targets = list()
icon_state = "pinonmedium" var/turf/here = get_turf(src)
if(16 to INFINITY) for(var/V in ticker.mode.syndicates)
icon_state = "pinonfar" var/datum/mind/M = V
if(M.current && M.current.stat != DEAD)
possible_targets |= M.current
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
if(closest_operative)
target = closest_operative
if(TRACK_ATOM)
if(constant_target)
target = constant_target
if(TRACK_COORDINATES)
var/turf/T = get_turf(src)
target = locate(target_x, target_y, T.z)
spawn(5) .() /obj/item/weapon/pinpointer/proc/point_to_target() //If we found what we're looking for, show the distance and direction
/obj/item/weapon/pinpointer/nukeop/proc/worklocation()
if(!active) if(!active)
return return
if(!mode) if(!target || (mode == TRACK_ATOM && !constant_target))
workdisk() icon_state = "pinon[nuke_warning ? "alert" : ""]null"
return return
if(!bomb_set) var/turf/here = get_turf(src)
mode = 0 var/turf/there = get_turf(target)
workdisk() if(here.z != there.z)
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) icon_state = "pinon[nuke_warning ? "alert" : ""]null"
visible_message("<span class='notice'>Authentication Disk Locator mode actived.</span>")
return return
if(!home) if(here == there)
home = SSshuttle.getShuttle("syndicate") icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
if(!home)
icon_state = "pinonnull"
return
if(loc.z != home.z) //If you are on a different z-level from the shuttle
icon_state = "pinonnull"
else else
setDir(get_dir(src, home)) setDir(get_dir(here, there))
switch(get_dist(src, home)) switch(get_dist(here, there))
if(0)
icon_state = "pinondirect"
if(1 to 8) if(1 to 8)
icon_state = "pinonclose" icon_state = "pinon[nuke_warning ? "alert" : "close"]"
if(9 to 16) if(9 to 16)
icon_state = "pinonmedium" icon_state = "pinon[nuke_warning ? "alert" : "medium"]"
if(16 to INFINITY) if(16 to INFINITY)
icon_state = "pinonfar" icon_state = "pinon[nuke_warning ? "alert" : "far"]"
spawn(5) /obj/item/weapon/pinpointer/proc/my_god_jc_a_bomb() //If we should get the hell back to the ship
.() for(var/obj/machinery/nuclearbomb/bomb in machines)
if(bomb.timing)
if(!nuke_warning)
nuke_warning = TRUE
playsound(src, 'sound/items/Nuke_toy_lowpower.ogg', 50, 0)
if(isliving(loc))
var/mob/living/L = loc
L << "<span class='userdanger'>Your [name] vibrates and lets out a tinny alarm. Uh oh.</span>"
/obj/item/weapon/pinpointer/operative /obj/item/weapon/pinpointer/proc/switch_mode_to(new_mode) //If we shouldn't be tracking what we are
name = "operative pinpointer" if(isliving(loc))
icon = 'icons/obj/device.dmi' var/mob/living/L = loc
desc = "A pinpointer that leads to the first Syndicate operative detected." L << "<span class='userdanger'>Your [name] beeps as it reconfigures its tracking algorithms.</span>"
var/mob/living/carbon/nearest_op = null playsound(L, 'sound/machines/triple_beep.ogg', 50, 1)
mode = new_mode
target = null //Switch modes so we can find the new target
/obj/item/weapon/pinpointer/operative/attack_self() /obj/item/weapon/pinpointer/proc/refresh_target() //Periodically removes the target to allow the pinpointer to update (i.e. malf AI shunts, an operative dies)
if(!usr.mind || !(usr.mind in ticker.mode.syndicates)) target = null
usr << "<span class='danger'>AUTHENTICATION FAILURE. ACCESS DENIED.</span>"
return 0
if(!active)
active = 1
workop()
usr << "<span class='notice'>You activate the pinpointer.</span>"
else
active = 0
icon_state = "pinoff"
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
/obj/item/weapon/pinpointer/operative/proc/scan_for_ops() /obj/item/weapon/pinpointer/syndicate //Syndicate pinpointers automatically point towards the infiltrator once the nuke is active.
if(active) name = "syndicate pinpointer"
nearest_op = null //Resets nearest_op every time it scans desc = "A handheld tracking device that locks onto certain signals. It's configured to switch tracking modes once it detects the activation signal of a nuclear device."
var/closest_distance = 1000
for(var/mob/living/carbon/M in mob_list)
if(M.mind && (M.mind in ticker.mode.syndicates))
if(get_dist(M, get_turf(src)) < closest_distance) //Actually points toward the nearest op, instead of a random one like it used to
nearest_op = M
/obj/item/weapon/pinpointer/operative/proc/workop() /obj/item/weapon/pinpointer/syndicate/cyborg //Cyborg pinpointers just look for a random operative.
if(active) name = "cyborg syndicate pinpointer"
scan_for_ops() desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
point_at(nearest_op, 0) mode = TRACK_OPERATIVES
spawn(5) flags = NODROP
.()
else
return 0
/obj/item/weapon/pinpointer/operative/examine(mob/user)
..()
if(active)
if(nearest_op)
user << "Nearest operative detected is <i>[nearest_op.real_name].</i>"
else
user << "No operatives detected within scanning range."

View File

@@ -24,8 +24,9 @@
if(nuking) if(nuking)
set_security_level("red") set_security_level("red")
nuking = FALSE nuking = FALSE
for(var/obj/item/weapon/pinpointer/point in pinpointer_list) for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
point.the_disk = null //Point back to the disk. P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
P.nuke_warning = FALSE
if(doomsday_device) if(doomsday_device)
doomsday_device.timing = FALSE doomsday_device.timing = FALSE

View File

@@ -336,7 +336,7 @@
modules += new /obj/item/weapon/gun/projectile/revolver/grenadelauncher/cyborg(src) modules += new /obj/item/weapon/gun/projectile/revolver/grenadelauncher/cyborg(src)
modules += new /obj/item/weapon/card/emag(src) modules += new /obj/item/weapon/card/emag(src)
modules += new /obj/item/weapon/crowbar/cyborg(src) modules += new /obj/item/weapon/crowbar/cyborg(src)
modules += new /obj/item/weapon/pinpointer/operative(src) modules += new /obj/item/weapon/pinpointer/syndicate/cyborg(src)
emag = null emag = null
fix_modules() fix_modules()
@@ -357,7 +357,7 @@
modules += new /obj/item/roller/robo(src) modules += new /obj/item/roller/robo(src)
modules += new /obj/item/weapon/card/emag(src) modules += new /obj/item/weapon/card/emag(src)
modules += new /obj/item/weapon/crowbar/cyborg(src) modules += new /obj/item/weapon/crowbar/cyborg(src)
modules += new /obj/item/weapon/pinpointer/operative(src) modules += new /obj/item/weapon/pinpointer/syndicate/cyborg(src)
emag = null emag = null
add_module(new /obj/item/stack/medical/gauze/cyborg()) add_module(new /obj/item/stack/medical/gauze/cyborg())

View File

@@ -829,9 +829,6 @@
qdel(malf) qdel(malf)
src.occupier.verbs += /mob/living/silicon/ai/proc/corereturn src.occupier.verbs += /mob/living/silicon/ai/proc/corereturn
src.occupier.cancel_camera() src.occupier.cancel_camera()
if ((seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) && malf.nuking)
for(var/obj/item/weapon/pinpointer/point in pinpointer_list)
point.the_disk = src //the pinpointer will detect the shunted AI
/obj/machinery/power/apc/proc/malfvacate(forced) /obj/machinery/power/apc/proc/malfvacate(forced)
@@ -843,11 +840,6 @@
src.occupier.parent.adjustOxyLoss(src.occupier.getOxyLoss()) src.occupier.parent.adjustOxyLoss(src.occupier.getOxyLoss())
src.occupier.parent.cancel_camera() src.occupier.parent.cancel_camera()
qdel(src.occupier) qdel(src.occupier)
if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
for(var/obj/item/weapon/pinpointer/point in pinpointer_list)
for(var/mob/living/silicon/ai/A in ai_list)
if((A.stat != DEAD) && A.nuking)
point.the_disk = A //The pinpointer tracks the AI back into its core.
else else
src.occupier << "<span class='danger'>Primary core damaged, unable to return core processes.</span>" src.occupier << "<span class='danger'>Primary core damaged, unable to return core processes.</span>"
@@ -855,9 +847,9 @@
src.occupier.loc = src.loc src.occupier.loc = src.loc
src.occupier.death() src.occupier.death()
src.occupier.gib() src.occupier.gib()
for(var/obj/item/weapon/pinpointer/point in pinpointer_list) for(var/obj/item/weapon/pinpointer/P in pinpointer_list)
point.the_disk = null //the pinpointer will go back to pointing at the nuke disc. P.switch_mode_to(TRACK_NUKE_DISK) //Pinpointers go back to tracking the nuke disk
P.nuke_warning = FALSE
/obj/machinery/power/apc/surplus() /obj/machinery/power/apc/surplus()
if(terminal) if(terminal)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

View File

@@ -38,6 +38,7 @@
#include "code\__DEFINES\math.dm" #include "code\__DEFINES\math.dm"
#include "code\__DEFINES\MC.dm" #include "code\__DEFINES\MC.dm"
#include "code\__DEFINES\misc.dm" #include "code\__DEFINES\misc.dm"
#include "code\__DEFINES\pinpointers.dm"
#include "code\__DEFINES\pipe_construction.dm" #include "code\__DEFINES\pipe_construction.dm"
#include "code\__DEFINES\preferences.dm" #include "code\__DEFINES\preferences.dm"
#include "code\__DEFINES\qdel.dm" #include "code\__DEFINES\qdel.dm"