diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d041306d6a5..44c4712617d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -32,6 +32,11 @@ qdel(S) else S.be_replaced() + //NSV13 - stop runtiming + if(registered_z) + SSmobs.clients_by_zlevel[registered_z] -= src + registered_z = null + //NSV13 end if(ranged_ability) ranged_ability.remove_ranged_ability(src) if(buckled) diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm index 3516758366d..732db5c9c66 100644 --- a/code/modules/recycling/conveyor.dm +++ b/code/modules/recycling/conveyor.dm @@ -195,6 +195,11 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) if(!operating) SSmove_manager.stop_looping(convayable, SSconveyors) return + //NSV13 - account for potentially changing location between sig send and reaching this. + if(convayable.loc != source) + SSmove_manager.stop_looping(convayable, SSconveyors) + return + //NSV13 end. start_conveying(convayable) /obj/machinery/conveyor/proc/conveyable_exit(datum/source, atom/convayable, direction) diff --git a/nsv13/code/modules/munitions/ship_weapons/ballistic_weapons/revision2/automation.dm b/nsv13/code/modules/munitions/ship_weapons/ballistic_weapons/revision2/automation.dm index 3da4d67b4bd..02feb57dd98 100644 --- a/nsv13/code/modules/munitions/ship_weapons/ballistic_weapons/revision2/automation.dm +++ b/nsv13/code/modules/munitions/ship_weapons/ballistic_weapons/revision2/automation.dm @@ -8,30 +8,23 @@ anchored = TRUE can_be_unanchored = TRUE density = TRUE - subsystem_type = /datum/controller/subsystem/processing //Needs to go faster than SSmachines - var/process_delay = 0.5 SECONDS - var/next_process = 0 + processing_flags = START_PROCESSING_MANUALLY //Does not process. + ///Icon state the arm of this device will have var/arm_icon_state = "welder3" - var/tier = 1 - var/list/held_components = list() //All the missile construction components that they've put into the arm. - var/obj/item/arm = null - var/obj/item/ship_weapon/ammunition/missile/missile_casing/target - var/munition_types = list(/obj/item/ship_weapon/ammunition/missile/missile_casing, /obj/item/ship_weapon/ammunition/torpedo/torpedo_casing) - var/list/target_states = list(1, 7, 9) //The target construction state of the missile - -/obj/machinery/missile_builder/examine(mob/user) - . = ..() - if(held_components.len) - . += "It currently holds..." - var/listofitems = list() - for(var/obj/item/C in held_components) - var/path = C.type - if (listofitems[path]) - listofitems[path]["amount"]++ - else - listofitems[path] = list("name" = C.name, "amount" = 1) - for(var/i in listofitems) - . += "[listofitems[i]["name"]] x[listofitems[i]["amount"]]" + ///An overlay for the machine that varies by its arm icon state. For some reason an item and not an overlay or any kind of effect. + var/obj/item/arm = null //This being an /item makes me scream. + ///List of valid munition types. These are SUPER DIRTY types. DO NOT TRUST THESE TYPES. If you are reading this, new coder, PLEASE keep a common ancestor if you want to access vars and have the things be basically the same!! + var/munition_types = list(/obj/item/ship_weapon/ammunition/missile/missile_casing, /obj/item/ship_weapon/ammunition/torpedo/torpedo_casing) //This is super bad but I don't feel like rewriting all of missile / torp casing code so it stays :) + ///The target construction states of the missile + var/list/target_states = list(1, 7, 9) //Who would magic number these even *after* having to reference them in machines too?? I am not cleaning up after you.. right now at least. -Delta + ///The turf this assembler is tracking + var/turf/target_turf + ///The timer that tracks how long the arm should be doing arm things. + var/active_arm_timer_id + ///Next time a success sound can play. + var/next_success_sound = 0 + ///Next time a fail sound can play. + var/next_fail_sound = 0 /obj/machinery/missile_builder/attackby(obj/item/I, mob/user, params) if(default_unfasten_wrench(user, I)) @@ -43,6 +36,19 @@ return . = ..() +/obj/machinery/missile_builder/default_unfasten_wrench(mob/user, obj/item/I, time) + . = ..() + if(. != SUCCESSFUL_UNFASTEN) + return + if(anchored) //just got anchored + target_turf = get_turf(get_step(src, src.dir)) + if(target_turf) + RegisterSignal(target_turf, COMSIG_ATOM_ENTERED, PROC_REF(attempt_assembler_action)) + else //just got unanchored + if(target_turf) + UnregisterSignal(target_turf, COMSIG_ATOM_ENTERED) + target_turf = null + /obj/item/stack/conveyor/slow name = "Slow conveyor assembly" conveyor_type = /obj/machinery/conveyor/slow @@ -70,59 +76,179 @@ /obj/machinery/missile_builder/AltClick(mob/user) . = ..() + if(target_turf) + UnregisterSignal(target_turf, COMSIG_ATOM_ENTERED) + target_turf = null setDir(turn(src.dir, -90)) + target_turf = get_turf(get_step(src, src.dir)) + if(target_turf) + RegisterSignal(target_turf, COMSIG_ATOM_ENTERED, PROC_REF(attempt_assembler_action)) /obj/machinery/missile_builder/Initialize(mapload) . = ..() - arm = new /obj/item(src) + arm = new /obj/item(src) //WHY IS THIS AN ITEM (worse, basetype..) and not an overlay or something else that would make more sense?! arm.icon = icon arm.icon_state = arm_icon_state vis_contents += arm arm.mouse_opacity = FALSE + target_turf = get_turf(get_step(src, src.dir)) + if(target_turf) + RegisterSignal(target_turf, COMSIG_ATOM_ENTERED, PROC_REF(attempt_assembler_action)) //aaa /obj/machinery/missile_builder/Destroy() qdel(arm) - . = ..() + if(target_turf) + UnregisterSignal(target_turf, COMSIG_ATOM_ENTERED) + target_turf = null + if(active_arm_timer_id) + deltimer(active_arm_timer_id) + active_arm_timer_id = null + return ..() -/obj/machinery/missile_builder/process() - if(world.time < next_process) +/** + * This beautiful proc handles interacting with objects that enter the turf we watch. Which is much more effective than processing all the time. + * * Does not return anything. SHOULD NOT RETURN ANYTHING. +**/ +/obj/machinery/missile_builder/proc/attempt_assembler_action(turf/source, atom/movable/entering, old_loc, old_locs) + SIGNAL_HANDLER + if(QDELETED(entering)) //How would this happen? Who knows.. but this is NSV after all. + return + if(!isobj(entering) || iseffect(entering)) return - next_process = world.time + process_delay - var/turf/input_turf = get_turf(get_step(src, src.dir)) - if(target && target.loc != input_turf) - target = null - visible_message("[name] shakes its arm melancholically.") + if(!(entering.type in munition_types)) + visible_message("[src] shakes its arm melancholically.") arm.shake_animation() - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) - if(target) - arm.icon_state = arm_icon_state - target.state++ //Next step! - target.check_completion() - do_sparks(10, TRUE, target) - playsound(src, 'sound/items/welder.ogg', 100, 1) - target = null + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.2 SECONDS return - for(var/munition_type in munition_types) - target = locate(munition_type) in input_turf - if(target) - break - if(!target) - target = null - arm.icon_state = arm_icon_state + switch(entering.type) //This is VERY BAD but they do not share a common type. + if(/obj/item/ship_weapon/ammunition/missile/missile_casing) + var/obj/item/ship_weapon/ammunition/missile/missile_casing/missile_target = entering + if(!(missile_target.state in target_states)) + visible_message("[src] sighs.") + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + trigger_arm_animation() + missile_target.state++ //Next step! + missile_target.check_completion() + if(world.time >= next_success_sound) + do_sparks(4, TRUE, missile_target) + playsound(src, 'sound/items/welder.ogg', 100, 1) + next_success_sound = world.time + 0.2 SECONDS + if(/obj/item/ship_weapon/ammunition/torpedo/torpedo_casing) + var/obj/item/ship_weapon/ammunition/torpedo/torpedo_casing/torpedo_target = entering + if(!(torpedo_target.state in target_states)) + visible_message("[src] sighs.") + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + trigger_arm_animation() + torpedo_target.state++ //Next step! + torpedo_target.check_completion() + if(world.time >= next_success_sound) + do_sparks(4, TRUE, torpedo_target) + playsound(src, 'sound/items/welder.ogg', 100, 1) + next_success_sound = world.time + 0.2 SECONDS + else + CRASH("Please stop handing the missile assemblers invalid types as valid ammunition. Type: [entering.type]. ALL valid casings must be missile or torpedo types.") + +//overrides parent. +/obj/machinery/missile_builder/assembler/attempt_assembler_action(turf/source, atom/movable/entering, old_loc, old_locs) + if(QDELETED(entering)) //How would this happen? Who knows.. but this is NSV after all. return - var/found = FALSE - for(var/target_state in target_states) - if(target.state == target_state) - found = TRUE - break - if(!found) - visible_message("[src] sighs.") - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) - target = null - return FALSE - src.visible_message("[src] whirrs into life!") - arm.icon_state = "[arm_icon_state]_anim" - playsound(src, 'sound/items/drill_use.ogg', 70, 1) + if(!isobj(entering) || iseffect(entering)) + return + if(entering.loc != source) + return + if(tracked_component_type && tracked_component_type == entering.type) //Please do throw these hungry machines some components. + var/obj/item/entering_item = entering + visible_message("[src] happily adds [entering_item] to its component storage.") + if(world.time >= next_success_sound) + playsound(src, 'sound/machines/ping.ogg', 50, 0) + next_success_sound = world.time + 0.2 SECONDS + entering_item.do_pickup_animation(src) + entering_item.forceMove(src) + held_components += entering_item + return + if(!(entering.type in munition_types)) + visible_message("[src] shakes its arm melancholically.") + arm.shake_animation() + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.2 SECONDS + return + switch(entering.type) //This is VERY BAD but they do not share a common type. + if(/obj/item/ship_weapon/ammunition/missile/missile_casing) + var/obj/item/ship_weapon/ammunition/missile/missile_casing/missile_target = entering + if(!length(held_components)) + visible_message("[src] sighs.") + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + var/obj/item/ship_weapon/parts/missile/missile_part = held_components[1] + if((missile_part.fits_type && !istype(missile_target, missile_part.fits_type)) || missile_target.state != missile_part.target_state) + visible_message("[src] sighs.") + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + trigger_arm_animation() + do_item_attack_animation(missile_target, used_item = missile_part) + + missile_target.state++ //Next step! + missile_part.forceMove(missile_target) + held_components -= missile_part + missile_target.check_completion() + if(world.time >= next_success_sound) + do_sparks(4, TRUE, missile_target) + playsound(src, 'sound/machines/ping.ogg', 50, 0) + next_success_sound = world.time + 0.2 SECONDS + if(/obj/item/ship_weapon/ammunition/torpedo/torpedo_casing) + var/obj/item/ship_weapon/ammunition/torpedo/torpedo_casing/torpedo_target = entering + if(!length(held_components)) + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + var/obj/item/ship_weapon/parts/missile/torpedo_part = held_components[1] + if((torpedo_part.fits_type && !istype(torpedo_target, torpedo_part.fits_type)) || torpedo_target.state != torpedo_part.target_state) + if(world.time >= next_fail_sound) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) + next_fail_sound = world.time + 0.5 SECONDS + return + trigger_arm_animation() + do_item_attack_animation(torpedo_target, used_item = torpedo_part) + + torpedo_target.state++ //Next step! + torpedo_part.forceMove(torpedo_target) + held_components -= torpedo_part + torpedo_target.check_completion() + if(world.time >= next_success_sound) + do_sparks(4, TRUE, torpedo_target) + playsound(src, 'sound/machines/ping.ogg', 50, 0) + next_success_sound = world.time + 0.2 SECONDS + else + CRASH("Please stop handing the missile assemblers invalid types as valid ammunition. Type: [entering.type]. ALL valid casings must be missile or torpedo types.") + + +///Starts the machine's arm animation to reset after some time. +/obj/machinery/missile_builder/proc/trigger_arm_animation() + if(arm.icon_state != "[arm_icon_state]_anim") + arm.icon_state = "[arm_icon_state]_anim" + visible_message("[src] whirrs into life!") + if(active_arm_timer_id) + deltimer(active_arm_timer_id) + active_arm_timer_id = addtimer(CALLBACK(src, PROC_REF(stop_arm_animation)), 1 SECONDS, TIMER_STOPPABLE) + +///Stops the machine's arm animation after some time. +/obj/machinery/missile_builder/proc/stop_arm_animation() + arm.icon_state = arm_icon_state + active_arm_timer_id = null /obj/machinery/missile_builder/assembler name = "Robotic Missile Part Applicator" @@ -130,6 +256,25 @@ desc = "An assembly arm which can slot a multitude of missile components into casings for you! Swipe it with an ID to release its stored components." req_one_access = list(ACCESS_MUNITIONS) circuit = /obj/item/circuitboard/machine/missile_builder/assembler + ///Currently loaded missile components. + var/list/held_components = list() + ///Currently tracked type for autopickup + var/tracked_component_type = null + +/obj/machinery/missile_builder/assembler/examine(mob/user) + . = ..() + if(!length(held_components)) + return + . += "It currently holds..." + var/listofitems = list() + for(var/obj/item/C in held_components) + var/path = C.type + if(listofitems[path]) + listofitems[path]["amount"]++ + else + listofitems[path] = list("name" = C.name, "amount" = 1) + for(var/i in listofitems) + . += "[listofitems[i]["name"]] x[listofitems[i]["amount"]]" /obj/machinery/missile_builder/assembler/attackby(obj/item/I, mob/living/user, params) . = ..() @@ -139,11 +284,13 @@ to_chat(user, "You slot [I] into [src], ready for construction.") I.forceMove(src) held_components += I + tracked_component_type = I.type if(istype(I, /obj/item/card/id) && allowed(user)) to_chat(user, "You dump [src]'s contents out.") for(var/obj/item/X in held_components) X.forceMove(get_turf(src)) held_components -= X + tracked_component_type = null /obj/machinery/missile_builder/assembler/MouseDrop_T(obj/structure/A, mob/user) . = ..() @@ -159,46 +306,6 @@ P.forceMove(src) held_components += P -/obj/machinery/missile_builder/assembler/process() - if(world.time < next_process) - return - next_process = world.time + process_delay - var/turf/input_turf = get_turf(get_step(src, src.dir)) - if(target && target.loc != input_turf) - target = null - visible_message("[name] shakes its arm melancholically.") - arm.shake_animation() - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0) - if(target) - var/found = FALSE - for(var/obj/item/ship_weapon/parts/missile/M in held_components) - if(M.fits_type && !istype(target, M.fits_type)) - continue - if(target.state == M.target_state) - M.forceMove(target) - held_components -= M - target.state ++ - found = TRUE - break - if(found) - target.check_completion() - playsound(src, 'sound/machines/ping.ogg', 50, 0) - do_sparks(10, TRUE, target) - target = null - arm.icon_state = arm_icon_state - return - for(var/munition_type in munition_types) - target = locate(munition_type) in input_turf - if(target) - break - if(!target || !held_components.len) - target = null - arm.icon_state = arm_icon_state - return - src.visible_message("[src] whirrs into life!") - arm.icon_state = "[arm_icon_state]_anim" - playsound(src, 'sound/items/drill_use.ogg', 70, 1) - /datum/design/board/ammo_sorter_computer name = "Ammo sorter console (circuitboard)" desc = "The central control console for ammo sorters.." diff --git a/nsv13/code/modules/overmap/FTL/components/drive.dm b/nsv13/code/modules/overmap/FTL/components/drive.dm index a1880a21904..65b375e0703 100644 --- a/nsv13/code/modules/overmap/FTL/components/drive.dm +++ b/nsv13/code/modules/overmap/FTL/components/drive.dm @@ -55,7 +55,7 @@ radio.keyslot = new radio_key radio.listening = 0 radio.recalculateChannels() - soundloop = new(list(src), FALSE, FALSE, CHANNEL_FTL_MANIFOLD, TRUE) + soundloop = new(src, FALSE, FALSE, CHANNEL_FTL_MANIFOLD, TRUE) STOP_PROCESSING(SSmachines, src) return INITIALIZE_HINT_LATELOAD