diff --git a/GainStation13/code/datums/components/crafting/recipes/recipes_misc_gs.dm b/GainStation13/code/datums/components/crafting/recipes/recipes_misc_gs.dm index 19da0bca4d..9d53cff605 100644 --- a/GainStation13/code/datums/components/crafting/recipes/recipes_misc_gs.dm +++ b/GainStation13/code/datums/components/crafting/recipes/recipes_misc_gs.dm @@ -3,13 +3,15 @@ /datum/crafting_recipe/industrial_feeding_tube name = "Industrial Feeding Tube" reqs = list( - /obj/machinery/iv_drip/feeding_tube = 1, - /obj/item/stack/sheet/metal = 2, - /obj/item/pipe = 2 + // /obj/machinery/iv_drip/feeding_tube = 1, //Removing this. Seems to be buggy with not-items used to craft + /obj/item/stack/sheet/metal = 5, + /obj/item/stack/sheet/plastic = 5, + /obj/item/pipe = 2, + /obj/item/stock_parts/matter_bin = 2 ) parts = list( - /obj/machinery/iv_drip/feeding_tube = 1 + /obj/item/stock_parts/matter_bin = 2 ) - results = /obj/structure/disposaloutlet/industrial_feeding_tube + result = /obj/structure/disposaloutlet/industrial_feeding_tube tools = list(TOOL_WELDER, TOOL_WRENCH, TOOL_SCREWDRIVER) category = CAT_MISC diff --git a/GainStation13/code/machinery/feeding_tube_industrial.dm b/GainStation13/code/machinery/feeding_tube_industrial.dm index f4f445a0ca..7de83343fa 100644 --- a/GainStation13/code/machinery/feeding_tube_industrial.dm +++ b/GainStation13/code/machinery/feeding_tube_industrial.dm @@ -5,9 +5,10 @@ /obj/structure/disposaloutlet/industrial_feeding_tube name = "\improper industrial feeding tube" - desc = "An imposing machine designed to pump an absurd amount of food down something's throat. It seems to connect to disposal pipes." - icon = 'GainStation13/icons/obj/feeding_tube.dmi' - icon_state = "feeding_tube" + desc = "An imposing machine designed to pump an absurd amount of \"food\" down something's throat. It seems to connect to disposal pipes." + icon = 'GainStation13/icons/obj/feeding_tube_industrial.dmi' + icon_state = "base" + max_integrity = 500 //Durable... anchored = FALSE /// Is it welded down? var/welded = FALSE @@ -17,44 +18,73 @@ var/output_dest /// It's Glogged ! var/clogged = FALSE - /// This is made using a feeding tube - var/obj/machinery/iv_drip/feeding_tube/storedFeeder //Really wish I could redefine stored. + /// Are we currently pumping? + var/pumping = FALSE + /// Stuff we're currently trying to pump out + var/list/pump_stuff = list() + /// How many items we can push per-pump. + var/pump_limit = 5 -/obj/structure/disposaloutlet/industrial_feeding_tube/Initialize(mapload, obj/machinery/iv_drip/feeding_tube/make_from) +/obj/structure/disposaloutlet/industrial_feeding_tube/Initialize(mapload) . = ..() - if(make_from) - make_from.forceMove(src) - storedFeeder = make_from - else - storedFeeder = new /obj/machinery/iv_drip/feeding_tube(src) - trunk = locate() in loc - if(trunk) + update_icon() + + if(anchored) // So it can be mapped in, attached to something. + trunk = locate() in loc + if(!trunk) + return trunk.linked = src // link the pipe trunk to self anchored = TRUE welded = TRUE //Make it functional /obj/structure/disposaloutlet/industrial_feeding_tube/CheckParts(list/parts_list) ..() - storedFeeder = locate(/obj/machinery/iv_drip/feeding_tube) in contents + pump_limit = 0 + for(var/obj/item/stock_parts/matter_bin/mb in contents) + if(pump_stuff.Find(mb)) //stuff we're going to pump are not being used to build us. + continue + pump_limit += mb.rating * 2.5 // ~20 items per pump with 2 bluespace bins + pump_limit = ceil(pump_limit) //Only whole numbers + +/obj/structure/disposaloutlet/industrial_feeding_tube/deconstruct(disassembled) + if(!(flags_1 & NODECONSTRUCT_1)) + new /obj/item/stack/sheet/metal(loc, 5) + new /obj/item/stack/sheet/plastic(loc, 5) + new /obj/item/pipe/binary(loc, PIPE_STRAIGHT, NORTH) + new /obj/item/pipe/binary(loc, PIPE_STRAIGHT, NORTH) + + if(contents) //Anything still glogged inside... + for(var/atom/movable/AM in src) + AM.forceMove(loc) + qdel(src) + /obj/structure/disposaloutlet/industrial_feeding_tube/Destroy() if(attached) attached = null if(output_dest) output_dest = null - QDEL_NULL(storedFeeder) + + if(LAZYLEN(contents)) // Just to be safe, lets dump everything out before it's deleted. + for(var/atom/movable/AM in contents) + if(istype(AM, /obj/item/stock_parts/matter_bin)) + if(AM in pump_stuff) // Unless it's one of our component parts.. + AM.forceMove(loc) + continue + qdel(AM) + return ..() /obj/structure/disposaloutlet/industrial_feeding_tube/MouseDrop(mob/living/target) . = ..() - if(!usr.canUseTopic(src, BE_CLOSE) || !isliving(target)) + if(!usr.canUseTopic(src, BE_CLOSE)) // iscarbon() so that xenos/wendigos(?) can do feeding stuff maybe. Maybe. return - - if(!anchored || !welded) - to_chat(usr, "You need to anchor down \the [src] before you can use it.") + if(!welded) + to_chat(usr, "You need to weld down \the [src] before you can use it.") + return + if(!isliving(target)) return - if(attached) attached.visible_message("[attached] is detached from [src].") attached = null @@ -62,18 +92,39 @@ return if(iscarbon(target)) - var/mob/living/carbon/feedee + var/mob/living/carbon/feedee = target + + if(HAS_TRAIT(feedee, TRAIT_TRASHCAN)) + var/food_dump = input(usr, "Where do you shove the tube? (cancel for to just feed normally)", "Select belly") as null|anything in feedee.vore_organs + if(food_dump && isbelly(food_dump)) + // Best to be safe with this thing. Since you can eat pretty much anythign with it... + // Including People, Intentionally or otherwise. + if(usr != feedee) // If someone is feeding themself, skip the prefcheck. + var/feedeePrefCheck = alert(feedee, "[usr] is attempting to shove \the [src]'s tube into your [food_dump]! Do you want this?", "THE TUBE", "Yes!!", "No!") + if(feedeePrefCheck != "Yes!!") + to_chat(usr, "[feedee] doesnt want to be fed by \the [src]...") + return - if(HAS_TRAIT(feedee, TRAIT_TRASHCAN) || feedee) - var/food_dump = input("Where do you shove the tube? (cancel for it to just feed normally)", "Select belly") as null|anything in feedee.vore_organs - if(!food_dump || !isbelly(food_dump)) - output_dest = feedee //Attach normally - else output_dest = food_dump //Attach to vorebelly + attached = feedee + update_icon() + START_PROCESSING(SSobj, src) + face_atom(feedee) + return + //Either we arn't attaching to vorebelly, or we arnt able to. Let's try to feed them normally! + if(usr != feedee) // + var/feedeePrefCheck = alert(feedee, "[usr] is attempting to shove \the [src]'s tube into your mouth! Do you want this?", "THE TUBE", "Yes!!", "No!") + if(feedeePrefCheck != "Yes!!") + to_chat(usr, "[feedee] doesnt want to be fed by \the [src]...") + return + + output_dest = feedee //Attach normally attached = feedee + update_icon() - START_PROCESSING(SSmachines, src) + START_PROCESSING(SSobj, src) + face_atom(feedee) return /obj/structure/disposaloutlet/industrial_feeding_tube/process() @@ -87,21 +138,28 @@ update_icon() return PROCESS_KILL - //face_atom(attached) + face_atom(attached) -/obj/structure/disposaloutlet/industrial_feeding_tube/update_icon() +/obj/structure/disposaloutlet/industrial_feeding_tube/update_overlays() // A lot of this is temp. More likely than not you shouldnt see this comment as it'll be properly updated when reo PRs this. // Or it wont because epic fail :333 - if(attached) - icon_state = "injecting" //Temp. Change it when proper icons are made - else - icon_state = "injectidle" //Temp. - + . = ..() cut_overlays() + var/mutable_appearance/tube_overlay = mutable_appearance('GainStation13/icons/obj/feeding_tube_industrial.dmi', "tube_idle") + + if(pumping) + tube_overlay.icon_state = "tube-pump" + else + if(attached) + tube_overlay.icon_state = "tube-active" + else + tube_overlay.icon_state = "tube-idle" + + add_overlay("light-[clogged ? "r" : "g"]") + + add_overlay(tube_overlay) - - // expel the contents of the holder object, then delete it // called when the holder exits the outlet @@ -111,71 +169,109 @@ clunkVol += 25 playsound(src, H.hasmob ? "clang" : "clangsmall", clamp(clunkVol, 5, H.hasmob ? 50 : 25)) H.active = FALSE + H.vent_gas(get_turf(src)) if(clogged) clog(H.contents) - if(!attached) - //flick("ind-tube-spew", src) - - addtimer(CALLBACK(src,PROC_REF(expel_holder), H, TRUE), 5) - return - + else + for(var/atom/movable/AM in H.contents) + pump_stuff += AM // Get ready to pump! + AM.forceMove(src) + if(!pumping) //Lets start a new pump cycle if we arnt pumping. Otherwise, it'll just be added to the queue. + pump() + qdel(H) - if(isliving(output_dest)) - var/list/not_food = list() - var/turf/T = get_turf(src) - - for(var/atom/movable/AM in H) - if(istype(AM, /obj/item/reagent_containers/food/snacks)) - var/obj/item/reagent_containers/food/snacks/food = AM - - var/datum/reagents/food_reagents = food.reagents - if(food_reagents.total_volume) - var/food_size = food_reagents.total_volume //We're cramming the Whole Thing down your throat~ - - SEND_SIGNAL(food, COMSIG_FOOD_EATEN, attached) - - food_reagents.reaction(attached, INGEST, food_size) - food_reagents.trans_to(attached, food_size) - - food.checkLiked(food_size, attached) //...Hopefully you like the taste. - - if(food.trash) //Lets make the trash the food's supposed to make, if it has any - var/obj/item/trash = food.generate_trash(src) - if(not_food) - not_food += trash // If it's already going to get clogged, clog it more with the trash - else - trash.forceMove(T) // Otherwise move it to the tile. For convinience - - qdel(food) //Gulp... - continue - - else - not_food += AM // That's not (traditionally) edible! - - if(not_food) - clog(not_food) // Now you've gone and clogged us... - H.vent_gas(T) - qdel(H) +/obj/structure/disposaloutlet/industrial_feeding_tube/proc/pump(repeat = TRUE, unlimited = FALSE) + if(clogged) return + var/list/this_pump = list() //What we're going to pump this cycle + var/item_count = 0 + for(var/atom/movable/AM in pump_stuff) + this_pump += AM // Add to the stuff we're currently pumping + item_count++ + if(item_count > pump_limit && !unlimited) //We're pumping as much as our parts allow! + break + if(!pumping) + pumping = TRUE + update_icon() + spawn(8) + pumping = FALSE + update_icon() + spawn(9) //Wait for the animation to finish - if(isbelly(output_dest)) - var/list/inedible //Some things shouldnt be eaten... - var/turf/T = get_turf(src) - - for(var/atom/movable/AM in H) - if(isliving(AM)) - var/mob/living/cutie = AM - if(cutie.devourable != TRUE) //Do not eat this QT... - inedible += cutie - continue - - AM.forceMove(attached) - if(inedible) - clog(inedible) + if(!output_dest || !attached) //We either arnt, or got disconnected by time stuff was about to splort out! + spew(this_pump, TRUE) + if(LAZYLEN(pump_stuff) && repeat) + pump() + return - H.vent_gas(T) - qdel(H) + var/fed_something = FALSE + // Feed Normally + if(isliving(output_dest)) + var/list/not_food = list() + for(var/atom/movable/AM in this_pump) + if(istype(AM, /obj/item/reagent_containers/food/snacks)) + var/obj/item/reagent_containers/food/snacks/food = AM + var/datum/reagents/food_reagents = food.reagents + if(food_reagents.total_volume) + var/food_size = food_reagents.total_volume //We're cramming the Whole Thing down your throat~ + SEND_SIGNAL(food, COMSIG_FOOD_EATEN, attached) + + food_reagents.reaction(attached, INGEST, food_size) + food_reagents.trans_to(attached, food_size) + + food.checkLiked(food_size, attached) //...Hopefully you like the taste. + + + if(food.trash) //Lets make the trash the food's supposed to make, if it has any + var/obj/item/trash = food.generate_trash(src) + if(not_food) + not_food += trash // If it's already going to get clogged, clog it more with the trash + else + trash.forceMove(get_turf(src)) // Otherwise move it to the tile. For convinience + + fed_something = TRUE + pump_stuff -= food + qdel(food) //Gulp... + continue + else + not_food += AM // That's not (traditionally) edible! + + if(LAZYLEN(not_food)) + clog(not_food) // Now you've gone and clogged us... + + // Feed Voraciously + if(isbelly(output_dest)) + var/list/inedible //Some things shouldnt be eaten... + for(var/atom/movable/AM in this_pump) + pump_stuff -= AM // We're putting this in. Remove it from the list. + if(isitem(AM)) + var/obj/item/I = AM + if(is_type_in_list(I, item_vore_blacklist)) + inedible += I + continue + if(isliving(AM)) + var/mob/living/cutie = AM + if(cutie.devourable != TRUE) //Do not eat this QT... + inedible += cutie + continue + + fed_something = TRUE + AM.forceMove(output_dest) + if(inedible) + clog(inedible) + + // After everything, if we've pushed something, play the "rubber tube noise" + // It's technically an evil digestion sound from a snowflake shadekin, but it makes for a good tube sound. Thanks Verkie! + if(fed_something) + playsound(attached.loc, 'v_CHOMPstation2/sound/rakshasa/Corrosion3.ogg', rand(10,50), 1) + + if(LAZYLEN(pump_stuff) && repeat) + pump() + else + pumping = FALSE + update_icon() + /obj/structure/disposaloutlet/industrial_feeding_tube/expel_holder(obj/structure/disposalholder/H, playsound=FALSE) if(playsound) playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) @@ -183,18 +279,9 @@ if(!H) return - var/turf/T = get_turf(src) + spew(H.contents) - for(var/A in H) - var/atom/movable/AM = A - - target = get_offset_target_turf(loc, rand(5)-rand(5), rand(5)-rand(5)) - - AM.forceMove(T) - AM.pipe_eject(dir) - AM.throw_at(target, eject_range, 1) - - H.vent_gas(T) + H.vent_gas(get_turf(src)) qdel(H) /obj/structure/disposaloutlet/industrial_feeding_tube/attack_hand(mob/user) @@ -202,41 +289,49 @@ if(attached) attached.visible_message("[attached] is detached from [src].") attached = null + output_dest = null update_icon() return /obj/structure/disposaloutlet/industrial_feeding_tube/attackby(obj/item/I, mob/living/user, params) - if(user.a_intent == INTENT_HARM) + if(user.a_intent != INTENT_HELP) return ..() switch(I.tool_behaviour) if(TOOL_WRENCH) if(welded) to_chat(user, "\The [src] is firmly welded to the floor. Cut the floorwelds before trying to unwrench it!") + return TRUE var/turf/T = get_turf(src) - if(!T.intact || !isfloorturf(T)) - to_chat(user, "You need to remove the floor tiles before detaching \the [src]!") - return + if(T.intact && isfloorturf(T)) + to_chat(user, "You need to remove the floor tiles before [anchored ? "detaching" : "attaching"] \the [src]!") + return TRUE if(anchored) I.play_tool_sound(src, 100) - anchored = !anchored + + anchored = FALSE trunk.linked = null trunk = null attached = null output_dest = null + user.visible_message("[user] detaches \the [src] from the floor!") - return + return TRUE else var/found_trunk = FALSE for(var/obj/structure/disposalpipe/P in T) if(istype(P, /obj/structure/disposalpipe/trunk)) + var/obj/structure/disposalpipe/trunk/newtrunk = P + if(newtrunk.linked) //Trunk is already linked to something + continue found_trunk = TRUE + trunk = newtrunk break if(!found_trunk) to_chat(user, "\The [src] requires a trunk underneath it in order to work!") return - + to_chat(user, "You attach \the [src] to the trunk.") - return + anchored = TRUE I.play_tool_sound(src, 100) update_icon() @@ -245,84 +340,113 @@ if(TOOL_CROWBAR) if(!clogged) to_chat(user, "\The [src] doesnt seem to be clogged at the moment...") - return + return TRUE - user.visible_message("[user] inserts [user.p_their()] [I] into the maintenance hatch of \the [src], attempting to unclog it...") + user.visible_message("[user] starts to pry open the maintenance hatch of \the [src], attempting to unclog it...") if(do_after(user, 30, TRUE, src)) user.visible_message("[user] unclogs \the [src]!") unclog() - + return . = ..() -/obj/structure/disposaloutlet/industrial_feeding_tube/proc/clog(list/clog_junk) - for(var/atom/movable/AM in clog_junk) - AM.forceMove(src) - clogged = TRUE - playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 1) - -/obj/structure/disposaloutlet/industrial_feeding_tube/proc/unclog() - - var/turf/T = get_turf(src) - for(var/atom/movable/AM in src) - if(AM == storedFeeder) // We need to keep this... - continue - - target = get_offset_target_turf(loc, rand(2)-rand(2), rand(2)-rand(2)) - - AM.forceMove(T) - AM.pipe_eject(dir) - AM.throw_at(target, eject_range, 1) - /obj/structure/disposaloutlet/industrial_feeding_tube/welder_act(mob/living/user, obj/item/I) if(!I.tool_start_check(user, amount=0)) return if(anchored) - var/turf/T = get_turf(src) - if(!welded) // If we're attaching it, we need to check for the pipe we're attaching to - var/found_trunk = FALSE - for(var/obj/structure/disposalpipe/P in T) - if(istype(P, /obj/structure/disposalpipe/trunk)) - found_trunk = TRUE - break - if(!found_trunk) // No pipe, no attach. - to_chat(user, "\The [src] needs to be welded to a trunk!") - return - - to_chat(user, welded ? "You start slicing the floorweld off \the [src]..." : "You start welding \the [src] in place...") + //var/turf/T = get_turf(src) + if(!welded) + if(!trunk) // If we're attaching it, we need to check for the pipe we're attaching to + to_chat(user, "\The [src] needs to be welded to a trunk.") + return TRUE + to_chat(user, "You start welding \the [src] in place...") + else + if(clogged) // There's junk inside! + to_chat(user, "There's junk inside \the [src]! Clean it out before trying to remove it!") + return TRUE + //Already welded, lets cut it free + to_chat(user, "You start slicing the floorweld off \the [src]...") + playsound(src, 'sound/items/welder2.ogg', 100, 1) if(I.use_tool(src, user, 20)) if(welded) to_chat(user, "You slice the floorweld off [src].") welded = FALSE - return + trunk.linked = null + return TRUE else to_chat(user, "You weld \the [src] to the floor.") welded = TRUE - trunk = locate(/obj/structure/disposalpipe/trunk) in T trunk.linked = src - return + return TRUE else to_chat(user, "You begin deconstructing \the [src]") if(I.use_tool(src, user, 30)) deconstruct(TRUE) - return + return TRUE -/obj/structure/disposaloutlet/industrial_feeding_tube/deconstruct(disassembled) - if(!(flags_1 & NODECONSTRUCT_1)) - if(storedFeeder) - storedFeeder.forceMove(loc) //Lets get our Feeder back - transfer_fingerprints_to(storedFeeder) - storedFeeder = null +// Someone got stuck inside after it got clogged! +// Lets let them force their way out +/obj/structure/disposaloutlet/industrial_feeding_tube/container_resist(mob/living/user) + if(user.stat || !clogged) //If it's not clogged, they'll be ejected soon... One way or another. + return + playsound(src, "clang", 50) + visible_message("\The [src] loudly clongs as something inside tries to break free!") + if(do_after(user, 100)) + unclog() + +/obj/structure/disposaloutlet/industrial_feeding_tube/proc/clog(list/clog_junk) + clogged = TRUE + for(var/atom/movable/AM in clog_junk) + if(!pump_stuff.Find(AM)) + pump_stuff += AM + + playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 1) + +/obj/structure/disposaloutlet/industrial_feeding_tube/proc/unclog() + + spew(pump_stuff) + + clogged = FALSE + +/obj/structure/disposaloutlet/industrial_feeding_tube/proc/spew(var/list/spew_stuff, playsound = FALSE) + var/turf/T = get_turf(src) + + if(playsound) + playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) + for(var/atom/movable/AM in spew_stuff) + if(AM in pump_stuff) + pump_stuff -= AM + target = get_offset_target_turf(loc, rand(2)-rand(2), rand(2)-rand(2)) + + AM.forceMove(T) + AM.pipe_eject(dir) + AM.throw_at(target, eject_range, 1) + +/obj/structure/disposaloutlet/industrial_feeding_tube/proc/face_atom(atom/A) //Literally stolen from /mob. Sue me. + if(!A || !x || !y || !A.x || !A.y ) + return + var/dx = A.x - x + var/dy = A.y - y + if(!dx && !dy) // Wall items are graphically shifted but on the floor + if(A.pixel_y > 16) + setDir(NORTH) + else if(A.pixel_y < -16) + setDir(SOUTH) + else if(A.pixel_x > 16) + setDir(EAST) + else if(A.pixel_x < -16) + setDir(WEST) + return + + if(abs(dx) < abs(dy)) + if(dy > 0) + setDir(NORTH) else - var/feeder = new /obj/machinery/iv_drip/feeding_tube(loc) - transfer_fingerprints_to(feeder) - new /obj/item/stack/sheet/metal(loc, 2) - new /obj/item/pipe(loc) - new /obj/item/pipe(loc) - if(contents) //Anything still glogged inside... - for(var/atom/movable/AM in src) - AM.forceMove(loc) - qdel(src) - \ No newline at end of file + setDir(SOUTH) + else + if(dx > 0) + setDir(EAST) + else + setDir(WEST) diff --git a/GainStation13/icons/obj/feeding_tube_industrial.dmi b/GainStation13/icons/obj/feeding_tube_industrial.dmi new file mode 100644 index 0000000000..99adb797ec Binary files /dev/null and b/GainStation13/icons/obj/feeding_tube_industrial.dmi differ diff --git a/v_CHOMPstation2/sound/rakshasa/Corrosion3.ogg b/v_CHOMPstation2/sound/rakshasa/Corrosion3.ogg new file mode 100644 index 0000000000..cef4bf5c2d Binary files /dev/null and b/v_CHOMPstation2/sound/rakshasa/Corrosion3.ogg differ