diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index a38ccf59ca..b2bd6b80e4 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -12,45 +12,51 @@ var/obj/item/weapon/disk/nuclear/the_disk = null var/active = 0 - - attack_self() - if(!active) - active = 1 - workdisk() - to_chat(usr, "You activate the pinpointer") - else - active = 0 - icon_state = "pinoff" - to_chat(usr, "You deactivate the pinpointer") - - proc/workdisk() - if(!active) return - if(!the_disk) - the_disk = locate() - if(!the_disk) - icon_state = "pinonnull" - return - set_dir(get_dir(src,the_disk)) - switch(get_dist(src,the_disk)) - if(0) - icon_state = "pinondirect" - if(1 to 8) - icon_state = "pinonclose" - if(9 to 16) - icon_state = "pinonmedium" - if(16 to INFINITY) - icon_state = "pinonfar" - spawn(5) .() - - examine(mob/user) - ..(user) - for(var/obj/machinery/nuclearbomb/bomb in machines) - if(bomb.timing) - to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]") - /obj/item/weapon/pinpointer/Destroy() active = 0 - ..() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/weapon/pinpointer/attack_self() + if(!active) + active = 1 + START_PROCESSING(SSobj, src) + to_chat(usr, "You activate the pinpointer") + else + active = 0 + STOP_PROCESSING(SSobj, src) + icon_state = "pinoff" + to_chat(usr, "You deactivate the pinpointer") + +/obj/item/weapon/pinpointer/process() + if(!active) + return PROCESS_KILL + + if(!the_disk) + the_disk = locate() + if(!the_disk) + icon_state = "pinonnull" + return + + set_dir(get_dir(src,the_disk)) + + switch(get_dist(src,the_disk)) + if(0) + icon_state = "pinondirect" + if(1 to 8) + icon_state = "pinonclose" + if(9 to 16) + icon_state = "pinonmedium" + if(16 to INFINITY) + icon_state = "pinonfar" + +/obj/item/weapon/pinpointer/examine(mob/user) + ..(user) + for(var/obj/machinery/nuclearbomb/bomb in machines) + if(bomb.timing) + to_chat(user, "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]") + + /obj/item/weapon/pinpointer/advpinpointer name = "Advanced Pinpointer" @@ -60,58 +66,49 @@ var/turf/location = null var/obj/target = null - attack_self() - if(!active) - active = 1 - if(mode == 0) - workdisk() - if(mode == 1) - worklocation() - if(mode == 2) - workobj() - to_chat(usr, "You activate the pinpointer") - else - active = 0 - icon_state = "pinoff" - to_chat(usr, "You deactivate the pinpointer") +/obj/item/weapon/pinpointer/advpinpointer/process() + if(!active) + return PROCESS_KILL + if(mode == 0) + ..() + if(mode == 1) + worklocation() + if(mode == 2) + workobj() +/obj/item/weapon/pinpointer/advpinpointer/proc/worklocation() + if(!location) + icon_state = "pinonnull" + return - proc/worklocation() - if(!active) - return - if(!location) - icon_state = "pinonnull" - return - set_dir(get_dir(src,location)) - switch(get_dist(src,location)) - if(0) - icon_state = "pinondirect" - if(1 to 8) - icon_state = "pinonclose" - if(9 to 16) - icon_state = "pinonmedium" - if(16 to INFINITY) - icon_state = "pinonfar" - spawn(5) .() + set_dir(get_dir(src,location)) + switch(get_dist(src,location)) + if(0) + icon_state = "pinondirect" + if(1 to 8) + icon_state = "pinonclose" + if(9 to 16) + icon_state = "pinonmedium" + if(16 to INFINITY) + icon_state = "pinonfar" - proc/workobj() - if(!active) - return - if(!target) - icon_state = "pinonnull" - return - set_dir(get_dir(src,target)) - switch(get_dist(src,target)) - if(0) - icon_state = "pinondirect" - if(1 to 8) - icon_state = "pinonclose" - if(9 to 16) - icon_state = "pinonmedium" - if(16 to INFINITY) - icon_state = "pinonfar" - spawn(5) .() +/obj/item/weapon/pinpointer/advpinpointer/proc/workobj() + if(!target) + icon_state = "pinonnull" + return + + set_dir(get_dir(src,target)) + + switch(get_dist(src,target)) + if(0) + icon_state = "pinondirect" + if(1 to 8) + icon_state = "pinonclose" + if(9 to 16) + icon_state = "pinonmedium" + if(16 to INFINITY) + icon_state = "pinonfar" /obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode() set category = "Object" @@ -140,7 +137,6 @@ to_chat(usr, "You set the pinpointer to locate [locationx],[locationy]") - return attack_self() if("Disk Recovery") @@ -150,9 +146,10 @@ if("Other Signature") mode = 2 switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) + if("Item") var/datum/objective/steal/itemlist - itemlist = itemlist // To supress a 'variable defined but not used' error. + itemlist = itemlist var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in itemlist.possible_items if(!targetitem) return @@ -161,6 +158,7 @@ to_chat(usr, "Failed to locate [targetitem]!") return to_chat(usr, "You set the pinpointer to locate [targetitem]") + if("DNA") var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "") if(!DNAstring) @@ -187,6 +185,7 @@ /obj/item/weapon/pinpointer/nukeop/attack_self(mob/user as mob) if(!active) active = 1 + START_PROCESSING(SSobj, src) if(!mode) workdisk() to_chat(user, "Authentication Disk Locator active.") @@ -195,30 +194,35 @@ to_chat(user, "Shuttle Locator active.") else active = 0 + STOP_PROCESSING(SSobj, src) icon_state = "pinoff" to_chat(user, "You deactivate the pinpointer.") +/obj/item/weapon/pinpointer/nukeop/process() + if(!active) + return PROCESS_KILL -/obj/item/weapon/pinpointer/nukeop/workdisk() - if(!active) return - if(mode) //Check in case the mode changes while operating - worklocation() - return + switch(mode) + if(0) + workdisk() + if(1) + worklocation() + +/obj/item/weapon/pinpointer/nukeop/proc/workdisk() if(bomb_set) //If the bomb is set, lead to the shuttle mode = 1 //Ensures worklocation() continues to work - worklocation() playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep - visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed + visible_message("Shuttle Locator active.") //Lets the mob holding it know that the mode has changed return //Get outta here + if(!the_disk) the_disk = locate() if(!the_disk) icon_state = "pinonnull" return -// if(loc.z != the_disk.z) //If you are on a different z-level from the disk -// icon_state = "pinonnull" -// else + set_dir(get_dir(src, the_disk)) + switch(get_dist(src, the_disk)) if(0) icon_state = "pinondirect" @@ -229,29 +233,25 @@ if(16 to INFINITY) icon_state = "pinonfar" - spawn(5) .() - - /obj/item/weapon/pinpointer/nukeop/proc/worklocation() - if(!active) return - if(!mode) - workdisk() - return if(!bomb_set) mode = 0 - workdisk() playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) visible_message("Authentication Disk Locator active.") return + if(!home) home = locate() 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 set_dir(get_dir(src, home)) + switch(get_dist(src, home)) if(0) icon_state = "pinondirect" @@ -262,8 +262,6 @@ if(16 to INFINITY) icon_state = "pinonfar" - spawn(5) .() - // This one only points to the ship. Useful if there is no nuking to occur today. /obj/item/weapon/pinpointer/shuttle @@ -273,16 +271,17 @@ /obj/item/weapon/pinpointer/shuttle/attack_self(mob/user as mob) if(!active) active = TRUE - find_shuttle() + START_PROCESSING(SSobj, src) to_chat(user, "Shuttle Locator active.") else active = FALSE + STOP_PROCESSING(SSobj, src) icon_state = "pinoff" to_chat(user, "You deactivate the pinpointer.") -/obj/item/weapon/pinpointer/shuttle/proc/find_shuttle() +/obj/item/weapon/pinpointer/shuttle/process() if(!active) - return + return PROCESS_KILL if(!our_shuttle) for(var/obj/machinery/computer/shuttle_control/S in machines) @@ -296,8 +295,10 @@ if(loc.z != our_shuttle.z) //If you are on a different z-level from the shuttle icon_state = "pinonnull" + else set_dir(get_dir(src, our_shuttle)) + switch(get_dist(src, our_shuttle)) if(0) icon_state = "pinondirect" @@ -308,9 +309,6 @@ if(16 to INFINITY) icon_state = "pinonfar" - spawn(5) - .() - /obj/item/weapon/pinpointer/shuttle/merc shuttle_comp_id = "Mercenary" diff --git a/code/game/objects/effects/map_effects/map_effects.dm b/code/game/objects/effects/map_effects/map_effects.dm index 9e2986072d..188afddad2 100644 --- a/code/game/objects/effects/map_effects/map_effects.dm +++ b/code/game/objects/effects/map_effects/map_effects.dm @@ -1,72 +1,68 @@ -// These are objects you can use inside special maps (like PoIs), or for adminbuse. -// Players cannot see or interact with these. -/obj/effect/map_effect - anchored = TRUE - invisibility = 99 // So a badmin can go view these by changing their see_invisible. - icon = 'icons/effects/map_effects.dmi' - - // Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects. - var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it. - var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run. - var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement. - var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well. - var/retry_delay = 3 SECONDS // How long until we check for players again. - -/obj/effect/map_effect/ex_act() - return - -/obj/effect/map_effect/singularity_pull() - return - -/obj/effect/map_effect/singularity_act() - return - -// Base type for effects that run on variable intervals. -/obj/effect/map_effect/interval - var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger. - var/interval_upper_bound = 5 SECONDS // Higher number for above. - var/halt = FALSE // Set to true to stop the loop when it reaches the next iteration. - -/obj/effect/map_effect/interval/Initialize() - handle_interval_delay() - return ..() - -/obj/effect/map_effect/interval/Destroy() - halt = TRUE // Shouldn't need it to GC but just in case. - return ..() - -// Override this for the specific thing to do. Be sure to call parent to keep looping. -/obj/effect/map_effect/interval/proc/trigger() - handle_interval_delay() - -// Handles the delay and making sure it doesn't run when it would be bad. -/obj/effect/map_effect/interval/proc/handle_interval_delay() - // Check to see if we're useful first. - if(halt) - return // Do not pass .(), do not recursively collect 200 thaler. - - if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk)) - spawn(retry_delay) // Maybe someday we'll have fancy TG timers/schedulers. - if(!QDELETED(src)) - .() - return - - var/next_interval = rand(interval_lower_bound, interval_upper_bound) - spawn(next_interval) - if(!QDELETED(src)) - trigger() - -// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it. -/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE) - if(!proximity_to) - return FALSE - - for(var/thing in player_list) - var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways. - if(ignore_ghosts && isobserver(M)) - continue - if(ignore_afk && M.client && M.client.is_afk(5 MINUTES)) - continue - if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius) - return TRUE - return FALSE \ No newline at end of file +// These are objects you can use inside special maps (like PoIs), or for adminbuse. +// Players cannot see or interact with these. +/obj/effect/map_effect + anchored = TRUE + invisibility = 99 // So a badmin can go view these by changing their see_invisible. + icon = 'icons/effects/map_effects.dmi' + + // Below vars concern check_for_player_proximity() and is used to not waste effort if nobody is around to appreciate the effects. + var/always_run = FALSE // If true, the game will not try to suppress this from firing if nobody is around to see it. + var/proximity_needed = 12 // How many tiles a mob with a client must be for this to run. + var/ignore_ghosts = FALSE // If true, ghosts won't satisfy the above requirement. + var/ignore_afk = TRUE // If true, AFK people (5 minutes) won't satisfy it as well. + var/retry_delay = 5 SECONDS // How long until we check for players again. + +/obj/effect/map_effect/ex_act() + return + +/obj/effect/map_effect/singularity_pull() + return + +/obj/effect/map_effect/singularity_act() + return + +// Base type for effects that run on variable intervals. +/obj/effect/map_effect/interval + var/interval_lower_bound = 5 SECONDS // Lower number for how often the map_effect will trigger. + var/interval_upper_bound = 5 SECONDS // Higher number for above. + var/halt = FALSE // Set to true to stop the loop when it reaches the next iteration. + +/obj/effect/map_effect/interval/Initialize() + handle_interval_delay() + return ..() + +/obj/effect/map_effect/interval/Destroy() + halt = TRUE // Shouldn't need it to GC but just in case. + return ..() + +// Override this for the specific thing to do. Be sure to call parent to keep looping. +/obj/effect/map_effect/interval/proc/trigger() + handle_interval_delay() + +// Handles the delay and making sure it doesn't run when it would be bad. +/obj/effect/map_effect/interval/proc/handle_interval_delay() + // Check to see if we're useful first. + if(halt) + return // Do not pass .(), do not recursively collect 200 thaler. + + if(!always_run && !check_for_player_proximity(src, proximity_needed, ignore_ghosts, ignore_afk)) + //Nobody home, try again after retry_delay + addtimer(CALLBACK(src, .proc/handle_interval_delay), retry_delay) + else + //Someone was here! + addtimer(CALLBACK(src, .proc/trigger), rand(interval_lower_bound, interval_upper_bound)) + +// Helper proc to optimize the use of effects by making sure they do not run if nobody is around to perceive it. +/proc/check_for_player_proximity(var/atom/proximity_to, var/radius = 12, var/ignore_ghosts = FALSE, var/ignore_afk = TRUE) + if(!proximity_to) + return FALSE + + for(var/thing in player_list) + var/mob/M = thing // Avoiding typechecks for more speed, player_list will only contain mobs anyways. + if(ignore_ghosts && isobserver(M)) + continue + if(ignore_afk && M.client && M.client.is_afk(5 MINUTES)) + continue + if(M.z == proximity_to.z && get_dist(M, proximity_to) <= radius) + return TRUE + return FALSE