diff --git a/code/game/objects/structures/construction_console/construction_console.dm b/code/game/objects/structures/construction_console/construction_console.dm index 73884ac7913..16b070f2d9f 100644 --- a/code/game/objects/structures/construction_console/construction_console.dm +++ b/code/game/objects/structures/construction_console/construction_console.dm @@ -66,12 +66,12 @@ eyeobj = new /mob/eye/camera/remote/base_construction(spawn_spot, src) return TRUE -/obj/machinery/computer/camera_advanced/base_construction/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) +/obj/machinery/computer/camera_advanced/base_construction/item_interaction(mob/living/user, obj/item/tool, list/modifiers) //If we have an internal RCD, we can refill it by slapping the console with some materials - if(internal_rcd && (istype(W, /obj/item/rcd_ammo) || istype(W, /obj/item/stack/sheet))) - internal_rcd.attackby(W, user, modifiers) - else - return ..() + if(!internal_rcd || (!istype(tool, /obj/item/rcd_ammo) && !istype(tool, /obj/item/stack/sheet))) + return NONE + internal_rcd.item_interaction(user, tool, modifiers) + return ITEM_INTERACT_SUCCESS /obj/machinery/computer/camera_advanced/base_construction/Destroy() qdel(internal_rcd) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 858ab649ee9..4c557d67d51 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -693,13 +693,123 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) req_access = accesses req_one_access = null -/obj/structure/closet/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if(user in src) - return - if(src.tool_interact(W,user)) - return 1 // No afterattack - else - return ..() +/obj/structure/closet/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(user in contents) + return ITEM_INTERACT_BLOCKING // can't even attack it from inside + + if(!opened && istype(tool, /obj/item/airlock_painter)) + if(!length(paint_jobs)) + return ITEM_INTERACT_BLOCKING + + var/choice = tgui_input_list(user, "Set Closet Paintjob", "Paintjob", paint_jobs) + if(isnull(choice)) + return ITEM_INTERACT_BLOCKING + + var/obj/item/airlock_painter/painter = tool + if(!painter.use_paint(user)) + return ITEM_INTERACT_BLOCKING + + var/list/paint_job = paint_jobs[choice] + icon_state = paint_job["icon_state"] + base_icon_state = icon_state + icon_door = paint_job["icon_door"] + + update_appearance() + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/electronics/airlock) && can_install_airlock_electronics(user)) + user.visible_message(span_notice("[user] installs the electronics into the [src]."),\ + span_notice("You start to install electronics into the [src]...")) + + if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_airlock_electronics), user))) + return ITEM_INTERACT_BLOCKING + + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + + inherit_airlock_electronics_access(tool) + qdel(tool) + secure = TRUE + balloon_alert(user, "electronics installed") + + update_appearance() + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/stock_parts/card_reader) && can_install_card_reader(user)) + user.visible_message(span_notice("[user] is installing a card reader."), + span_notice("You begin installing the card reader.")) + + if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_card_reader), user))) + return ITEM_INTERACT_BLOCKING + + qdel(tool) + card_reader_installed = TRUE + + balloon_alert(user, "card reader installed") + return ITEM_INTERACT_SUCCESS + + var/obj/item/card/id/card = tool.GetID() + + if(secure && !broken && card_reader_installed && !locked && !opened && !access_locked && card) + var/num_choices = length(access_choices) + if(!num_choices) + return ITEM_INTERACT_BLOCKING + + var/choice + if(num_choices == 1) + choice = access_choices[1] + else + choice = tgui_input_list(user, "Set Access Type", "Access Type", access_choices) + if(isnull(choice)) + return ITEM_INTERACT_BLOCKING + + id_card = null + switch(choice) + if("Personal") //only the player who swiped their id has access. + id_card = WEAKREF(card) + name = "[card.registered_name]'s locker" + desc += " It has been ID locked to [card.registered_name]." + if("Job") //anyone who has the same access permissions as this id has access. Does NOT apply to the whole department. + name = "[card.assignment]'s locker" + desc += " It has been access locked to [card.assignment]s." + set_access(card.GetAccess()) + if("None") //free for all + name = initial(name) + desc = initial(desc) + req_access = list() + req_one_access = null + set_access(list()) + + if(!isnull(id_card)) + balloon_alert(user, "now owned by [card.registered_name]") + else + balloon_alert(user, "set to [choice]") + return ITEM_INTERACT_SUCCESS + + if(opened) + if(istype(tool, cutting_tool) && tool.tool_behaviour != TOOL_WELDER) // for example cardboard box is cut with wirecutters + user.visible_message(span_notice("[user] cut apart \the [src]."), \ + span_notice("You cut \the [src] apart with \the [tool].")) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + + if (user.combat_mode) + return ITEM_INTERACT_SKIP_TO_ATTACK + + if(!user.transfer_item_to_turf(tool, drop_location())) // so we put in unlit welder too + return ITEM_INTERACT_BLOCKING + + return ITEM_INTERACT_SUCCESS + + if(!user.combat_mode || (tool.item_flags & NOBLUDGEON)) + if(!card) + return NONE + if(opened) + return ITEM_INTERACT_BLOCKING + togglelock(user) + return ITEM_INTERACT_SUCCESS + + return NONE /obj/structure/closet/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) if (attack_hand(user, modifiers)) @@ -764,172 +874,96 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) return TRUE -/// returns TRUE if attackBy call shouldn't be continued (because tool was used/closet was of wrong type), FALSE if otherwise -/obj/structure/closet/proc/tool_interact(obj/item/weapon, mob/living/user) - . = TRUE - var/obj/item/card/id/id = null - if(!opened && istype(weapon, /obj/item/airlock_painter)) - if(!length(paint_jobs)) - return - var/choice = tgui_input_list(user, "Set Closet Paintjob", "Paintjob", paint_jobs) - if(isnull(choice)) - return +/obj/structure/closet/screwdriver_act(mob/living/user, obj/item/tool) + if(user in contents) + return ITEM_INTERACT_BLOCKING - var/obj/item/airlock_painter/painter = weapon - if(!painter.use_paint(user)) - return - var/list/paint_job = paint_jobs[choice] - icon_state = paint_job["icon_state"] - base_icon_state = icon_state - icon_door = paint_job["icon_door"] + if(!can_unscrew_airlock_electronics(user)) + return NONE - update_appearance() + user.visible_message(span_notice("[user] begins to remove the electronics from the [src]."),\ + span_notice("You begin to remove the electronics from the [src]...")) - else if(istype(weapon, /obj/item/electronics/airlock) && can_install_airlock_electronics(user)) - user.visible_message(span_notice("[user] installs the electronics into the [src]."),\ - span_notice("You start to install electronics into the [src]...")) + if (!tool.use_tool(src, user, 4 SECONDS, volume = 50, extra_checks = CALLBACK(src, PROC_REF(can_unscrew_airlock_electronics), user))) + return ITEM_INTERACT_BLOCKING - if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_airlock_electronics), user))) - return - if(!user.transferItemToLoc(weapon, src)) - return - - inherit_airlock_electronics_access(weapon) - qdel(weapon) - secure = TRUE - balloon_alert(user, "electronics installed") - - update_appearance() - - else if(weapon.tool_behaviour == TOOL_SCREWDRIVER && can_unscrew_airlock_electronics(user)) - user.visible_message(span_notice("[user] begins to remove the electronics from the [src]."),\ - span_notice("You begin to remove the electronics from the [src]...")) - - if (!weapon.use_tool(src, user, 40, volume = 50, extra_checks = CALLBACK(src, PROC_REF(can_unscrew_airlock_electronics), user))) - return - - var/obj/item/electronics/airlock/airlock_electronics = new(drop_location()) - if(length(req_one_access)) - airlock_electronics.one_access = TRUE - airlock_electronics.accesses = req_one_access - else - airlock_electronics.accesses = req_access - - req_access = list() - req_one_access = null - id_card = null - secure = FALSE - balloon_alert(user, "electronics removed") - - update_appearance() - - else if(istype(weapon, /obj/item/stock_parts/card_reader) && can_install_card_reader(user)) - user.visible_message(span_notice("[user] is installing a card reader."), - span_notice("You begin installing the card reader.")) - - if(!do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, PROC_REF(can_install_card_reader), user))) - return - - qdel(weapon) - card_reader_installed = TRUE - - balloon_alert(user, "card reader installed") - - else if(weapon.tool_behaviour == TOOL_CROWBAR && can_pryout_card_reader(user)) - user.visible_message(span_notice("[user] begins to pry the card reader out from [src]."),\ - span_notice("You begin to pry the card reader out from [src]...")) - - if(!weapon.use_tool(src, user, 4 SECONDS, extra_checks = CALLBACK(src, PROC_REF(can_pryout_card_reader), user))) - return - - new /obj/item/stock_parts/card_reader(drop_location()) - card_reader_installed = FALSE - - balloon_alert(user, "card reader removed") - - else if(secure && !broken && card_reader_installed && !locked && !opened && !access_locked && !isnull((id = weapon.GetID()))) - var/num_choices = length(access_choices) - if(!num_choices) - return - - var/choice - if(num_choices == 1) - choice = access_choices[1] - else - choice = tgui_input_list(user, "Set Access Type", "Access Type", access_choices) - if(isnull(choice)) - return - - id_card = null - switch(choice) - if("Personal") //only the player who swiped their id has access. - id_card = WEAKREF(id) - name = "[id.registered_name]'s locker" - desc += " It has been ID locked to [id.registered_name]." - if("Job") //anyone who has the same access permissions as this id has access. Does NOT apply to the whole department. - name = "[id.assignment]'s locker" - desc += " It has been access locked to [id.assignment]s." - set_access(id.GetAccess()) - if("None") //free for all - name = initial(name) - desc = initial(desc) - req_access = list() - req_one_access = null - set_access(list()) - - if(!isnull(id_card)) - balloon_alert(user, "now owned by [id.registered_name]") - else - balloon_alert(user, "set to [choice]") - - else if(opened) - if(istype(weapon, cutting_tool)) - if(weapon.tool_behaviour == TOOL_WELDER) - if(!weapon.tool_start_check(user, amount=1)) - return - - to_chat(user, span_notice("You begin cutting \the [src] apart...")) - if(weapon.use_tool(src, user, 40, volume=50)) - if(!opened) - return - user.visible_message(span_notice("[user] slices apart \the [src]."), - span_notice("You cut \the [src] apart with \the [weapon]."), - span_hear("You hear welding.")) - deconstruct(TRUE) - return - else // for example cardboard box is cut with wirecutters - user.visible_message(span_notice("[user] cut apart \the [src]."), \ - span_notice("You cut \the [src] apart with \the [weapon].")) - deconstruct(TRUE) - return - if (user.combat_mode) - return - if(user.transfer_item_to_turf(weapon, drop_location())) // so we put in unlit welder too - return - - else if(weapon.tool_behaviour == TOOL_WELDER && can_weld_shut) - if(!weapon.tool_start_check(user, amount=1)) - return - - if(weapon.use_tool(src, user, 40, volume=50)) - if(opened) - return - welded = !welded - after_weld(welded) - user.visible_message(span_notice("[user] [welded ? "welds shut" : "unwelded"] \the [src]."), - span_notice("You [welded ? "weld" : "unwelded"] \the [src] with \the [weapon]."), - span_hear("You hear welding.")) - user.log_message("[welded ? "welded":"unwelded"] closet [src] with [weapon]", LOG_GAME) - update_appearance() - - else if(!user.combat_mode || (weapon.item_flags & NOBLUDGEON)) - var/item_is_id = weapon.GetID() - if(!item_is_id) - return FALSE - if((item_is_id || !toggle(user)) && !opened) - togglelock(user) + var/obj/item/electronics/airlock/airlock_electronics = new(drop_location()) + if(length(req_one_access)) + airlock_electronics.one_access = TRUE + airlock_electronics.accesses = req_one_access else - return FALSE + airlock_electronics.accesses = req_access + + req_access = list() + req_one_access = null + id_card = null + secure = FALSE + balloon_alert(user, "electronics removed") + + update_appearance() + return ITEM_INTERACT_SUCCESS + +/obj/structure/closet/crowbar_act(mob/living/user, obj/item/tool) + if(user in contents) + return ITEM_INTERACT_BLOCKING + + if(!can_pryout_card_reader(user)) + return NONE + + user.visible_message(span_notice("[user] begins to pry the card reader out from [src]."),\ + span_notice("You begin to pry the card reader out from [src]...")) + + if(!tool.use_tool(src, user, 4 SECONDS, extra_checks = CALLBACK(src, PROC_REF(can_pryout_card_reader), user))) + return ITEM_INTERACT_BLOCKING + + new /obj/item/stock_parts/card_reader(drop_location()) + card_reader_installed = FALSE + + balloon_alert(user, "card reader removed") + return ITEM_INTERACT_SUCCESS + +/obj/structure/closet/welder_act(mob/living/user, obj/item/tool) + if(user in contents) + return ITEM_INTERACT_BLOCKING + + if(opened && istype(tool, cutting_tool)) // not all of them take welders + if(!tool.tool_start_check(user, amount=1)) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You begin cutting \the [src] apart...")) + if(!tool.use_tool(src, user, 4 SECONDS, volume=50)) + return ITEM_INTERACT_BLOCKING + + if(!opened) + return ITEM_INTERACT_BLOCKING + + user.visible_message(span_notice("[user] slices apart \the [src]."), + span_notice("You cut \the [src] apart with \the [tool]."), + span_hear("You hear welding.")) + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS + + if(!can_weld_shut) + return NONE + + if(!tool.tool_start_check(user, amount=1)) + return ITEM_INTERACT_BLOCKING + + if(!tool.use_tool(src, user, 4 SECONDS, volume=50)) + return ITEM_INTERACT_BLOCKING + + if(opened) + return ITEM_INTERACT_BLOCKING + + welded = !welded + after_weld(welded) + user.visible_message(span_notice("[user] [welded ? "welds shut" : "unwelded"] \the [src]."), + span_notice("You [welded ? "weld" : "unwelded"] \the [src] with \the [tool]."), + span_hear("You hear welding.")) + user.log_message("[welded ? "welded":"unwelded"] closet [src] with [tool]", LOG_GAME) + update_appearance() + return ITEM_INTERACT_SUCCESS + /obj/structure/closet/wrench_act_secondary(mob/living/user, obj/item/tool) if(!anchorable) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 56c61bb39c5..f1fd3166e43 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -202,14 +202,25 @@ . = ..() . += span_notice("Right-click with a Security-level ID to reset [src]'s registered ID.") -/obj/structure/closet/secure_closet/brig/genpop/attackby(obj/item/card/id/advanced/prisoner/user_id, mob/user, list/modifiers, list/attack_modifiers) - if(!secure || !istype(user_id)) +/obj/structure/closet/secure_closet/brig/genpop/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!secure || !istype(tool, /obj/item/card/id)) return ..() - if(isnull(id_card)) - say("Prisoner ID linked to locker.") - id_card = WEAKREF(user_id) - name = "genpop storage locker - [user_id.registered_name]" + if(!isnull(id_card)) + return ITEM_INTERACT_BLOCKING + + say("Prisoner ID linked to locker.") + id_card = WEAKREF(tool) + name = "genpop storage locker - [astype(tool, /obj/item/card/id/advanced/prisoner).registered_name]" + return ITEM_INTERACT_SUCCESS + +/obj/structure/closet/secure_closet/brig/genpop/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + var/list/id_access = astype(tool, /obj/item/card/id).GetAccess() + if(!id_card || !(ACCESS_BRIG in id_access)) + return NONE + + clear_access() + return ITEM_INTERACT_SUCCESS /obj/structure/closet/secure_closet/brig/genpop/proc/clear_access() say("Authorized ID detected. Unlocking locker and resetting ID.") @@ -218,16 +229,6 @@ name = initial(name) update_appearance() -/obj/structure/closet/secure_closet/brig/genpop/attackby_secondary(obj/item/card/id/advanced/used_id, mob/user, list/modifiers, list/attack_modifiers) - if(!secure || !istype(used_id)) - return ..() - - var/list/id_access = used_id.GetAccess() - if(!isnull(id_card) && (ACCESS_BRIG in id_access)) - clear_access() - - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - /obj/structure/closet/secure_closet/evidence anchored = TRUE name = "secure evidence closet" diff --git a/code/game/objects/structures/crates_lockers/crates/bins.dm b/code/game/objects/structures/crates_lockers/crates/bins.dm index 36a907ee0b6..4867e42a471 100644 --- a/code/game/objects/structures/crates_lockers/crates/bins.dm +++ b/code/game/objects/structures/crates_lockers/crates/bins.dm @@ -33,17 +33,15 @@ return . += base_icon_state + "_some" -/obj/structure/closet/crate/bin/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if(istype(W, /obj/item/storage/bag/trash) && !opened) - var/obj/item/storage/bag/trash/T = W - to_chat(user, span_notice("You fill the bag.")) - for(var/obj/item/O in src) - T.atom_storage?.attempt_insert(O, user, TRUE) - T.update_appearance() - do_animate() - return TRUE - else +/obj/structure/closet/crate/bin/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/storage/bag/trash) || !opened) return ..() + var/obj/item/storage/bag/trash/garbage_bag = tool + to_chat(user, span_notice("You fill the bag.")) + for(var/obj/item/garbage in src) + garbage_bag.atom_storage?.attempt_insert(garbage, user, TRUE) + do_animate() + return ITEM_INTERACT_SUCCESS /obj/structure/closet/crate/bin/proc/do_animate() playsound(loc, open_sound, 15, TRUE, -3) diff --git a/code/game/objects/structures/crates_lockers/crates/large.dm b/code/game/objects/structures/crates_lockers/crates/large.dm index a527d48727a..2ebef6224a7 100644 --- a/code/game/objects/structures/crates_lockers/crates/large.dm +++ b/code/game/objects/structures/crates_lockers/crates/large.dm @@ -31,32 +31,31 @@ else to_chat(user, span_warning("You need a crowbar to pry this open!")) -/obj/structure/closet/crate/large/attackby(obj/item/W, mob/living/user, list/modifiers, list/attack_modifiers) - if(W.tool_behaviour == TOOL_CROWBAR) - if(manifest) - tear_manifest(user) - if(!open(user)) - return FALSE - user.visible_message(span_notice("[user] pries \the [src] open."), \ - span_notice("You pry open \the [src]."), \ - span_hear("You hear splitting wood.")) - playsound(src.loc, 'sound/items/weapons/slashmiss.ogg', 75, TRUE) +/obj/structure/closet/crate/large/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(user.combat_mode) + return ITEM_INTERACT_SKIP_TO_ATTACK //Stops it from opening and turning invisible when items are used on it. - var/turf/T = get_turf(src) - for(var/i in 1 to material_drop_amount) - new material_drop(src) - for(var/atom/movable/AM in contents) - AM.forceMove(T) - qdel(src) + to_chat(user, span_warning("You need a crowbar to pry this open!")) + return ITEM_INTERACT_BLOCKING //Just stop. Do nothing. Don't turn into an invisible sprite. Don't open like a locker. + //The large crate has no non-attack interactions other than the crowbar, anyway. - else - if(user.combat_mode) //Only return ..() if intent is harm, otherwise return 0 or just end it. - return ..() //Stops it from opening and turning invisible when items are used on it. +/obj/structure/closet/crate/large/crowbar_act(mob/living/user, obj/item/tool) + if(manifest) + tear_manifest(user) + if(!open(user)) + return ITEM_INTERACT_BLOCKING + user.visible_message(span_notice("[user] pries \the [src] open."), \ + span_notice("You pry open \the [src]."), \ + span_hear("You hear splitting wood.")) + playsound(src.loc, 'sound/items/weapons/slashmiss.ogg', 75, TRUE) - else - to_chat(user, span_warning("You need a crowbar to pry this open!")) - return FALSE //Just stop. Do nothing. Don't turn into an invisible sprite. Don't open like a locker. - //The large crate has no non-attack interactions other than the crowbar, anyway. + var/turf/dump = get_turf(src) + for(var/i in 1 to material_drop_amount) + new material_drop(src) + for(var/atom/movable/stuff in contents) + stuff.forceMove(dump) + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/structure/closet/crate/large/hats/PopulateContents() ..() diff --git a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm index 45ffc987a0e..f1f6ce6863e 100644 --- a/code/game/objects/structures/crates_lockers/crates/syndicrate.dm +++ b/code/game/objects/structures/crates_lockers/crates/syndicrate.dm @@ -43,17 +43,18 @@ qdel(src) ///ensures that the syndicrate can only be unlocked by opening it with a syndicrate_key -/obj/structure/closet/crate/secure/syndicrate/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers) - if(!istype(item, /obj/item/syndicrate_key) || created_items) +/obj/structure/closet/crate/secure/syndicrate/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/syndicrate_key) || created_items) return ..() created_items = TRUE for(var/item_path in unlock_contents) new item_path(src) unlock_contents = list() - qdel(item) + qdel(tool) to_chat(user, span_notice("You twist the key into both locks at once, opening the crate.")) playsound(src, 'sound/machines/airlock/boltsup.ogg', 50, vary = FALSE) togglelock(user) + return ITEM_INTERACT_SUCCESS /obj/structure/closet/crate/secure/syndicrate/togglelock(mob/living/user, silent) if(broken || !created_items) @@ -67,8 +68,8 @@ ) update_appearance() -/obj/structure/closet/crate/secure/syndicrate/attackby_secondary(obj/item/weapon, mob/user, list/modifiers, list/attack_modifiers) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/structure/closet/crate/secure/syndicrate/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + return ITEM_INTERACT_BLOCKING /obj/item/syndicrate_key name = "syndicrate key" diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index e9322232650..ca935f2914e 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -66,15 +66,16 @@ /obj/structure/lattice/blob_act(obj/structure/blob/B) return -/obj/structure/lattice/attackby(obj/item/C, mob/user, list/modifiers, list/attack_modifiers) +/obj/structure/lattice/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + var/turf/underneath = get_turf(src) + return underneath.item_interaction(user, tool) //hand this off to the turf instead (for building plating, catwalks, etc) + +/obj/structure/lattice/wirecutter_act(mob/living/user, obj/item/tool) if(resistance_flags & INDESTRUCTIBLE) - return - if(C.tool_behaviour == TOOL_WIRECUTTER) - to_chat(user, span_notice("Slicing [name] joints ...")) - deconstruct() - else - var/turf/T = get_turf(src) - return T.attackby(C, user) //hand this off to the turf instead (for building plating, catwalks, etc) + return NONE + to_chat(user, span_notice("Slicing [name] joints ...")) + deconstruct() + return ITEM_INTERACT_SUCCESS /obj/structure/lattice/atom_deconstruct(disassembled = TRUE) if(!isnull(build_material) && number_of_mats >= 1) @@ -158,13 +159,6 @@ desc = "A heavily reinforced catwalk used to build bridges in hostile environments. It doesn't look like anything could make this budge." resistance_flags = INDESTRUCTIBLE -/obj/structure/lattice/catwalk/mining/attackby(obj/item/C, mob/user, list/modifiers, list/attack_modifiers) - // Allow cable placement even though we're indestructible - if(istype(C, /obj/item/stack/cable_coil)) - var/turf/T = get_turf(src) - return T.attackby(C, user) - return ..() - /obj/structure/lattice/catwalk/mining/deconstruction_hints(mob/user) return @@ -181,21 +175,22 @@ /obj/structure/lattice/catwalk/lava/deconstruction_hints(mob/user) return span_notice("The rods look like they could be cut, but the heat treatment will shatter off. There's space for a tile.") -/obj/structure/lattice/catwalk/lava/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - . = ..() - if(!ismetaltile(attacking_item)) - return - var/obj/item/stack/tile/iron/attacking_tiles = attacking_item +/obj/structure/lattice/catwalk/lava/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!ismetaltile(tool)) + return ..() + var/obj/item/stack/tile/iron/attacking_tiles = tool if(!attacking_tiles.use(1)) to_chat(user, span_warning("You need one floor tile to build atop [src].")) - return + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You construct new plating with [src] as support.")) playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE) - var/turf/turf_we_place_on = get_turf(src) - turf_we_place_on.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) + var/turf/base = get_turf(src) + base.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/structure/lattice/catwalk/boulder name = "boulder platform" @@ -214,10 +209,10 @@ fast_emissive_blocker(src) AddElement(/datum/element/elevation, pixel_shift = 8) -/obj/structure/lattice/catwalk/boulder/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - if(ismetaltile(attacking_item)) +/obj/structure/lattice/catwalk/boulder/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(ismetaltile(tool)) balloon_alert(user, "too unstable!") - return FALSE + return ITEM_INTERACT_BLOCKING return ..() /obj/structure/lattice/catwalk/boulder/CanAllowThrough(atom/movable/mover, border_dir) diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm index eb969552f3a..5c8a748cd41 100644 --- a/code/game/objects/structures/lavaland/geyser.dm +++ b/code/game/objects/structures/lavaland/geyser.dm @@ -62,14 +62,14 @@ RegisterSignal(reagents, COMSIG_REAGENTS_HOLDER_UPDATED, PROC_REF(start_chemming)) return PROCESS_KILL -/obj/structure/geyser/attackby(obj/item/item, mob/user, list/modifiers, list/attack_modifiers) - if(!istype(item, /obj/item/mining_scanner) && !istype(item, /obj/item/t_scanner/adv_mining_scanner)) +/obj/structure/geyser/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/mining_scanner) && !istype(tool, /obj/item/t_scanner/adv_mining_scanner)) playsound(src, SFX_INDUSTRIAL_SCAN, 20, TRUE, -2, TRUE, FALSE) - return ..() //this runs the plunger code + return NONE //this runs the plunger code if(discovered) to_chat(user, span_warning("This geyser has already been discovered!")) - return + return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You discovered the geyser and mark it on the GPS system!")) playsound(src, 'sound/machines/beep/twobeep_high.ogg', 30) @@ -83,13 +83,11 @@ AddComponent(/datum/component/gps, true_name) //put it on the gps so miners can mark it and chemists can profit off of it - if(isliving(user)) - var/mob/living/living = user - - var/obj/item/card/id/card = living.get_idcard() - if(card) - to_chat(user, span_notice("[point_value] mining points have been paid out!")) - card.registered_account.mining_points += point_value + var/obj/item/card/id/card = user.get_idcard() + if(card) + to_chat(user, span_notice("[point_value] mining points have been paid out!")) + card.registered_account.mining_points += point_value + return ITEM_INTERACT_SUCCESS /obj/structure/geyser/wittel reagent_id = /datum/reagent/wittel diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 3f2edfc7416..f70db6870f6 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -107,17 +107,16 @@ SSore_generation.processed_vents -= src return ..() -/obj/structure/ore_vent/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - . = ..() - if(.) - return TRUE - if(!is_type_in_list(attacking_item, scanning_equipment)) - return TRUE +/obj/structure/ore_vent/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!is_type_in_list(tool, scanning_equipment)) + return NONE + if(tapped) balloon_alert_to_viewers("vent tapped!") - return TRUE + return ITEM_INTERACT_BLOCKING + scan_and_confirm(user) - return TRUE + return ITEM_INTERACT_SUCCESS /obj/structure/ore_vent/attack_hand(mob/living/user, list/modifiers) . = ..() diff --git a/code/game/objects/structures/plaques/_plaques.dm b/code/game/objects/structures/plaques/_plaques.dm index de143b17f9f..fa0e8ff0db6 100644 --- a/code/game/objects/structures/plaques/_plaques.dm +++ b/code/game/objects/structures/plaques/_plaques.dm @@ -82,37 +82,45 @@ atom_integrity = max_integrity return TRUE -/obj/structure/plaque/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(istype(I, /obj/item/pen/fountain)) - if(engraved) - to_chat(user, span_warning("This plaque has already been engraved.")) - return - var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) - if(!namechoice) - return - var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) - if(!descriptionchoice) - return - if(!Adjacent(user)) //Make sure user is adjacent still - to_chat(user, span_warning("You need to stand next to the plaque to engrave it!")) - return - user.visible_message(span_notice("[user] begins engraving [src]."), \ - span_notice("You begin engraving [src].")) - if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay. - return - name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title. - desc = "The plaque reads: '[descriptionchoice]'" - engraved = TRUE //The plaque now has a name, description, and can't be altered again. - user.visible_message(span_notice("[user] engraves [src]."), \ - span_notice("You engrave [src].")) - return - if(istype(I, /obj/item/pen)) +/obj/structure/plaque/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/pen)) + return NONE + + if(!istype(tool, /obj/item/pen/fountain)) if(engraved) to_chat(user, span_warning("This plaque has already been engraved, and your pen isn't fancy enough to engrave it anyway! Find a fountain pen.")) - return + return ITEM_INTERACT_BLOCKING + to_chat(user, span_warning("Your pen isn't fancy enough to engrave this! Find a fountain pen.")) //Go steal the Curator's. - return - return ..() + return ITEM_INTERACT_BLOCKING + + if(engraved) + to_chat(user, span_warning("This plaque has already been engraved.")) + return ITEM_INTERACT_BLOCKING + + var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) + if(!namechoice) + return ITEM_INTERACT_BLOCKING + + var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) + if(!descriptionchoice) + return ITEM_INTERACT_BLOCKING + + if(!Adjacent(user)) //Make sure user is adjacent still + to_chat(user, span_warning("You need to stand next to the plaque to engrave it!")) + return ITEM_INTERACT_BLOCKING + + user.visible_message(span_notice("[user] begins engraving [src]."), \ + span_notice("You begin engraving [src].")) + if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay. + return ITEM_INTERACT_BLOCKING + + name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title. + desc = "The plaque reads: '[descriptionchoice]'" + engraved = TRUE //The plaque now has a name, description, and can't be altered again. + user.visible_message(span_notice("[user] engraves [src]."), \ + span_notice("You engrave [src].")) + return ITEM_INTERACT_SUCCESS /obj/item/plaque //The item version of the above. icon = 'icons/obj/signs.dmi' @@ -155,37 +163,45 @@ return TRUE -/obj/item/plaque/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) //Same as part of the above, except for the item in hand instead of the structure. - if(istype(I, /obj/item/pen/fountain)) - if(engraved) - to_chat(user, span_warning("This plaque has already been engraved.")) - return - var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) - if(!namechoice) - return - var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) - if(!descriptionchoice) - return - if(!Adjacent(user)) //Make sure user is adjacent still - to_chat(user, span_warning("You need to stand next to the plaque to engrave it!")) - return - user.visible_message(span_notice("[user] begins engraving [src]."), \ - span_notice("You begin engraving [src].")) - if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay. - return - name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title. - desc = "The plaque reads: '[descriptionchoice]'" - engraved = TRUE //The plaque now has a name, description, and can't be altered again. - user.visible_message(span_notice("[user] engraves [src]."), \ - span_notice("You engrave [src].")) - return - if(istype(I, /obj/item/pen)) +/obj/item/plaque/item_interaction(mob/living/user, obj/item/tool, list/modifiers) //Same as part of the above, except for the item in hand instead of the structure. + if(!istype(tool, /obj/item/pen)) + return NONE + + if(!istype(tool, /obj/item/pen/fountain)) if(engraved) to_chat(user, span_warning("This plaque has already been engraved, and your pen isn't fancy enough to engrave it anyway! Find a fountain pen.")) - return + return ITEM_INTERACT_BLOCKING + to_chat(user, span_warning("Your pen isn't fancy enough to engrave this! Find a fountain pen.")) //Go steal the Curator's. - return - return ..() + return ITEM_INTERACT_BLOCKING + + if(engraved) + to_chat(user, span_warning("This plaque has already been engraved.")) + return ITEM_INTERACT_BLOCKING + + var/namechoice = tgui_input_text(user, "Title this plaque. (e.g. 'Best HoP Award', 'Great Ashwalker War Memorial')", "Plaque Customization", max_length = MAX_NAME_LEN) + if(!namechoice) + return ITEM_INTERACT_BLOCKING + + var/descriptionchoice = tgui_input_text(user, "Engrave this plaque's text", "Plaque Customization", max_length = MAX_PLAQUE_LEN) + if(!descriptionchoice) + return ITEM_INTERACT_BLOCKING + + if(!Adjacent(user)) //Make sure user is adjacent still + to_chat(user, span_warning("You need to stand next to the plaque to engrave it!")) + return ITEM_INTERACT_BLOCKING + + user.visible_message(span_notice("[user] begins engraving [src]."), \ + span_notice("You begin engraving [src].")) + if(!do_after(user, 4 SECONDS, target = src)) //This spits out a visible message that somebody is engraving a plaque, then has a delay. + return ITEM_INTERACT_BLOCKING + + name = "\improper [namechoice]" //We want improper here so examine doesn't get weird if somebody capitalizes the plaque title. + desc = "The plaque reads: '[descriptionchoice]'" + engraved = TRUE //The plaque now has a name, description, and can't be altered again. + user.visible_message(span_notice("[user] engraves [src]."), \ + span_notice("You engrave [src].")) + return ITEM_INTERACT_SUCCESS /obj/item/plaque/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!iswallturf(interacting_with)) diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index 7be5596412f..8e7aaf902f6 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -81,33 +81,38 @@ atom_integrity = max_integrity return TRUE -/obj/structure/sign/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(is_editable && IS_WRITING_UTENSIL(I)) - if(!length(GLOB.editable_sign_types)) - CRASH("GLOB.editable_sign_types failed to populate") - var/choice = tgui_input_list(user, "Select a sign type", "Sign Customization", GLOB.editable_sign_types) - if(isnull(choice)) - return - if(!Adjacent(user)) //Make sure user is adjacent still. - to_chat(user, span_warning("You need to stand next to the sign to change it!")) - return - user.visible_message(span_notice("[user] begins changing [src]."), \ - span_notice("You begin changing [src].")) - if(!do_after(user, 4 SECONDS, target = src)) //Small delay for changing signs instead of it being instant, so somebody could be shoved or stunned to prevent them from doing so. - return - var/sign_type = GLOB.editable_sign_types[choice] - //It's import to clone the pixel layout information. - //Otherwise signs revert to being on the turf and - //move jarringly. - var/obj/structure/sign/changedsign = new sign_type(get_turf(src)) - changedsign.pixel_x = pixel_x - changedsign.pixel_y = pixel_y - changedsign.atom_integrity = atom_integrity - qdel(src) - user.visible_message(span_notice("[user] finishes changing the sign."), \ - span_notice("You finish changing the sign.")) - return - return ..() +/obj/structure/sign/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!is_editable || !IS_WRITING_UTENSIL(tool)) + return NONE + + if(!length(GLOB.editable_sign_types)) + CRASH("GLOB.editable_sign_types failed to populate") + + var/choice = tgui_input_list(user, "Select a sign type", "Sign Customization", GLOB.editable_sign_types) + if(isnull(choice)) + return ITEM_INTERACT_BLOCKING + + if(!Adjacent(user)) //Make sure user is adjacent still. + to_chat(user, span_warning("You need to stand next to the sign to change it!")) + return ITEM_INTERACT_BLOCKING + + user.visible_message(span_notice("[user] begins changing [src]."), \ + span_notice("You begin changing [src].")) + if(!do_after(user, 4 SECONDS, target = src)) //Small delay for changing signs instead of it being instant, so somebody could be shoved or stunned to prevent them from doing so. + return ITEM_INTERACT_BLOCKING + + var/sign_type = GLOB.editable_sign_types[choice] + //It's import to clone the pixel layout information. + //Otherwise signs revert to being on the turf and + //move jarringly. + var/obj/structure/sign/changedsign = new sign_type(get_turf(src)) + changedsign.pixel_x = pixel_x + changedsign.pixel_y = pixel_y + changedsign.atom_integrity = atom_integrity + qdel(src) + user.visible_message(span_notice("[user] finishes changing the sign."), \ + span_notice("You finish changing the sign.")) + return ITEM_INTERACT_SUCCESS /obj/structure/sign/atom_deconstruct(disassembled) var/turf/drop_turf = drop_location() diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index 213d086bfc3..e35232700a0 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -93,12 +93,13 @@ break -/obj/structure/transit_tube/station/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if(W.tool_behaviour == TOOL_CROWBAR) - for(var/obj/structure/transit_tube_pod/P in loc) - P.deconstruct(FALSE, user) - else - return ..() +/obj/structure/transit_tube/station/crowbar_act(mob/living/user, obj/item/tool) + var/anything_done = FALSE + for(var/obj/structure/transit_tube_pod/victim in loc) + victim.deconstruct(FALSE, user) + anything_done = TRUE + to_chat(user, span_notice("[anything_done ? "You empty \the [src]." : "\The [src] is already empty!"]")) + return ITEM_INTERACT_SUCCESS /obj/structure/transit_tube/station/proc/open_animation() if(open_status == STATION_TUBE_CLOSED) diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm index 4991eb9df11..5cae9c9b989 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube.dm @@ -32,25 +32,31 @@ if(current_size >= STAGE_FIVE) deconstruct(FALSE) -/obj/structure/transit_tube/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers) - if(W.tool_behaviour == TOOL_WRENCH) - if(tube_construction) - for(var/obj/structure/transit_tube_pod/pod in src.loc) - to_chat(user, span_warning("Remove the pod first!")) - return - user.visible_message(span_notice("[user] starts to detach \the [src]."), span_notice("You start to detach \the [src]...")) - if(W.use_tool(src, user, 2 SECONDS, volume=50)) - to_chat(user, span_notice("You detach \the [src].")) - var/obj/structure/c_transit_tube/R = new tube_construction(loc) - R.setDir(dir) - transfer_fingerprints_to(R) - R.add_fingerprint(user) - qdel(src) - else if(W.tool_behaviour == TOOL_CROWBAR) - for(var/obj/structure/transit_tube_pod/pod in src.loc) - pod.attackby(W, user) - else - return ..() +/obj/structure/transit_tube/wrench_act(mob/living/user, obj/item/tool) + if(!tube_construction) + return NONE + + for(var/obj/structure/transit_tube_pod/pod in loc) + to_chat(user, span_warning("Remove the pod first!")) + return ITEM_INTERACT_BLOCKING + + user.visible_message(span_notice("[user] starts to detach \the [src]."), \ + span_notice("You start to detach \the [src]...")) + if(!tool.use_tool(src, user, 2 SECONDS, volume=50)) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You detach \the [src].")) + var/obj/structure/c_transit_tube/husk = new tube_construction(loc) + husk.setDir(dir) + transfer_fingerprints_to(husk) + husk.add_fingerprint(user) + qdel(src) + return ITEM_INTERACT_SUCCESS + +/obj/structure/transit_tube/crowbar_act(mob/living/user, obj/item/tool) + for(var/obj/structure/transit_tube_pod/pod in loc) + pod.item_interaction(user, tool) + return ITEM_INTERACT_SUCCESS // Called to check if a pod should stop upon entering this tube. /obj/structure/transit_tube/proc/should_stop_pod(pod, from_dir) diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 30ea69ff0d4..d9653d94bd8 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -26,17 +26,18 @@ icon_state = contents.len ? occupied_icon_state : initial(icon_state) return ..() -/obj/structure/transit_tube_pod/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers) - if(I.tool_behaviour == TOOL_CROWBAR) - if(!moving) - I.play_tool_sound(src) - if(contents.len) - user.visible_message(span_notice("[user] empties \the [src]."), span_notice("You empty \the [src].")) - empty_pod() - else - deconstruct(TRUE) +/obj/structure/transit_tube_pod/crowbar_act(mob/living/user, obj/item/tool) + if(moving) // can you even click on one of these while they're in a tube? + return NONE // for that matter can you click them when they're outside of a tube? + + tool.play_tool_sound(src) + if(contents.len) + user.visible_message(span_notice("[user] empties \the [src]."), \ + span_notice("You empty \the [src].")) + empty_pod() else - return ..() + deconstruct(TRUE) + return ITEM_INTERACT_SUCCESS /obj/structure/transit_tube_pod/atom_deconstruct(disassembled = TRUE) var/atom/location = get_turf(src) diff --git a/code/game/objects/structures/water_structures/urinal.dm b/code/game/objects/structures/water_structures/urinal.dm index 485fe6fb3f4..ced7b893973 100644 --- a/code/game/objects/structures/water_structures/urinal.dm +++ b/code/game/objects/structures/water_structures/urinal.dm @@ -51,21 +51,25 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/urinal, 32) return return ..() -/obj/structure/urinal/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) - if(exposed) - if(hidden_item) - to_chat(user, span_warning("There is already something in the drain enclosure!")) - return - if(attacking_item.w_class > WEIGHT_CLASS_TINY) - to_chat(user, span_warning("[attacking_item] is too large for the drain enclosure.")) - return - if(!user.transferItemToLoc(attacking_item, src)) - to_chat(user, span_warning("[attacking_item] is stuck to your hand, you cannot put it in the drain enclosure!")) - return - hidden_item = attacking_item - to_chat(user, span_notice("You place [attacking_item] into the drain enclosure.")) - return - return ..() +/obj/structure/urinal/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!exposed) + return NONE + + if(hidden_item) + to_chat(user, span_warning("There is already something in the drain enclosure!")) + return ITEM_INTERACT_BLOCKING + + if(tool.w_class > WEIGHT_CLASS_TINY) + to_chat(user, span_warning("[tool] is too large for the drain enclosure.")) + return ITEM_INTERACT_BLOCKING + + if(!user.transferItemToLoc(tool, src)) + to_chat(user, span_warning("[tool] is stuck to your hand, you cannot put it in the drain enclosure!")) + return ITEM_INTERACT_BLOCKING + + hidden_item = tool + to_chat(user, span_notice("You place [tool] into the drain enclosure.")) + return ITEM_INTERACT_SUCCESS /obj/structure/urinal/screwdriver_act(mob/living/user, obj/item/I) if(..()) diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm index fc5411991fc..967614f8565 100644 --- a/code/game/objects/structures/water_structures/water_source.dm +++ b/code/game/objects/structures/water_structures/water_source.dm @@ -57,26 +57,28 @@ span_notice("You wash your [washing_face ? "face" : "hands"] using [src]."), ) -/obj/structure/water_source/attackby(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers) +/obj/structure/water_source/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(busy) to_chat(user, span_warning("Someone's already washing here!")) - return + return ITEM_INTERACT_BLOCKING - if(attacking_item.item_flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand. - return + if(tool.item_flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand. + return ITEM_INTERACT_BLOCKING - if(is_reagent_container(attacking_item)) - var/obj/item/reagent_containers/container = attacking_item - if(container.is_refillable()) - if(!container.reagents.holder_full()) - container.reagents.add_reagent(dispensedreagent, min(container.volume - container.reagents.total_volume, container.amount_per_transfer_from_this)) - to_chat(user, span_notice("You fill [container] from [src].")) - return TRUE - to_chat(user, span_notice("\The [container] is full.")) - return FALSE + if(is_reagent_container(tool)) + var/obj/item/reagent_containers/container = tool + if(container.is_refillable()) // no early return, we want items that cannot perform their unique interactions to wash + if(container.reagents.holder_full()) + to_chat(user, span_notice("\The [container] is full.")) + return ITEM_INTERACT_BLOCKING - if(istype(attacking_item, /obj/item/melee/baton/security)) - var/obj/item/melee/baton/security/baton = attacking_item + container.reagents.add_reagent(dispensedreagent, min(container.volume - container.reagents.total_volume, container.amount_per_transfer_from_this)) + to_chat(user, span_notice("You fill [container] from [src].")) + return ITEM_INTERACT_SUCCESS + + + if(istype(tool, /obj/item/melee/baton/security)) + var/obj/item/melee/baton/security/baton = tool if(baton.cell?.charge && baton.active) flick("baton_active", src) user.Paralyze(baton.knockdown_time) @@ -86,29 +88,29 @@ span_warning("[user] shocks [user.p_them()]self while attempting to wash the active [baton.name]!"), span_userdanger("You unwisely attempt to wash [baton] while it's still on.")) playsound(src, baton.on_stun_sound, 50, TRUE) - return + return ITEM_INTERACT_SUCCESS - if(istype(attacking_item, /obj/item/mop)) - attacking_item.reagents.add_reagent(dispensedreagent, 5) - to_chat(user, span_notice("You wet [attacking_item] in [src].")) + if(istype(tool, /obj/item/mop)) + tool.reagents.add_reagent(dispensedreagent, 5) + to_chat(user, span_notice("You wet [tool] in [src].")) playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE) - return + return ITEM_INTERACT_SUCCESS - if(!user.combat_mode || (attacking_item.item_flags & NOBLUDGEON)) - to_chat(user, span_notice("You start washing [attacking_item]...")) + if(!user.combat_mode || (tool.item_flags & NOBLUDGEON)) + to_chat(user, span_notice("You start washing [tool]...")) busy = TRUE if(!do_after(user, 4 SECONDS, target = src)) busy = FALSE - return TRUE + return ITEM_INTERACT_BLOCKING busy = FALSE - attacking_item.wash(CLEAN_WASH) - reagents.expose(attacking_item, TOUCH, 5 / max(reagents.total_volume, 5)) + tool.wash(CLEAN_WASH) + reagents.expose(tool, TOUCH, 5 / max(reagents.total_volume, 5)) user.visible_message( - span_notice("[user] washes [attacking_item] using [src]."), - span_notice("You wash [attacking_item] using [src].")) - return TRUE + span_notice("[user] washes [tool] using [src]."), + span_notice("You wash [tool] using [src].")) + return ITEM_INTERACT_SUCCESS - return ..() + return NONE /obj/structure/water_source/puddle //splishy splashy ^_^ name = "puddle" @@ -132,7 +134,7 @@ . = ..() icon_state = base_icon_state -/obj/structure/water_source/puddle/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers) +/obj/structure/water_source/puddle/item_interaction(mob/living/user, obj/item/tool, list/modifiers) icon_state = "[base_icon_state]-splash" . = ..() icon_state = base_icon_state diff --git a/code/game/turfs/closed/minerals.dm b/code/game/turfs/closed/minerals.dm index 54ba5d28796..b16e8b45bdf 100644 --- a/code/game/turfs/closed/minerals.dm +++ b/code/game/turfs/closed/minerals.dm @@ -69,7 +69,7 @@ if(!held_item) INVOKE_ASYNC(bumping, TYPE_PROC_REF(/mob, ClickOn), src) else if(held_item.tool_behaviour == TOOL_MINING) - attackby(held_item, bumping) + item_interaction(bumping, held_item) /turf/closed/mineral/proc/spread_vein(ore_type) if(!ispath(ore_type, /obj/item/stack/ore)) @@ -211,29 +211,35 @@ return TRUE return ..() -/turf/closed/mineral/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1) +/turf/closed/mineral/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(tool.tool_behaviour != TOOL_MINING) + return ..() + + return manual_mine(user, tool) + +///Mining manually with a hand tool or something masquerading as one +/turf/closed/mineral/proc/manual_mine(mob/living/user, obj/item/tool, exp_multiplier = 1) if (!ISADVANCEDTOOLUSER(user)) - to_chat(usr, span_warning("You don't have the dexterity to do this!")) - return + to_chat(user, span_warning("You don't have the dexterity to do this!")) + return ITEM_INTERACT_BLOCKING - if(I.tool_behaviour != TOOL_MINING) - return - - var/turf/T = user.loc - if (!isturf(T)) - return + if (!isturf(user.loc)) + return ITEM_INTERACT_BLOCKING if(TIMER_COOLDOWN_RUNNING(src, REF(user))) //prevents mining turfs in progress - return + return ITEM_INTERACT_BLOCKING TIMER_COOLDOWN_START(src, REF(user), tool_mine_speed) - if(!I.use_tool(src, user, tool_mine_speed, volume=50)) + if(!tool.use_tool(src, user, tool_mine_speed, volume = 50)) TIMER_COOLDOWN_END(src, REF(user)) //if we fail we can start again immediately - return + return ITEM_INTERACT_BLOCKING - if(ismineralturf(src)) - gets_drilled(user, exp_multiplier) - SSblackbox.record_feedback("tally", "pick_used_mining", 1, I.type) + if(!ismineralturf(src)) + return ITEM_INTERACT_BLOCKING + + gets_drilled(user, exp_multiplier) + SSblackbox.record_feedback("tally", "pick_used_mining", 1, tool.type) + return ITEM_INTERACT_SUCCESS /turf/closed/mineral/attack_hand(mob/user) var/mining_arms = HAS_TRAIT(user, TRAIT_FIST_MINING) @@ -1066,19 +1072,19 @@ det_time = rand(8,10) //So you don't know exactly when the hot potato will explode . = ..() -/turf/closed/mineral/gibtonite/attackby(obj/item/attacking_item, mob/living/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1) +/turf/closed/mineral/gibtonite/item_interaction(mob/living/user, obj/item/tool, list/modifiers) var/previous_stage = stage - if(istype(attacking_item, /obj/item/goliath_infuser_hammer) && stage == GIBTONITE_ACTIVE) - user.visible_message(span_notice("[user] digs [attacking_item] to [src]..."), span_notice("Your tendril hammer instictively digs and wraps around [src] to stop it...")) + if(istype(tool, /obj/item/goliath_infuser_hammer) && stage == GIBTONITE_ACTIVE) + user.visible_message(span_notice("[user] digs [tool] to [src]..."), span_notice("Your tendril hammer instictively digs and wraps around [src] to stop it...")) defuse(user) - else if(istype(attacking_item, /obj/item/mining_scanner) || istype(attacking_item, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE) - user.visible_message(span_notice("[user] holds [attacking_item] to [src]..."), span_notice("You use [attacking_item] to locate where to cut off the chain reaction and attempt to stop it...")) + else if(istype(tool, /obj/item/mining_scanner) || istype(tool, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE) + user.visible_message(span_notice("[user] holds [tool] to [src]..."), span_notice("You use [tool] to locate where to cut off the chain reaction and attempt to stop it...")) defuse(user) . = ..() - if(istype(attacking_item, /obj/item/clothing/gloves/gauntlets) && previous_stage == GIBTONITE_UNSTRUCK && stage == GIBTONITE_ACTIVE && istype(user)) + if(istype(tool, /obj/item/clothing/gloves/gauntlets) && previous_stage == GIBTONITE_UNSTRUCK && stage == GIBTONITE_ACTIVE && istype(user)) user.Immobilize(0.5 SECONDS) user.throw_at(get_ranged_target_turf(src, get_dir(src, user), 5), range = 5, speed = 3, spin = FALSE) - user.visible_message(span_danger("[user] hit gibtonite with [attacking_item.name], launching [user.p_them()] back!"), span_danger("You've struck gibtonite! Your [attacking_item.name] launched you back!")) + user.visible_message(span_danger("[user] hit gibtonite with [tool.name], launching [user.p_them()] back!"), span_danger("You've struck gibtonite! Your [tool.name] launched you back!")) /turf/closed/mineral/gibtonite/proc/explosive_reaction(mob/user = null) if(stage != GIBTONITE_UNSTRUCK) @@ -1224,15 +1230,16 @@ base_icon_state = "rock_wall" smoothing_flags = SMOOTH_BITMASK | SMOOTH_BORDER -/turf/closed/mineral/strong/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers, exp_multiplier = 1) +/turf/closed/mineral/strong/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(!ishuman(user)) to_chat(usr, span_warning("Only a more advanced species could break a rock such as this one!")) - return FALSE - if(user.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER) - . = ..() - else - to_chat(usr, span_warning("The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.")) + return ITEM_INTERACT_BLOCKING + if(!user.mind?.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER) + to_chat(usr, span_warning("The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.")) + return ITEM_INTERACT_BLOCKING + + return ..() /turf/closed/mineral/strong/gets_drilled(mob/user, exp_multiplier = 0) if(istype(user)) diff --git a/code/game/turfs/closed/wall/mineral_walls.dm b/code/game/turfs/closed/wall/mineral_walls.dm index 02e40a4054e..23700a6c949 100644 --- a/code/game/turfs/closed/wall/mineral_walls.dm +++ b/code/game/turfs/closed/wall/mineral_walls.dm @@ -173,15 +173,18 @@ custom_materials = list(/datum/material/wood = SHEET_MATERIAL_AMOUNT*2) rust_resistance = RUST_RESISTANCE_BASIC -/turf/closed/wall/mineral/wood/attackby(obj/item/W, mob/user) - if(W.get_sharpness() && W.force) - var/duration = ((4.8 SECONDS)/W.force) * 2 //In seconds, for now. - if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/fireaxe)) - duration /= 4 //Much better with hatchets and axes. - if(do_after(user, duration * (1 SECONDS), target=src)) //Into deciseconds. - dismantle_wall(FALSE,FALSE) - return - return ..() +/turf/closed/wall/mineral/wood/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!tool.get_sharpness() || !tool.force) + return ..() + + var/duration = (4.8 SECONDS / tool.force) * 2 //In seconds, for now. + if(istype(tool, /obj/item/hatchet) || istype(tool, /obj/item/fireaxe)) + duration /= 4 //Much better with hatchets and axes. + if(!do_after(user, duration * 1 SECONDS, target = src)) //Into deciseconds. + return ITEM_INTERACT_BLOCKING + + dismantle_wall(FALSE,FALSE) + return ITEM_INTERACT_SUCCESS /turf/closed/wall/mineral/hulk_recoil(obj/item/bodypart/arm, mob/living/carbon/human/hulkman, damage = 0) return ..() //No recoil damage, wood is weak diff --git a/code/game/turfs/open/asteroid.dm b/code/game/turfs/open/asteroid.dm index af7c082e23a..35d6e8cdbb7 100644 --- a/code/game/turfs/open/asteroid.dm +++ b/code/game/turfs/open/asteroid.dm @@ -62,29 +62,36 @@ /turf/open/misc/asteroid/ex_act(severity, target) return FALSE -/turf/open/misc/asteroid/attackby(obj/item/attack_item, mob/user, list/modifiers) +/turf/open/misc/asteroid/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(.) - return TRUE + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . - if(attack_item.tool_behaviour == TOOL_SHOVEL || attack_item.tool_behaviour == TOOL_MINING) - if(!can_dig(user)) - return TRUE - - if(!isturf(user.loc)) - return - - balloon_alert(user, "digging...") - - if(attack_item.use_tool(src, user, 4 SECONDS, volume = 50)) - if(!can_dig(user)) - return TRUE - getDug() - SSblackbox.record_feedback("tally", "pick_used_mining", 1, attack_item.type) - return TRUE - else if(istype(attack_item, /obj/item/storage/bag/ore)) + if(istype(tool, /obj/item/storage/bag/ore)) for(var/obj/item/stack/ore/dropped_ore in src) - SEND_SIGNAL(attack_item, COMSIG_ATOM_ATTACKBY, dropped_ore) + SEND_SIGNAL(tool, COMSIG_ATOM_ATTACKBY, dropped_ore) + return ITEM_INTERACT_SUCCESS + + if(tool.tool_behaviour != TOOL_SHOVEL && tool.tool_behaviour != TOOL_MINING) + return . // it still could be SKIP_TO_ATTACK and we don't want to step on that + + if(!can_dig(user)) + return ITEM_INTERACT_BLOCKING + + if(!isturf(user.loc)) + return ITEM_INTERACT_BLOCKING + + balloon_alert(user, "digging...") + + if(!tool.use_tool(src, user, 4 SECONDS, volume = 50)) + return ITEM_INTERACT_BLOCKING + + if(!can_dig(user)) + return ITEM_INTERACT_BLOCKING + + getDug() + SSblackbox.record_feedback("tally", "pick_used_mining", 1, tool.type) + return ITEM_INTERACT_SUCCESS /// Drops itemstack when dug and changes icon /turf/open/misc/asteroid/proc/getDug() diff --git a/code/game/turfs/open/chasm.dm b/code/game/turfs/open/chasm.dm index 47c425da544..dd7e01ed224 100644 --- a/code/game/turfs/open/chasm.dm +++ b/code/game/turfs/open/chasm.dm @@ -55,26 +55,18 @@ underlay_appearance.icon_state = /turf/open/misc/asteroid/basalt::icon_state return TRUE -/turf/open/chasm/attackby(obj/item/C, mob/user, params, area/area_restriction) +/turf/open/chasm/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(ismetaltile(C)) - build_with_floor_tiles(C, user) - return + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . - if(!istype(C, /obj/item/stack/rods)) - return + if(istype(tool, /obj/item/stack/rods)) + build_with_rods(tool, user) + return ITEM_INTERACT_SUCCESS - var/obj/item/stack/rods/R = C - var/obj/structure/lattice/L = locate(/obj/structure/lattice, src) - if(L) - return - if(!R.use(1)) - to_chat(user, span_warning("You need one rod to build a lattice.")) - return - to_chat(user, span_notice("You construct a lattice.")) - playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE) - // Create a lattice, without reverting to our baseturf - new /obj/structure/lattice(src) + if(ismetaltile(tool)) + build_with_floor_tiles(tool, user) + return ITEM_INTERACT_SUCCESS /// Handles adding the chasm component to the turf (So stuff falls into it!) @@ -140,9 +132,11 @@ /turf/open/chasm/true/no_smooth/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data) return FALSE -/turf/open/chasm/true/no_smooth/attackby(obj/item/item, mob/user, params, area/area_restriction) - if(istype(item, /obj/item/stack/rods)) - return - else if(ismetaltile(item)) - return +/turf/open/chasm/true/no_smooth/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/stack/rods)) + return ITEM_INTERACT_BLOCKING + + if(ismetaltile(tool)) + return ITEM_INTERACT_BLOCKING + return ..() diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index 01be12d84af..7fe3cb6a267 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -125,19 +125,21 @@ W.update_appearance() return W -/turf/open/floor/attackby(obj/item/object, mob/living/user, list/modifiers) - if(!object || !user) - return TRUE +/turf/open/floor/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(.) + if(ITEM_INTERACT_ANY_BLOCKER & .) return . - if(overfloor_placed && istype(object, /obj/item/stack/tile)) - try_replace_tile(object, user, modifiers) - return TRUE - if(user.combat_mode && istype(object, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/sheets = object - return sheets.on_attack_floor(src, user, modifiers) - return FALSE + + if(overfloor_placed && istype(tool, /obj/item/stack/tile)) + try_replace_tile(tool, user, modifiers) + return ITEM_INTERACT_SUCCESS + + if(user.combat_mode && istype(tool, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/sheets = tool + if(!sheets.on_attack_floor(src, user, modifiers)) + return ITEM_INTERACT_BLOCKING + + return ITEM_INTERACT_SUCCESS /turf/open/floor/crowbar_act(mob/living/user, obj/item/I) if(overfloor_placed && pry_tile(I, user)) diff --git a/code/game/turfs/open/floor/light_floor.dm b/code/game/turfs/open/floor/light_floor.dm index 93ae88597ad..7c5aa262984 100644 --- a/code/game/turfs/open/floor/light_floor.dm +++ b/code/game/turfs/open/floor/light_floor.dm @@ -129,21 +129,31 @@ currentcolor = choice update_appearance() -/turf/open/floor/light/attackby(obj/item/C, mob/user, list/modifiers) - if(..()) - return - if(istype(C, /obj/item/light/bulb)) //only for light tiles - var/obj/item/light/bulb/B = C - if(B.status)/// check if broken - to_chat(user, span_danger("The light bulb is broken!")) - return - if(state && user.temporarilyRemoveItemFromInventory(C)) - qdel(C) - state = LIGHTFLOOR_FINE //fixing it by bashing it with a light bulb, fun eh? - update_appearance() - to_chat(user, span_notice("You replace the light bulb.")) - else - to_chat(user, span_notice("The light bulb seems fine, no need to replace it.")) +/turf/open/floor/light/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . + + if(!istype(tool, /obj/item/light/bulb)) //only for light tiles + return . + + if(astype(tool, /obj/item/light/bulb).status)/// check if broken + to_chat(user, span_danger("The light bulb is broken!")) + return ITEM_INTERACT_BLOCKING + + if(!state) + to_chat(user, span_notice("The light bulb seems fine, no need to replace it.")) + return ITEM_INTERACT_BLOCKING + + if(!user.temporarilyRemoveItemFromInventory(tool)) + return ITEM_INTERACT_BLOCKING + + qdel(tool) + state = LIGHTFLOOR_FINE //fixing it by bashing it with a light bulb, fun eh? + update_appearance() + to_chat(user, span_notice("You replace the light bulb.")) + return ITEM_INTERACT_SUCCESS + /turf/open/floor/light/emp_act(severity) . = ..() diff --git a/code/game/turfs/open/floor/plating.dm b/code/game/turfs/open/floor/plating.dm index 7718f4b143e..97b9b6edc35 100644 --- a/code/game/turfs/open/floor/plating.dm +++ b/code/game/turfs/open/floor/plating.dm @@ -42,99 +42,111 @@ #define PLATE_REINFORCE_COST 2 -/turf/open/floor/plating/attackby(obj/item/C, mob/user, list/modifiers) - if(..()) - return - if(istype(C, /obj/item/stack/rods) && attachment_holes) - if(broken || burnt) - if(!iscyborg(user)) - to_chat(user, span_warning("Repair the plating first! Use a welding tool to fix the damage.")) - else - to_chat(user, span_warning("Repair the plating first! Use a welding tool or a plating repair tool to fix the damage.")) //we don't need to confuse humans by giving them a message about plating repair tools, since only janiborgs should have access to them outside of Christmas presents or admin intervention - return - var/obj/item/stack/rods/R = C - if (R.get_amount() < 2) - to_chat(user, span_warning("You need two rods to make a reinforced floor!")) - return - else - to_chat(user, span_notice("You begin reinforcing the floor...")) - if(do_after(user, 3 SECONDS, target = src)) - if (R.get_amount() >= 2 && !istype(src, /turf/open/floor/engine)) - place_on_top(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) - playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE) - R.use(2) - to_chat(user, span_notice("You reinforce the floor.")) - return - else if(istype(C, /obj/item/stack/tile)) - if(!broken && !burnt) - for(var/obj/O in src) - for(var/M in O.buckled_mobs) - to_chat(user, span_warning("Someone is buckled to \the [O]! Unbuckle [M] to move \him out of the way.")) - return - var/obj/item/stack/tile/tile = C - tile.place_tile(src, user) - else - if(!iscyborg(user)) - balloon_alert(user, "too damaged, use a welding tool!") - else - balloon_alert(user, "too damaged, use a welding or plating repair tool!") - else if(istype(C, /obj/item/cautery/prt)) //plating repair tool - if((broken || burnt) && C.use_tool(src, user, 0, volume=80)) - to_chat(user, span_danger("You fix some dents on the broken plating.")) - icon_state = base_icon_state - burnt = FALSE - broken = FALSE - update_appearance() - else if(istype(C, /obj/item/stack/sheet/plasteel) && upgradable) //Reinforcement! - if(!broken && !burnt) - var/obj/item/stack/sheet/sheets = C - if(sheets.get_amount() < PLATE_REINFORCE_COST) - return - balloon_alert(user, "reinforcing plating...") - if(do_after(user, 12 SECONDS, target = src)) - if(sheets.get_amount() < PLATE_REINFORCE_COST) - return - sheets.use(PLATE_REINFORCE_COST) - playsound(src, 'sound/machines/creak.ogg', 100, vary = TRUE) - place_on_top(/turf/open/floor/plating/reinforced, CHANGETURF_INHERIT_AIR) - else - if(!iscyborg(user)) - balloon_alert(user, "too damaged, use a welding tool!") - else - balloon_alert(user, "too damaged, use a welding or plating repair tool!") - else if(istype(C, /obj/item/stack/sheet/mineral/plastitanium) && attachment_holes) - if(broken || burnt) - if(!iscyborg(user)) - to_chat(user, span_warning("Repair the plating first! Use a welding tool to fix the damage.")) - else - to_chat(user, span_warning("Repair the plating first! Use a welding tool or a plating repair tool to fix the damage.")) - return - var/obj/item/stack/sheet/mineral/plastitanium/sheet = C - if (sheet.get_amount() < 1) - to_chat(user, span_warning("You are literally holding nothing.")) - return - else - balloon_alert(user, "insulating flooring...") - if(!do_after(user, 1.5 SECONDS, target = src)) - return - if(sheet.get_amount() < 1 || istype(src, /turf/open/floor/engine/insulation)) - return - place_on_top(/turf/open/floor/engine/insulation, flags = CHANGETURF_INHERIT_AIR) - playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE) - sheet.use(1) - to_chat(user, span_notice("You insulate the floor.")) - balloon_alert(user, "insulated!") +/turf/open/floor/plating/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . + + if(istype(tool, /obj/item/stack/rods) && attachment_holes) + if(broken || burnt) + to_chat(user, span_warning("Repair the plating first! Use a welding tool[iscyborg(user) ? " or a plating repair tool" : ""] to fix the damage.")) + return ITEM_INTERACT_BLOCKING + + var/obj/item/stack/rods/material = tool + if (material.get_amount() < 2) + to_chat(user, span_warning("You need two rods to make a reinforced floor!")) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You begin reinforcing the floor...")) + if(!do_after(user, 3 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + + if (material.get_amount() < 2 || istype(src, /turf/open/floor/engine)) + return ITEM_INTERACT_BLOCKING + + place_on_top(/turf/open/floor/engine, flags = CHANGETURF_INHERIT_AIR) + playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE) + material.use(2) + to_chat(user, span_notice("You reinforce the floor.")) + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/stack/tile)) + if(broken || burnt) + balloon_alert(user, "too damaged, use a welding[iscyborg(user) ? "or plating repair " : ""] tool!") + return ITEM_INTERACT_BLOCKING + + for(var/obj/blocker in src) + for(var/mob/sitter as anything in blocker.buckled_mobs) + to_chat(user, span_warning("Someone is buckled to \the [blocker]! Unbuckle [sitter] to move [sitter.p_them()] out of the way.")) + return ITEM_INTERACT_BLOCKING + + var/obj/item/stack/tile/tile = tool + tile.place_tile(src, user) + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/cautery/prt)) //plating repair tool + if((!broken && !burnt) || !tool.use_tool(src, user, 0, volume=80)) + return ITEM_INTERACT_BLOCKING -/turf/open/floor/plating/welder_act(mob/living/user, obj/item/I) - ..() - if((broken || burnt) && I.use_tool(src, user, 0, volume=80)) to_chat(user, span_danger("You fix some dents on the broken plating.")) icon_state = base_icon_state burnt = FALSE broken = FALSE update_appearance() + return ITEM_INTERACT_SUCCESS - return TRUE + if(istype(tool, /obj/item/stack/sheet/plasteel) && upgradable) //Reinforcement! + if(broken || burnt) + balloon_alert(user, "too damaged, use a welding[iscyborg(user) ? "or plating repair " : ""] tool!") + return ITEM_INTERACT_BLOCKING + + var/obj/item/stack/sheet/sheets = tool + if(sheets.get_amount() < PLATE_REINFORCE_COST) + return ITEM_INTERACT_BLOCKING + + balloon_alert(user, "reinforcing plating...") + if(!do_after(user, 12 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + if(sheets.get_amount() < PLATE_REINFORCE_COST || istype(src, /turf/open/floor/plating/reinforced)) + return ITEM_INTERACT_BLOCKING + sheets.use(PLATE_REINFORCE_COST) + playsound(src, 'sound/machines/creak.ogg', 100, vary = TRUE) + place_on_top(/turf/open/floor/plating/reinforced, CHANGETURF_INHERIT_AIR) + return ITEM_INTERACT_SUCCESS + + if(istype(tool, /obj/item/stack/sheet/mineral/plastitanium) && attachment_holes) + if(broken || burnt) + to_chat(user, span_warning("Repair the plating first! Use a welding tool[iscyborg(user) ? " or a plating repair tool" : ""] to fix the damage.")) + return ITEM_INTERACT_BLOCKING + + var/obj/item/stack/sheet/mineral/plastitanium/sheet = tool + if (sheet.get_amount() < 1) + to_chat(user, span_warning("You are literally holding nothing.")) // finally a reasonable message + return ITEM_INTERACT_BLOCKING + + balloon_alert(user, "insulating flooring...") + if(!do_after(user, 1.5 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + + if(sheet.get_amount() < 1 || istype(src, /turf/open/floor/engine/insulation)) + return ITEM_INTERACT_BLOCKING + + place_on_top(/turf/open/floor/engine/insulation, flags = CHANGETURF_INHERIT_AIR) + playsound(src, 'sound/items/deconstruct.ogg', 80, TRUE) + sheet.use(1) + to_chat(user, span_notice("You insulate the floor.")) + balloon_alert(user, "insulated!") + return ITEM_INTERACT_SUCCESS + +/turf/open/floor/plating/welder_act(mob/living/user, obj/item/tool) + if((!broken && !burnt) || !tool.use_tool(src, user, 0, volume=80)) + return NONE + to_chat(user, span_danger("You fix some dents on the broken plating.")) + icon_state = base_icon_state + burnt = FALSE + broken = FALSE + update_appearance() + return ITEM_INTERACT_SUCCESS #undef PLATE_REINFORCE_COST @@ -239,20 +251,21 @@ icon_state = "r_plate-[deconstruction_state]" return ..() -/turf/open/floor/plating/reinforced/attackby(obj/item/tool_used, mob/user, list/modifiers) +/turf/open/floor/plating/reinforced/item_interaction(mob/living/user, obj/item/tool, list/modifiers) user.changeNext_move(CLICK_CD_MELEE) if (!ISADVANCEDTOOLUSER(user)) to_chat(user, span_warning("You don't have the dexterity to do this!")) - return + return ITEM_INTERACT_BLOCKING //get the user's location if(!isturf(user.loc)) - return //can't do this stuff whilst inside objects and such + return ITEM_INTERACT_BLOCKING//can't do this stuff whilst inside objects and such add_fingerprint(user) - if(deconstruct_steps(tool_used, user)) - return + if(deconstruct_steps(tool, user)) + return ITEM_INTERACT_SUCCESS + return ..() /turf/open/floor/plating/reinforced/proc/deconstruct_steps(obj/item/tool_used, mob/user) diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 63a4e1e5045..cd33a38fef7 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -205,35 +205,41 @@ /turf/open/lava/TakeTemperature(temp) -/turf/open/lava/attackby(obj/item/C, mob/user, list/modifiers) - ..() - if(istype(C, /obj/item/stack/rods/lava)) - var/obj/item/stack/rods/lava/R = C - var/obj/structure/lattice/catwalk/lava/H = locate(/obj/structure/lattice/catwalk/lava, src) - if(H) +/turf/open/lava/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . + + if(istype(tool, /obj/item/stack/rods/lava)) + if(locate(/obj/structure/lattice/catwalk/lava, src)) to_chat(user, span_warning("There is already a lattice here!")) - return - if(R.use(1)) - to_chat(user, span_notice("You construct a lattice.")) - playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE) - new /obj/structure/lattice/catwalk/lava(locate(x, y, z)) - else + return ITEM_INTERACT_BLOCKING + + if(!astype(tool, /obj/item/stack/rods/lava).use(1)) to_chat(user, span_warning("You need one rod to build a heatproof lattice.")) - return + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_notice("You construct a lattice.")) + playsound(src, 'sound/items/weapons/genhit.ogg', 50, TRUE) + new /obj/structure/lattice/catwalk/lava(locate(x, y, z)) + return ITEM_INTERACT_SUCCESS + // Light a cigarette in the lava - if(istype(C, /obj/item/cigarette)) - var/obj/item/cigarette/ciggie = C + if(istype(tool, /obj/item/cigarette)) + var/obj/item/cigarette/ciggie = tool if(ciggie.lit) to_chat(user, span_warning("\The [ciggie] is already lit!")) - return TRUE + return ITEM_INTERACT_BLOCKING + var/clumsy_modifier = HAS_TRAIT(user, TRAIT_CLUMSY) ? 2 : 1 - if(prob(25 * clumsy_modifier) && isliving(user)) + if(prob(25 * clumsy_modifier)) ciggie.light(span_warning("[user] expertly dips \the [ciggie.name] into [src], along with the rest of [user.p_their()] arm. What a dumbass.")) var/mob/living/burned_guy = user burned_guy.apply_damage(90, BURN, user.get_active_hand()) - else - ciggie.light(span_rose("[user] expertly dips \the [ciggie.name] into [src], lighting it with the scorching heat of the planet. Witnessing such a feat is almost enough to make you cry.")) - return TRUE + return ITEM_INTERACT_SUCCESS + + ciggie.light(span_rose("[user] expertly dips \the [ciggie.name] into [src], lighting it with the scorching heat of the planet. Witnessing such a feat is almost enough to make you cry.")) + return ITEM_INTERACT_SUCCESS /turf/open/lava/proc/is_safe() return HAS_TRAIT(src, TRAIT_LAVA_STOPPED) diff --git a/code/game/turfs/open/misc.dm b/code/game/turfs/open/misc.dm index 666ad1aef85..7a4bdacf781 100644 --- a/code/game/turfs/open/misc.dm +++ b/code/game/turfs/open/misc.dm @@ -21,18 +21,18 @@ heat_capacity = 20000 tiled_turf = TRUE -/turf/open/misc/attackby(obj/item/attacking_item, mob/user, list/modifiers) +/turf/open/misc/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() - if(.) - return TRUE + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . - if(istype(attacking_item, /obj/item/stack/rods)) - build_with_rods(attacking_item, user) - return TRUE + if(istype(tool, /obj/item/stack/rods)) + build_with_rods(tool, user) + return ITEM_INTERACT_SUCCESS - if(ismetaltile(attacking_item)) - build_with_floor_tiles(attacking_item, user) - return TRUE + if(ismetaltile(tool)) + build_with_floor_tiles(tool, user) + return ITEM_INTERACT_SUCCESS /turf/open/misc/attack_paw(mob/user, list/modifiers) return attack_hand(user, modifiers) diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 380d7bbf315..da9141e400c 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -114,18 +114,24 @@ /turf/open/openspace/CanBuildHere() return can_build_on -/turf/open/openspace/attackby(obj/item/attacking_item, mob/user, list/modifiers) - ..() +/turf/open/openspace/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . + if(!CanBuildHere()) - return - if(istype(attacking_item, /obj/item/stack/rods)) - build_with_rods(attacking_item, user) - else if(ismetaltile(attacking_item)) - build_with_floor_tiles(attacking_item, user) - else if(istype(attacking_item, /obj/item/stack/thermoplastic)) - build_with_transport_tiles(attacking_item, user) - else if(istype(attacking_item, /obj/item/stack/sheet/mineral/titanium)) - build_with_titanium(attacking_item, user) + return . + + if(istype(tool, /obj/item/stack/rods)) + build_with_rods(tool, user) + else if(ismetaltile(tool)) + build_with_floor_tiles(tool, user) + else if(istype(tool, /obj/item/stack/thermoplastic)) + build_with_transport_tiles(tool, user) + else if(istype(tool, /obj/item/stack/sheet/mineral/titanium)) + build_with_titanium(tool, user) + + return ITEM_INTERACT_SUCCESS /turf/open/openspace/build_with_floor_tiles(obj/item/stack/tile/iron/used_tiles) if(!CanCoverUp()) diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index e4c447008da..5045e6136ff 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -127,14 +127,19 @@ GLOBAL_LIST_EMPTY(starlight) /turf/open/space/handle_slip() return -/turf/open/space/attackby(obj/item/attacking_item, mob/user, list/modifiers) - ..() +/turf/open/space/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() + if(ITEM_INTERACT_ANY_BLOCKER & .) + return . + if(!CanBuildHere()) - return - if(istype(attacking_item, /obj/item/stack/rods)) - build_with_rods(attacking_item, user) - else if(ismetaltile(attacking_item)) - build_with_floor_tiles(attacking_item, user) + return . + + if(istype(tool, /obj/item/stack/rods)) + build_with_rods(tool, user) + else if(ismetaltile(tool)) + build_with_floor_tiles(tool, user) + return ITEM_INTERACT_SUCCESS /turf/open/space/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent) return diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 62c346be9a1..47457310fca 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -253,11 +253,10 @@ if(decal) . += decal -/obj/structure/closet/supplypod/tool_interact(obj/item/W, mob/user) +/obj/structure/closet/supplypod/item_interaction(mob/living/user, obj/item/tool, list/modifiers) if(bluespace) //We dont want to worry about interacting with bluespace pods, as they are due to delete themselves soon anyways. - return FALSE - else - ..() + return ITEM_INTERACT_BLOCKING + return ..() /obj/structure/closet/supplypod/ex_act() //Explosions dont do SHIT TO US! This is because supplypods create explosions when they land. return FALSE diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm index ffcd8c07a49..fe8997d47ae 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/elephantgraveyard.dm @@ -234,52 +234,56 @@ dug_closed = FALSE return TRUE -/obj/structure/closet/crate/grave/tool_interact(obj/item/weapon, mob/living/carbon/user) +/obj/structure/closet/crate/grave/item_interaction(mob/living/user, obj/item/tool, list/modifiers) //anything that isn't a shovel does normal stuff to the grave[like putting stuff in] - if(weapon.tool_behaviour != TOOL_SHOVEL) + if(tool.tool_behaviour != TOOL_SHOVEL) return ..() - //player is attempting to open/close the grave with a shovel - if(!user.combat_mode) - user.visible_message( - span_notice("[user] Is attempting to [opened ? "close" : "dig open"] [src]."), - span_notice("You start [opened ? "closing" : "digging open"] [src]."), - ) - if(!weapon.use_tool(src, user, delay = 15, volume = 40)) - return TRUE - - var/is_chill_with_robbing = HAS_MIND_TRAIT(user, TRAIT_MORBID) || HAS_PERSONALITY(user, /datum/personality/callous) || HAS_PERSONALITY(user, /datum/personality/misanthropic) - if(opened) - dug_closed = TRUE - close(user) - else if(open(user, force = TRUE) && affect_mood) - user.add_mood_event("graverobbing", is_chill_with_robbing ? /datum/mood_event/morbid_graverobbing : /datum/mood_event/graverobbing) - if(lead_tomb && first_open) - if(is_chill_with_robbing) - to_chat(user, span_notice("Did someone say something? I'm sure it was nothing.")) - else - user.gain_trauma(/datum/brain_trauma/magic/stalker) - to_chat(user, span_boldwarning("Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!")) - first_open = FALSE - - return TRUE //player is attempting to destroy the open grave with a shovel - else + if(user.combat_mode) if(!opened) - return TRUE + return ITEM_INTERACT_BLOCKING user.visible_message( span_notice("[user] Is attempting to remove [src]."), span_notice("You start removing [src]."), ) - if(!weapon.use_tool(src, user, delay = 15, volume = 40) || !opened) - return TRUE + if(!tool.use_tool(src, user, delay = 1.5 SECONDS , volume = 40) || !opened) + return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You remove \the [src] completely.")) user.add_mood_event("graverobbing", /datum/mood_event/graverobbing) deconstruct(TRUE) - return TRUE + return ITEM_INTERACT_SUCCESS + + //player is attempting to open/close the grave with a shovel + user.visible_message( + span_notice("[user] Is attempting to [opened ? "close" : "dig open"] [src]."), + span_notice("You start [opened ? "closing" : "digging open"] [src]."), + ) + if(!tool.use_tool(src, user, delay = 1.5 SECONDS, volume = 40)) + return ITEM_INTERACT_BLOCKING + + var/is_chill_with_robbing = HAS_MIND_TRAIT(user, TRAIT_MORBID) || HAS_PERSONALITY(user, /datum/personality/callous) || HAS_PERSONALITY(user, /datum/personality/misanthropic) + if(opened) + dug_closed = TRUE + close(user) + return ITEM_INTERACT_SUCCESS + + if(!open(user, force = TRUE) || !affect_mood) + return ITEM_INTERACT_SUCCESS + + user.add_mood_event("graverobbing", is_chill_with_robbing ? /datum/mood_event/morbid_graverobbing : /datum/mood_event/graverobbing) + if(lead_tomb && first_open) + if(is_chill_with_robbing || !astype(user, /mob/living/carbon)?.gain_trauma(/datum/brain_trauma/magic/stalker)) + to_chat(user, span_notice("Did someone say something? I'm sure it was nothing.")) + else + to_chat(user, span_boldwarning("Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!")) + first_open = FALSE + + return ITEM_INTERACT_SUCCESS + /obj/structure/closet/crate/grave/container_resist_act(mob/living/user, loc_required = TRUE) if(opened) diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm index bef136cabea..2e3d21141f1 100644 --- a/code/modules/mod/modules/modules_supply.dm +++ b/code/modules/mod/modules/modules_supply.dm @@ -212,7 +212,7 @@ var/has_ore = !isnull(rock.mineral_type) if (has_ore) toolspeed /= 2 - rock.attackby(src, bumper, null, null, exp_multiplier) + rock.manual_mine(bumper, src, exp_multiplier) if (has_ore) toolspeed *= 2