From 217c68d1ec0e6ea1c71faeb6c73883fc51312d41 Mon Sep 17 00:00:00 2001 From: NovaBot <154629622+NovaBot13@users.noreply.github.com> Date: Sun, 16 Jun 2024 11:20:34 -0400 Subject: [PATCH] [MIRROR] Afterattack is dead, long live Afterattack [MDB IGNORE] (#2986) * Afterattack is dead, long live Afterattack * Modular updates pt 1 * Fixes blood magic applying wounds when casted (#73170) Fixes cult blood magic applying wounds to the users hand when casted * afterattack is dead, aughhhh * this is totally unrelated but whatever * reset a couple diffs --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Mal <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: SuperSlayer <91609255+SuperSlayer0@users.noreply.github.com> Co-authored-by: Fluffles --- code/__DEFINES/cleaning.dm | 13 +- code/__DEFINES/combat.dm | 7 - .../signals_atom/signals_atom_attack.dm | 2 +- .../signals_atom/signals_atom_x_act.dm | 21 + code/__DEFINES/dcs/signals/signals_heretic.dm | 8 +- .../signals/signals_mob/signals_mob_living.dm | 6 +- .../signals/signals_mob/signals_mob_main.dm | 4 - code/__DEFINES/dcs/signals/signals_object.dm | 19 +- code/__DEFINES/tools.dm | 2 + code/__HELPERS/atoms.dm | 11 + code/_onclick/click.dm | 13 +- code/_onclick/cyborg.dm | 8 +- code/_onclick/item_attack.dm | 97 ++--- code/_onclick/telekinesis.dm | 88 ++-- code/datums/ai/monkey/monkey_behaviors.dm | 2 +- code/datums/ai/monkey/monkey_controller.dm | 5 +- code/datums/components/cleaner.dm | 48 +-- code/datums/components/igniter.dm | 5 +- code/datums/components/infective.dm | 11 +- code/datums/components/jousting.dm | 4 +- code/datums/components/lockable_storage.dm | 11 + code/datums/components/on_hit_effect.dm | 1 - code/datums/components/reagent_refiller.dm | 6 +- code/datums/components/scope.dm | 8 +- code/datums/components/soul_stealer.dm | 13 +- code/datums/components/spirit_holding.dm | 2 +- code/datums/components/style/style.dm | 13 +- code/datums/components/summoning.dm | 5 +- code/datums/components/trapdoor.dm | 21 +- code/datums/elements/can_shatter.dm | 2 +- code/datums/elements/easily_fragmented.dm | 17 +- code/datums/elements/envenomable_casing.dm | 17 +- code/datums/elements/food/dunkable.dm | 18 +- code/datums/elements/knockback.dm | 5 +- code/datums/elements/light_eater.dm | 5 +- .../elements/openspace_item_click_handler.dm | 14 +- code/datums/elements/selfknockback.dm | 17 +- code/datums/status_effects/neutral.dm | 27 +- code/datums/storage/storage.dm | 26 +- .../storage/subtypes/extract_inventory.dm | 2 + code/game/atom/atom_tool_acts.dm | 103 ++++- code/game/machinery/launch_pad.dm | 18 +- code/game/machinery/spaceheater.dm | 2 +- code/game/objects/items.dm | 11 +- code/game/objects/items/airlock_painter.dm | 13 +- code/game/objects/items/bear_armor.dm | 36 +- code/game/objects/items/bodybag.dm | 1 + code/game/objects/items/broom.dm | 9 +- code/game/objects/items/cards_ids.dm | 71 ++-- code/game/objects/items/cigs_lighters.dm | 13 +- code/game/objects/items/climbingrope.dm | 20 +- code/game/objects/items/clown_items.dm | 18 +- code/game/objects/items/control_wand.dm | 36 +- code/game/objects/items/crayons.dm | 52 +-- code/game/objects/items/debug_items.dm | 12 +- .../objects/items/devices/anomaly_releaser.dm | 32 +- .../objects/items/devices/chameleonproj.dm | 26 +- .../devices/electroadaptive_pseudocircuit.dm | 19 +- code/game/objects/items/devices/flashlight.dm | 321 +++++++------- .../items/devices/forcefieldprojector.dm | 38 +- .../objects/items/devices/geiger_counter.dm | 18 +- .../objects/items/devices/laserpointer.dm | 13 +- .../objects/items/devices/lightreplacer.dm | 39 +- .../objects/items/devices/pipe_painter.dm | 22 +- .../items/devices/scanners/gas_analyzer.dm | 13 +- .../devices/scanners/sequence_scanner.dm | 37 +- .../objects/items/devices/traitordevices.dm | 36 +- code/game/objects/items/dna_probe.dm | 16 +- code/game/objects/items/emags.dm | 14 +- code/game/objects/items/extinguisher.dm | 100 +++-- code/game/objects/items/fireaxe.dm | 14 +- code/game/objects/items/flamethrower.dm | 22 +- code/game/objects/items/food/egg.dm | 33 +- code/game/objects/items/food/packaged.dm | 12 +- code/game/objects/items/grenades/_grenade.dm | 8 +- code/game/objects/items/grenades/plastic.dm | 92 ++-- code/game/objects/items/hand_items.dm | 8 +- code/game/objects/items/holosign_creator.dm | 40 +- code/game/objects/items/hot_potato.dm | 9 +- .../items/implants/security/implant_chem.dm | 2 +- code/game/objects/items/knives.dm | 5 +- code/game/objects/items/machine_wand.dm | 15 +- code/game/objects/items/melee/misc.dm | 61 +-- code/game/objects/items/mop.dm | 8 +- code/game/objects/items/paint.dm | 33 +- code/game/objects/items/pneumaticCannon.dm | 17 +- code/game/objects/items/rcd/RCD.dm | 32 +- code/game/objects/items/rcd/RLD.dm | 87 ++-- code/game/objects/items/rcd/RPLD.dm | 21 +- code/game/objects/items/rcd/RSF.dm | 22 +- code/game/objects/items/rcd/RTD.dm | 57 ++- code/game/objects/items/religion.dm | 15 +- code/game/objects/items/robot/items/food.dm | 36 +- .../game/objects/items/robot/items/generic.dm | 10 +- code/game/objects/items/robot/items/hypo.dm | 66 ++- code/game/objects/items/rollertable_dock.dm | 15 +- code/game/objects/items/spear.dm | 47 +-- .../stacks/golem_food/golem_hand_actions.dm | 30 +- code/game/objects/items/stacks/rods.dm | 5 +- .../game/objects/items/stacks/sheets/glass.dm | 20 +- .../items/stacks/sheets/sheet_types.dm | 50 +-- code/game/objects/items/stacks/tape.dm | 19 +- .../objects/items/stacks/tiles/tile_types.dm | 5 +- code/game/objects/items/stacks/wrap.dm | 64 +-- code/game/objects/items/storage/bags.dm | 12 +- .../objects/items/storage/boxes/_boxes.dm | 5 - .../objects/items/storage/boxes/food_boxes.dm | 10 +- .../objects/items/storage/boxes/job_boxes.dm | 20 +- .../items/storage/boxes/service_boxes.dm | 11 +- code/game/objects/items/storage/lockbox.dm | 46 +- code/game/objects/items/storage/medkit.dm | 36 +- code/game/objects/items/storage/toolbox.dm | 33 +- code/game/objects/items/syndie_spraycan.dm | 27 +- code/game/objects/items/tanks/watertank.dm | 44 +- code/game/objects/items/taster.dm | 21 +- code/game/objects/items/teleportation.dm | 24 +- code/game/objects/items/theft_tools.dm | 15 +- code/game/objects/items/tools/weldingtool.dm | 38 +- code/game/objects/items/toys.dm | 54 ++- code/game/objects/items/v8_engine.dm | 17 +- code/game/objects/items/weaponry.dm | 39 +- code/game/objects/items/wizard_weapons.dm | 30 +- .../objects/structures/beds_chairs/chair.dm | 18 +- .../structures/crates_lockers/closets.dm | 2 +- .../objects/structures/deployable_turret.dm | 14 +- .../objects/structures/plaques/_plaques.dm | 10 +- code/game/objects/structures/signs/_signs.dm | 10 +- .../objects/structures/training_machine.dm | 15 +- .../abductor/equipment/gear/abductor_items.dm | 34 +- .../changeling/powers/mutations.dm | 12 +- code/modules/antagonists/cult/blood_magic.dm | 399 +++++++++--------- code/modules/antagonists/cult/cult_items.dm | 96 ++--- .../antagonists/heretic/heretic_antag.dm | 19 +- .../heretic/items/forbidden_book.dm | 18 +- .../heretic/items/heretic_blades.dm | 26 +- .../antagonists/heretic/items/keyring.dm | 16 +- .../heretic/items/labyrinth_handbook.dm | 47 ++- .../heretic/structures/carving_knife.dm | 19 +- .../antagonists/ninja/energy_katana.dm | 11 +- .../antagonists/ninja/ninja_explosive.dm | 17 +- .../equipment/nuclear_bomb/beer_nuke.dm | 2 +- .../traitor/objectives/locate_weakpoint.dm | 18 +- .../antagonists/traitor/objectives/steal.dm | 20 +- .../antagonists/wizard/equipment/artefact.dm | 61 +-- .../antagonists/wizard/equipment/soulstone.dm | 2 +- .../wizard/equipment/teleport_rod.dm | 28 +- code/modules/art/statues.dm | 30 +- .../gas_recipe_machines/crystallizer_items.dm | 28 +- code/modules/basketball/basketball.dm | 30 +- code/modules/cargo/universal_scanner.dm | 17 +- .../clothing/chameleon/chameleon_scanner.dm | 21 +- code/modules/clothing/gloves/insulated.dm | 24 +- code/modules/clothing/head/wig.dm | 15 +- code/modules/clothing/neck/_neck.dm | 16 +- code/modules/detectivework/evidence.dm | 11 +- code/modules/detectivework/scanner.dm | 16 +- .../experiment/handlers/experiment_handler.dm | 8 +- code/modules/explorer_drone/loot.dm | 21 +- .../modules/fishing/aquarium/fish_analyzer.dm | 28 +- code/modules/fishing/fishing_rod.dm | 38 +- .../hydroponics/beekeeping/bee_smoker.dm | 23 +- .../modules/hydroponics/unique_plant_genes.dm | 17 +- code/modules/library/bibles.dm | 30 +- .../ruins/lavalandruin_code/puzzle.dm | 28 +- .../ruins/objects_and_mobs/sin_ruins.dm | 25 +- .../ruins/spaceruin_code/hilbertshotel.dm | 15 +- code/modules/mining/equipment/grapple_gun.dm | 23 +- .../mining/equipment/kinetic_crusher.dm | 58 ++- .../mining/equipment/lazarus_injector.dm | 18 +- .../equipment/monster_organs/monster_organ.dm | 28 +- code/modules/mining/fulton.dm | 45 +- .../modules/mining/lavaland/megafauna_loot.dm | 96 +++-- code/modules/mining/ores_coins.dm | 24 +- .../mob/living/basic/minebots/minebot.dm | 4 +- .../basic/minebots/minebot_remote_control.dm | 14 +- .../living/basic/minebots/minebot_upgrades.dm | 11 +- .../space_fauna/wumborian_fugu/fugu_gland.dm | 14 +- code/modules/mob/living/basic/vermin/mouse.dm | 24 +- code/modules/mob/living/carbon/carbon.dm | 5 +- .../mob/living/simple_animal/bot/firebot.dm | 6 +- .../hostile/mining_mobs/elites/elite.dm | 40 +- code/modules/mod/mod_control.dm | 78 ++-- code/modules/paperwork/filingcabinet.dm | 3 +- code/modules/paperwork/handlabeler.dm | 2 +- code/modules/paperwork/pen.dm | 10 +- code/modules/photography/camera/camera.dm | 24 +- code/modules/plumbing/ducts.dm | 17 +- code/modules/power/cell.dm | 4 - code/modules/power/singularity/emitter.dm | 12 +- code/modules/projectiles/gun.dm | 107 ++--- .../projectiles/guns/ballistic/automatic.dm | 31 +- .../projectiles/guns/ballistic/bows/_bow.dm | 7 +- .../projectiles/guns/ballistic/launchers.dm | 4 +- .../projectiles/guns/ballistic/pistol.dm | 21 +- .../projectiles/guns/ballistic/shotgun.dm | 29 +- .../projectiles/guns/energy/beam_rifle.dm | 21 +- .../projectiles/guns/energy/laser_gatling.dm | 5 +- .../projectiles/guns/energy/recharge.dm | 12 +- .../projectiles/guns/energy/special.dm | 27 +- code/modules/projectiles/guns/magic/wand.dm | 23 +- .../projectiles/guns/special/blastcannon.dm | 15 +- .../projectiles/guns/special/hand_of_midas.dm | 41 +- .../projectiles/guns/special/syringe_gun.dm | 46 +- code/modules/projectiles/pins.dm | 57 +-- code/modules/reagents/chemistry/items.dm | 99 ++--- .../chemistry/machinery/chem_heater.dm | 2 +- .../reagents/chemistry/machinery/pandemic.dm | 4 +- .../reagents/reagent_containers/condiment.dm | 49 +-- .../reagents/reagent_containers/cups/_cup.dm | 42 +- .../reagent_containers/cups/drinks.dm | 12 +- .../reagents/reagent_containers/dropper.dm | 40 +- .../reagents/reagent_containers/misc.dm | 17 +- .../reagents/reagent_containers/pill.dm | 14 +- .../reagents/reagent_containers/spray.dm | 50 ++- .../reagents/reagent_containers/syringes.dm | 96 +++-- code/modules/recycling/conveyor.dm | 28 +- code/modules/recycling/sortingmachinery.dm | 2 +- code/modules/research/stock_parts.dm | 31 +- .../xenobiology/crossbreeding/_misc.dm | 22 +- .../xenobiology/crossbreeding/_potions.dm | 128 +++--- .../crossbreeding/_status_effects.dm | 2 +- .../xenobiology/crossbreeding/_weapons.dm | 5 +- .../xenobiology/crossbreeding/chilling.dm | 44 +- .../xenobiology/crossbreeding/prismatic.dm | 32 +- .../xenobiology/crossbreeding/regenerative.dm | 13 +- .../research/xenobiology/xenobiology.dm | 95 +++-- code/modules/shuttle/emergency.dm | 10 +- .../spell_types/self/sanguine_strike.dm | 2 +- .../spells/spell_types/touch/_touch.dm | 28 +- code/modules/surgery/tools.dm | 9 +- code/modules/unit_tests/projectiles.dm | 2 +- code/modules/unit_tests/reagent_mob_expose.dm | 2 +- .../admin/signal_handler/signal_list.dm | 1 - code/modules/wiremod/shell/scanner.dm | 13 +- code/modules/zombie/items.dm | 13 +- .../code/game/objects/items/RCD.dm | 17 +- .../ashwalkers/code/buildings/railroad.dm | 13 +- .../ashwalkers/code/items/ashwalker_shaman.dm | 44 +- .../borg_buffs/code/snack_dispensor.dm | 63 +-- .../modules/borgs/code/robot_items.dm | 23 +- .../modules/borgs/code/robot_upgrade.dm | 42 +- modular_nova/modules/bsrpd/code/bsrpd.dm | 16 +- .../cargo_teleporter/code/cargo_teleporter.dm | 17 +- .../code/items/replica_fabricator.dm | 32 +- .../modules/clock_cult/code/items/weaponry.dm | 5 +- .../clock_cult/code/structures/traps/trap.dm | 10 +- .../code/construction/turfs.dm | 24 +- .../conveyor_sorter/code/conveyor_sorter.dm | 27 +- .../game/objects/items/conversion_kits.dm | 29 +- .../modules/surgery/organs/wings.dm | 16 +- modular_nova/modules/faction/code/id.dm | 19 +- .../game/objects/items/gladiator_items.dm | 8 +- .../modules/gunpoint/code/gunpoint_datum.dm | 2 +- .../modules/hyposprays/code/hyposprays_II.dm | 66 ++- .../icemoon_additions/code/icecat_recipes.dm | 8 +- .../code/liquid_systems/liquid_interaction.dm | 11 +- modular_nova/modules/liquids/code/mop.dm | 2 +- .../magfed_turret/code/turret_framework.dm | 37 +- modular_nova/modules/marines/code/gear.dm | 40 +- .../modules/medical/code/smartdarts.dm | 33 +- .../modular_implants/code/misc_devices.dm | 18 +- .../soulcatcher/attachable_soulcatcher.dm | 20 +- .../modular_items/code/summon_beacon.dm | 18 +- .../code/lewd_clothing/bdsm_mask.dm | 212 ++++------ .../code/lewd_items/_masturbation_item.dm | 9 +- .../lewd_items/code/lewd_items/serviette.dm | 50 +-- .../carwo_defense_systems/grenade_launcher.dm | 11 +- .../modules/morenarcotics/code/vapecarts.dm | 27 +- .../modules/moretraitoritems/code/glue.dm | 39 +- .../code/mounted_machine_gun.dm | 4 +- .../modules/mutants/code/mutant_cure.dm | 26 +- .../modules/mutants/code/mutant_species.dm | 7 +- .../modules/novaya_ert/code/mod_suit.dm | 6 +- .../polarization_controller.dm | 10 +- .../modules/pollution/code/air_refresher.dm | 11 +- .../modules/pollution/code/perfumes.dm | 9 +- .../primitive_catgirls/code/smelling_salts.dm | 2 +- .../primitive_catgirls/code/spawner.dm | 4 +- .../primitive_production/code/glassblowing.dm | 30 +- .../reagent_forging/code/forge_items.dm | 2 +- .../modules/resleeving/code/rsd_interface.dm | 20 +- .../code/peacekeeper/peacekeeper_hammer.dm | 27 +- .../synths/code/bodyparts/power_cord.dm | 18 +- .../wargame_projectors/code/projectors.dm | 30 +- .../research/xenoarch/xenoarch_tool.dm | 37 +- 285 files changed, 3823 insertions(+), 3921 deletions(-) diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm index 79708cd152b..1db2a9d31aa 100644 --- a/code/__DEFINES/cleaning.dm +++ b/code/__DEFINES/cleaning.dm @@ -1,8 +1,17 @@ // Cleaning flags -///Whether we should not attempt to clean. -#define DO_NOT_CLEAN "do_not_clean" +/// Return to prevent clean attempts +#define CLEAN_BLOCKED (1<<0) +/// Return to allow clean attempts +/// This is (currently) the same as returning null / none but more explicit +#define CLEAN_ALLOWED (1<<1) +/// Return to prevent XP gain +/// Only does anything if [CLEAN_ALLOWED] is also returned +#define CLEAN_NO_XP (1<<2) +/// Return to stop cleaner component from blocking interaction chain further +/// Only does anything if [CLEAN_BLOCKED] is also returned +#define CLEAN_DONT_BLOCK_INTERACTION (1<<3) // Different kinds of things that can be cleaned. // Use these when overriding the wash proc or registering for the clean signals to check if your thing should be cleaned diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index a90523144cb..6246e25e93b 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -319,13 +319,6 @@ GLOBAL_LIST_INIT(leg_zones, list(BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) /// Proceed with the attack chain, but don't call the normal methods. #define SECONDARY_ATTACK_CONTINUE_CHAIN 3 -/// Flag for when /afterattack potentially acts on an item. -/// Used for the swap hands/drop tutorials to know when you might just be trying to do something normally. -/// Does not necessarily imply success, or even that it did hit an item, just intent. -// This is intentionally not (1 << 0) because some stuff currently erroneously returns TRUE/FALSE for afterattack. -// Doesn't need to be set if proximity flag is FALSE. -#define AFTERATTACK_PROCESSED_ITEM (1 << 1) - //Autofire component /// Compatible firemode is in the gun. Wait until it's held in the user hands. #define AUTOFIRE_STAT_IDLE (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm index f79f91ff641..5c5c2aefa6c 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_attack.dm @@ -6,7 +6,7 @@ #define COMSIG_ATOM_ATTACKBY "atom_attackby" /// From base of [atom/proc/attacby_secondary()]: (/obj/item/weapon, /mob/user, params) #define COMSIG_ATOM_ATTACKBY_SECONDARY "atom_attackby_secondary" -///from [/item/afterattack()], sent by an atom which was just attacked by an item: (/obj/item/weapon, /mob/user, proximity_flag, click_parameters) +/// From [/item/attack()], sent by an atom which was just attacked by an item: (/obj/item/weapon, /mob/user, proximity_flag, click_parameters) #define COMSIG_ATOM_AFTER_ATTACKEDBY "atom_after_attackby" /// From base of [/atom/proc/attack_hand_secondary]: (mob/user, list/modifiers) - Called when the atom receives a secondary unarmed attack. #define COMSIG_ATOM_ATTACK_HAND_SECONDARY "atom_attack_hand_secondary" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm index f6f7f6e4a29..6448be3fecb 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm @@ -56,6 +56,8 @@ /// Args: (mob/living/user, obj/item/tool, list/modifiers) /// Return any ITEM_INTERACT_ flags as relevant (see tools.dm) #define COMSIG_ATOM_ITEM_INTERACTION_SECONDARY "atom_item_interaction_secondary" +/// Sent from [atom/proc/item_interaction], to a mob clicking on an atom with an item +#define COMSIG_USER_ITEM_INTERACTION "user_item_interaction" /// Sent from [atom/proc/item_interaction], to an item clicking on an atom /// Args: (mob/living/user, atom/interacting_with, list/modifiers) /// Return any ITEM_INTERACT_ flags as relevant (see tools.dm) @@ -64,6 +66,8 @@ /// Args: (mob/living/user, atom/interacting_with, list/modifiers) /// Return any ITEM_INTERACT_ flags as relevant (see tools.dm) #define COMSIG_ITEM_INTERACTING_WITH_ATOM_SECONDARY "item_interacting_with_atom_secondary" +/// Sent from [atom/proc/item_interaction], when this atom is right-clicked on by a mob with a tool +#define COMSIG_USER_ITEM_INTERACTION_SECONDARY "user_item_interaction_secondary" /// Sent from [atom/proc/item_interaction], when this atom is left-clicked on by a mob with a tool of a specific tool type /// Args: (mob/living/user, obj/item/tool, list/recipes) /// Return any ITEM_INTERACT_ flags as relevant (see tools.dm) @@ -72,3 +76,20 @@ /// Args: (mob/living/user, obj/item/tool) /// Return any ITEM_INTERACT_ flags as relevant (see tools.dm) #define COMSIG_ATOM_SECONDARY_TOOL_ACT(tooltype) "tool_secondary_act_[tooltype]" + +/// Sent from [atom/proc/ranged_item_interaction], when this atom is left-clicked on by a mob with an item while not adjacent +#define COMSIG_ATOM_RANGED_ITEM_INTERACTION "atom_ranged_item_interaction" +/// Sent from [atom/proc/ranged_item_interaction], when this atom is right-clicked on by a mob with an item while not adjacent +#define COMSIG_ATOM_RANGED_ITEM_INTERACTION_SECONDARY "atom_ranged_item_interaction_secondary" +/// Sent from [atom/proc/ranged_item_interaction], when a mob is using this item while left-clicking on by an atom while not adjacent +#define COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM "ranged_item_interacting_with_atom" +/// Sent from [atom/proc/ranged_item_interaction], when a mob is using this item while right-clicking on by an atom while not adjacent +#define COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM_SECONDARY "ranged_item_interacting_with_atom_secondary" + +/// Sent from [atom/proc/item_interaction], when this atom is used as a tool and an event occurs +#define COMSIG_ITEM_TOOL_ACTED "tool_item_acted" + +/// This is sent via item interaction (IE, item clicking on atom) right before the item's inserted into the atom's storage +/// Args: (obj/item/inserting, mob/living/user) +#define COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT "atom_storage_item_interact_insert" + #define BLOCK_STORAGE_INSERT (1<<0) diff --git a/code/__DEFINES/dcs/signals/signals_heretic.dm b/code/__DEFINES/dcs/signals/signals_heretic.dm index a80526f96ab..bce4269720c 100644 --- a/code/__DEFINES/dcs/signals/signals_heretic.dm +++ b/code/__DEFINES/dcs/signals/signals_heretic.dm @@ -1,15 +1,15 @@ /// Heretic signals -/// From /obj/item/melee/touch_attack/mansus_fist/on_mob_hit : (mob/living/source, mob/living/target) +/// From /datum/action/cooldown/spell/touch/mansus_grasp/cast_on_hand_hit : (mob/living/source, mob/living/target) #define COMSIG_HERETIC_MANSUS_GRASP_ATTACK "mansus_grasp_attack" /// Default behavior is to use the hand, so return this to blocks the mansus fist from being consumed after use. #define COMPONENT_BLOCK_HAND_USE (1<<0) -/// From /obj/item/melee/touch_attack/mansus_fist/afterattack_secondary : (mob/living/source, atom/target) +/// From /datum/action/cooldown/spell/touch/mansus_grasp/cast_on_secondary_hand_hit : (mob/living/source, atom/target) #define COMSIG_HERETIC_MANSUS_GRASP_ATTACK_SECONDARY "mansus_grasp_attack_secondary" /// Default behavior is to continue attack chain and do nothing else, so return this to use up the hand after use. #define COMPONENT_USE_HAND (1<<0) -/// From /obj/item/melee/sickly_blade/afterattack (with proximity) : (mob/living/source, mob/living/target) +/// From /obj/item/melee/sickly_blade/afterattack : (mob/living/source, mob/living/target) #define COMSIG_HERETIC_BLADE_ATTACK "blade_attack" -/// From /obj/item/melee/sickly_blade/afterattack (without proximity) : (mob/living/source, mob/living/target) +/// From /obj/item/melee/sickly_blade/ranged_interact_with_atom (without proximity) : (mob/living/source, mob/living/target) #define COMSIG_HERETIC_RANGED_BLADE_ATTACK "ranged_blade_attack" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index cf6a5a12ef7..1515c8b7347 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -43,10 +43,12 @@ #define COMSIG_LIVING_SET_BUCKLED "living_set_buckled" ///from base of mob/living/set_body_position() #define COMSIG_LIVING_SET_BODY_POSITION "living_set_body_position" +/// Sent to a mob being injected with a syringe when the do_after initiates +#define COMSIG_LIVING_TRY_SYRINGE_INJECT "living_try_syringe_inject" +/// Sent to a mob being withdrawn from with a syringe when the do_after initiates +#define COMSIG_LIVING_TRY_SYRINGE_WITHDRAW "living_try_syringe_withdraw" ///from base of mob/living/set_usable_legs() #define COMSIG_LIVING_LIMBLESS_SLOWDOWN "living_limbless_slowdown" -///From post-can inject check of syringe after attack (mob/user) -#define COMSIG_LIVING_TRY_SYRINGE "living_try_syringe" ///From living/Life(). (deltatime, times_fired) #define COMSIG_LIVING_LIFE "living_life" /// Block the Life() proc from proceeding... this should really only be done in some really wacky situations. diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 3a13c683601..8ada1c30be3 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -181,10 +181,6 @@ #define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" ///from base of /obj/item/attack(): (mob/M, mob/user) #define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" -///from base of obj/item/afterattack(): (atom/target, obj/item/weapon, proximity_flag, click_parameters) -#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" -///from base of obj/item/afterattack_secondary(): (atom/target, obj/item/weapon, proximity_flag, click_parameters) -#define COMSIG_MOB_ITEM_AFTERATTACK_SECONDARY "mob_item_afterattack_secondary" ///from base of mob/RangedAttack(): (atom/A, modifiers) #define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" ///from base of mob/ranged_secondary_attack(): (atom/target, modifiers) diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index d7e895221d0..d92408f2192 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -9,7 +9,7 @@ #define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" ///from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide #define COMSIG_OBJ_HIDE "obj_hide" -/// from /obj/item/toy/crayon/spraycan/afterattack: (user, spraycan, color_is_dark) +/// from /obj/item/toy/crayon/spraycan/use_on: (user, spraycan, color_is_dark) #define COMSIG_OBJ_PAINTED "obj_painted" #define DONT_USE_SPRAYCAN_CHARGES (1<<0) /// from /obj/obj_reskin: (mob/user, skin) @@ -161,9 +161,6 @@ /// Return to prevent the default behavior (attack_selfing) from ocurring. #define COMPONENT_ITEM_ACTION_SLOT_INVALID (1<<0) -/// Sent from /obj/item/attack_atom(): (atom/attacked_atom, mob/living/user) -#define COMSIG_ITEM_POST_ATTACK_ATOM "item_post_attack_atom" - ///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) #define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" ///from base of obj/item/hit_reaction(): (owner, hitby, attack_text, final_block_chance, damage, attack_type, damage_type) @@ -208,7 +205,7 @@ #define COMSIG_STACK_CAN_MERGE "stack_can_merge" #define CANCEL_STACK_MERGE (1<<0) -///from /obj/item/book/bible/afterattack(): (mob/user, proximity) +///from /obj/item/book/bible/interact_with_atom(): (mob/user) #define COMSIG_BIBLE_SMACKED "bible_smacked" ///stops the bible chain from continuing. When all of the effects of the bible smacking have been moved to a signal we can kill this #define COMSIG_END_BIBLE_CHAIN (1<<0) @@ -450,8 +447,6 @@ ///from base of /obj/item/attack(): (mob/living, mob/living, params) #define COMSIG_ITEM_ATTACK "item_attack" -///from base of /obj/item/attack(): (mob/living, mob/living, params) -#define COMSIG_ITEM_POST_ATTACK "item_post_attack" // called only if the attack was executed ///from base of obj/item/attack_self(): (/mob) #define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self_secondary(): (/mob) @@ -467,14 +462,8 @@ #define COMPONENT_SECONDARY_CALL_NORMAL_ATTACK_CHAIN (1<<2) /// From base of [/obj/item/proc/attack_secondary()]: (atom/target, mob/user, params) #define COMSIG_ITEM_ATTACK_SECONDARY "item_attack_secondary" -///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) +///from base of [obj/item/attack()]: (atom/target, mob/user, proximity_flag, click_parameters) #define COMSIG_ITEM_AFTERATTACK "item_afterattack" - /// Flag for when /afterattack potentially acts on an item. - /// Used for the swap hands/drop tutorials to know when you might just be trying to do something normally. - /// Does not necessarily imply success, or even that it did hit an item, just intent. - #define COMPONENT_AFTERATTACK_PROCESSED_ITEM (1<<0) -///from base of obj/item/afterattack_secondary(): (atom/target, mob/user, proximity_flag, click_parameters) -#define COMSIG_ITEM_AFTERATTACK_SECONDARY "item_afterattack_secondary" ///from base of obj/item/embedded(): (atom/target, obj/item/bodypart/part) #define COMSIG_ITEM_EMBEDDED "item_embedded" ///from base of datum/component/embedded/safeRemove(): (mob/living/carbon/victim) @@ -495,7 +484,7 @@ ///from base of /obj/item/mmi/set_brainmob(): (mob/living/brain/new_brainmob) #define COMSIG_MMI_SET_BRAINMOB "mmi_set_brainmob" -/// from base of /obj/item/slimepotion/speed/afterattack(): (obj/target, /obj/src, mob/user) +/// from base of /obj/item/slimepotion/speed/interact_with_atom(): (obj/target, /obj/src, mob/user) #define COMSIG_SPEED_POTION_APPLIED "speed_potion" #define SPEED_POTION_STOP (1<<0) diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 3e78ecf40d0..7809610e6ab 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -31,6 +31,8 @@ /// Return to prevent the rest of the attack chain from being executed / preventing the item user from thwacking the target. /// Similar to [ITEM_INTERACT_SUCCESS], but does not necessarily indicate success. #define ITEM_INTERACT_BLOCKING (1<<1) + /// Only for people who get confused by the naming scheme + #define ITEM_INTERACT_FAILURE ITEM_INTERACT_BLOCKING /// Return to skip the rest of the interaction chain, going straight to attack. #define ITEM_INTERACT_SKIP_TO_ATTACK (1<<2) diff --git a/code/__HELPERS/atoms.dm b/code/__HELPERS/atoms.dm index 406ea75143c..cb1e2a87f76 100644 --- a/code/__HELPERS/atoms.dm +++ b/code/__HELPERS/atoms.dm @@ -325,3 +325,14 @@ rough example of the "cone" made by the 3 dirs checked "x" = icon_width > world.icon_size && pixel_x != 0 ? (icon_width - world.icon_size) * 0.5 : 0, "y" = icon_height > world.icon_size && pixel_y != 0 ? (icon_height - world.icon_size) * 0.5 : 0, ) + +/** + * Called before an item is put into this atom's storage datum via the item clicking on this atom + * + * This can be used to add item-atom interactions that you want handled before inserting something into storage + * (But it's also fairly snowflakey) + * + * Returning FALSE will block that item from being put into our storage + */ +/atom/proc/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + return TRUE diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 0f314eff03f..4dde5a7f04a 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -53,11 +53,10 @@ /** * Standard mob ClickOn() - * Handles exceptions: Buildmode, middle click, modified clicks, mech actions * * After that, mostly just check your state, check whether you're holding an item, - * check whether you're adjacent to the target, then pass off the click to whoever - * is receiving it. + * check whether you're adjacent to the target, then pass off the click to whoever is receiving it. + * * The most common are: * * [mob/proc/UnarmedAttack] (atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves * * [atom/proc/attackby] (item,user) - used only when adjacent @@ -167,13 +166,7 @@ UnarmedAttack(A, TRUE, modifiers) else if(W) - if(LAZYACCESS(modifiers, RIGHT_CLICK)) - var/after_attack_secondary_result = W.afterattack_secondary(A, src, FALSE, params) - - if(after_attack_secondary_result == SECONDARY_ATTACK_CALL_NORMAL) - W.afterattack(A, src, FALSE, params) - else - W.afterattack(A, src, FALSE, params) + A.base_ranged_item_interaction(src, W, modifiers) else if(LAZYACCESS(modifiers, RIGHT_CLICK)) ranged_secondary_attack(A, modifiers) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 691f436be5c..ca933c1c2bb 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -84,13 +84,7 @@ W.melee_attack_chain(src, A, params) return else if(isturf(A) || isturf(A.loc)) - if(LAZYACCESS(modifiers, RIGHT_CLICK)) - var/after_attack_secondary_result = W.afterattack_secondary(A, src, FALSE, params) - - if(after_attack_secondary_result == SECONDARY_ATTACK_CALL_NORMAL) - W.afterattack(A, src, FALSE, params) - else - W.afterattack(A, src, FALSE, params) + A.base_ranged_item_interaction(src, W, modifiers) //Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks // for non-doors/apcs diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 3e57d024483..ed5204eb218 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -17,6 +17,8 @@ if(item_interact_result & ITEM_INTERACT_BLOCKING) return FALSE + // At this point it means we're not doing a non-combat interaction so let's just try to bash it + var/pre_attack_result if (is_right_clicking) switch (pre_attack_secondary(target, user, params)) @@ -34,8 +36,9 @@ if(pre_attack_result) return TRUE - var/attackby_result + // At this point the attack is really about to happen + var/attackby_result if (is_right_clicking) switch (target.attackby_secondary(src, user, params)) if (SECONDARY_ATTACK_CALL_NORMAL) @@ -50,24 +53,19 @@ attackby_result = target.attackby(src, user, params) if (attackby_result) + // This means the attack failed or was handled for whatever reason return TRUE - if (is_right_clicking) - var/after_attack_secondary_result = afterattack_secondary(target, user, TRUE, params) - - // There's no chain left to continue at this point, so CANCEL_ATTACK_CHAIN and CONTINUE_CHAIN are functionally the same. - if (after_attack_secondary_result == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN || after_attack_secondary_result == SECONDARY_ATTACK_CONTINUE_CHAIN) - return TRUE + // At this point it means the attack was "successful", or at least unhandled, in some way + // This can mean nothing happened, this can mean the target took damage, etc. - var/afterattack_result = afterattack(target, user, TRUE, params) - - if (!(afterattack_result & AFTERATTACK_PROCESSED_ITEM) && isitem(target)) - if (isnull(user.get_inactive_held_item())) + if(user.client && isitem(target)) + if(isnull(user.get_inactive_held_item())) SStutorials.suggest_tutorial(user, /datum/tutorial/switch_hands, params2list(params)) else SStutorials.suggest_tutorial(user, /datum/tutorial/drop, params2list(params)) - return afterattack_result & TRUE //this is really stupid but its needed because afterattack can return TRUE | FLAGS. + return TRUE /// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user, modifiers) @@ -160,16 +158,6 @@ return attacking_item.attack_atom(src, user, params) /mob/living/item_interaction(mob/living/user, obj/item/tool, list/modifiers) - // Surgery and such happens very high up in the interaction chain, before parent call - var/attempt_tending = item_tending(user, tool, modifiers) - if(attempt_tending & ITEM_INTERACT_ANY_BLOCKER) - return attempt_tending - - return ..() | attempt_tending - -/// Handles any use of using a surgical tool or item on a mob to tend to them. -/// The sole reason this is a separate proc is so carbons can tend wounds AFTER the check for surgery. -/mob/living/proc/item_tending(mob/living/user, obj/item/tool, list/modifiers) for(var/datum/surgery/operation as anything in surgeries) if(IS_IN_INVALID_SURGICAL_POSITION(src, operation)) continue @@ -211,21 +199,21 @@ if(signal_return & COMPONENT_CANCEL_ATTACK_CHAIN) return TRUE if(signal_return & COMPONENT_SKIP_ATTACK) - return + return FALSE SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user, params) if(item_flags & NOBLUDGEON) - return + return FALSE if(damtype != STAMINA && force && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, span_warning("You don't want to harm other living beings!")) - return + return FALSE if(!force && !HAS_TRAIT(src, TRAIT_CUSTOM_TAP_SOUND)) - playsound(loc, 'sound/weapons/tap.ogg', get_clamped_volume(), TRUE, -1) + playsound(src, 'sound/weapons/tap.ogg', get_clamped_volume(), TRUE, -1) else if(hitsound) - playsound(loc, hitsound, get_clamped_volume(), TRUE, extrarange = stealthy_audio ? SILENCED_SOUND_EXTRARANGE : -1, falloff_distance = 0) + playsound(src, hitsound, get_clamped_volume(), TRUE, extrarange = stealthy_audio ? SILENCED_SOUND_EXTRARANGE : -1, falloff_distance = 0) target_mob.lastattacker = user.real_name target_mob.lastattackerckey = user.ckey @@ -233,14 +221,18 @@ if(force && target_mob == user && user.client) user.client.give_award(/datum/award/achievement/misc/selfouch, user) - user.do_attack_animation(target_mob) + if(get(src, /mob/living) == user) // telekinesis. + user.do_attack_animation(target_mob) if(!target_mob.attacked_by(src, user)) return TRUE - SEND_SIGNAL(src, COMSIG_ITEM_POST_ATTACK, target_mob, user, params) + SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target_mob, user, params) + SEND_SIGNAL(target_mob, COMSIG_ATOM_AFTER_ATTACKEDBY, src, user, params) + afterattack(target_mob, user, params) log_combat(user, target_mob, "attacked", src.name, "(COMBAT MODE: [uppertext(user.combat_mode)]) (DAMTYPE: [uppertext(damtype)])") add_fingerprint(user) + return FALSE // unhandled /// The equivalent of [/obj/item/proc/attack] but for alternate attacks, AKA right clicking /obj/item/proc/attack_secondary(mob/living/victim, mob/living/user, params) @@ -256,14 +248,21 @@ /// The equivalent of the standard version of [/obj/item/proc/attack] but for non mob targets. /obj/item/proc/attack_atom(atom/attacked_atom, mob/living/user, params) - if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_ATOM, attacked_atom, user) & COMPONENT_CANCEL_ATTACK_CHAIN) - return + var/signal_return = SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_ATOM, attacked_atom, user) + if(signal_return & COMPONENT_SKIP_ATTACK) + return TRUE + if(signal_return & COMPONENT_CANCEL_ATTACK_CHAIN) + return FALSE if(item_flags & NOBLUDGEON) - return + return FALSE user.changeNext_move(attack_speed) - user.do_attack_animation(attacked_atom) + if(get(src, /mob/living) == user) // telekinesis. + user.do_attack_animation(attacked_atom) attacked_atom.attacked_by(src, user) - SEND_SIGNAL(src, COMSIG_ITEM_POST_ATTACK_ATOM, attacked_atom, user) + SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, attacked_atom, user, params) + SEND_SIGNAL(attacked_atom, COMSIG_ATOM_AFTER_ATTACKEDBY, src, user, params) + afterattack(attacked_atom, user, params) + return FALSE // unhandled /// Called from [/obj/item/proc/attack_atom] and [/obj/item/proc/attack] if the attack succeeds /atom/proc/attacked_by(obj/item/attacking_item, mob/living/user) @@ -443,33 +442,9 @@ * * proximity_flag - is 1 if this afterattack was called on something adjacent, in your square, or on your person. * * click_parameters - is the params string from byond [/atom/proc/Click] code, see that documentation. */ -/obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = NONE - . |= SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters) - SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, src, proximity_flag, click_parameters) - SEND_SIGNAL(target, COMSIG_ATOM_AFTER_ATTACKEDBY, src, user, proximity_flag, click_parameters) - return . - -/** - * Called at the end of the attack chain if the user right-clicked. - * - * Arguments: - * * atom/target - The thing that was hit - * * mob/user - The mob doing the hitting - * * proximity_flag - is 1 if this afterattack was called on something adjacent, in your square, or on your person. - * * click_parameters - is the params string from byond [/atom/proc/Click] code, see that documentation. - */ -/obj/item/proc/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - var/signal_result = SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK_SECONDARY, target, user, proximity_flag, click_parameters) - SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK_SECONDARY, target, src, proximity_flag, click_parameters) - - if(signal_result & COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - - if(signal_result & COMPONENT_SECONDARY_CONTINUE_ATTACK_CHAIN) - return SECONDARY_ATTACK_CONTINUE_CHAIN - - return SECONDARY_ATTACK_CALL_NORMAL +/obj/item/proc/afterattack(atom/target, mob/user, click_parameters) + PROTECTED_PROC(TRUE) + return /obj/item/proc/get_clamped_volume() if(w_class) diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index c0ef2b6001f..bdbf6ab0a02 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -71,7 +71,7 @@ /obj/item/attack_self_tk(mob/user) if(attack_self(user)) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /atom/proc/attack_self_secondary_tk(mob/user) return @@ -79,7 +79,7 @@ /obj/item/attack_self_secondary_tk(mob/user) if(attack_self_secondary(user)) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /* @@ -146,80 +146,44 @@ if(QDELING(focus)) qdel(src) return - if(focus.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) + if(focus.attack_self_tk(user) & ITEM_INTERACT_ANY_BLOCKER) . = TRUE update_appearance() +/obj/item/tk_grab/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) -/obj/item/tk_grab/afterattack(atom/target, mob/living/carbon/user, proximity, params)//TODO: go over this - . = ..() - if(.) - return - - if(!target || !user) - return - +/obj/item/tk_grab/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!focus) - focus_object(target) - return TRUE + focus_object(interacting_with) + return ITEM_INTERACT_BLOCKING if(!check_if_focusable(focus)) - return + return NONE - if(target == focus) - if(target.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) - . = TRUE - update_appearance() - return + if(interacting_with == focus) + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + . = focus.attack_self_secondary_tk(user) || NONE + else + . = interacting_with.attack_self_tk(user) || NONE - if(isitem(focus)) - var/obj/item/I = focus + else if(isitem(focus)) + var/obj/item/focused_item = focus apply_focus_overlay() - if(target.Adjacent(focus)) - . = I.melee_attack_chain(tk_user, target, params) //isn't copying the attack chain fun. we should do it more often. + if(interacting_with.Adjacent(focus)) + . = focused_item.melee_attack_chain(user, interacting_with, list2params(modifiers)) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING if(check_if_focusable(focus)) - focus.do_attack_animation(target, null, focus) - else if(isgun(I)) //I've only tested this with guns, and it took some doing to make it work - . = I.afterattack(target, tk_user, 0, params) - . |= AFTERATTACK_PROCESSED_ITEM - - user.changeNext_move(CLICK_CD_MELEE) - update_appearance() - return . - -/obj/item/tk_grab/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return - - if(!target || !user) - return - - if(!focus) - focus_object(target) - return TRUE - - if(!check_if_focusable(focus)) - return - - if(target == focus) - if(target.attack_self_secondary_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) - . = TRUE - update_appearance() - return + focus.do_attack_animation(interacting_with, null, focus) - if(isitem(focus)) - var/obj/item/I = focus - apply_focus_overlay() - if(target.Adjacent(focus)) - . = I.melee_attack_chain(tk_user, target, click_parameters) //isn't copying the attack chain fun. we should do it more often. - if(check_if_focusable(focus)) - focus.do_attack_animation(target, null, focus) - else if(isgun(I)) //I've only tested this with guns, and it took some doing to make it work - . = I.afterattack_secondary(target, tk_user, 0, click_parameters) + // isgun check lets us shoot guns at range + // quoting the old comment: "I've only tested this with guns, and it took some doing to make it work" + // reader beware if trying to add other snowflake cases + else if(isgun(focused_item)) + . = interacting_with.base_ranged_item_interaction(user, focus, modifiers) user.changeNext_move(CLICK_CD_MELEE) update_appearance() + return . /obj/item/tk_grab/on_thrown(mob/living/carbon/user, atom/target) if(!target || !user) @@ -232,7 +196,7 @@ return if(target == focus) - if(target.attack_self_tk(user) & COMPONENT_CANCEL_ATTACK_CHAIN) + if(target.attack_self_tk(user) & ITEM_INTERACT_ANY_BLOCKER) return update_appearance() return diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index af9091db2dd..a5febe03143 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -197,7 +197,7 @@ var/can_shoot = gun?.can_shoot() || FALSE if(gun && controller.blackboard[BB_MONKEY_GUN_WORKED] && prob(95)) // We attempt to attack even if we can't shoot so we get the effects of pulling the trigger - gun.afterattack(real_target, living_pawn, FALSE) + gun.melee_attack_chain(living_pawn, real_target) controller.set_blackboard_key(BB_MONKEY_GUN_WORKED, can_shoot ? TRUE : prob(80)) // Only 20% likely to notice it didn't work if(can_shoot) controller.set_blackboard_key(BB_MONKEY_GUN_NEURONS_ACTIVATED, TRUE) diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm index 693427ba4bd..451d692b65d 100644 --- a/code/datums/ai/monkey/monkey_controller.dm +++ b/code/datums/ai/monkey/monkey_controller.dm @@ -80,7 +80,7 @@ have ways of interacting with a specific mob and control it. living_pawn.AddElement(/datum/element/relay_attackers) RegisterSignal(new_pawn, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) RegisterSignal(new_pawn, COMSIG_LIVING_START_PULL, PROC_REF(on_startpulling)) - RegisterSignal(new_pawn, COMSIG_LIVING_TRY_SYRINGE, PROC_REF(on_try_syringe)) + RegisterSignals(new_pawn, list(COMSIG_LIVING_TRY_SYRINGE_INJECT, COMSIG_LIVING_TRY_SYRINGE_WITHDRAW), PROC_REF(on_try_syringe)) RegisterSignal(new_pawn, COMSIG_CARBON_CUFF_ATTEMPTED, PROC_REF(on_attempt_cuff)) RegisterSignal(new_pawn, COMSIG_MOB_MOVESPEED_UPDATED, PROC_REF(update_movespeed)) @@ -92,7 +92,8 @@ have ways of interacting with a specific mob and control it. UnregisterSignal(pawn, list( COMSIG_ATOM_WAS_ATTACKED, COMSIG_LIVING_START_PULL, - COMSIG_LIVING_TRY_SYRINGE, + COMSIG_LIVING_TRY_SYRINGE_INJECT, + COMSIG_LIVING_TRY_SYRINGE_WITHDRAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_MOB_MOVESPEED_UPDATED, )) diff --git a/code/datums/components/cleaner.dm b/code/datums/components/cleaner.dm index 49f200b4b92..3001fde9837 100644 --- a/code/datums/components/cleaner.dm +++ b/code/datums/components/cleaner.dm @@ -35,16 +35,16 @@ return ..() /datum/component/cleaner/RegisterWithParent() - if(isbot(parent)) + if(ismob(parent)) RegisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack)) - return - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(on_interaction)) /datum/component/cleaner/UnregisterFromParent() - if(isbot(parent)) - UnregisterSignal(parent, COMSIG_LIVING_UNARMED_ATTACK) - return - UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(parent, list( + COMSIG_ITEM_INTERACTING_WITH_ATOM, + COMSIG_LIVING_UNARMED_ATTACK, + )) /** * Handles the COMSIG_LIVING_UNARMED_ATTACK signal used for cleanbots @@ -52,29 +52,27 @@ */ /datum/component/cleaner/proc/on_unarmed_attack(datum/source, atom/target, proximity_flags, modifiers) SIGNAL_HANDLER - return on_afterattack(source, target, parent, proximity_flags, modifiers) + if(on_interaction(source, source, target, modifiers) & ITEM_INTERACT_ANY_BLOCKER) + return COMPONENT_CANCEL_ATTACK_CHAIN + return NONE /** - * Handles the COMSIG_ITEM_AFTERATTACK signal by calling the clean proc. - * - * Arguments - * * source the datum that sent the signal to start cleaning - * * target the thing being cleaned - * * user the person doing the cleaning - * * clean_target set this to false if the target should not be washed and if experience should not be awarded to the user + * Handles the COMSIG_ITEM_INTERACTING_WITH_ATOM signal by calling the clean proc. */ -/datum/component/cleaner/proc/on_afterattack(datum/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/component/cleaner/proc/on_interaction(datum/source, mob/living/user, atom/target, list/modifiers) SIGNAL_HANDLER - if(!proximity_flag) - return - . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - var/clean_target + + // By default, give XP + var/give_xp = TRUE if(pre_clean_callback) - clean_target = pre_clean_callback?.Invoke(source, target, user) - if(clean_target == DO_NOT_CLEAN) - return . - INVOKE_ASYNC(src, PROC_REF(clean), source, target, user, clean_target) //signal handlers can't have do_afters inside of them - return . + var/callback_return = pre_clean_callback.Invoke(source, target, user) + if(callback_return & CLEAN_BLOCKED) + return (callback_return & CLEAN_DONT_BLOCK_INTERACTION) ? NONE : ITEM_INTERACT_BLOCKING + if(callback_return & CLEAN_NO_XP) + give_xp = FALSE + + INVOKE_ASYNC(src, PROC_REF(clean), source, target, user, give_xp) + return ITEM_INTERACT_SUCCESS /** * Cleans something using this cleaner. diff --git a/code/datums/components/igniter.dm b/code/datums/components/igniter.dm index d94c4be101a..ad9351b34e9 100644 --- a/code/datums/components/igniter.dm +++ b/code/datums/components/igniter.dm @@ -20,13 +20,10 @@ /datum/component/igniter/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_POST_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) -/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, click_parameters) SIGNAL_HANDLER - if(!proximity_flag) - return do_igniter(target) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM /datum/component/igniter/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success) SIGNAL_HANDLER diff --git a/code/datums/components/infective.dm b/code/datums/components/infective.dm index 0e5341eabbf..bc7cc2e6af3 100644 --- a/code/datums/components/infective.dm +++ b/code/datums/components/infective.dm @@ -118,17 +118,16 @@ try_infect(target, hit_zone) -/datum/component/infective/proc/try_infect_attack_zone(datum/source, mob/living/carbon/target, mob/living/user, hit_zone) +/datum/component/infective/proc/try_infect_attack_zone(obj/item/source, mob/living/carbon/target, mob/living/user, hit_zone) SIGNAL_HANDLER - try_infect(user, BODY_ZONE_L_ARM) try_infect(target, hit_zone) -/datum/component/infective/proc/try_infect_attack(datum/source, mob/living/target, mob/living/user) +/datum/component/infective/proc/try_infect_attack(obj/item/source, mob/living/target, mob/living/user) SIGNAL_HANDLER - if(!iscarbon(target)) //this case will be handled by try_infect_attack_zone - try_infect(target) - try_infect(user, BODY_ZONE_L_ARM) + if(source.loc == user) + var/obj/item/bodypart/hand = user.get_active_hand() + try_infect(user, hand.body_zone) /datum/component/infective/proc/try_infect_equipped(datum/source, mob/living/L, slot) SIGNAL_HANDLER diff --git a/code/datums/components/jousting.dm b/code/datums/components/jousting.dm index 2fc565cf63b..d741bffd1ea 100644 --- a/code/datums/components/jousting.dm +++ b/code/datums/components/jousting.dm @@ -44,7 +44,7 @@ RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop)) - RegisterSignal(parent, COMSIG_ITEM_POST_ATTACK, PROC_REF(on_successful_attack)) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_successful_attack)) RegisterSignal(parent, COMSIG_TRANSFORMING_ON_TRANSFORM, PROC_REF(on_transform)) /datum/component/jousting/UnregisterFromParent() @@ -53,7 +53,7 @@ COMSIG_ATOM_EXAMINE, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, - COMSIG_ITEM_POST_ATTACK, + COMSIG_ITEM_AFTERATTACK, COMSIG_TRANSFORMING_ON_TRANSFORM, )) diff --git a/code/datums/components/lockable_storage.dm b/code/datums/components/lockable_storage.dm index 52aba799741..c559c008c79 100644 --- a/code/datums/components/lockable_storage.dm +++ b/code/datums/components/lockable_storage.dm @@ -47,6 +47,7 @@ if(can_hack_open) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), PROC_REF(on_screwdriver_act)) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_multitool_act)) + RegisterSignal(parent, COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT, PROC_REF(block_insert)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item)) @@ -62,6 +63,7 @@ UnregisterSignal(parent, list( COMSIG_ATOM_TOOL_ACT(TOOL_SCREWDRIVER), COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), + COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT, )) UnregisterSignal(parent, list( COMSIG_ATOM_EXAMINE, @@ -140,6 +142,15 @@ source.balloon_alert(user, "hacked") lock_code = null +/// Stops you from shoving your tools into the storage if you're trying to hack it +/datum/component/lockable_storage/proc/block_insert(atom/source, obj/item/inserting, mob/living/user) + SIGNAL_HANDLER + if(!can_hack_open || !source.atom_storage.locked) + return NONE // allow insert + if(inserting.tool_behaviour == TOOL_MULTITOOL || inserting.tool_behaviour == TOOL_SCREWDRIVER) + return BLOCK_STORAGE_INSERT // block insert + return NONE + ///Updates the icon state depending on if we're locked or not. /datum/component/lockable_storage/proc/on_update_icon_state(obj/source) SIGNAL_HANDLER diff --git a/code/datums/components/on_hit_effect.dm b/code/datums/components/on_hit_effect.dm index 4093249c1ad..9d1d0474290 100644 --- a/code/datums/components/on_hit_effect.dm +++ b/code/datums/components/on_hit_effect.dm @@ -58,7 +58,6 @@ if(!extra_check_callback.Invoke(user, target, source)) return on_hit_callback.Invoke(source, user, target, user.zone_selected) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM /datum/component/on_hit_effect/proc/hostile_attackingtarget(mob/living/attacker, atom/target, success) SIGNAL_HANDLER diff --git a/code/datums/components/reagent_refiller.dm b/code/datums/components/reagent_refiller.dm index 35bdcb4ce51..7e455b150ad 100644 --- a/code/datums/components/reagent_refiller.dm +++ b/code/datums/components/reagent_refiller.dm @@ -33,11 +33,11 @@ return ..() /datum/component/reagent_refiller/RegisterWithParent() - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(refill)) + RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(refill)) RegisterSignal(parent, COMSIG_ATOM_EXITED, PROC_REF(delete_self)) /datum/component/reagent_refiller/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_ATOM_EXITED)) + UnregisterSignal(parent, list(COMSIG_ITEM_INTERACTING_WITH_ATOM, COMSIG_ATOM_EXITED)) /datum/component/reagent_refiller/proc/delete_self() SIGNAL_HANDLER @@ -48,8 +48,6 @@ /datum/component/reagent_refiller/proc/refill() SIGNAL_HANDLER - . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - var/obj/item/reagent_containers/container = parent var/amount = min((container.amount_per_transfer_from_this + container.reagents.total_volume), container.reagents.total_volume) if (amount == 0) diff --git a/code/datums/components/scope.dm b/code/datums/components/scope.dm index 531ff9e9962..dfc9d1c66c4 100644 --- a/code/datums/components/scope.dm +++ b/code/datums/components/scope.dm @@ -27,7 +27,7 @@ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) switch(zoom_method) if(ZOOM_METHOD_RIGHT_CLICK) - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK_SECONDARY, PROC_REF(on_secondary_afterattack)) + RegisterSignal(parent, COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM_SECONDARY, PROC_REF(do_secondary_zoom)) if(ZOOM_METHOD_WIELD) RegisterSignal(parent, SIGNAL_ADDTRAIT(TRAIT_WIELDED), PROC_REF(on_wielded)) RegisterSignal(parent, SIGNAL_REMOVETRAIT(TRAIT_WIELDED), PROC_REF(on_unwielded)) @@ -46,7 +46,7 @@ parent_item.remove_item_action(scope) UnregisterSignal(parent, list( COMSIG_MOVABLE_MOVED, - COMSIG_ITEM_AFTERATTACK_SECONDARY, + COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM_SECONDARY, SIGNAL_ADDTRAIT(TRAIT_WIELDED), SIGNAL_REMOVETRAIT(TRAIT_WIELDED), COMSIG_GUN_TRY_FIRE, @@ -71,14 +71,14 @@ return stop_zooming(tracker.owner) -/datum/component/scope/proc/on_secondary_afterattack(datum/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/component/scope/proc/do_secondary_zoom(datum/source, mob/user, atom/target, click_parameters) SIGNAL_HANDLER if(tracker) stop_zooming(user) else zoom(user) - return COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /datum/component/scope/proc/on_action_trigger(datum/action/source) SIGNAL_HANDLER diff --git a/code/datums/components/soul_stealer.dm b/code/datums/components/soul_stealer.dm index a69265421bb..e725792bffe 100644 --- a/code/datums/components/soul_stealer.dm +++ b/code/datums/components/soul_stealer.dm @@ -22,9 +22,10 @@ /datum/component/soul_stealer/RegisterWithParent() RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(try_transfer_soul)) /datum/component/soul_stealer/UnregisterFromParent() - UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_AFTERATTACK)) + UnregisterSignal(parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ITEM_AFTERATTACK, COMSIG_ITEM_INTERACTING_WITH_ATOM)) ///signal called on parent being examined /datum/component/soul_stealer/proc/on_examine(datum/source, mob/user, list/examine_list) @@ -41,15 +42,15 @@ if(10 to INFINITY) examine_list += span_notice("A staggering [num_souls] souls have been claimed by it! And it hungers for more!") -/datum/component/soul_stealer/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, proximity_flag, click_parameters) +/datum/component/soul_stealer/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, click_parameters) SIGNAL_HANDLER - if(!proximity_flag) - return - if(ishuman(target)) INVOKE_ASYNC(src, PROC_REF(try_capture), target, user) +/datum/component/soul_stealer/proc/try_transfer_soul(obj/item/source, mob/user, atom/target, click_parameters) + SIGNAL_HANDLER + if(istype(target, /obj/structure/constructshell) && length(soulstones)) var/obj/item/soulstone/soulstone = soulstones[1] INVOKE_ASYNC(soulstone, TYPE_PROC_REF(/obj/item/soulstone, transfer_to_construct), target, user) @@ -58,7 +59,7 @@ else if(!length(soulstone.contents)) // something fucky happened qdel(soulstone) soulstones -= soulstone - + return ITEM_INTERACT_SUCCESS /datum/component/soul_stealer/proc/try_capture(mob/living/carbon/human/victim, mob/living/captor) if(victim.stat == CONSCIOUS) diff --git a/code/datums/components/spirit_holding.dm b/code/datums/components/spirit_holding.dm index e2b1cfb96bc..578e378b51c 100644 --- a/code/datums/components/spirit_holding.dm +++ b/code/datums/components/spirit_holding.dm @@ -115,7 +115,7 @@ SIGNAL_HANDLER return COMSIG_BLOCK_RELAYMOVE -/datum/component/spirit_holding/proc/on_bible_smacked(datum/source, mob/living/user, direction) +/datum/component/spirit_holding/proc/on_bible_smacked(datum/source, mob/living/user, ...) SIGNAL_HANDLER INVOKE_ASYNC(src, PROC_REF(attempt_exorcism), user) diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index 7132608e723..2dcc6ee7104 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -97,7 +97,7 @@ src.multitooled = multitooled /datum/component/style/RegisterWithParent() - RegisterSignal(parent, COMSIG_MOB_ITEM_AFTERATTACK, PROC_REF(hotswap)) + RegisterSignal(parent, COMSIG_USER_ITEM_INTERACTION, PROC_REF(hotswap)) RegisterSignal(parent, COMSIG_MOB_MINED, PROC_REF(on_mine)) RegisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(on_take_damage)) RegisterSignal(parent, COMSIG_MOB_EMOTED("flip"), PROC_REF(on_flip)) @@ -125,7 +125,7 @@ ) /datum/component/style/UnregisterFromParent() - UnregisterSignal(parent, COMSIG_MOB_ITEM_AFTERATTACK) + UnregisterSignal(parent, COMSIG_USER_ITEM_INTERACTION) UnregisterSignal(parent, COMSIG_MOB_MINED) UnregisterSignal(parent, COMSIG_MOB_APPLY_DAMAGE) UnregisterSignal(parent, list(COMSIG_MOB_EMOTED("flip"), COMSIG_MOB_EMOTED("spin"))) @@ -318,26 +318,27 @@ return "#364866" /// A proc that lets a user, when their rank >= `hotswap_rank`, swap items in storage with what's in their hands, simply by clicking on the stored item with a held item -/datum/component/style/proc/hotswap(mob/living/source, atom/target, obj/item/weapon, proximity_flag, click_parameters) +/datum/component/style/proc/hotswap(mob/living/source, atom/target, obj/item/weapon, click_parameters) SIGNAL_HANDLER if((rank < hotswap_rank) || !isitem(target) || !(target in source.get_all_contents())) - return + return NONE var/obj/item/item_target = target if(!(item_target.item_flags & IN_STORAGE)) - return + return NONE var/datum/storage/atom_storage = item_target.loc.atom_storage if(!atom_storage.can_insert(weapon, source, messages = FALSE)) source.balloon_alert(source, "unable to hotswap!") - return + return NONE atom_storage.attempt_insert(weapon, source, override = TRUE) INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, put_in_hands), target) source.visible_message(span_notice("[source] quickly swaps [weapon] out with [target]!"), span_notice("You quickly swap [weapon] with [target].")) + return ITEM_INTERACT_BLOCKING // Point givers /datum/component/style/proc/on_punch(mob/living/carbon/human/punching_person, atom/attacked_atom, proximity) diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm index 220a4baca5f..69ade1e2f1b 100644 --- a/code/datums/components/summoning.dm +++ b/code/datums/components/summoning.dm @@ -49,13 +49,10 @@ /datum/component/summoning/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_POST_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) -/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, click_parameters) SIGNAL_HANDLER - if(!proximity_flag) - return do_spawn_mob(get_turf(target), user) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM /datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success) SIGNAL_HANDLER diff --git a/code/datums/components/trapdoor.dm b/code/datums/components/trapdoor.dm index bda67048ffe..e606648c212 100644 --- a/code/datums/components/trapdoor.dm +++ b/code/datums/components/trapdoor.dm @@ -354,26 +354,23 @@ . = ..() AddElement(/datum/element/openspace_item_click_handler) -/obj/item/trapdoor_kit/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) - afterattack(target, user, proximity_flag, click_parameters) +/obj/item/trapdoor_kit/handle_openspace_click(turf/target, mob/user, click_parameters) + interact_with_atom(target, user, click_parameters) -/obj/item/trapdoor_kit/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - var/turf/target_turf = get_turf(target) +/obj/item/trapdoor_kit/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/target_turf = get_turf(interacting_with) if(!isopenspaceturf(target_turf)) - return + return NONE in_use = TRUE balloon_alert(user, "constructing trapdoor") - if(!do_after(user, 5 SECONDS, target = target)) + if(!do_after(user, 5 SECONDS, interacting_with)) in_use = FALSE - return + return ITEM_INTERACT_BLOCKING in_use = FALSE if(!isopenspaceturf(target_turf)) // second check to make sure nothing changed during constructions - return + return ITEM_INTERACT_BLOCKING var/turf/new_turf = target_turf.place_on_top(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) new_turf.AddComponent(/datum/component/trapdoor, starts_open = FALSE, conspicuous = TRUE) balloon_alert(user, "trapdoor constructed") qdel(src) - return + return ITEM_INTERACT_SUCCESS diff --git a/code/datums/elements/can_shatter.dm b/code/datums/elements/can_shatter.dm index 73b025ad83c..be7e02e25b4 100644 --- a/code/datums/elements/can_shatter.dm +++ b/code/datums/elements/can_shatter.dm @@ -31,7 +31,7 @@ RegisterSignal(target, COMSIG_MOVABLE_IMPACT, PROC_REF(on_throw_impact)) RegisterSignal(target, COMSIG_ATOM_ON_Z_IMPACT, PROC_REF(on_z_impact)) if(shatters_as_weapon) - RegisterSignal(target, COMSIG_ITEM_POST_ATTACK_ATOM, PROC_REF(on_post_attack_atom)) + RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_post_attack_atom)) /datum/element/can_shatter/Detach(datum/target) . = ..() diff --git a/code/datums/elements/easily_fragmented.dm b/code/datums/elements/easily_fragmented.dm index eb7f499c0f2..aa8b07a866e 100644 --- a/code/datums/elements/easily_fragmented.dm +++ b/code/datums/elements/easily_fragmented.dm @@ -17,18 +17,21 @@ src.break_chance = break_chance RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + RegisterSignal(target, COMSIG_ITEM_TOOL_ACTED, PROC_REF(on_tool_use)) /datum/element/easily_fragmented/Detach(datum/target) . = ..() - UnregisterSignal(target, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(target, list(COMSIG_ITEM_AFTERATTACK, COMSIG_ITEM_TOOL_ACTED)) -/datum/element/easily_fragmented/proc/on_afterattack(datum/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/element/easily_fragmented/proc/on_afterattack(datum/source, atom/target, mob/user, click_parameters) SIGNAL_HANDLER + try_break(source, user) - var/obj/item/item = source +/datum/element/easily_fragmented/proc/on_tool_use(datum/source, atom/target, mob/user, tool_type, result) + SIGNAL_HANDLER + try_break(source, user) +/datum/element/easily_fragmented/proc/try_break(obj/item/source, mob/user) if(prob(break_chance)) - user.visible_message(span_danger("[user]'s [item.name] snap[item.p_s()] into tiny pieces in [user.p_their()] hand.")) - item.deconstruct(disassembled = FALSE) - - return COMPONENT_AFTERATTACK_PROCESSED_ITEM + user.visible_message(span_danger("[user]'s [source.name] snap[source.p_s()] into tiny pieces in [user.p_their()] hand.")) + source.deconstruct(disassembled = FALSE) diff --git a/code/datums/elements/envenomable_casing.dm b/code/datums/elements/envenomable_casing.dm index 8cf77a2f2cc..5e080adaf00 100644 --- a/code/datums/elements/envenomable_casing.dm +++ b/code/datums/elements/envenomable_casing.dm @@ -15,7 +15,7 @@ if(!istype(target, /obj/item/ammo_casing)) return ELEMENT_INCOMPATIBLE src.amount_allowed = amount_allowed - RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(handle_interaction)) RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine_before_dip)) /datum/element/envenomable_casing/Detach(datum/target) @@ -23,28 +23,29 @@ UnregisterSignal(target, list(COMSIG_ITEM_AFTERATTACK, COMSIG_ATOM_EXAMINE)) ///signal called on the parent attacking an item -/datum/element/envenomable_casing/proc/on_afterattack(obj/item/ammo_casing/casing, atom/target, mob/user, proximity_flag, click_parameters) +/datum/element/envenomable_casing/proc/handle_interaction(obj/item/ammo_casing/casing, mob/user, atom/target, click_parameters) SIGNAL_HANDLER if(!is_reagent_container(target)) - return + return NONE var/obj/item/reagent_containers/venom_container = target if(!casing.loaded_projectile) user.balloon_alert(user, "casing is already spent!") - return + return ITEM_INTERACT_BLOCKING if(!(venom_container.reagent_flags & OPENCONTAINER)) user.balloon_alert(user, "open the container!") - return + return ITEM_INTERACT_BLOCKING var/datum/reagent/venom_applied = venom_container.reagents.get_master_reagent() if(!venom_applied) - return + return ITEM_INTERACT_BLOCKING var/amount_applied = min(venom_applied.volume, amount_allowed) casing.loaded_projectile.AddElement(/datum/element/venomous, venom_applied.type, amount_applied) to_chat(user, span_notice("You coat [casing] in [venom_applied].")) venom_container.reagents.remove_reagent(venom_applied.type, amount_applied) ///stops further poison application - UnregisterSignal(casing, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(casing, COMSIG_ITEM_INTERACTING_WITH_ATOM) RegisterSignal(casing, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine_after_dip), override = TRUE) + return ITEM_INTERACT_SUCCESS ///signal called on parent being examined while not coated /datum/element/envenomable_casing/proc/on_examine_before_dip(obj/item/ammo_casing/casing, mob/user, list/examine_list) @@ -55,5 +56,3 @@ /datum/element/envenomable_casing/proc/on_examine_after_dip(obj/item/ammo_casing/casing, mob/user, list/examine_list) SIGNAL_HANDLER examine_list += span_warning("It's coated in some kind of chemical...") - - diff --git a/code/datums/elements/food/dunkable.dm b/code/datums/elements/food/dunkable.dm index d413119e285..baf4be2a813 100644 --- a/code/datums/elements/food/dunkable.dm +++ b/code/datums/elements/food/dunkable.dm @@ -10,29 +10,27 @@ if(!isitem(target)) return ELEMENT_INCOMPATIBLE dunk_amount = amount_per_dunk - RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(get_dunked)) + RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(get_dunked)) /datum/element/dunkable/Detach(datum/target) . = ..() - UnregisterSignal(target, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM) -/datum/element/dunkable/proc/get_dunked(datum/source, atom/target, mob/user, proximity_flag) +/datum/element/dunkable/proc/get_dunked(datum/source, mob/user, atom/target, params) SIGNAL_HANDLER - if(!proximity_flag) // if the user is not adjacent to the container - return var/obj/item/reagent_containers/container = target // the container we're trying to dunk into - if(istype(container) && container.reagent_flags & DUNKABLE) // container should be a valid target for dunking - . = COMPONENT_AFTERATTACK_PROCESSED_ITEM + if(istype(container) && (container.reagent_flags & DUNKABLE)) // container should be a valid target for dunking if(!container.is_drainable()) to_chat(user, span_warning("[container] is unable to be dunked in!")) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING var/obj/item/I = source // the item that has the dunkable element if(container.reagents.trans_to(I, dunk_amount, transferred_by = user)) //if reagents were transferred, show the message to_chat(user, span_notice("You dunk \the [I] into \the [container].")) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_SUCCESS if(!container.reagents.total_volume) to_chat(user, span_warning("[container] is empty!")) else to_chat(user, span_warning("[I] is full!")) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + return NONE diff --git a/code/datums/elements/knockback.dm b/code/datums/elements/knockback.dm index 2ad669f9892..c8f06efa430 100644 --- a/code/datums/elements/knockback.dm +++ b/code/datums/elements/knockback.dm @@ -30,13 +30,10 @@ return ..() /// triggered after an item attacks something -/datum/element/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/element/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, click_parameters) SIGNAL_HANDLER - if(!proximity_flag) - return do_knockback(target, user, get_dir(source, target)) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM /// triggered after a hostile simplemob attacks something /datum/element/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success) diff --git a/code/datums/elements/light_eater.dm b/code/datums/elements/light_eater.dm index 50f88cb9e9b..ed3851944d9 100644 --- a/code/datums/elements/light_eater.dm +++ b/code/datums/elements/light_eater.dm @@ -126,12 +126,9 @@ * - [user][/mob/living]: The mob using the source to strike the target * - proximity: Whether the strike was in melee range so you can't eat lights from cameras */ -/datum/element/light_eater/proc/on_afterattack(obj/item/source, atom/target, mob/living/user, proximity) +/datum/element/light_eater/proc/on_afterattack(obj/item/source, atom/target, mob/living/user) SIGNAL_HANDLER - if(!proximity) - return NONE eat_lights(target, source) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM /** * Called when a source object is used to block a thrown object, projectile, or attack diff --git a/code/datums/elements/openspace_item_click_handler.dm b/code/datums/elements/openspace_item_click_handler.dm index c9de01f381c..67a3dbefbde 100644 --- a/code/datums/elements/openspace_item_click_handler.dm +++ b/code/datums/elements/openspace_item_click_handler.dm @@ -8,22 +8,22 @@ . = ..() if(!isitem(target)) return ELEMENT_INCOMPATIBLE - RegisterSignal(target, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_afterattack)) + RegisterSignal(target, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(divert_interaction)) /datum/element/openspace_item_click_handler/Detach(datum/source) - UnregisterSignal(source, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(source, COMSIG_ITEM_INTERACTING_WITH_ATOM) return ..() //Invokes the proctype with a turf above as target. -/datum/element/openspace_item_click_handler/proc/on_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/element/openspace_item_click_handler/proc/divert_interaction(obj/item/source, mob/user, atom/target, click_parameters) SIGNAL_HANDLER if(target.z == user.z) - return + return NONE var/turf/checked_turf = get_turf(target) while(!isnull(checked_turf)) checked_turf = GET_TURF_ABOVE(checked_turf) - if(checked_turf?.z == user.z) - INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, handle_openspace_click), checked_turf, user, user.CanReach(checked_turf, source), click_parameters) + if(checked_turf?.z == user.z && user.CanReach(checked_turf, source)) + INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, handle_openspace_click), checked_turf, user, click_parameters) break - return COMPONENT_AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING diff --git a/code/datums/elements/selfknockback.dm b/code/datums/elements/selfknockback.dm index 61b2d17c3db..d330b30debc 100644 --- a/code/datums/elements/selfknockback.dm +++ b/code/datums/elements/selfknockback.dm @@ -36,19 +36,16 @@ clamping the Knockback_Force value below. */ else return default_speed -/datum/element/selfknockback/proc/Item_SelfKnockback(obj/item/I, atom/attacktarget, mob/usertarget, proximity_flag) +/datum/element/selfknockback/proc/Item_SelfKnockback(obj/item/I, atom/attacktarget, mob/usertarget) SIGNAL_HANDLER - if(isturf(attacktarget) && !attacktarget.density) - return - if(proximity_flag || (get_dist(attacktarget, usertarget) <= I.reach)) - var/knockback_force = Get_Knockback_Force(clamp(CEILING((I.force / 10), 1), 1, 5)) - var/knockback_speed = Get_Knockback_Speed(clamp(knockback_force, 1, 5)) + var/knockback_force = Get_Knockback_Force(clamp(CEILING((I.force / 10), 1), 1, 5)) + var/knockback_speed = Get_Knockback_Speed(clamp(knockback_force, 1, 5)) - var/target_angle = get_angle(attacktarget, usertarget) - var/move_target = get_ranged_target_turf(usertarget, angle2dir(target_angle), knockback_force) - usertarget.throw_at(move_target, knockback_force, knockback_speed) - usertarget.visible_message(span_warning("[usertarget] gets thrown back by the force of \the [I] impacting \the [attacktarget]!"), span_warning("The force of \the [I] impacting \the [attacktarget] sends you flying!")) + var/target_angle = get_angle(attacktarget, usertarget) + var/move_target = get_ranged_target_turf(usertarget, angle2dir(target_angle), knockback_force) + usertarget.throw_at(move_target, knockback_force, knockback_speed) + usertarget.visible_message(span_warning("[usertarget] gets thrown back by the force of \the [I] impacting \the [attacktarget]!"), span_warning("The force of \the [I] impacting \the [attacktarget] sends you flying!")) /datum/element/selfknockback/proc/Projectile_SelfKnockback(obj/projectile/P) SIGNAL_HANDLER diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 9efc867a043..c9e94e0dd97 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -1,13 +1,38 @@ //entirely neutral or internal status effects go here -/datum/status_effect/crusher_damage //tracks the damage dealt to this mob by kinetic crushers +/datum/status_effect/crusher_damage id = "crusher_damage" duration = -1 tick_interval = -1 status_type = STATUS_EFFECT_UNIQUE alert_type = null + /// How much damage? var/total_damage = 0 +/datum/status_effect/crusher_damage/on_apply() + RegisterSignal(owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(damage_taken)) + return TRUE + +/datum/status_effect/crusher_damage/on_remove() + UnregisterSignal(owner, COMSIG_MOB_AFTER_APPLY_DAMAGE) + +/datum/status_effect/crusher_damage/proc/damage_taken( + datum/source, + damage_dealt, + damagetype, + def_zone, + blocked, + wound_bonus, + bare_wound_bonus, + sharpness, + attack_direction, + attacking_item, +) + SIGNAL_HANDLER + + if(istype(attacking_item, /obj/item/kinetic_crusher)) + total_damage += damage_dealt + /datum/status_effect/syphon_mark id = "syphon_mark" duration = 50 diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index 66ea26fe87f..9bcc0f03b7a 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -199,14 +199,14 @@ parent = new_parent // a few of theses should probably be on the real_location rather than the parent - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_interact)) RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_HAND), PROC_REF(on_attack)) RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, PROC_REF(on_mousedrop_onto)) RegisterSignal(parent, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(on_mousedropped_onto)) RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(on_preattack)) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, PROC_REF(mass_empty)) RegisterSignals(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_ATOM_ATTACK_HAND_SECONDARY), PROC_REF(open_storage_on_signal)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY_SECONDARY, PROC_REF(open_storage_attackby_secondary)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY, PROC_REF(on_item_interact_secondary)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(close_distance)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(update_actions)) RegisterSignal(parent, COMSIG_TOPIC, PROC_REF(topic_handle)) @@ -806,17 +806,23 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) attempt_insert(dropping, user) /// Signal handler for whenever we're attacked by an object. -/datum/storage/proc/on_attackby(datum/source, obj/item/thing, mob/user, params) +/datum/storage/proc/on_item_interact(datum/source, mob/user, obj/item/thing, params) SIGNAL_HANDLER - if(!insert_on_attack || !thing.attackby_storage_insert(src, parent, user)) - return + if(!insert_on_attack) + return NONE + if(!thing.storage_insert_on_interaction(src, parent, user)) + return NONE + if(!parent.storage_insert_on_interacted_with(src, thing, user)) + return NONE + if(SEND_SIGNAL(parent, COMSIG_ATOM_STORAGE_ITEM_INTERACT_INSERT, thing, user) & BLOCK_STORAGE_INSERT) + return NONE if(iscyborg(user)) - return COMPONENT_NO_AFTERATTACK + return ITEM_INTERACT_BLOCKING attempt_insert(thing, user) - return COMPONENT_NO_AFTERATTACK + return ITEM_INTERACT_SUCCESS /// Signal handler for whenever we're attacked by a mob. /datum/storage/proc/on_attack(datum/source, mob/user) @@ -926,14 +932,16 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /// Signal handler for when we get attacked with secondary click by an item. -/datum/storage/proc/open_storage_attackby_secondary(datum/source, atom/weapon, mob/user) +/datum/storage/proc/on_item_interact_secondary(datum/source, mob/user, atom/weapon) SIGNAL_HANDLER if(istype(weapon, /obj/item/chameleon)) var/obj/item/chameleon/chameleon_weapon = weapon chameleon_weapon.make_copy(source, user) - return open_storage_on_signal(source, user) + if(open_storage_on_signal(source, user)) + return ITEM_INTERACT_BLOCKING + return NONE /// Signal handler to open up the storage when we receive a signal. /datum/storage/proc/open_storage_on_signal(datum/source, mob/to_show) diff --git a/code/datums/storage/subtypes/extract_inventory.dm b/code/datums/storage/subtypes/extract_inventory.dm index 0fea7ffed63..9d75b6eb1d3 100644 --- a/code/datums/storage/subtypes/extract_inventory.dm +++ b/code/datums/storage/subtypes/extract_inventory.dm @@ -7,6 +7,8 @@ locked = STORAGE_FULLY_LOCKED rustle_sound = FALSE silent = TRUE + // Snowflake so you can feed it + insert_on_attack = FALSE /datum/storage/extract_inventory/New( atom/parent, diff --git a/code/game/atom/atom_tool_acts.dm b/code/game/atom/atom_tool_acts.dm index 8cc80f5e47c..4987cbcb23b 100644 --- a/code/game/atom/atom_tool_acts.dm +++ b/code/game/atom/atom_tool_acts.dm @@ -13,11 +13,23 @@ var/is_left_clicking = !is_right_clicking var/early_sig_return = NONE if(is_left_clicking) + /* + * This is intentionally using `||` instead of `|` to short-circuit the signal calls + * This is because we want to return early if ANY of these signals return a value + * + * This puts priority on the atom's signals, then the tool's signals, then the user's signals + * So stuff like storage can be handled before stuff the item wants to do like cleaner component + * + * Future idea: Being on combat mode could change/reverse the priority of these signals + */ early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_ITEM_INTERACTION, user, tool, modifiers) \ - | SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM, user, src, modifiers) + || SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM, user, src, modifiers) \ + || SEND_SIGNAL(user, COMSIG_USER_ITEM_INTERACTION, src, tool, modifiers) else + // See above early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_ITEM_INTERACTION_SECONDARY, user, tool, modifiers) \ - | SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM_SECONDARY, user, src, modifiers) + || SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM_SECONDARY, user, src, modifiers) \ + || SEND_SIGNAL(user, COMSIG_USER_ITEM_INTERACTION_SECONDARY, src, tool, modifiers) if(early_sig_return) return early_sig_return @@ -86,6 +98,7 @@ else log_tool("[key_name(user)] used [tool] on [src] (right click) at [AREACOORD(src)]") SEND_SIGNAL(tool, COMSIG_TOOL_ATOM_ACTED_SECONDARY(tool_type), src) + SEND_SIGNAL(tool, COMSIG_ITEM_TOOL_ACTED, src, user, tool_type, act_result) return act_result /** @@ -131,6 +144,92 @@ /obj/item/proc/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) return interact_with_atom(interacting_with, user, modifiers) +/** + * ## Ranged item interaction + * + * Handles non-combat ranged interactions of a tool on this atom, + * such as shooting a gun in the direction of someone*, + * having a scanner you can point at someone to scan them at any distance, + * or pointing a laser pointer at something. + * + * *While this intuitively sounds combat related, it is not, + * because a "combat use" of a gun is gun-butting. + */ +/atom/proc/base_ranged_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + SHOULD_CALL_PARENT(TRUE) + PROTECTED_PROC(TRUE) + + var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK) + var/is_left_clicking = !is_right_clicking + var/early_sig_return = NONE + if(is_left_clicking) + // See [base_item_interaction] for defails on why this is using `||` (TL;DR it's short circuiting) + early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_RANGED_ITEM_INTERACTION, user, tool, modifiers) \ + || SEND_SIGNAL(tool, COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM, user, src, modifiers) + else + // See above + early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_RANGED_ITEM_INTERACTION_SECONDARY, user, tool, modifiers) \ + || SEND_SIGNAL(tool, COMSIG_RANGED_ITEM_INTERACTING_WITH_ATOM_SECONDARY, user, src, modifiers) + if(early_sig_return) + return early_sig_return + + var/self_interaction = is_left_clicking \ + ? ranged_item_interaction(user, tool, modifiers) \ + : ranged_item_interaction_secondary(user, tool, modifiers) + if(self_interaction) + return self_interaction + + var/interact_return = is_left_clicking \ + ? tool.ranged_interact_with_atom(src, user, modifiers) \ + : tool.ranged_interact_with_atom_secondary(src, user, modifiers) + if(interact_return) + return interact_return + + return NONE + +/** + * Called when this atom has an item used on it from a distance. + * IE, a mob is clicking on this atom with an item and is not adjacent. + * + * Does NOT include Telekinesis users, they are considered adjacent generally. + * + * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code. + */ +/atom/proc/ranged_item_interaction(mob/living/user, obj/item/tool, list/modifiers) + return NONE + +/** + * Called when this atom has an item used on it from a distance WITH RIGHT CLICK, + * IE, a mob is right clicking on this atom with an item and is not adjacent. + * + * Default behavior has it run the same code as left click. + * + * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code. + */ +/atom/proc/ranged_item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + return ranged_item_interaction(user, tool, modifiers) + +/** + * Called when this item is being used to interact with an atom from a distance, + * IE, a mob is clicking on an atom with this item and is not adjacent. + * + * Does NOT include Telekinesis users, they are considered adjacent generally + * (so long as this item is adjacent to the atom). + * + * Return an ITEM_INTERACT_ flag in the event the interaction was handled, to cancel further interaction code. + */ +/obj/item/proc/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return NONE + +/** + * Called when this item is being used to interact with an atom from a distance WITH RIGHT CLICK, + * IE, a mob is right clicking on an atom with this item and is not adjacent. + * + * Default behavior has it run the same code as left click. + */ +/obj/item/proc/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + /* * Tool-specific behavior procs. * diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 76105eb10fa..f8dc9887758 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -351,15 +351,15 @@ user.transferItemToLoc(src, pad, TRUE) atom_storage.close_all() -/obj/item/storage/briefcase/launchpad/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/launchpad_remote)) - var/obj/item/launchpad_remote/L = I - if(L.pad == WEAKREF(src.pad)) //do not attempt to link when already linked - return ..() - L.pad = WEAKREF(src.pad) - to_chat(user, span_notice("You link [pad] to [L].")) - else - return ..() +/obj/item/storage/briefcase/launchpad/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(istype(inserted, /obj/item/launchpad_remote)) + var/obj/item/launchpad_remote/remote = inserted + if(remote.pad == WEAKREF(src.pad)) + return TRUE + remote.pad = WEAKREF(src.pad) + to_chat(user, span_notice("You link [pad] to [remote].")) + return FALSE // no insert + return TRUE /obj/item/launchpad_remote name = "folder" diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index e4a620cab8c..f514ef00b73 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -413,7 +413,7 @@ //Dropper tools if(beaker) if(is_type_in_list(item, list(/obj/item/reagent_containers/dropper, /obj/item/ph_meter, /obj/item/ph_paper, /obj/item/reagent_containers/syringe))) - item.afterattack(beaker, user, 1) + item.interact_with_atom(beaker, user) return /obj/machinery/space_heater/improvised_chem_heater/on_deconstruction(disassembled = TRUE) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 4bc3ad79b06..c67443e9d04 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1457,7 +1457,7 @@ mob_loc.update_clothing(slot_flags) /// Called on [/datum/element/openspace_item_click_handler/proc/on_afterattack]. Check the relative file for information. -/obj/item/proc/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) +/obj/item/proc/handle_openspace_click(turf/target, mob/user, click_parameters) stack_trace("Undefined handle_openspace_click() behaviour. Ascertain the openspace_item_click_handler element has been attached to the right item and that its proc override doesn't call parent.") /** @@ -1559,8 +1559,13 @@ SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED_AS_OUTFIT, outfit_wearer, visuals_only, item_slot) -/// Whether or not this item can be put into a storage item through attackby -/obj/item/proc/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/** + * Called before this item is placed into a storage container + * via the item clicking on the target atom + * + * Returning FALSE will prevent the item from being stored + */ +/obj/item/proc/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) return TRUE /obj/item/proc/do_pickup_animation(atom/target, turf/source) diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index 9c4f9620847..30496671ee0 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -219,14 +219,11 @@ . = ..() stored_custom_color = stored_color -/obj/item/airlock_painter/decal/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - balloon_alert(user, "get closer!") - return - - if(isfloorturf(target) && use_paint(user)) - paint_floor(target) +/obj/item/airlock_painter/decal/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isfloorturf(interacting_with) && use_paint(user)) + paint_floor(interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /** * Actually add current decal to the floor. diff --git a/code/game/objects/items/bear_armor.dm b/code/game/objects/items/bear_armor.dm index 556875a474e..8cfad42be15 100644 --- a/code/game/objects/items/bear_armor.dm +++ b/code/game/objects/items/bear_armor.dm @@ -5,23 +5,21 @@ icon = 'icons/obj/tools.dmi' icon_state = "bear_armor_upgrade" -/obj/item/bear_armor/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - if(!istype(target, /mob/living/basic/bear)) - return - var/mob/living/basic/bear/bear_target = target - if(bear_target.armored) - to_chat(user, span_warning("[bear_target] has already been armored up!")) - return - bear_target.armored = TRUE - bear_target.maxHealth += 60 - bear_target.health += 60 - bear_target.armour_penetration += 20 - bear_target.melee_damage_lower += 3 - bear_target.melee_damage_upper += 5 - bear_target.wound_bonus += 5 - bear_target.update_icons() - to_chat(user, span_info("You strap the armor plating to [bear_target] and sharpen [bear_target.p_their()] claws with the nail filer. This was a great idea.")) +/obj/item/bear_armor/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /mob/living/basic/bear)) + return NONE + var/mob/living/basic/bear/bear = interacting_with + if(bear.armored) + to_chat(user, span_warning("[bear] has already been armored up!")) + return ITEM_INTERACT_BLOCKING + bear.armored = TRUE + bear.maxHealth += 60 + bear.health += 60 + bear.armour_penetration += 20 + bear.melee_damage_lower += 3 + bear.melee_damage_upper += 5 + bear.wound_bonus += 5 + bear.update_icons() + to_chat(user, span_info("You strap the armor plating to [bear] and sharpen [bear.p_their()] claws with the nail filer. This was a great idea.")) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 19d3d273337..c949f977508 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -19,6 +19,7 @@ deploy_bodybag(user, interacting_with) return ITEM_INTERACT_SUCCESS return NONE + /obj/item/bodybag/attempt_pickup(mob/user) // can't pick ourselves up if we are inside of the bodybag, else very weird things may happen if(contains(user)) diff --git a/code/game/objects/items/broom.dm b/code/game/objects/items/broom.dm index 4f7cb137d30..fa849c51437 100644 --- a/code/game/objects/items/broom.dm +++ b/code/game/objects/items/broom.dm @@ -54,12 +54,9 @@ /obj/item/pushbroom/proc/on_unwield(obj/item/source, mob/user) UnregisterSignal(user, COMSIG_MOVABLE_PRE_MOVE) -/obj/item/pushbroom/afterattack(atom/A, mob/user, proximity) - . = ..() - if(!proximity) - return - sweep(user, A) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/pushbroom/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + sweep(user, interacting_with) + return NONE // I guess /** * Attempts to push up to BROOM_PUSH_LIMIT atoms from a given location the user's faced direction diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index e5332d7aa22..fd051031e6b 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -425,13 +425,11 @@ user.visible_message(span_notice("[user] shows you: [icon2html(src, viewers(user))] [src.name][minor]."), span_notice("You show \the [src.name][minor].")) add_fingerprint(user) -/obj/item/card/id/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return - if(!proximity_flag || !check_allowed_items(target) || !isfloorturf(target)) - return - try_project_paystand(user, target) +/obj/item/card/id/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!check_allowed_items(interacting_with) || !isfloorturf(interacting_with)) + return NONE + try_project_paystand(user, interacting_with) + return ITEM_INTERACT_SUCCESS /obj/item/card/id/attack_self_secondary(mob/user, modifiers) . = ..() @@ -1401,68 +1399,59 @@ theft_target = null return ..() -/obj/item/card/id/advanced/chameleon/afterattack(atom/target, mob/user, proximity, click_parameters) - . = ..() - if(!proximity) - return - - if(isidcard(target)) - theft_target = WEAKREF(target) +/obj/item/card/id/advanced/chameleon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isidcard(interacting_with)) + theft_target = WEAKREF(interacting_with) ui_interact(user) - return . | AFTERATTACK_PROCESSED_ITEM - -/obj/item/card/id/advanced/chameleon/pre_attack_secondary(atom/target, mob/living/user, params) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return . + return ITEM_INTERACT_SUCCESS + return NONE +/obj/item/card/id/advanced/chameleon/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) // If we're attacking a human, we want it to be covert. We're not ATTACKING them, we're trying // to sneakily steal their accesses by swiping our agent ID card near them. As a result, we - // return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN to cancel any part of the following the attack chain. - if(ishuman(target)) - target.balloon_alert(user, "scanning ID card...") + // return ITEM_INTERACT_BLOCKING to cancel any part of the following the attack chain. + if(ishuman(interacting_with)) + interacting_with.balloon_alert(user, "scanning ID card...") - if(!do_after(user, 2 SECONDS, target)) - target.balloon_alert(user, "interrupted!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - - var/mob/living/carbon/human/human_target = target + if(!do_after(user, 2 SECONDS, interacting_with)) + interacting_with.balloon_alert(user, "interrupted!") + return ITEM_INTERACT_BLOCKING + var/mob/living/carbon/human/human_target = interacting_with var/list/target_id_cards = human_target.get_all_contents_type(/obj/item/card/id) if(!length(target_id_cards)) - target.balloon_alert(user, "no IDs!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + interacting_with.balloon_alert(user, "no IDs!") + return ITEM_INTERACT_BLOCKING var/selected_id = pick(target_id_cards) - target.balloon_alert(user, UNLINT("IDs synced")) + interacting_with.balloon_alert(user, UNLINT("IDs synced")) theft_target = WEAKREF(selected_id) ui_interact(user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS - if(isitem(target)) - var/obj/item/target_item = target + if(isitem(interacting_with)) + var/obj/item/target_item = interacting_with - target.balloon_alert(user, "scanning ID card...") + interacting_with.balloon_alert(user, "scanning ID card...") var/list/target_id_cards = target_item.get_all_contents_type(/obj/item/card/id) - var/target_item_id = target_item.GetID() if(target_item_id) target_id_cards |= target_item_id if(!length(target_id_cards)) - target.balloon_alert(user, "no IDs!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + interacting_with.balloon_alert(user, "no IDs!") + return ITEM_INTERACT_BLOCKING var/selected_id = pick(target_id_cards) - target.balloon_alert(user, UNLINT("IDs synced")) + interacting_with.balloon_alert(user, UNLINT("IDs synced")) theft_target = WEAKREF(selected_id) ui_interact(user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS - return . + return NONE /obj/item/card/id/advanced/chameleon/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index f7a7c0a817f..f41a9a84530 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -282,12 +282,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/mob/living/carbon/the_smoker = user return the_smoker.can_breathe_helmet() -/obj/item/clothing/mask/cigarette/afterattack(obj/item/reagent_containers/cup/glass, mob/user, proximity) - . = ..() - if(!proximity || lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead) - return +/obj/item/clothing/mask/cigarette/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(lit) //can't dip if cigarette is lit (it will heat the reagents in the glass instead) + return NONE + var/obj/item/reagent_containers/cup/glass = interacting_with if(!istype(glass)) //you can dip cigarettes into beakers - return + return NONE if(glass.reagents.trans_to(src, chem_volume, transferred_by = user)) //if reagents were transferred, show the message to_chat(user, span_notice("You dip \the [src] into \the [glass].")) @@ -296,8 +296,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM to_chat(user, span_warning("[glass] is empty!")) else to_chat(user, span_warning("[src] is full!")) - - return AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_SUCCESS /obj/item/clothing/mask/cigarette/update_icon_state() . = ..() diff --git a/code/game/objects/items/climbingrope.dm b/code/game/objects/items/climbingrope.dm index 03178604074..693f850be2a 100644 --- a/code/game/objects/items/climbingrope.dm +++ b/code/game/objects/items/climbingrope.dm @@ -26,20 +26,23 @@ . += span_notice("Then, click solid ground adjacent to the hole above you.") . += span_notice("The rope looks like you could use it [uses] times before it falls apart.") -/obj/item/climbing_hook/afterattack(turf/open/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(target.z == user.z) - return +/obj/item/climbing_hook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/climbing_hook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(interacting_with.z == user.z) + return NONE + var/turf/open/target = interacting_with if(!istype(target) || isopenspaceturf(target)) - return - + return ITEM_INTERACT_BLOCKING + var/turf/user_turf = get_turf(user) var/turf/above = GET_TURF_ABOVE(user_turf) if(target_blocked(target, above)) - return + return ITEM_INTERACT_BLOCKING if(!isopenspaceturf(above) || !above.Adjacent(target)) //are we below a hole, is the target blocked, is the target adjacent to our hole balloon_alert(user, "blocked!") - return + return ITEM_INTERACT_BLOCKING var/away_dir = get_dir(above, target) user.visible_message(span_notice("[user] begins climbing upwards with [src]."), span_notice("You get to work on properly hooking [src] and going upwards.")) @@ -56,6 +59,7 @@ qdel(src) QDEL_LIST(effects) + return ITEM_INTERACT_SUCCESS // didnt want to mess up is_blocked_turf_ignore_climbable /// checks if our target is blocked, also checks for border objects facing the above turf and climbable stuff diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 52ba71a2538..3b10f044fc3 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -118,7 +118,9 @@ return TOXLOSS /obj/item/soap/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner) - return check_allowed_items(atom_to_clean) + . = CLEAN_ALLOWED + if(!check_allowed_items(atom_to_clean)) + . |= CLEAN_NO_XP /** * Decrease the number of uses the bar of soap has. @@ -145,17 +147,15 @@ qdel(src) /obj/item/soap/nanotrasen/cyborg/noUses(mob/user) - to_chat(user, span_warning("The soap has ran out of chemicals")) + to_chat(user, span_warning("[src] has ran out of chemicals! Head to a recharger to refill it.")) -/obj/item/soap/nanotrasen/cyborg/afterattack(atom/target, mob/user, proximity) - . = isitem(target) ? AFTERATTACK_PROCESSED_ITEM : NONE +/obj/item/soap/nanotrasen/cyborg/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner) if(uses <= 0) - to_chat(user, span_warning("No good, you need to recharge!")) - return . - return ..() | . + return CLEAN_BLOCKED + return ..() -/obj/item/soap/attackby_storage_insert(datum/storage, atom/storage_holder, mob/living/user) - return !user?.combat_mode // only cleans a storage item if on combat +/obj/item/soap/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user) + return !user.combat_mode // only cleans a storage item if on combat /* * Bike Horns diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm index de81caa22e9..abad07f96d8 100644 --- a/code/game/objects/items/control_wand.dm +++ b/code/game/objects/items/control_wand.dm @@ -35,35 +35,35 @@ update_icon_state() balloon_alert(user, "mode: [desc[mode]]") -// Airlock remote works by sending NTNet packets to whatever it's pointed at. -/obj/item/door_remote/afterattack(atom/target, mob/user) - . = ..() +/obj/item/door_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) +/obj/item/door_remote/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/obj/machinery/door/door - if (istype(target, /obj/machinery/door)) - door = target - + if (istype(interacting_with, /obj/machinery/door)) + door = interacting_with if (!door.opens_with_door_remote) - return + return ITEM_INTERACT_BLOCKING + else - for (var/obj/machinery/door/door_on_turf in get_turf(target)) + for (var/obj/machinery/door/door_on_turf in get_turf(interacting_with)) if (door_on_turf.opens_with_door_remote) door = door_on_turf break if (isnull(door)) - return + return ITEM_INTERACT_BLOCKING if (!door.check_access_list(access_list) || !door.requiresID()) - target.balloon_alert(user, "can't access!") - return + interacting_with.balloon_alert(user, "can't access!") + return ITEM_INTERACT_BLOCKING var/obj/machinery/door/airlock/airlock = door if (!door.hasPower() || (istype(airlock) && !airlock.canAIControl())) - target.balloon_alert(user, mode == WAND_OPEN ? "it won't budge!" : "nothing happens!") - return + interacting_with.balloon_alert(user, mode == WAND_OPEN ? "it won't budge!" : "nothing happens!") + return ITEM_INTERACT_BLOCKING switch (mode) if (WAND_OPEN) @@ -73,8 +73,8 @@ door.close() if (WAND_BOLT) if (!istype(airlock)) - target.balloon_alert(user, "only airlocks!") - return + interacting_with.balloon_alert(user, "only airlocks!") + return ITEM_INTERACT_BLOCKING if (airlock.locked) airlock.unbolt() @@ -84,12 +84,14 @@ log_combat(user, airlock, "bolted", src) if (WAND_EMERGENCY) if (!istype(airlock)) - target.balloon_alert(user, "only airlocks!") - return + interacting_with.balloon_alert(user, "only airlocks!") + return ITEM_INTERACT_BLOCKING airlock.emergency = !airlock.emergency airlock.update_appearance(UPDATE_ICON) + return ITEM_INTERACT_SUCCESS + /obj/item/door_remote/update_icon_state() var/icon_state_mode switch(mode) diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 1bb67d92587..3ca57f38051 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -421,7 +421,7 @@ return LOWER_TEXT(crayon_regex.Replace(text, "")) /// Attempts to color the target. Returns how many charges were used. -/obj/item/toy/crayon/proc/use_on(atom/target, mob/user, params) +/obj/item/toy/crayon/proc/use_on(atom/target, mob/user, list/modifiers) var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&") if(istype(target, /obj/effect/decal/cleanable)) @@ -491,7 +491,6 @@ else graf_rot = 0 - var/list/modifiers = params2list(params) var/clickx var/clicky @@ -568,19 +567,12 @@ reagents.expose(draw_turf, methods = TOUCH, volume_modifier = volume_multiplier) check_empty(user) -/obj/item/toy/crayon/afterattack(atom/target, mob/user, proximity, params) - . = ..() - - if(!proximity) - return - - if (isitem(target)) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/toy/crayon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (!check_allowed_items(interacting_with)) + return NONE - if (!check_allowed_items(target)) - return - - use_on(target, user, params) + use_on(interacting_with, user, modifiers) + return ITEM_INTERACT_BLOCKING /obj/item/toy/crayon/get_writing_implement_details() return list( @@ -674,7 +666,7 @@ charges = INFINITE_CHARGES dye_color = DYE_RAINBOW -/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params) +/obj/item/toy/crayon/rainbow/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) set_painting_tool_color(rgb(rand(0,255), rand(0,255), rand(0,255))) return ..() @@ -833,7 +825,7 @@ . += "It is empty." . += span_notice("Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"]. Right-click a colored object to match its existing color.") -/obj/item/toy/crayon/spraycan/use_on(atom/target, mob/user, params) +/obj/item/toy/crayon/spraycan/use_on(atom/target, mob/user, list/modifiers) if(is_capped) balloon_alert(user, "take the cap off first!") return @@ -927,17 +919,15 @@ return ..() -/obj/item/toy/crayon/spraycan/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/toy/crayon/spraycan/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(is_capped) balloon_alert(user, "take the cap off first!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(check_empty(user)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING - if(isbodypart(target) && actually_paints) - var/obj/item/bodypart/limb = target + if(isbodypart(interacting_with) && actually_paints) + var/obj/item/bodypart/limb = interacting_with if(!IS_ORGANIC_LIMB(limb)) var/list/skins = list() var/static/list/style_list_icons = GLOB.robotic_styles_list //NOVA EDIT CHANGE - Original: var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi') @@ -950,16 +940,14 @@ if(choice && (use_charges(user, 5, requires_full = FALSE))) playsound(user.loc, 'sound/effects/spray.ogg', 5, TRUE, 5) limb.change_appearance(style_list_icons[choice], greyscale = FALSE) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(target.color) - paint_color = target.color + return ITEM_INTERACT_SUCCESS + if(interacting_with.color) + paint_color = interacting_with.color balloon_alert(user, "matched colour of target") update_appearance() - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - else - balloon_alert(user, "can't match those colours!") - - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING + balloon_alert(user, "can't match those colours!") + return ITEM_INTERACT_BLOCKING /obj/item/toy/crayon/spraycan/click_alt(mob/user) if(!has_cap) @@ -969,7 +957,7 @@ update_appearance() return CLICK_ACTION_SUCCESS -/obj/item/toy/crayon/spraycan/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/obj/item/toy/crayon/spraycan/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) return is_capped /obj/item/toy/crayon/spraycan/update_icon_state() diff --git a/code/game/objects/items/debug_items.dm b/code/game/objects/items/debug_items.dm index 44f53df2c2b..0a944b300d4 100644 --- a/code/game/objects/items/debug_items.dm +++ b/code/game/objects/items/debug_items.dm @@ -12,12 +12,16 @@ var/datum/species/selected_species var/valid_species = list() -/obj/item/debug/human_spawner/afterattack(atom/target, mob/user, proximity) - ..() - if(isturf(target)) - var/mob/living/carbon/human/H = new /mob/living/carbon/human(target) +/obj/item/debug/human_spawner/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/debug/human_spawner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isturf(interacting_with)) + var/mob/living/carbon/human/H = new /mob/living/carbon/human(interacting_with) if(selected_species) H.set_species(selected_species) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/debug/human_spawner/attack_self(mob/user) ..() diff --git a/code/game/objects/items/devices/anomaly_releaser.dm b/code/game/objects/items/devices/anomaly_releaser.dm index 0556b2a2afd..a7a58bb5d94 100644 --- a/code/game/objects/items/devices/anomaly_releaser.dm +++ b/code/game/objects/items/devices/anomaly_releaser.dm @@ -19,32 +19,28 @@ ///Can we be used infinitely? var/infinite = FALSE -/obj/item/anomaly_releaser/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - - if(used || !proximity_flag || !istype(target, /obj/item/assembly/signaler/anomaly)) - return +/obj/item/anomaly_releaser/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!istype(target, /obj/item/assembly/signaler/anomaly)) + return NONE + if(used) + return ITEM_INTERACT_BLOCKING if(!do_after(user, 3 SECONDS, target)) - return - + return ITEM_INTERACT_BLOCKING if(used) - return + return ITEM_INTERACT_BLOCKING var/obj/item/assembly/signaler/anomaly/core = target - if(!core.anomaly_type) - return + return ITEM_INTERACT_BLOCKING var/obj/effect/anomaly/anomaly = new core.anomaly_type(get_turf(core)) anomaly.stabilize() log_combat(user, anomaly, "released", object = src, addition = "in [get_area(target)].") - if(infinite) - return - - icon_state = used_icon_state - used = TRUE - name = "used " + name - - qdel(core) + if(!infinite) + icon_state = used_icon_state + used = TRUE + name = "used " + name + qdel(core) + return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index e5507473fae..1920e47f97f 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -36,29 +36,25 @@ else to_chat(user, span_warning("You can't use [src] while inside something!")) -/obj/item/chameleon/afterattack(atom/target, mob/user , proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/chameleon/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(!check_sprite(target)) - return + return ITEM_INTERACT_BLOCKING if(active_dummy)//I now present you the blackli(f)st - return + return ITEM_INTERACT_BLOCKING if(isturf(target)) - return + return ITEM_INTERACT_BLOCKING if(ismob(target)) - return + return ITEM_INTERACT_BLOCKING if(istype(target, /obj/structure/falsewall)) - return + return ITEM_INTERACT_BLOCKING if(target.alpha != 255) - return + return ITEM_INTERACT_BLOCKING if(target.invisibility != 0) - return - if(iseffect(target)) - if(!(istype(target, /obj/effect/decal))) //be a footprint - return + return ITEM_INTERACT_BLOCKING + if(iseffect(target) && !istype(target, /obj/effect/decal)) //be a footprint + return ITEM_INTERACT_BLOCKING make_copy(target, user) + return ITEM_INTERACT_SUCCESS /obj/item/chameleon/proc/make_copy(atom/target, mob/user) playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, TRUE, -6) diff --git a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm index d5d2e6c4d14..5814101463b 100644 --- a/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm +++ b/code/game/objects/items/devices/electroadaptive_pseudocircuit.dm @@ -55,19 +55,18 @@ addtimer(CALLBACK(src, PROC_REF(recharge)), ROUND_UP(recharge_time)) return TRUE //The actual circuit magic itself is done on a per-object basis -/obj/item/electroadaptive_pseudocircuit/afterattack(atom/target, mob/living/user, proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(!is_type_in_typecache(target, recycleable_circuits)) - return +/obj/item/electroadaptive_pseudocircuit/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!is_type_in_typecache(interacting_with, recycleable_circuits)) + return NONE circuits++ maptext = MAPTEXT(circuits) - user.visible_message(span_notice("User breaks down [target] with [src]."), \ - span_notice("You recycle [target] into [src]. It now has material for [circuits] circuits.")) + user.visible_message( + span_notice("User breaks down [interacting_with] with [src]."), + span_notice("You recycle [interacting_with] into [src]. It now has material for [circuits] circuits.") + ) playsound(user, 'sound/items/deconstruct.ogg', 50, TRUE) - qdel(target) + qdel(interacting_with) + return ITEM_INTERACT_SUCCESS /obj/item/electroadaptive_pseudocircuit/proc/recharge() playsound(src, 'sound/machines/chime.ogg', 25, TRUE) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 3fb46f24840..e1e9d077271 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -109,162 +109,170 @@ user.visible_message(span_suicide("[user] is putting [src] close to [user.p_their()] eyes and turning it on! It looks like [user.p_theyre()] trying to commit suicide!")) return FIRELOSS -/obj/item/flashlight/attack(mob/living/carbon/M, mob/living/carbon/human/user) - add_fingerprint(user) - if(istype(M) && light_on && (user.zone_selected in list(BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH))) +/obj/item/flashlight/proc/eye_examine(mob/living/carbon/human/M, mob/living/user) + . = list() + if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) + to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first!")) + return - if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly - return ..() //just hit them in the head + var/obj/item/organ/internal/eyes/E = M.get_organ_slot(ORGAN_SLOT_EYES) + var/obj/item/organ/internal/brain = M.get_organ_slot(ORGAN_SLOT_BRAIN) + if(!E) + to_chat(user, span_warning("[M] doesn't have any eyes!")) + return - if(!ISADVANCEDTOOLUSER(user)) - to_chat(user, span_warning("You don't have the dexterity to do this!")) - return + M.flash_act(visual = TRUE, length = (user.combat_mode) ? 2.5 SECONDS : 1 SECONDS) // Apply a 1 second flash effect to the target. The duration increases to 2.5 Seconds if you have combat mode on. - if(!M.get_bodypart(BODY_ZONE_HEAD)) - to_chat(user, span_warning("[M] doesn't have a head!")) - return + if(M == user) //they're using it on themselves + user.visible_message(span_warning("[user] shines [src] into [M.p_their()] eyes."), ignored_mobs = user) + . += span_info("You direct [src] to into your eyes:\n") - if(light_power < 1) - to_chat(user, "[span_warning("\The [src] isn't bright enough to see anything!")] ") - return - - var/render_list = list()//information will be packaged in a list for clean display to the user + if(M.is_blind()) + . += "You're not entirely certain what you were expecting...\n" + else + . += "Trippy!\n" - switch(user.zone_selected) - if(BODY_ZONE_PRECISE_EYES) - if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) - to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first!")) - return + else + user.visible_message(span_warning("[user] directs [src] to [M]'s eyes."), ignored_mobs = user) + . += span_info("You direct [src] to [M]'s eyes:\n") - var/obj/item/organ/internal/eyes/E = M.get_organ_slot(ORGAN_SLOT_EYES) - var/obj/item/organ/internal/brain = M.get_organ_slot(ORGAN_SLOT_BRAIN) - if(!E) - to_chat(user, span_warning("[M] doesn't have any eyes!")) - return + if(M.stat == DEAD || M.is_blind() || M.get_eye_protection() > FLASH_PROTECTION_WELDER) + . += "[M.p_Their()] pupils don't react to the light!\n"//mob is dead + else if(brain.damage > 20) + . += "[M.p_Their()] pupils contract unevenly!\n"//mob has sustained damage to their brain + else + . += "[M.p_Their()] pupils narrow.\n"//they're okay :D - M.flash_act(visual = TRUE, length = (user.combat_mode) ? 2.5 SECONDS : 1 SECONDS) // Apply a 1 second flash effect to the target. The duration increases to 2.5 Seconds if you have combat mode on. + if(M.dna && M.dna.check_mutation(/datum/mutation/human/xray)) + . += "[M.p_Their()] pupils give an eerie glow!\n"//mob has X-ray vision - if(M == user) //they're using it on themselves - user.visible_message(span_warning("[user] shines [src] into [M.p_their()] eyes."), ignored_mobs = user) - render_list += span_info("You direct [src] to into your eyes:\n") + return . - if(M.is_blind()) - render_list += "You're not entirely certain what you were expecting...\n" - else - render_list += "Trippy!\n" +/obj/item/flashlight/proc/mouth_examine(mob/living/carbon/human/M, mob/living/user) + . = list() + if(M.is_mouth_covered()) + to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first!")) + return + var/list/mouth_organs = list() + for(var/obj/item/organ/organ as anything in M.organs) + if(organ.zone == BODY_ZONE_PRECISE_MOUTH) + mouth_organs.Add(organ) + var/organ_list = "" + var/organ_count = LAZYLEN(mouth_organs) + if(organ_count) + for(var/I in 1 to organ_count) + if(I > 1) + if(I == mouth_organs.len) + organ_list += ", and " else - user.visible_message(span_warning("[user] directs [src] to [M]'s eyes."), ignored_mobs = user) - render_list += span_info("You direct [src] to [M]'s eyes:\n") - - if(M.stat == DEAD || M.is_blind() || M.get_eye_protection() > FLASH_PROTECTION_WELDER) - render_list += "[M.p_Their()] pupils don't react to the light!\n"//mob is dead - else if(brain.damage > 20) - render_list += "[M.p_Their()] pupils contract unevenly!\n"//mob has sustained damage to their brain - else - render_list += "[M.p_Their()] pupils narrow.\n"//they're okay :D - - if(M.dna && M.dna.check_mutation(/datum/mutation/human/xray)) - render_list += "[M.p_Their()] pupils give an eerie glow!\n"//mob has X-ray vision - - //display our packaged information in an examine block for easy reading - to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) - - if(BODY_ZONE_PRECISE_MOUTH) - - if(M.is_mouth_covered()) - to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first!")) - return - - var/list/mouth_organs = new - for(var/obj/item/organ/organ as anything in M.organs) - if(organ.zone == BODY_ZONE_PRECISE_MOUTH) - mouth_organs.Add(organ) - var/organ_list = "" - var/organ_count = LAZYLEN(mouth_organs) - if(organ_count) - for(var/I in 1 to organ_count) - if(I > 1) - if(I == mouth_organs.len) - organ_list += ", and " - else - organ_list += ", " - var/obj/item/organ/O = mouth_organs[I] - organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") - - var/pill_count = 0 - for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions) - pill_count++ - - if(M == user)//if we're looking on our own mouth - var/can_use_mirror = FALSE - if(isturf(user.loc)) - var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) - if(mirror) - switch(user.dir) - if(NORTH) - can_use_mirror = mirror.pixel_y > 0 - if(SOUTH) - can_use_mirror = mirror.pixel_y < 0 - if(EAST) - can_use_mirror = mirror.pixel_x > 0 - if(WEST) - can_use_mirror = mirror.pixel_x < 0 - - M.visible_message(span_notice("[M] directs [src] to [ M.p_their()] mouth."), ignored_mobs = user) - render_list += span_info("You point [src] into your mouth:\n") - if(!can_use_mirror) - to_chat(user, span_notice("You can't see anything without a mirror.")) - return - if(organ_count) - render_list += "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" - else - render_list += "There's nothing inside your mouth.\n" - if(pill_count) - render_list += "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].\n" - - else //if we're looking in someone elses mouth - user.visible_message(span_notice("[user] directs [src] to [M]'s mouth."), ignored_mobs = user) - render_list += span_info("You point [src] into [M]'s mouth:\n") - if(organ_count) - render_list += "Inside [ M.p_their()] mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" - else - render_list += "[M] doesn't have any organs in [ M.p_their()] mouth.\n" - if(pill_count) - render_list += "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [ M.p_their()] teeth.\n" - - //assess any suffocation damage - var/hypoxia_status = M.getOxyLoss() > 20 - - if(M == user) - if(hypoxia_status) - render_list += "Your lips appear blue!\n"//you have suffocation damage - else - render_list += "Your lips appear healthy.\n"//you're okay! - else - if(hypoxia_status) - render_list += "[M.p_Their()] lips appear blue!\n"//they have suffocation damage - else - render_list += "[M.p_Their()] lips appear healthy.\n"//they're okay! - - //assess blood level - if(M == user) - render_list += span_info("You press a finger to your gums:\n") - else - render_list += span_info("You press a finger to [M.p_their()] gums:\n") + organ_list += ", " + var/obj/item/organ/O = mouth_organs[I] + organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") + + var/pill_count = 0 + for(var/datum/action/item_action/hands_free/activate_pill/AP in M.actions) + pill_count++ + + if(M == user)//if we're looking on our own mouth + var/can_use_mirror = FALSE + if(isturf(user.loc)) + var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) + if(mirror) + switch(user.dir) + if(NORTH) + can_use_mirror = mirror.pixel_y > 0 + if(SOUTH) + can_use_mirror = mirror.pixel_y < 0 + if(EAST) + can_use_mirror = mirror.pixel_x > 0 + if(WEST) + can_use_mirror = mirror.pixel_x < 0 + + M.visible_message(span_notice("[M] directs [src] to [ M.p_their()] mouth."), ignored_mobs = user) + . += span_info("You point [src] into your mouth:\n") + if(!can_use_mirror) + to_chat(user, span_notice("You can't see anything without a mirror.")) + return + if(organ_count) + . += "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" + else + . += "There's nothing inside your mouth.\n" + if(pill_count) + . += "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].\n" + + else //if we're looking in someone elses mouth + user.visible_message(span_notice("[user] directs [src] to [M]'s mouth."), ignored_mobs = user) + . += span_info("You point [src] into [M]'s mouth:\n") + if(organ_count) + . += "Inside [ M.p_their()] mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" + else + . += "[M] doesn't have any organs in [ M.p_their()] mouth.\n" + if(pill_count) + . += "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [ M.p_their()] teeth.\n" - if(M.blood_volume <= BLOOD_VOLUME_SAFE && M.blood_volume > BLOOD_VOLUME_OKAY) - render_list += "Color returns slowly!\n"//low blood - else if(M.blood_volume <= BLOOD_VOLUME_OKAY) - render_list += "Color does not return!\n"//critical blood - else - render_list += "Color returns quickly.\n"//they're okay :D + //assess any suffocation damage + var/hypoxia_status = M.getOxyLoss() > 20 + + if(M == user) + if(hypoxia_status) + . += "Your lips appear blue!\n"//you have suffocation damage + else + . += "Your lips appear healthy.\n"//you're okay! + else + if(hypoxia_status) + . += "[M.p_Their()] lips appear blue!\n"//they have suffocation damage + else + . += "[M.p_Their()] lips appear healthy.\n"//they're okay! - //display our packaged information in an examine block for easy reading - to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) + //assess blood level + if(M == user) + . += span_info("You press a finger to your gums:\n") + else + . += span_info("You press a finger to [M.p_their()] gums:\n") + if(M.blood_volume <= BLOOD_VOLUME_SAFE && M.blood_volume > BLOOD_VOLUME_OKAY) + . += "Color returns slowly!\n"//low blood + else if(M.blood_volume <= BLOOD_VOLUME_OKAY) + . += "Color does not return!\n"//critical blood else - return ..() + . += "Color returns quickly.\n"//they're okay :D + +/obj/item/flashlight/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ishuman(interacting_with)) + return NONE + if(!light_on) + return NONE + add_fingerprint(user) + if(user.combat_mode || (user.zone_selected != BODY_ZONE_PRECISE_EYES && user.zone_selected != BODY_ZONE_PRECISE_MOUTH)) + return NONE + if((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) //too dumb to use flashlight properly + return ITEM_INTERACT_SKIP_TO_ATTACK //just hit them in the head + + . = ITEM_INTERACT_BLOCKING + if(!ISADVANCEDTOOLUSER(user)) + to_chat(user, span_warning("You don't have the dexterity to do this!")) + return + var/mob/living/scanning = interacting_with + if(!scanning.get_bodypart(BODY_ZONE_HEAD)) + to_chat(user, span_warning("[scanning] doesn't have a head!")) + return + if(light_power < 1) + to_chat(user, span_warning("[src] isn't bright enough to see anything!")) + return + + var/list/render_list = list() + switch(user.zone_selected) + if(BODY_ZONE_PRECISE_EYES) + render_list += eye_examine(scanning, user) + if(BODY_ZONE_PRECISE_MOUTH) + render_list += mouth_examine(scanning, user) + + if(length(render_list)) + //display our packaged information in an examine block for easy reading + to_chat(user, examine_block(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /// for directional sprites - so we get the same sprite in the inventory each time we pick one up /obj/item/flashlight/equipped(mob/user, slot, initial) @@ -300,24 +308,21 @@ light_color = "#CCFFFF" COOLDOWN_DECLARE(holosign_cooldown) -/obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(proximity_flag) - return - +/obj/item/flashlight/pen/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, holosign_cooldown)) balloon_alert(user, "not ready!") - return + return ITEM_INTERACT_BLOCKING - var/target_turf = get_turf(target) + var/turf/target_turf = get_turf(interacting_with) var/mob/living/living_target = locate(/mob/living) in target_turf if(!living_target || (living_target == user)) - return + return ITEM_INTERACT_BLOCKING to_chat(living_target, span_boldnotice("[user] is offering medical assistance; please halt your actions.")) new /obj/effect/temp_visual/medical_holosign(target_turf, user) //produce a holographic glow COOLDOWN_START(src, holosign_cooldown, 10 SECONDS) + return ITEM_INTERACT_SUCCESS // see: [/datum/wound/burn/flesh/proc/uv()] /obj/item/flashlight/pen/paramedic @@ -735,26 +740,26 @@ ..() return -/obj/item/flashlight/emp/afterattack(atom/movable/A, mob/user, proximity) +/obj/item/flashlight/emp/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) . = ..() - if(!proximity) + if(. & ITEM_INTERACT_ANY_BLOCKER) return if(emp_cur_charges > 0) emp_cur_charges -= 1 - if(ismob(A)) - var/mob/M = A - log_combat(user, M, "attacked", "EMP-light") - M.visible_message(span_danger("[user] blinks \the [src] at \the [A]."), \ + if(ismob(interacting_with)) + var/mob/empd = interacting_with + log_combat(user, empd, "attacked", "EMP-light") + empd.visible_message(span_danger("[user] blinks \the [src] at \the [empd]."), \ span_userdanger("[user] blinks \the [src] at you.")) else - A.visible_message(span_danger("[user] blinks \the [src] at \the [A].")) + interacting_with.visible_message(span_danger("[user] blinks \the [src] at \the [interacting_with].")) to_chat(user, span_notice("\The [src] now has [emp_cur_charges] charge\s.")) - A.emp_act(EMP_HEAVY) + interacting_with.emp_act(EMP_HEAVY) else to_chat(user, span_warning("\The [src] needs time to recharge!")) - return + return ITEM_INTERACT_SUCCESS /obj/item/flashlight/emp/debug //for testing emp_act() name = "debug EMP flashlight" diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index d102f062756..5d40d40a4d9 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -21,41 +21,42 @@ /// Checks to make sure the projector isn't busy with making another forcefield. var/force_proj_busy = FALSE -/obj/item/forcefield_projector/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!check_allowed_items(target, not_inside = TRUE)) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(istype(target, /obj/structure/projected_forcefield)) - var/obj/structure/projected_forcefield/F = target +/obj/item/forcefield_projector/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/forcefield_projector/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!check_allowed_items(interacting_with, not_inside = TRUE)) + return NONE + if(istype(interacting_with, /obj/structure/projected_forcefield)) + var/obj/structure/projected_forcefield/F = interacting_with if(F.generator == src) to_chat(user, span_notice("You deactivate [F].")) qdel(F) - return - var/turf/T = get_turf(target) + return ITEM_INTERACT_BLOCKING + var/turf/T = get_turf(interacting_with) var/obj/structure/projected_forcefield/found_field = locate() in T if(found_field) to_chat(user, span_warning("There is already a forcefield in that location!")) - return + return ITEM_INTERACT_BLOCKING if(T.density) - return + return ITEM_INTERACT_BLOCKING if(get_dist(T,src) > field_distance_limit) - return - if (get_turf(src) == T) + return ITEM_INTERACT_BLOCKING + if(get_turf(src) == T) to_chat(user, span_warning("Target is too close, aborting!")) - return + return ITEM_INTERACT_BLOCKING if(LAZYLEN(current_fields) >= max_fields) to_chat(user, span_warning("[src] cannot sustain any more forcefields!")) - return + return ITEM_INTERACT_BLOCKING if(force_proj_busy) to_chat(user, span_notice("[src] is busy creating a forcefield.")) - return + return ITEM_INTERACT_BLOCKING playsound(loc, 'sound/machines/click.ogg', 20, TRUE) if(creation_time) force_proj_busy = TRUE - if(!do_after(user, creation_time, target = target)) + if(!do_after(user, creation_time, target = interacting_with)) force_proj_busy = FALSE - return + return ITEM_INTERACT_BLOCKING force_proj_busy = FALSE playsound(src,'sound/weapons/resonator_fire.ogg',50,TRUE) @@ -63,6 +64,7 @@ var/obj/structure/projected_forcefield/F = new(T, src) current_fields += F user.changeNext_move(CLICK_CD_MELEE) + return ITEM_INTERACT_SUCCESS /obj/item/forcefield_projector/attack_self(mob/user) if(LAZYLEN(current_fields)) diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index db2d0d820ba..1d5ef17a90c 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -67,18 +67,18 @@ update_appearance(UPDATE_ICON) balloon_alert(user, "switch [scanning ? "on" : "off"]") -/obj/item/geiger_counter/afterattack(atom/target, mob/living/user, params) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/geiger_counter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) +/obj/item/geiger_counter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if (user.combat_mode) - return - - if (!CAN_IRRADIATE(target)) - return + return NONE + if (!CAN_IRRADIATE(interacting_with)) + return NONE - user.visible_message(span_notice("[user] scans [target] with [src]."), span_notice("You scan [target]'s radiation levels with [src]...")) - addtimer(CALLBACK(src, PROC_REF(scan), target, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents + user.visible_message(span_notice("[user] scans [interacting_with] with [src]."), span_notice("You scan [interacting_with]'s radiation levels with [src]...")) + addtimer(CALLBACK(src, PROC_REF(scan), interacting_with, user), 20, TIMER_UNIQUE) // Let's not have spamming GetAllContents + return ITEM_INTERACT_SUCCESS /obj/item/geiger_counter/equipped(mob/user, slot, initial) . = ..() diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index a41867b85c6..e973fe54751 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -182,13 +182,15 @@ . += "\The [diode.name]'s size is much smaller compared to the previous generation lasers, \ and the wide margin between it and the focus lens could probably house a crystal of some sort." -/obj/item/laser_pointer/afterattack(atom/target, mob/living/user, flag, params) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - laser_act(target, user, params) +/obj/item/laser_pointer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/laser_pointer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + laser_act(interacting_with, user, modifiers) + return ITEM_INTERACT_BLOCKING ///Handles shining the clicked atom, -/obj/item/laser_pointer/proc/laser_act(atom/target, mob/living/user, params) +/obj/item/laser_pointer/proc/laser_act(atom/target, mob/living/user, list/modifiers) if(isnull(diode)) to_chat(user, span_notice("You point [src] at [target], but nothing happens!")) return @@ -288,7 +290,6 @@ //setup pointer blip var/mutable_appearance/laser = mutable_appearance('icons/obj/weapons/guns/projectiles.dmi', pointer_icon_state) - var/list/modifiers = params2list(params) if(modifiers) if(LAZYACCESS(modifiers, ICON_X)) laser.pixel_x = (text2num(LAZYACCESS(modifiers, ICON_X)) - 16) diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index 375ddd49d2d..07a1db55a9c 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -62,11 +62,23 @@ . = ..() . += status_string() -/obj/item/lightreplacer/pre_attack(atom/target, mob/living/user, params) - . = ..() - if(.) - return - return do_action(target, user) //if we are attacking a valid target[light, floodlight or turf] stop here +/obj/item/lightreplacer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return do_action(interacting_with, user) ? ITEM_INTERACT_SUCCESS : NONE + +/obj/item/lightreplacer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + // has no bluespace capabilities + if(!bluespace_toggle) + return NONE + // target not in range + if(interacting_with.z != user.z) + return NONE + // target not in view + if(!(interacting_with in view(7, get_turf(user)))) + user.balloon_alert(user, "out of range!") + return ITEM_INTERACT_BLOCKING + + //replace lights & stuff + return do_action(interacting_with, user) ? ITEM_INTERACT_SUCCESS : NONE /obj/item/lightreplacer/attackby(obj/item/insert, mob/user, params) . = ..() @@ -239,23 +251,6 @@ return FALSE -/obj/item/lightreplacer/afterattack(atom/target, mob/user, proximity) - . = ..() - - // has no bluespace capabilities - if(!bluespace_toggle) - return - // target not in range - if(target.z != user.z) - return - // target not in view - if(!(target in view(7, get_turf(user)))) - user.balloon_alert(user, "out of range!") - return - - //replace lights & stuff - do_action(target, user) - /obj/item/lightreplacer/proc/status_string() return "It has [uses] light\s remaining (plus [bulb_shards]/[BULB_SHARDS_REQUIRED] fragment\s)." diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm index 3a3b9055725..12b73d79e27 100644 --- a/code/game/objects/items/devices/pipe_painter.dm +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -9,24 +9,24 @@ custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 2.5, /datum/material/glass = SHEET_MATERIAL_AMOUNT) -/obj/item/pipe_painter/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - //Make sure we only paint adjacent items - if(!proximity_flag) - return - - if(istype(target, /obj/machinery/atmospherics)) - var/obj/machinery/atmospherics/target_pipe = target +/obj/item/pipe_painter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/machinery/atmospherics)) + var/obj/machinery/atmospherics/target_pipe = interacting_with target_pipe.paint(GLOB.pipe_paint_colors[paint_color]) playsound(src, 'sound/machines/click.ogg', 50, TRUE) balloon_alert(user, "painted in [paint_color] color") - else if(istype(target, /obj/item/pipe)) - var/obj/item/pipe/target_pipe = target + return ITEM_INTERACT_SUCCESS + + if(istype(interacting_with, /obj/item/pipe)) + var/obj/item/pipe/target_pipe = interacting_with var/color = GLOB.pipe_paint_colors[paint_color] target_pipe.pipe_color = color - target.add_atom_colour(color, FIXED_COLOUR_PRIORITY) + target_pipe.add_atom_colour(color, FIXED_COLOUR_PRIORITY) playsound(src, 'sound/machines/click.ogg', 50, TRUE) balloon_alert(user, "painted in [paint_color] color") + return ITEM_INTERACT_SUCCESS + + return NONE /obj/item/pipe_painter/attack_self(mob/user) paint_color = tgui_input_list(user, "Which colour do you want to use?", "Pipe painter", GLOB.pipe_paint_colors) diff --git a/code/game/objects/items/devices/scanners/gas_analyzer.dm b/code/game/objects/items/devices/scanners/gas_analyzer.dm index 8341ad1753b..e9b6ae699f4 100644 --- a/code/game/objects/items/devices/scanners/gas_analyzer.dm +++ b/code/game/objects/items/devices/scanners/gas_analyzer.dm @@ -145,12 +145,13 @@ ui_interact(user) -/obj/item/analyzer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!can_see(user, target, ranged_scan_distance)) - return - . |= AFTERATTACK_PROCESSED_ITEM - atmos_scan(user, (target.return_analyzable_air() ? target : get_turf(target))) +/obj/item/analyzer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/analyzer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(can_see(user, interacting_with, ranged_scan_distance)) + atmos_scan(user, (interacting_with.return_analyzable_air() ? interacting_with : get_turf(interacting_with))) + return NONE // Non-blocking /// Called when our analyzer is used on something /obj/item/analyzer/proc/on_analyze(datum/source, atom/target) diff --git a/code/game/objects/items/devices/scanners/sequence_scanner.dm b/code/game/objects/items/devices/scanners/sequence_scanner.dm index 4c4c202f26f..03ed5670d7e 100644 --- a/code/game/objects/items/devices/scanners/sequence_scanner.dm +++ b/code/game/objects/items/devices/scanners/sequence_scanner.dm @@ -30,6 +30,15 @@ . += span_notice("It has the genetic makeup of \"[genetic_makeup_buffer["name"]]\" stored inside its buffer") /obj/item/sequence_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/machinery/computer/scan_consolenew)) + var/obj/machinery/computer/scan_consolenew/console = interacting_with + if(console.stored_research) + to_chat(user, span_notice("[name] linked to central research database.")) + discovered = console.stored_research.discovered_mutations + else + to_chat(user,span_warning("No database to update from.")) + return ITEM_INTERACT_SUCCESS + if(!isliving(interacting_with)) return NONE @@ -47,6 +56,12 @@ return ITEM_INTERACT_BLOCKING /obj/item/sequence_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/machinery/computer/scan_consolenew)) + var/obj/machinery/computer/scan_consolenew/console = interacting_with + var/buffer_index = tgui_input_number(user, "Slot:", "Which slot to export:", 1, LAZYLEN(console.genetic_makeup_buffer), 1) + console.genetic_makeup_buffer[buffer_index] = genetic_makeup_buffer + return ITEM_INTERACT_SUCCESS + if(!isliving(interacting_with)) return NONE @@ -66,34 +81,12 @@ user.visible_message(span_notice("[user] fails to analyze [interacting_with]'s genetic makeup."), span_warning("[interacting_with] has no readable genetic makeup!")) return ITEM_INTERACT_BLOCKING -/obj/item/sequence_scanner/afterattack_secondary(obj/object, mob/user, proximity) - . = ..() - if(!istype(object) || !proximity) - return - if(istype(object, /obj/machinery/computer/scan_consolenew)) - var/obj/machinery/computer/scan_consolenew/console = object - var/buffer_index = tgui_input_number(user, "Slot:", "Which slot to export:", 1, LAZYLEN(console.genetic_makeup_buffer), 1) - console.genetic_makeup_buffer[buffer_index] = genetic_makeup_buffer - /obj/item/sequence_scanner/attack_self(mob/user) display_sequence(user) /obj/item/sequence_scanner/attack_self_tk(mob/user) return -/obj/item/sequence_scanner/afterattack(obj/object, mob/user, proximity) - . = ..() - if(!istype(object) || !proximity) - return - - if(istype(object, /obj/machinery/computer/scan_consolenew)) - var/obj/machinery/computer/scan_consolenew/console = object - if(console.stored_research) - to_chat(user, span_notice("[name] linked to central research database.")) - discovered = console.stored_research.discovered_mutations - else - to_chat(user,span_warning("No database to update from.")) - ///proc for scanning someone's mutations /obj/item/sequence_scanner/proc/gene_scan(mob/living/carbon/target, mob/living/user) if(!iscarbon(target) || !target.has_dna()) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index 7e6ee077fce..b87bbda2841 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -361,29 +361,41 @@ effective or pretty fucking useless. new /obj/item/analyzer(src) new /obj/item/wirecutters(src) -/obj/item/storage/toolbox/emergency/turret/attackby(obj/item/attacking_item, mob/living/user, params) - if(!istype(attacking_item, /obj/item/wrench/combat)) - return ..() - +/obj/item/storage/toolbox/emergency/turret/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(!istype(inserted, /obj/item/wrench/combat)) + return TRUE if(!user.combat_mode) - return - - if(!attacking_item.toolspeed) - return + return TRUE + if(!inserted.toolspeed) + return TRUE + return FALSE +/obj/item/storage/toolbox/emergency/turret/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/wrench/combat)) + return NONE + if(!user.combat_mode) + return NONE + if(!tool.toolspeed) + return ITEM_INTERACT_BLOCKING balloon_alert(user, "constructing...") - if(!attacking_item.use_tool(src, user, 2 SECONDS, volume = 20)) - return + if(!tool.use_tool(src, user, 2 SECONDS, volume = 20)) + return ITEM_INTERACT_BLOCKING balloon_alert(user, "constructed!") - user.visible_message(span_danger("[user] bashes [src] with [attacking_item]!"), \ - span_danger("You bash [src] with [attacking_item]!"), null, COMBAT_MESSAGE_RANGE) + user.visible_message( + span_danger("[user] bashes [src] with [tool]!"), + span_danger("You bash [src] with [tool]!"), + null, + COMBAT_MESSAGE_RANGE, + ) playsound(src, "sound/items/drill_use.ogg", 80, TRUE, -1) var/obj/machinery/porta_turret/syndicate/toolbox/turret = new(get_turf(loc)) set_faction(turret, user) turret.toolbox = src forceMove(turret) + return ITEM_INTERACT_SUCCESS + /obj/item/storage/toolbox/emergency/turret/proc/set_faction(obj/machinery/porta_turret/turret, mob/user) turret.faction = list("[REF(user)]") diff --git a/code/game/objects/items/dna_probe.dm b/code/game/objects/items/dna_probe.dm index 6f9944bc949..f299a9254f8 100644 --- a/code/game/objects/items/dna_probe.dm +++ b/code/game/objects/items/dna_probe.dm @@ -30,18 +30,12 @@ ///weak ref to the dna vault var/datum/weakref/dna_vault_ref -/obj/item/dna_probe/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !target) - return . - - if (isitem(target)) - . |= AFTERATTACK_PROCESSED_ITEM - - if(istype(target, /obj/machinery/dna_vault) && !dna_vault_ref?.resolve()) - try_linking_vault(target, user) +/obj/item/dna_probe/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/machinery/dna_vault) && !dna_vault_ref?.resolve()) + try_linking_vault(interacting_with, user) else - scan_dna(target, user) + scan_dna(interacting_with, user) + return ITEM_INTERACT_BLOCKING /obj/item/dna_probe/proc/try_linking_vault(atom/target, mob/user) var/obj/machinery/dna_vault/our_vault = dna_vault_ref?.resolve() diff --git a/code/game/objects/items/emags.dm b/code/game/objects/items/emags.dm index ed0b228d598..ad6b83fac17 100644 --- a/code/game/objects/items/emags.dm +++ b/code/game/objects/items/emags.dm @@ -58,6 +58,9 @@ . = ..() type_blacklist = list(typesof(/obj/machinery/door/airlock) + typesof(/obj/machinery/door/window/) + typesof(/obj/machinery/door/firedoor) - typesof(/obj/machinery/door/airlock/tram)) //list of all typepaths that require a specialized emag to hack. +/obj/item/card/emag/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user) + return !user.combat_mode + /obj/item/card/emag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!can_emag(interacting_with, user)) return ITEM_INTERACT_BLOCKING @@ -65,15 +68,8 @@ interacting_with.emag_act(user, src) return ITEM_INTERACT_SUCCESS -/obj/item/card/emag/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - // Proximity based emagging is handled by above - // This is only for ranged emagging - if(proximity_flag || prox_check) - return - - . |= AFTERATTACK_PROCESSED_ITEM - interact_with_atom(target, user) +/obj/item/card/emag/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return prox_check ? NONE : interact_with_atom(interacting_with, user) /obj/item/card/emag/proc/can_emag(atom/target, mob/user) for (var/subtypelist in type_blacklist) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index cdbc536a9ac..36e8d73e3d0 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -142,7 +142,7 @@ /obj/item/extinguisher/suicide_act(mob/living/carbon/user) if (!safety && (reagents.total_volume >= 1)) user.visible_message(span_suicide("[user] puts the nozzle to [user.p_their()] mouth. It looks like [user.p_theyre()] trying to extinguish the spark of life!")) - afterattack(user,user) + interact_with_atom(user, user) return OXYLOSS else if (safety && (reagents.total_volume >= 1)) user.visible_message(span_warning("[user] puts the nozzle to [user.p_their()] mouth... The safety's still on!")) @@ -196,67 +196,65 @@ else return FALSE -/obj/item/extinguisher/afterattack(atom/target, mob/user , flag) - . = ..() - // Make it so the extinguisher doesn't spray yourself when you click your inventory items - if (target.loc == user) - return +/obj/item/extinguisher/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/extinguisher/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (interacting_with.loc == user) + return NONE if(refilling) refilling = FALSE - return . - if (!safety) - - - if (src.reagents.total_volume < 1) - balloon_alert(user, "it's empty!") - return . + return NONE + if(safety) + return NONE - if (world.time < src.last_use + 12) - return . + if (src.reagents.total_volume < 1) + balloon_alert(user, "it's empty!") + return . - src.last_use = world.time + if (world.time < src.last_use + 12) + return . - playsound(src.loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3) + src.last_use = world.time - var/direction = get_dir(src,target) + playsound(src.loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3) - if(user.buckled && isobj(user.buckled) && !user.buckled.anchored) - var/obj/B = user.buckled - var/movementdirection = REVERSE_DIR(direction) - addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/extinguisher, move_chair), B, movementdirection), 0.1 SECONDS) - else - user.newtonian_move(REVERSE_DIR(direction)) + var/direction = get_dir(src,interacting_with) - //Get all the turfs that can be shot at - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - var/list/the_targets = list(T,T1,T2) + if(user.buckled && isobj(user.buckled) && !user.buckled.anchored) + var/obj/B = user.buckled + var/movementdirection = REVERSE_DIR(direction) + addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/extinguisher, move_chair), B, movementdirection), 0.1 SECONDS) + else + user.newtonian_move(REVERSE_DIR(direction)) + + //Get all the turfs that can be shot at + var/turf/T = get_turf(interacting_with) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + var/list/the_targets = list(T,T1,T2) + if(precision) + var/turf/T3 = get_step(T1, turn(direction, 90)) + var/turf/T4 = get_step(T2,turn(direction, -90)) + the_targets.Add(T3,T4) + + var/list/water_particles = list() + for(var/a in 1 to 5) + var/obj/effect/particle_effect/water/extinguisher/water = new /obj/effect/particle_effect/water/extinguisher(get_turf(src)) + var/my_target = pick(the_targets) + water_particles[water] = my_target + // If precise, remove turf from targets so it won't be picked more than once if(precision) - var/turf/T3 = get_step(T1, turn(direction, 90)) - var/turf/T4 = get_step(T2,turn(direction, -90)) - the_targets.Add(T3,T4) - - var/list/water_particles = list() - for(var/a in 1 to 5) - var/obj/effect/particle_effect/water/extinguisher/water = new /obj/effect/particle_effect/water/extinguisher(get_turf(src)) - var/my_target = pick(the_targets) - water_particles[water] = my_target - // If precise, remove turf from targets so it won't be picked more than once - if(precision) - the_targets -= my_target - var/datum/reagents/water_reagents = new /datum/reagents(5) - water.reagents = water_reagents - water_reagents.my_atom = water - reagents.trans_to(water, 1, transferred_by = user) - - //Make em move dat ass, hun - move_particles(water_particles) - - return . + the_targets -= my_target + var/datum/reagents/water_reagents = new /datum/reagents(5) + water.reagents = water_reagents + water_reagents.my_atom = water + reagents.trans_to(water, 1, transferred_by = user) + + //Make em move dat ass, hun + move_particles(water_particles) + return ITEM_INTERACT_SKIP_TO_ATTACK // You can smack while spraying //Particle movement loop /obj/item/extinguisher/proc/move_particles(list/particles) diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm index 2859b4d3b2c..38e4c840694 100644 --- a/code/game/objects/items/fireaxe.dm +++ b/code/game/objects/items/fireaxe.dm @@ -51,15 +51,13 @@ user.visible_message(span_suicide("[user] axes [user.p_them()]self from head to toe! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS -/obj/item/fireaxe/afterattack(atom/A, mob/user, proximity) - . = ..() - if(!proximity) +/obj/item/fireaxe/afterattack(atom/target, mob/user, click_parameters) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) //destroys windows and grilles in one hit + return + if(target.resistance_flags & INDESTRUCTIBLE) return - if(HAS_TRAIT(src, TRAIT_WIELDED)) //destroys windows and grilles in one hit - if(istype(A, /obj/structure/window) || istype(A, /obj/structure/grille)) - if(!(A.resistance_flags & INDESTRUCTIBLE)) - var/obj/structure/W = A - W.atom_destruction("fireaxe") + if(istype(target, /obj/structure/window) || istype(target, /obj/structure/grille)) + target.atom_destruction("fireaxe") /* * Bone Axe diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index be89193ba7e..e2d587cd359 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -79,21 +79,17 @@ if(lit) . += "+lit" -/obj/item/flamethrower/afterattack(atom/target, mob/user, flag) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - if(flag) - return // too close +/obj/item/flamethrower/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, span_warning("You can't bring yourself to fire \the [src]! You don't want to risk harming anyone...")) - log_combat(user, target, "attempted to flamethrower", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\" ([src]), igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = 9)]\"" + (lit ? " while lit" : "" + " but failed due to pacifism.")) - return - if(user && user.get_active_held_item() == src) // Make sure our user is still holding us - var/turf/target_turf = get_turf(target) - if(target_turf) - var/turflist = get_line(user, target_turf) - log_combat(user, target, "flamethrowered", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\", igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = 9)]\"" + (lit ? " while lit." : ".")) - flame_turf(turflist) + log_combat(user, interacting_with, "attempted to flamethrower", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\" ([src]), igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = 9)]\"" + (lit ? " while lit" : "" + " but failed due to pacifism.")) + return ITEM_INTERACT_BLOCKING + var/turf/target_turf = get_turf(interacting_with) + if(target_turf) + var/turflist = get_line(user, target_turf) + log_combat(user, interacting_with, "flamethrowered", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\", igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = 9)]\"" + (lit ? " while lit." : ".")) + flame_turf(turflist) + return ITEM_INTERACT_SUCCESS /obj/item/flamethrower/wrench_act(mob/living/user, obj/item/tool) . = TRUE diff --git a/code/game/objects/items/food/egg.dm b/code/game/objects/items/food/egg.dm index 62113e02e77..b669e16b103 100644 --- a/code/game/objects/items/food/egg.dm +++ b/code/game/objects/items/food/egg.dm @@ -120,26 +120,27 @@ GLOBAL_VAR_INIT(chicks_from_eggs, 0) else ..() -/obj/item/food/egg/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return - - if(!istype(target, /obj/machinery/griddle)) - return SECONDARY_ATTACK_CALL_NORMAL - - var/atom/broken_egg = new /obj/item/food/rawegg(target.loc) - broken_egg.pixel_x = pixel_x - broken_egg.pixel_y = pixel_y - playsound(get_turf(user), 'sound/items/sheath.ogg', 40, TRUE) - reagents.copy_to(broken_egg,reagents.total_volume) +/obj/item/food/egg/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/machinery/griddle)) + return NONE + + var/obj/machinery/griddle/hit_griddle = interacting_with + if(length(hit_griddle.griddled_objects) >= hit_griddle.max_items) + interacting_with.balloon_alert(user, "no room!") + return ITEM_INTERACT_BLOCKING + var/atom/broken_egg = new /obj/item/food/rawegg(interacting_with.loc) + if(LAZYACCESS(modifiers, ICON_X)) + broken_egg.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size/2), world.icon_size/2) + if(LAZYACCESS(modifiers, ICON_Y)) + broken_egg.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size/2), world.icon_size/2) + playsound(user, 'sound/items/sheath.ogg', 40, TRUE) + reagents.copy_to(broken_egg, reagents.total_volume) - var/obj/machinery/griddle/hit_griddle = target hit_griddle.AddToGrill(broken_egg, user) - target.balloon_alert(user, "cracks [src] open") + interacting_with.balloon_alert(user, "cracks [src] open") qdel(src) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /obj/item/food/egg/blue icon_state = "egg-blue" diff --git a/code/game/objects/items/food/packaged.dm b/code/game/objects/items/food/packaged.dm index 820b10927f6..0f08fd8f57d 100644 --- a/code/game/objects/items/food/packaged.dm +++ b/code/game/objects/items/food/packaged.dm @@ -117,13 +117,11 @@ return ..() apply_buff(user) -/obj/item/food/canned/envirochow/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - if(!check_buffability(target)) - return - apply_buff(target, user) +/obj/item/food/canned/envirochow/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!check_buffability(interacting_with)) + return NONE + apply_buff(interacting_with, user) + return ITEM_INTERACT_SUCCESS ///This proc checks if the mob is able to receive the buff. /obj/item/food/canned/envirochow/proc/check_buffability(mob/living/hungry_pet) diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index 4c737ed53f3..5deb833b1f2 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -263,8 +263,8 @@ qdel(src) return TRUE //It hit the grenade, not them -/obj/item/grenade/afterattack(atom/target, mob/user) - . = ..() +/obj/item/grenade/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(active) - user.throw_item(target) - return . | AFTERATTACK_PROCESSED_ITEM + user.throw_item(interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index c1cf8c1010d..336c9e5e2ee 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -105,58 +105,56 @@ det_time = newtime to_chat(user, "Timer set for [det_time] seconds.") -/obj/item/grenade/c4/afterattack(atom/movable/bomb_target, mob/user, flag) - . = ..() - aim_dir = get_dir(user, bomb_target) - if(isdead(bomb_target)) - return - if(!flag) - return - - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/grenade/c4/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + // Here lies C4 ghosts. We hardly knew ye + if(isdead(interacting_with)) + return NONE + aim_dir = get_dir(user, interacting_with) + return plant_c4(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + +/obj/item/grenade/c4/proc/plant_c4(atom/bomb_target, mob/living/user) if(bomb_target != user && HAS_TRAIT(user, TRAIT_PACIFISM) && isliving(bomb_target)) to_chat(user, span_warning("You don't want to harm other living beings!")) - return . + return FALSE to_chat(user, span_notice("You start planting [src]. The timer is set to [det_time]...")) - if(do_after(user, 3 SECONDS, target = bomb_target)) - if(!user.temporarilyRemoveItemFromInventory(src)) - return . - target = bomb_target - active = TRUE - - message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_VERBOSEJMP(target)] with [det_time] second fuse") - user.log_message("planted [name] on [target.name] with a [det_time] second fuse.", LOG_ATTACK) - var/icon/target_icon = icon(bomb_target.icon, bomb_target.icon_state) - target_icon.Blend(icon(icon, icon_state), ICON_OVERLAY) - var/mutable_appearance/bomb_target_image = mutable_appearance(target_icon) - notify_ghosts( - "[user] has planted \a [src] on [target] with a [det_time] second fuse!", - source = bomb_target, - header = "Explosive Planted", - alert_overlay = bomb_target_image, - notify_flags = NOTIFY_CATEGORY_NOFLASH, - ) - - moveToNullspace() //Yep - - if(isitem(bomb_target)) //your crappy throwing star can't fly so good with a giant brick of c4 on it. - var/obj/item/thrown_weapon = bomb_target - thrown_weapon.throw_speed = max(1, (thrown_weapon.throw_speed - 3)) - thrown_weapon.throw_range = max(1, (thrown_weapon.throw_range - 3)) - if(thrown_weapon.embedding) - thrown_weapon.embedding["embed_chance"] = 0 - thrown_weapon.updateEmbedding() - else if(isliving(bomb_target)) - plastic_overlay.layer = FLOAT_LAYER - - target.add_overlay(plastic_overlay) - to_chat(user, span_notice("You plant the bomb. Timer counting down from [det_time].")) - addtimer(CALLBACK(src, PROC_REF(detonate)), det_time*10) - - return . + if(!do_after(user, 3 SECONDS, target = bomb_target)) + return FALSE + if(!user.temporarilyRemoveItemFromInventory(src)) + return FALSE + target = bomb_target + active = TRUE + + message_admins("[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_VERBOSEJMP(target)] with [det_time] second fuse") + user.log_message("planted [name] on [target.name] with a [det_time] second fuse.", LOG_ATTACK) + var/icon/target_icon = icon(bomb_target.icon, bomb_target.icon_state) + target_icon.Blend(icon(icon, icon_state), ICON_OVERLAY) + var/mutable_appearance/bomb_target_image = mutable_appearance(target_icon) + notify_ghosts( + "[user] has planted \a [src] on [target] with a [det_time] second fuse!", + source = bomb_target, + header = "Explosive Planted", + alert_overlay = bomb_target_image, + notify_flags = NOTIFY_CATEGORY_NOFLASH, + ) + + moveToNullspace() //Yep + + if(isitem(bomb_target)) //your crappy throwing star can't fly so good with a giant brick of c4 on it. + var/obj/item/thrown_weapon = bomb_target + thrown_weapon.throw_speed = max(1, (thrown_weapon.throw_speed - 3)) + thrown_weapon.throw_range = max(1, (thrown_weapon.throw_range - 3)) + if(thrown_weapon.embedding) + thrown_weapon.embedding["embed_chance"] = 0 + thrown_weapon.updateEmbedding() + else if(isliving(bomb_target)) + plastic_overlay.layer = FLOAT_LAYER + + target.add_overlay(plastic_overlay) + to_chat(user, span_notice("You plant the bomb. Timer counting down from [det_time].")) + addtimer(CALLBACK(src, PROC_REF(detonate)), det_time*10) + return TRUE /obj/item/grenade/c4/proc/shout_syndicate_crap(mob/player) if(!player) diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm index 1f780ac8c4d..c8043f63693 100644 --- a/code/game/objects/items/hand_items.dm +++ b/code/game/objects/items/hand_items.dm @@ -475,9 +475,10 @@ /// TRUE if the user was aiming anywhere but the mouth when they offer the kiss, if it's offered var/cheek_kiss -/obj/item/hand_item/kisser/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/hand_item/kisser/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/hand_item/kisser/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) if(HAS_TRAIT(user, TRAIT_GARLIC_BREATH)) kiss_type = /obj/projectile/kiss/french @@ -495,6 +496,7 @@ blown_kiss.preparePixelProjectile(target, user) blown_kiss.fire() qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/hand_item/kisser/on_offered(mob/living/carbon/offerer, mob/living/carbon/offered) if(!(locate(/mob/living/carbon) in orange(1, offerer))) diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm index b4835a0d565..ff4d0260c4f 100644 --- a/code/game/objects/items/holosign_creator.dm +++ b/code/game/objects/items/holosign_creator.dm @@ -26,8 +26,8 @@ AddElement(/datum/element/openspace_item_click_handler) RegisterSignal(src, COMSIG_OBJ_PAINTED, TYPE_PROC_REF(/obj/item/holosign_creator, on_color_change)) -/obj/item/holosign_creator/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) - afterattack(target, user, proximity_flag, click_parameters) +/obj/item/holosign_creator/handle_openspace_click(turf/target, mob/user, click_parameters) + interact_with_atom(target, user, click_parameters) /obj/item/holosign_creator/examine(mob/user) . = ..() @@ -35,39 +35,35 @@ return . += span_notice("It is currently maintaining [signs.len]/[max_signs] projections.") -/obj/item/holosign_creator/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(!check_allowed_items(target, not_inside = TRUE)) - return . - var/turf/target_turf = get_turf(target) +/obj/item/holosign_creator/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!check_allowed_items(interacting_with, not_inside = TRUE)) + return NONE + var/turf/target_turf = get_turf(interacting_with) var/obj/structure/holosign/target_holosign = locate(holosign_type) in target_turf if(target_holosign) qdel(target_holosign) - return . + return ITEM_INTERACT_BLOCKING if(target_turf.is_blocked_turf(TRUE)) //can't put holograms on a tile that has dense stuff - return . + return ITEM_INTERACT_BLOCKING if(holocreator_busy) - to_chat(user, span_notice("[src] is busy creating a hologram.")) - return . + balloon_alert(user, "busy making a hologram!") + return ITEM_INTERACT_BLOCKING if(LAZYLEN(signs) >= max_signs) balloon_alert(user, "max capacity!") - return . - playsound(loc, 'sound/machines/click.ogg', 20, TRUE) + return ITEM_INTERACT_BLOCKING + playsound(src, 'sound/machines/click.ogg', 20, TRUE) if(creation_time) holocreator_busy = TRUE - if(!do_after(user, creation_time, target = target)) + if(!do_after(user, creation_time, target = interacting_with)) holocreator_busy = FALSE - return . + return ITEM_INTERACT_BLOCKING holocreator_busy = FALSE if(LAZYLEN(signs) >= max_signs) - return . + return ITEM_INTERACT_BLOCKING if(target_turf.is_blocked_turf(TRUE)) //don't try to sneak dense stuff on our tile during the wait. - return . - target_holosign = create_holosign(target, user) - return . + return ITEM_INTERACT_BLOCKING + target_holosign = create_holosign(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/holosign_creator/attack(mob/living/carbon/human/M, mob/user) return diff --git a/code/game/objects/items/hot_potato.dm b/code/game/objects/items/hot_potato.dm index 9a7da338885..20233db522b 100644 --- a/code/game/objects/items/hot_potato.dm +++ b/code/game/objects/items/hot_potato.dm @@ -95,11 +95,12 @@ if(active) to_chat(user, span_userdanger("You have a really bad feeling about [src]!")) -/obj/item/hot_potato/afterattack(atom/target, mob/user, adjacent, params) +/obj/item/hot_potato/attack(mob/living/target_mob, mob/living/user, params) . = ..() - if(!adjacent || !ismob(target)) - return - force_onto(target, user) + if(.) + return . + + return force_onto(target_mob, user) /obj/item/hot_potato/proc/force_onto(mob/living/victim, mob/user) if(!istype(victim) || user != loc || victim == user) diff --git a/code/game/objects/items/implants/security/implant_chem.dm b/code/game/objects/items/implants/security/implant_chem.dm index bad6cca8c69..c25496c634b 100644 --- a/code/game/objects/items/implants/security/implant_chem.dm +++ b/code/game/objects/items/implants/security/implant_chem.dm @@ -97,7 +97,7 @@ /obj/item/implantcase/chem/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/reagent_containers/syringe) && imp) - W.afterattack(imp, user, TRUE, params) + W.interact_with_atom(imp, user, params) return TRUE else return ..() diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm index 8b4808848c2..622ee6592cb 100644 --- a/code/game/objects/items/knives.dm +++ b/code/game/objects/items/knives.dm @@ -77,9 +77,8 @@ /// Bleed stacks applied when an organic mob target is hit var/bleed_stacks_per_hit = 3 -/obj/item/knife/bloodletter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!isliving(target) || !proximity_flag) +/obj/item/knife/bloodletter/afterattack(atom/target, mob/user, click_parameters) + if(!isliving(target)) return var/mob/living/M = target if(!(M.mob_biotypes & MOB_ORGANIC)) diff --git a/code/game/objects/items/machine_wand.dm b/code/game/objects/items/machine_wand.dm index bc5eb8583f9..fd0c730fff8 100644 --- a/code/game/objects/items/machine_wand.dm +++ b/code/game/objects/items/machine_wand.dm @@ -73,19 +73,22 @@ remove_old_machine() return CLICK_ACTION_SUCCESS -/obj/item/machine_remote/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() +/obj/item/machine_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/machine_remote/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, timeout_time)) playsound(src, 'sound/machines/synth_no.ogg', 30 , TRUE) say("Remote control disabled temporarily. Please try again soon.") - return FALSE - if(!ismachinery(target) && !isbot(target)) - return + return ITEM_INTERACT_BLOCKING + if(!ismachinery(interacting_with) && !isbot(interacting_with)) + return NONE if(moving_bug) //we have a bug in transit already, so let's kill it. QDEL_NULL(moving_bug) var/turf/spawning_turf = (controlling_machine_or_bot ? get_turf(controlling_machine_or_bot) : get_turf(src)) - moving_bug = new(spawning_turf, src, target) + moving_bug = new(spawning_turf, src, interacting_with) remove_old_machine() + return ITEM_INTERACT_SUCCESS ///Sets a controlled machine to a new machine, if possible. Checks if AIs can even control it. /obj/item/machine_remote/proc/set_controlled_machine(obj/machinery/new_machine) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 6dba721ffd6..bbbdb55e374 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -191,10 +191,7 @@ final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword return ..() -/obj/item/melee/beesword/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/melee/beesword/afterattack(atom/target, mob/user, click_parameters) if(iscarbon(target)) var/mob/living/carbon/carbon_target = target carbon_target.reagents.add_reagent(/datum/reagent/toxin, 4) @@ -242,20 +239,24 @@ if(!isspaceturf(turf)) consume_turf(turf) -/obj/item/melee/supermatter_sword/afterattack(target, mob/user, proximity_flag) +/obj/item/melee/supermatter_sword/pre_attack(atom/A, mob/living/user, params) . = ..() - if(user && target == user) - user.dropItemToGround(src) - if(proximity_flag) - consume_everything(target) - return . | AFTERATTACK_PROCESSED_ITEM + if(.) + return . + + if(A == user) + user.dropItemToGround(src, TRUE) + else + user.do_attack_animation(A) + consume_everything(A) + return TRUE /obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(ismob(hit_atom)) var/mob/mob = hit_atom if(src.loc == mob) - mob.dropItemToGround(src) + mob.dropItemToGround(src, TRUE) consume_everything(hit_atom) /obj/item/melee/supermatter_sword/pickup(user) @@ -330,10 +331,7 @@ attack_verb_simple = list("flog", "whip", "lash", "discipline") hitsound = 'sound/weapons/whip.ogg' -/obj/item/melee/curator_whip/attack(mob/living/target, mob/living/user, params) - . = ..() - if(.) - return +/obj/item/melee/curator_whip/afterattack(atom/target, mob/user, click_parameters) if(ishuman(target)) var/mob/living/carbon/human/human_target = target human_target.drop_all_held_items() @@ -429,22 +427,27 @@ held_sausage = null update_appearance() -/obj/item/melee/roastingstick/afterattack(atom/target, mob/user, proximity) - . = ..() +/obj/item/melee/roastingstick/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if (!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)) - return - if (!is_type_in_typecache(target, ovens)) - return - if (istype(target, /obj/singularity) && get_dist(user, target) < 10) - to_chat(user, span_notice("You send [held_sausage] towards [target].")) + return NONE + if (!is_type_in_typecache(interacting_with, ovens)) + return NONE + if (istype(interacting_with, /obj/singularity) && get_dist(user, interacting_with) < 10) + to_chat(user, span_notice("You send [held_sausage] towards [interacting_with].")) playsound(src, 'sound/items/rped.ogg', 50, TRUE) - beam = user.Beam(target, icon_state = "rped_upgrade", time = 10 SECONDS) - else if (user.Adjacent(target)) - to_chat(user, span_notice("You extend [src] towards [target].")) - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE) - else - return - finish_roasting(user, target) + beam = user.Beam(interacting_with, icon_state = "rped_upgrade", time = 10 SECONDS) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/melee/roastingstick/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)) + return NONE + if (!is_type_in_typecache(interacting_with, ovens)) + return NONE + to_chat(user, span_notice("You extend [src] towards [interacting_with].")) + playsound(src, 'sound/weapons/batonextend.ogg', 50, TRUE) + finish_roasting(user, interacting_with) + return ITEM_INTERACT_SUCCESS /obj/item/melee/roastingstick/proc/finish_roasting(user, atom/target) if(do_after(user, 10 SECONDS, target = user)) diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 907807397d7..2afc31d599e 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -46,11 +46,13 @@ ///Checks whether or not we should clean. /obj/item/mop/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner) if(clean_blacklist[atom_to_clean.type]) - return DO_NOT_CLEAN + return CLEAN_BLOCKED|CLEAN_DONT_BLOCK_INTERACTION if(reagents.total_volume < 0.1) cleaner.balloon_alert(cleaner, "mop is dry!") - return DO_NOT_CLEAN - return reagents.has_reagent(amount = 1, chemical_flags = REAGENT_CLEANS) + return CLEAN_BLOCKED + if(reagents.has_reagent(amount = 1, chemical_flags = REAGENT_CLEANS)) + return CLEAN_ALLOWED + return CLEAN_BLOCKED|CLEAN_NO_XP /** * Applies reagents to the cleaned floor and removes them from the mop. diff --git a/code/game/objects/items/paint.dm b/code/game/objects/items/paint.dm index 0b357c3c728..41c1809b558 100644 --- a/code/game/objects/items/paint.dm +++ b/code/game/objects/items/paint.dm @@ -112,17 +112,16 @@ return FALSE return TRUE -/obj/item/paint/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/paint/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isturf(interacting_with) || isspaceturf(interacting_with)) + return NONE if(paintleft <= 0) - icon_state = "paint_empty" - return - if(!isturf(target) || isspaceturf(target)) - return + return NONE paintleft-- - target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + interacting_with.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + if(paintleft <= 0) + icon_state = "paint_empty" + return ITEM_INTERACT_SUCCESS /obj/item/paint/paint_remover gender = PLURAL @@ -130,12 +129,10 @@ desc = "Used to remove color from anything." icon_state = "paint_neutral" -/obj/item/paint/paint_remover/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - if(!isturf(target) || !isobj(target)) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(target.color != initial(target.color)) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) +/obj/item/paint/paint_remover/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isturf(interacting_with) || !isobj(interacting_with)) + return NONE + if(interacting_with.color != initial(interacting_with.color)) + interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + return ITEM_INTERACT_SUCCESS + return NONE diff --git a/code/game/objects/items/pneumaticCannon.dm b/code/game/objects/items/pneumaticCannon.dm index bd31228f2fc..b49fb7ec260 100644 --- a/code/game/objects/items/pneumaticCannon.dm +++ b/code/game/objects/items/pneumaticCannon.dm @@ -161,14 +161,15 @@ loadedWeightClass++ return TRUE -/obj/item/pneumatic_cannon/afterattack(atom/target, mob/living/user, flag, params) - . = ..() - if(flag && user.combat_mode)//melee attack - return - if(!istype(user)) - return - Fire(user, target) - return AFTERATTACK_PROCESSED_ITEM +/obj/item/pneumatic_cannon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(user.combat_mode) + return ITEM_INTERACT_SKIP_TO_ATTACK + Fire(user, interacting_with) + return ITEM_INTERACT_SUCCESS + +/obj/item/pneumatic_cannon/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + Fire(user, interacting_with) + return ITEM_INTERACT_SUCCESS /obj/item/pneumatic_cannon/proc/Fire(mob/living/user, atom/target) if(!istype(user) && !target) diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index cdf200d3ef5..10a2a8c60a0 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -390,29 +390,27 @@ . = ..() ui_interact(user) -/obj/item/construction/rcd/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - //proximity check for normal rcd & range check for arcd - if((!proximity_flag && !ranged) || (ranged && !range_check(target, user))) - return FALSE - - //do the work +/obj/item/construction/rcd/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) mode = construction_mode - rcd_create(target, user) + rcd_create(interacting_with, user) + return ITEM_INTERACT_SUCCESS - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/construction/rcd/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ranged || !range_check(interacting_with, user)) + return ITEM_INTERACT_BLOCKING -/obj/item/construction/rcd/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - //proximity check for normal rcd & range check for arcd - if((!proximity_flag && !ranged) || (ranged && !range_check(target, user))) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return interact_with_atom(interacting_with, user, modifiers) - //do the work +/obj/item/construction/rcd/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) mode = RCD_DECONSTRUCT - rcd_create(target, user) + rcd_create(interacting_with, user) + return ITEM_INTERACT_SUCCESS + +/obj/item/construction/rcd/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!ranged || !range_check(interacting_with, user)) + return ITEM_INTERACT_BLOCKING - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return interact_with_atom_secondary(interacting_with, user, modifiers) /obj/item/construction/rcd/proc/detonate_pulse() audible_message("[src] begins to vibrate and \ diff --git a/code/game/objects/items/rcd/RLD.dm b/code/game/objects/items/rcd/RLD.dm index e321e5e941d..80d98382e64 100644 --- a/code/game/objects/items/rcd/RLD.dm +++ b/code/game/objects/items/rcd/RLD.dm @@ -88,61 +88,56 @@ else toggle_silo(user) -/obj/item/construction/rld/afterattack(atom/A, mob/user) - . = ..() - if(!range_check(A,user)) - return +/obj/item/construction/rld/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!range_check(interacting_with, user)) + return NONE + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/construction/rld/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/turf/start = get_turf(src) switch(mode) if(REMOVE_MODE) - if(!istype(A, /obj/machinery/light/)) - return FALSE + if(!istype(interacting_with, /obj/machinery/light)) + return NONE //resource sanity checks before & after delay if(!checkResource(DECONSTRUCT_COST, user)) - return FALSE - var/beam = user.Beam(A,icon_state="light_beam", time = 15) - playsound(loc, 'sound/machines/click.ogg', 50, TRUE) - if(!do_after(user, REMOVE_DELAY, target = A)) + return ITEM_INTERACT_BLOCKING + var/beam = user.Beam(interacting_with, icon_state="light_beam", time = 15) + playsound(src, 'sound/machines/click.ogg', 50, TRUE) + if(!do_after(user, REMOVE_DELAY, target = interacting_with)) qdel(beam) - return FALSE + return ITEM_INTERACT_BLOCKING if(!checkResource(DECONSTRUCT_COST, user)) - return FALSE - + return ITEM_INTERACT_BLOCKING if(!useResource(DECONSTRUCT_COST, user)) - return FALSE + return ITEM_INTERACT_BLOCKING activate() - qdel(A) - return TRUE + qdel(interacting_with) + return ITEM_INTERACT_SUCCESS if(LIGHT_MODE) //resource sanity checks before & after delay - var/cost = iswallturf(A) ? LIGHT_TUBE_COST : FLOOR_LIGHT_COST + var/cost = iswallturf(interacting_with) ? LIGHT_TUBE_COST : FLOOR_LIGHT_COST if(!checkResource(cost, user)) - return FALSE - var/beam = user.Beam(A,icon_state="light_beam", time = BUILD_DELAY) + return ITEM_INTERACT_BLOCKING + var/beam = user.Beam(interacting_with, icon_state="light_beam", time = BUILD_DELAY) playsound(loc, 'sound/machines/click.ogg', 50, TRUE) playsound(loc, 'sound/effects/light_flicker.ogg', 50, FALSE) - if(!do_after(user, BUILD_DELAY, target = A)) + if(!do_after(user, BUILD_DELAY, target = interacting_with)) qdel(beam) - return FALSE + return ITEM_INTERACT_BLOCKING if(!checkResource(cost, user)) - return FALSE + return ITEM_INTERACT_BLOCKING - if(iswallturf(A)) + if(iswallturf(interacting_with)) var/turf/open/winner = null var/winning_dist = null - var/skip = FALSE for(var/direction in GLOB.cardinals) - var/turf/C = get_step(A, direction) + var/turf/C = get_step(interacting_with, direction) //turf already has a light - skip = FALSE - for(var/obj/machinery/light/dupe in C) - if(istype(dupe, /obj/machinery/light)) - skip = TRUE - break - if(skip) + if(locate(/obj/machinery/light) in C) continue //can't put a light here if(!(isspaceturf(C) || TURF_SHARES(C))) @@ -159,43 +154,41 @@ winning_dist = contender if(!winner) balloon_alert(user, "no valid target!") - return FALSE - + return ITEM_INTERACT_BLOCKING if(!useResource(cost, user)) - return FALSE + return ITEM_INTERACT_BLOCKING activate() var/obj/machinery/light/L = new /obj/machinery/light(get_turf(winner)) - L.setDir(get_dir(winner, A)) + L.setDir(get_dir(winner, interacting_with)) L.color = color_choice L.set_light_color(color_choice) - return TRUE - - if(isfloorturf(A)) - var/turf/target = get_turf(A) - for(var/obj/machinery/light/floor/dupe in target) - if(istype(dupe)) - return FALSE + return ITEM_INTERACT_SUCCESS + if(isfloorturf(interacting_with)) + var/turf/target = get_turf(interacting_with) + if(locate(/obj/machinery/light/floor) in target) + return ITEM_INTERACT_BLOCKING if(!useResource(cost, user)) - return FALSE + return ITEM_INTERACT_BLOCKING activate() var/obj/machinery/light/floor/FL = new /obj/machinery/light/floor(target) FL.color = color_choice FL.set_light_color(color_choice) - return TRUE + return ITEM_INTERACT_SUCCESS if(GLOW_MODE) if(!useResource(GLOW_STICK_COST, user)) - return FALSE + return ITEM_INTERACT_BLOCKING activate() var/obj/item/flashlight/glowstick/new_stick = new /obj/item/flashlight/glowstick(start) new_stick.color = color_choice new_stick.set_light_color(new_stick.color) - new_stick.throw_at(A, 9, 3, user) + new_stick.throw_at(interacting_with, 9, 3, user) new_stick.turn_on() new_stick.update_brightness() + return ITEM_INTERACT_SUCCESS - return TRUE + return NONE /obj/item/construction/rld/mini name = "mini-rapid-light-device" diff --git a/code/game/objects/items/rcd/RPLD.dm b/code/game/objects/items/rcd/RPLD.dm index df743f8980a..f48449b7a19 100644 --- a/code/game/objects/items/rcd/RPLD.dm +++ b/code/game/objects/items/rcd/RPLD.dm @@ -248,31 +248,32 @@ if(duct_machine.duct_layer & layer_id) return FALSE -/obj/item/construction/plumbing/interact_with_atom(atom/target, mob/living/user, list/modifiers) - . = NONE +/obj/item/construction/plumbing/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) for(var/category_name in plumbing_design_types) var/list/designs = plumbing_design_types[category_name] for(var/obj/machinery/recipe as anything in designs) - if(target.type != recipe) + if(interacting_with.type != recipe) continue - var/obj/machinery/machine_target = target + var/obj/machinery/machine_target = interacting_with if(machine_target.anchored) balloon_alert(user, "unanchor first!") return ITEM_INTERACT_BLOCKING - if(do_after(user, 2 SECONDS, target = target)) + if(do_after(user, 2 SECONDS, target = interacting_with)) machine_target.deconstruct() //Let's not substract matter - playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect + playsound(src, 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect return ITEM_INTERACT_SUCCESS - if(create_machine(target, user)) + if(!isopenturf(interacting_with)) + return NONE + if(create_machine(interacting_with, user)) return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/construction/plumbing/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers) - . = NONE if(!istype(target, /obj/machinery/duct)) - return ITEM_INTERACT_BLOCKING + return NONE var/obj/machinery/duct/duct = target if(duct.duct_layer && duct.duct_color) @@ -280,6 +281,7 @@ current_layer = GLOB.plumbing_layer_names["[duct.duct_layer]"] balloon_alert(user, "using [current_color], layer [current_layer]") return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/construction/plumbing/click_alt(mob/user) ui_interact(user) @@ -398,4 +400,3 @@ plumbing_design_types = service_design_types . = ..() - diff --git a/code/game/objects/items/rcd/RSF.dm b/code/game/objects/items/rcd/RSF.dm index 8db8c2a9116..b267ecd05cf 100644 --- a/code/game/objects/items/rcd/RSF.dm +++ b/code/game/objects/items/rcd/RSF.dm @@ -125,21 +125,18 @@ RSF return FALSE return TRUE -/obj/item/rsf/afterattack(atom/A, mob/user, proximity) +/obj/item/rsf/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(cooldown > world.time) - return - . = ..() - if(!proximity) - return . - . |= AFTERATTACK_PROCESSED_ITEM - if (!is_allowed(A)) - return . + return NONE + if (!is_allowed(interacting_with)) + return NONE if(use_matter(dispense_cost, user))//If we can charge that amount of charge, we do so and return true playsound(loc, 'sound/machines/click.ogg', 10, TRUE) - var/atom/meme = new to_dispense(get_turf(A)) + var/atom/meme = new to_dispense(get_turf(interacting_with)) to_chat(user, span_notice("[action_type] [meme.name]...")) cooldown = world.time + cooldowndelay - return . + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING ///A helper proc. checks to see if we can afford the amount of charge that is passed, and if we can docs the charge from our base, and returns TRUE. If we can't we return FALSE /obj/item/rsf/proc/use_matter(charge, mob/user) @@ -163,10 +160,7 @@ RSF ///Helper proc that iterates through all the things we are allowed to spawn on, and sees if the passed atom is one of them /obj/item/rsf/proc/is_allowed(atom/to_check) - for(var/sort in allowed_surfaces) - if(istype(to_check, sort)) - return TRUE - return FALSE + return is_type_in_list(to_check, allowed_surfaces) /obj/item/rsf/cookiesynth name = "Cookie Synthesizer" diff --git a/code/game/objects/items/rcd/RTD.dm b/code/game/objects/items/rcd/RTD.dm index de06d156a02..783cb1914d4 100644 --- a/code/game/objects/items/rcd/RTD.dm +++ b/code/game/objects/items/rcd/RTD.dm @@ -228,10 +228,16 @@ return TRUE -/obj/item/construction/rtd/afterattack(turf/open/floor/floor, mob/user) - . = ..() - if(!istype(floor) || !range_check(floor,user)) - return TRUE +/obj/item/construction/rtd/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!range_check(interacting_with, user)) + return NONE + return interact_with_atom(interacting_with, user, modifiers) + + +/obj/item/construction/rtd/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/open/floor/floor = interacting_with + if(!istype(floor)) + return NONE var/floor_designs = GLOB.floor_designs if(!istype(floor, /turf/open/floor/plating)) //we infer what floor type it is if its not the usual plating @@ -260,11 +266,11 @@ selected_design.set_direction(floor.dir) balloon_alert(user, "tile changed to [selected_design.name]") - return TRUE + return ITEM_INTERACT_SUCCESS //can't infer floor type! balloon_alert(user, "design not supported!") - return TRUE + return ITEM_INTERACT_BLOCKING var/delay = CONSTRUCTION_TIME(selected_design.cost) var/obj/effect/constructing_effect/rcd_effect = new(floor, delay, RCD_TURF) @@ -272,27 +278,27 @@ //resource sanity check before & after delay along with special effects if(!checkResource(selected_design.cost, user)) qdel(rcd_effect) - return TRUE + return ITEM_INTERACT_BLOCKING var/beam = user.Beam(floor, icon_state = "light_beam", time = delay) playsound(loc, 'sound/effects/light_flicker.ogg', 50, FALSE) if(!build_delay(user, delay, target = floor)) qdel(beam) qdel(rcd_effect) - return TRUE + return ITEM_INTERACT_BLOCKING if(!checkResource(selected_design.cost, user)) qdel(rcd_effect) - return TRUE + return ITEM_INTERACT_BLOCKING if(!useResource(selected_design.cost, user)) qdel(rcd_effect) - return TRUE + return ITEM_INTERACT_BLOCKING activate() //step 1 create tile var/obj/item/stack/tile/final_tile = selected_design.new_tile(user.drop_location()) if(QDELETED(final_tile)) //if you were standing on a stack of tiles this newly spawned tile could get merged with it cause its spawned on your location qdel(rcd_effect) balloon_alert(user, "tile got merged with the stack beneath you!") - return TRUE + return ITEM_INTERACT_SUCCESS //step 2 lay tile var/turf/open/new_turf = final_tile.place_tile(floor, user) if(new_turf) //apply infered overlays @@ -300,16 +306,21 @@ info.add_decal(new_turf) rcd_effect.end_animation() - return TRUE + return ITEM_INTERACT_SUCCESS + +/obj/item/construction/rtd/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!range_check(interacting_with, user)) + return NONE + return interact_with_atom_secondary(interacting_with, user, modifiers) -/obj/item/construction/rtd/afterattack_secondary(turf/open/floor/floor, mob/user, proximity_flag, click_parameters) - ..() - if(!istype(floor) || !range_check(floor,user)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/construction/rtd/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/open/floor/floor = interacting_with + if(!istype(floor)) + return NONE if(istype(floor, /turf/open/floor/plating)) //cant deconstruct normal plating thats the RCD's job balloon_alert(user, "nothing to deconstruct!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING var/floor_designs = GLOB.floor_designs @@ -328,7 +339,7 @@ break if(!cost) balloon_alert(user, "can't deconstruct this type!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING var/delay = DECONSTRUCTION_TIME(cost) var/obj/effect/constructing_effect/rcd_effect = new(floor, delay, RCD_DECONSTRUCT) @@ -336,21 +347,21 @@ //resource sanity check before & after delay along with beam effects if(!checkResource(cost * 0.7, user)) //no ballon alert for checkResource as it already spans an alert to chat qdel(rcd_effect) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING var/beam = user.Beam(floor, icon_state = "light_beam", time = delay) playsound(loc, 'sound/effects/light_flicker.ogg', 50, FALSE) if(!do_after(user, delay, target = floor)) qdel(beam) qdel(rcd_effect) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(!checkResource(cost * 0.7, user)) qdel(rcd_effect) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING //do the tiling if(!useResource(cost * 0.7, user)) qdel(rcd_effect) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING activate() //find & collect all decals var/list/all_decals = list() @@ -366,7 +377,7 @@ floor.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) rcd_effect.end_animation() - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /obj/item/construction/rtd/loaded matter = 350 diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm index 86a79a2198b..a648ed120ce 100644 --- a/code/game/objects/items/religion.dm +++ b/code/game/objects/items/religion.dm @@ -343,15 +343,18 @@ var/staffcooldown = 0 var/staffwait = 30 -/obj/item/godstaff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() +/obj/item/godstaff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/godstaff/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(staffcooldown + staffwait > world.time) - return - . |= AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + user.visible_message(span_notice("[user] chants deeply and waves [user.p_their()] staff!")) - if(do_after(user, 2 SECONDS, src)) - target.add_atom_colour(conversion_color, WASHABLE_COLOUR_PRIORITY) //wololo + if(do_after(user, 2 SECONDS, interacting_with)) + interacting_with.add_atom_colour(conversion_color, WASHABLE_COLOUR_PRIORITY) //wololo staffcooldown = world.time + return ITEM_INTERACT_SUCCESS /obj/item/godstaff/red icon_state = "godstaff-red" diff --git a/code/game/objects/items/robot/items/food.dm b/code/game/objects/items/robot/items/food.dm index 40166a6a8fb..6e9b2143d12 100644 --- a/code/game/objects/items/robot/items/food.dm +++ b/code/game/objects/items/robot/items/food.dm @@ -117,23 +117,39 @@ user.visible_message(span_warning("[user] shoots a high-velocity gumball at [target]!")) check_amount() -/obj/item/borg/lollipop/afterattack(atom/target, mob/living/user, proximity, click_params) +/obj/item/borg/lollipop/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) check_amount() if(iscyborg(user)) var/mob/living/silicon/robot/robot_user = user - if(!robot_user.cell.use(0.012 * STANDARD_CELL_CHARGE)) + if(!robot_user.cell?.use(0.012 * STANDARD_CELL_CHARGE)) to_chat(user, span_warning("Not enough power.")) - return AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + switch(mode) - if(DISPENSE_LOLLIPOP_MODE, DISPENSE_ICECREAM_MODE) - if(!proximity) - return AFTERATTACK_PROCESSED_ITEM - dispense(target, user) if(THROW_LOLLIPOP_MODE) - shootL(target, user, click_params) + shootL(interacting_with, user, list2params(modifiers)) + return ITEM_INTERACT_SUCCESS + if(THROW_GUMBALL_MODE) - shootG(target, user, click_params) - return ..() | AFTERATTACK_PROCESSED_ITEM + shootG(interacting_with, user, list2params(modifiers)) + return ITEM_INTERACT_SUCCESS + + return NONE + +/obj/item/borg/lollipop/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + check_amount() + if(iscyborg(user)) + var/mob/living/silicon/robot/robot_user = user + if(!robot_user.cell?.use(0.012 * STANDARD_CELL_CHARGE)) + to_chat(user, span_warning("Not enough power.")) + return ITEM_INTERACT_BLOCKING + + switch(mode) + if(DISPENSE_LOLLIPOP_MODE, DISPENSE_ICECREAM_MODE) + dispense(interacting_with, user) + return ITEM_INTERACT_SUCCESS + + return NONE /obj/item/borg/lollipop/attack_self(mob/living/user) switch(mode) diff --git a/code/game/objects/items/robot/items/generic.dm b/code/game/objects/items/robot/items/generic.dm index b9f28b4003e..c3338ecc91c 100644 --- a/code/game/objects/items/robot/items/generic.dm +++ b/code/game/objects/items/robot/items/generic.dm @@ -234,11 +234,11 @@ to_chat(user, span_notice("You toggle [src] to \"[mode]\" mode.")) update_appearance() -/obj/item/borg/charger/afterattack(obj/item/target, mob/living/silicon/robot/user, proximity_flag) - . = ..() - if(!proximity_flag || !iscyborg(user)) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/borg/charger/interact_with_atom(atom/target, mob/living/silicon/robot/user, list/modifiers) + if(!iscyborg(user)) + return NONE + + . = ITEM_INTERACT_BLOCKING if(mode == "draw") if(is_type_in_list(target, charge_machines)) var/obj/machinery/target_machine = target diff --git a/code/game/objects/items/robot/items/hypo.dm b/code/game/objects/items/robot/items/hypo.dm index cdf2d0af7f7..6f9b5672ae4 100644 --- a/code/game/objects/items/robot/items/hypo.dm +++ b/code/game/objects/items/robot/items/hypo.dm @@ -362,31 +362,29 @@ NOVA EDIT REMOVAL END */ /obj/item/reagent_containers/borghypo/borgshaker/attack(mob/M, mob/user) return //Can't inject stuff with a shaker, can we? //not with that attitude -/obj/item/reagent_containers/borghypo/borgshaker/afterattack(obj/target, mob/user, proximity) - . = ..() - if(!proximity) - return . +/obj/item/reagent_containers/borghypo/borgshaker/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!interacting_with.is_refillable()) + return NONE if(!selected_reagent) balloon_alert(user, "no reagent selected!") - return . - . |= AFTERATTACK_PROCESSED_ITEM - if(target.is_refillable()) - if(!stored_reagents.has_reagent(selected_reagent.type, amount_per_transfer_from_this)) - balloon_alert(user, "not enough [selected_reagent.name]!") - return . - if(target.reagents.total_volume >= target.reagents.maximum_volume) - balloon_alert(user, "[target] is full!") - return . - - // This is the in-between where we're storing the reagent we're going to pour into the container - // because we cannot specify a singular reagent to transfer in trans_to - var/datum/reagents/shaker = new() - stored_reagents.remove_reagent(selected_reagent.type, amount_per_transfer_from_this) - shaker.add_reagent(selected_reagent.type, amount_per_transfer_from_this, reagtemp = dispensed_temperature, no_react = TRUE) + return ITEM_INTERACT_BLOCKING + if(!stored_reagents.has_reagent(selected_reagent.type, amount_per_transfer_from_this)) + balloon_alert(user, "not enough [selected_reagent.name]!") + return ITEM_INTERACT_BLOCKING + if(interacting_with.reagents.total_volume >= interacting_with.reagents.maximum_volume) + balloon_alert(user, "it's full!") + return ITEM_INTERACT_BLOCKING + + // This is the in-between where we're storing the reagent we're going to pour into the container + // because we cannot specify a singular reagent to transfer in trans_to + var/datum/reagents/shaker = new() + stored_reagents.remove_reagent(selected_reagent.type, amount_per_transfer_from_this) + shaker.add_reagent(selected_reagent.type, amount_per_transfer_from_this, reagtemp = dispensed_temperature, no_react = TRUE) + + shaker.trans_to(interacting_with, amount_per_transfer_from_this, transferred_by = user) + balloon_alert(user, "[amount_per_transfer_from_this] unit\s poured") + return ITEM_INTERACT_SUCCESS - shaker.trans_to(target, amount_per_transfer_from_this, transferred_by = user) - balloon_alert(user, "[amount_per_transfer_from_this] unit\s poured") - return . /obj/item/reagent_containers/borghypo/condiment_synthesizer // Solids! Condiments! The borger uprising! name = "Condiment Synthesizer" @@ -427,30 +425,26 @@ NOVA EDIT REMOVAL END */ /obj/item/reagent_containers/borghypo/condiment_synthesizer/attack(mob/M, mob/user) return -/obj/item/reagent_containers/borghypo/condiment_synthesizer/afterattack(obj/target, mob/user, proximity) - . = ..() - if(!proximity) - return . +/obj/item/reagent_containers/borghypo/condiment_synthesizer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!interacting_with.is_refillable()) + return NONE if(!selected_reagent) balloon_alert(user, "no reagent selected!") - return . - . |= AFTERATTACK_PROCESSED_ITEM - if(!target.is_refillable()) - return . + return ITEM_INTERACT_BLOCKING if(!stored_reagents.has_reagent(selected_reagent.type, amount_per_transfer_from_this)) balloon_alert(user, "not enough [selected_reagent.name]!") - return . - if(target.reagents.total_volume >= target.reagents.maximum_volume) - balloon_alert(user, "[target] is full!") - return . + return ITEM_INTERACT_BLOCKING + if(interacting_with.reagents.total_volume >= interacting_with.reagents.maximum_volume) + balloon_alert(user, "it's full!") + return ITEM_INTERACT_BLOCKING // This is the in-between where we're storing the reagent we're going to pour into the container // because we cannot specify a singular reagent to transfer in trans_to var/datum/reagents/shaker = new() stored_reagents.remove_reagent(selected_reagent.type, amount_per_transfer_from_this) shaker.add_reagent(selected_reagent.type, amount_per_transfer_from_this, reagtemp = dispensed_temperature, no_react = TRUE) - shaker.trans_to(target, amount_per_transfer_from_this, transferred_by = user) + shaker.trans_to(interacting_with, amount_per_transfer_from_this, transferred_by = user) balloon_alert(user, "[amount_per_transfer_from_this] unit\s poured") - + return ITEM_INTERACT_SUCCESS /obj/item/reagent_containers/borghypo/borgshaker/hacked name = "cyborg shaker" diff --git a/code/game/objects/items/rollertable_dock.dm b/code/game/objects/items/rollertable_dock.dm index 222c8287ac9..d0067e8c675 100644 --- a/code/game/objects/items/rollertable_dock.dm +++ b/code/game/objects/items/rollertable_dock.dm @@ -26,13 +26,14 @@ user.visible_message(span_notice("[user] collects [src]."), balloon_alert(user, "you collect the [src].")) return TRUE -/obj/item/rolling_table_dock/afterattack(obj/target, mob/user , proximity) - . = ..() - var/turf/target_turf = get_turf(target) - if(!proximity || target_turf.is_blocked_turf(TRUE) || locate(/mob/living) in target_turf) - return - if(isopenturf(target)) - deploy_rolling_table(user, target) +/obj/item/rolling_table_dock/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/target_turf = get_turf(interacting_with) + if(target_turf.is_blocked_turf(TRUE) || (locate(/mob/living) in target_turf)) + return NONE + if(isopenturf(interacting_with)) + deploy_rolling_table(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/rolling_table_dock/proc/deploy_rolling_table(mob/user, atom/location) var/obj/structure/table/rolling/rable = new /obj/structure/table/rolling(location) diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 2e78f6cd65f..f72c260b73d 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -167,30 +167,27 @@ return CLICK_ACTION_SUCCESS -/obj/item/spear/explosive/afterattack(atom/movable/AM, mob/user, proximity) - . = ..() - if(!proximity || !HAS_TRAIT(src, TRAIT_WIELDED) || !istype(AM)) +/obj/item/spear/explosive/afterattack(atom/movable/target, mob/user, click_parameters) + if(!HAS_TRAIT(src, TRAIT_WIELDED) || !istype(target)) + return + if(target.resistance_flags & INDESTRUCTIBLE) //due to the lich incident of 2021, embedding grenades inside of indestructible structures is forbidden return - . |= AFTERATTACK_PROCESSED_ITEM - if(AM.resistance_flags & INDESTRUCTIBLE) //due to the lich incident of 2021, embedding grenades inside of indestructible structures is forbidden - return . - if(ismob(AM)) - var/mob/mob_target = AM + if(ismob(target)) + var/mob/mob_target = target if(mob_target.status_flags & GODMODE) //no embedding grenade phylacteries inside of ghost poly either - return . - if(iseffect(AM)) //and no accidentally wasting your moment of glory on graffiti - return . + return + if(iseffect(target)) //and no accidentally wasting your moment of glory on graffiti + return user.say("[war_cry]", forced="spear warcry") if(isliving(user)) var/mob/living/living_user = user living_user.set_resting(new_resting = TRUE, silent = TRUE, instant = TRUE) - living_user.Move(get_turf(AM)) + living_user.Move(get_turf(target)) explosive.forceMove(get_turf(living_user)) explosive.detonate(lanced_by=user) if(!QDELETED(living_user)) living_user.set_resting(new_resting = FALSE, silent = TRUE, instant = TRUE) qdel(src) - return . //GREY TIDE /obj/item/spear/grey_tide @@ -201,20 +198,18 @@ force_unwielded = 15 force_wielded = 25 -/obj/item/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/spear/grey_tide/afterattack(atom/movable/target, mob/living/user, click_parameters) user.faction |= "greytide([REF(user)])" - if(isliving(AM)) - var/mob/living/L = AM - if(istype (L, /mob/living/simple_animal/hostile/illusion)) - return - if(!L.stat && prob(50)) - var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) - M.faction = user.faction.Copy() - M.Copy_Parent(user, 100, user.health/2.5, 12, 30) - M.GiveTarget(L) + if(!isliving(target)) + return + var/mob/living/stabbed = target + if(istype(stabbed, /mob/living/simple_animal/hostile/illusion)) + return + if(stabbed.stat == CONSCIOUS && prob(50)) + var/mob/living/simple_animal/hostile/illusion/fake_clone = new(user.loc) + fake_clone.faction = user.faction.Copy() + fake_clone.Copy_Parent(user, 100, user.health/2.5, 12, 30) + fake_clone.GiveTarget(stabbed) //MILITARY /obj/item/spear/military diff --git a/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm index 39c17d2346c..e4b65e03397 100644 --- a/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm +++ b/code/game/objects/items/stacks/golem_food/golem_hand_actions.dm @@ -26,20 +26,23 @@ held_gibtonite.forceMove(src) addtimer(CALLBACK(src, PROC_REF(release_gibtonite)), GIBTONITE_GOLEM_HOLD_TIME, TIMER_DELETE_ME) -/obj/item/gibtonite_hand/afterattack(atom/target, mob/living/user, flag, params) - . = ..() +/obj/item/gibtonite_hand/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/gibtonite_hand/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if (!held_gibtonite) to_chat(user, span_warning("[src] fizzles, it was a dud!")) qdel(src) - return TRUE | AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE) held_gibtonite.forceMove(get_turf(src)) held_gibtonite.det_time = 2 SECONDS - held_gibtonite.GibtoniteReaction(user, "A [src] has targeted [target] with a thrown and primed") - held_gibtonite.throw_at(target, range = 10, speed = 3, thrower = user) + held_gibtonite.GibtoniteReaction(user, "A [src] has targeted [interacting_with] with a thrown and primed") + held_gibtonite.throw_at(interacting_with, range = 10, speed = 3, thrower = user) held_gibtonite = null qdel(src) - return TRUE | AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_SUCCESS /// Called when you can't hold it in any longer and just drop it on the ground /obj/item/gibtonite_hand/proc/release_gibtonite() @@ -69,15 +72,17 @@ /// How accurate are you? var/teleport_vary = 2 -/obj/item/bluespace_finger/afterattack(atom/target, mob/living/user, flag, params) - . = ..() - var/turf/target_turf = get_turf(target) +/obj/item/bluespace_finger/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/bluespace_finger/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/target_turf = get_turf(interacting_with) if (get_dist(target_turf, get_turf(src)) > teleport_range) balloon_alert(user, "too far!") - return TRUE | AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING if (target_turf.is_blocked_turf(exclude_mobs = TRUE)) balloon_alert(user, "no room!") - return TRUE | AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING var/obj/effect/temp_visual/teleport_golem/landing_indicator = new(target_turf) user.add_filter(BLUESPACE_GLOW_FILTER, 2, list("type" = "outline", "color" = COLOR_BRIGHT_BLUE, "alpha" = 0, "size" = 1)) @@ -89,7 +94,7 @@ qdel(landing_indicator) user.remove_filter(BLUESPACE_GLOW_FILTER) if (!did_teleport) - return + return ITEM_INTERACT_BLOCKING var/list/valid_landing_tiles = list(target_turf) for (var/turf/potential_landing in oview(teleport_vary, target_turf)) @@ -101,6 +106,7 @@ telefrag.Knockdown(2 SECONDS) do_teleport(user, final_destination, asoundin = 'sound/effects/phasein.ogg', no_effects = TRUE) qdel(src) + return ITEM_INTERACT_SUCCESS #undef GIBTONITE_GOLEM_HOLD_TIME #undef BLUESPACE_GLOW_FILTER diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 20b79bdfa71..6011e0b3961 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -63,9 +63,8 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ slapcraft_recipes = slapcraft_recipe_list,\ ) -/obj/item/stack/rods/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag) - target.attackby(src, user, click_parameters) +/obj/item/stack/rods/handle_openspace_click(turf/target, mob/user, click_parameters) + target.attackby(src, user, click_parameters) /obj/item/stack/rods/get_main_recipes() . = ..() diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index e93b8c4cea5..59196639ffe 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -341,20 +341,16 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( if(T && is_station_level(T.z)) SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name) -/obj/item/shard/afterattack(atom/A as mob|obj, mob/user, proximity) - . = ..() - if(!proximity || !(src in user)) - return - if(isturf(A)) +/obj/item/shard/afterattack(atom/target, mob/user, click_parameters) + if(!iscarbon(user) || !user.is_holding(src)) return - if(istype(A, /obj/item/storage)) + + var/mob/living/carbon/jab = user + if(jab.get_all_covered_flags() & HANDS) return - var/hit_hand = ((user.active_hand_index % 2 == 0) ? "r_" : "l_") + "arm" - if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(!H.gloves && !HAS_TRAIT(H, TRAIT_PIERCEIMMUNE)) // golems, etc - to_chat(H, span_warning("[src] cuts into your hand!")) - H.apply_damage(force*0.5, BRUTE, hit_hand, attacking_item = src) + + to_chat(user, span_warning("[src] cuts into your hand!")) + jab.apply_damage(force * 0.5, BRUTE, user.get_active_hand(), attacking_item = src) /obj/item/shard/attackby(obj/item/item, mob/user, params) if(istype(item, /obj/item/lightreplacer)) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index ef915d59b78..a0a83437545 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -223,31 +223,31 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \ user.put_in_inactive_hand(new_item) return ITEM_INTERACT_SUCCESS -/obj/item/stack/sheet/iron/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if(isopenturf(target)) - var/turf/open/build_on = target - if(!user.Adjacent(build_on)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(isgroundlessturf(build_on)) - user.balloon_alert(user, "can't place it here!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(build_on.is_blocked_turf()) - user.balloon_alert(user, "something is blocking the tile!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(get_amount() < 2) - user.balloon_alert(user, "not enough material!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!do_after(user, 4 SECONDS, build_on)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(build_on.is_blocked_turf()) - user.balloon_alert(user, "something is blocking the tile!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!use(2)) - user.balloon_alert(user, "not enough material!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - new/obj/structure/girder/displaced(build_on) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/stack/sheet/iron/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!isopenturf(interacting_with)) + return NONE + var/turf/open/build_on = interacting_with + if(!user.Adjacent(build_on)) + return ITEM_INTERACT_BLOCKING + if(isgroundlessturf(build_on)) + user.balloon_alert(user, "can't place it here!") + return ITEM_INTERACT_BLOCKING + if(build_on.is_blocked_turf()) + user.balloon_alert(user, "something is blocking the tile!") + return ITEM_INTERACT_BLOCKING + if(get_amount() < 2) + user.balloon_alert(user, "not enough material!") + return ITEM_INTERACT_BLOCKING + if(!do_after(user, 4 SECONDS, build_on)) + return ITEM_INTERACT_BLOCKING + if(build_on.is_blocked_turf()) + user.balloon_alert(user, "something is blocking the tile!") + return ITEM_INTERACT_BLOCKING + if(!use(2)) + user.balloon_alert(user, "not enough material!") + return ITEM_INTERACT_BLOCKING + new/obj/structure/girder/displaced(build_on) + return ITEM_INTERACT_SUCCESS /* * Plasteel diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index c8b46e2d281..57aa666c046 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -39,18 +39,13 @@ . = ..() . += "[span_notice("You could rip a piece off by using an empty hand.")]" -/obj/item/stack/sticky_tape/afterattack(obj/item/target, mob/living/user, proximity) - if(!proximity) - return - - if(!istype(target)) - return - - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/stack/sticky_tape/interact_with_atom(obj/item/target, mob/living/user, list/modifiers) + if(!isitem(target)) + return NONE if(target.embedding && target.embedding == conferred_embed) to_chat(user, span_warning("[target] is already coated in [src]!")) - return . + return ITEM_INTERACT_BLOCKING user.visible_message(span_notice("[user] begins wrapping [target] with [src]."), span_notice("You begin wrapping [target] with [src].")) playsound(user, 'sound/items/duct_tape_rip.ogg', 50, TRUE) @@ -63,11 +58,11 @@ to_chat(user, span_notice("You turn [target] into [O] with [src].")) QDEL_NULL(target) user.put_in_hands(O) - return . + return ITEM_INTERACT_SUCCESS if(target.embedding && target.embedding == conferred_embed) to_chat(user, span_warning("[target] is already coated in [src]!")) - return . + return ITEM_INTERACT_BLOCKING target.embedding = conferred_embed target.updateEmbedding() @@ -78,7 +73,7 @@ var/obj/item/grenade/sticky_bomb = target sticky_bomb.sticky = TRUE - return . + return ITEM_INTERACT_SUCCESS /obj/item/stack/sticky_tape/super name = "super sticky tape" diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 592348bf5c1..ab0c5ee6263 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -101,9 +101,8 @@ playsound(target_plating, 'sound/weapons/genhit.ogg', 50, TRUE) return target_plating -/obj/item/stack/tile/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag) - target.attackby(src, user, click_parameters) +/obj/item/stack/tile/handle_openspace_click(turf/target, mob/user, click_parameters) + target.attackby(src, user, click_parameters) //Grass /obj/item/stack/tile/grass diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 0bd68d9e3cd..4928f72b00f 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -103,30 +103,33 @@ /obj/item/delivery/can_be_package_wrapped() return FALSE -/obj/item/stack/package_wrap/afterattack(obj/target, mob/user, proximity) - . = ..() - if(!proximity) - return - if(!istype(target)) - return - if(target.anchored) - return - // NOVA EDIT START - Cargo borgs +/obj/item/stack/package_wrap/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) + if(isitem(storage_holder)) + // Don't insert if the target can be wrapped + var/obj/item/item = storage_holder + return !item.can_be_package_wrapped() + return TRUE + +/obj/item/stack/package_wrap/interact_with_atom(obj/interacting_with, mob/living/user, list/modifiers) + if(!isobj(interacting_with)) + return NONE + if(interacting_with.anchored) + return NONE + // NOVA EDIT ADDITION START - Cargo borgs if(!amount) - return - // NOVA EDIT END + return NONE + // NOVA EDIT ADDITION END - if(isitem(target)) - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/item = target + if(isitem(interacting_with)) + var/obj/item/item = interacting_with if(!item.can_be_package_wrapped()) balloon_alert(user, "can't be wrapped!") - return + return ITEM_INTERACT_BLOCKING if(user.is_holding(item)) if(!user.dropItemToGround(item)) - return + return ITEM_INTERACT_BLOCKING else if(!isturf(item.loc)) - return + return ITEM_INTERACT_BLOCKING if(use(1)) var/obj/item/delivery/small/parcel = new(get_turf(item.loc)) if(user.Adjacent(item)) @@ -140,15 +143,17 @@ size = min(size, 5) parcel.base_icon_state = "deliverypackage[size]" parcel.update_icon() + else + return ITEM_INTERACT_BLOCKING - else if(istype(target, /obj/structure/closet)) - var/obj/structure/closet/closet = target + else if(istype(interacting_with, /obj/structure/closet)) + var/obj/structure/closet/closet = interacting_with if(closet.opened) balloon_alert(user, "can't wrap while open!") - return + return ITEM_INTERACT_BLOCKING if(!closet.delivery_icon) //no delivery icon means unwrappable closet (e.g. body bags) balloon_alert(user, "can't wrap!") - return + return ITEM_INTERACT_BLOCKING if(use(3)) var/obj/item/delivery/big/parcel = new(get_turf(closet.loc)) parcel.base_icon_state = closet.delivery_icon @@ -165,13 +170,13 @@ // NOVA EDIT END else balloon_alert(user, "not enough paper!") - return + return ITEM_INTERACT_BLOCKING - else if(istype(target, /obj/machinery/portable_atmospherics)) - var/obj/machinery/portable_atmospherics/portable_atmospherics = target + else if(istype(interacting_with, /obj/machinery/portable_atmospherics)) + var/obj/machinery/portable_atmospherics/portable_atmospherics = interacting_with if(portable_atmospherics.anchored) balloon_alert(user, "can't wrap while anchored!") - return + return ITEM_INTERACT_BLOCKING if(use(3)) var/obj/item/delivery/big/parcel = new(get_turf(portable_atmospherics.loc)) parcel.base_icon_state = "deliverybox" @@ -182,14 +187,15 @@ portable_atmospherics.add_fingerprint(user) else balloon_alert(user, "not enough paper!") - return + return ITEM_INTERACT_BLOCKING else balloon_alert(user, "can't wrap!") - return + return ITEM_INTERACT_BLOCKING - user.visible_message(span_notice("[user] wraps [target].")) - user.log_message("has used [name] on [key_name(target)]", LOG_ATTACK, color="blue") + user.visible_message(span_notice("[user] wraps [interacting_with].")) + user.log_message("has used [name] on [key_name(interacting_with)]", LOG_ATTACK, color="blue") + return ITEM_INTERACT_SUCCESS /obj/item/stack/package_wrap/use(used, transfer = FALSE, check = TRUE) var/turf/T = get_turf(src) diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 914badf0643..e3636876189 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -155,11 +155,13 @@ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) listeningTo = null -/obj/item/storage/bag/ore/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/boulder)) - to_chat(user, span_warning("You can't fit \the [attacking_item] into \the [src]. Perhaps you should break it down first, or find an ore box.")) - return TRUE - return ..() +/obj/item/storage/bag/ore/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(istype(inserted, /obj/item/boulder)) + to_chat(user, span_warning("You can't fit [inserted] into [src]. \ + Perhaps you should break it down first, or find an ore box.")) + return FALSE + + return TRUE /obj/item/storage/bag/ore/proc/pickup_ores(mob/living/user) SIGNAL_HANDLER diff --git a/code/game/objects/items/storage/boxes/_boxes.dm b/code/game/objects/items/storage/boxes/_boxes.dm index 1861a5bd2fc..56915d8a5fc 100644 --- a/code/game/objects/items/storage/boxes/_boxes.dm +++ b/code/game/objects/items/storage/boxes/_boxes.dm @@ -51,8 +51,3 @@ balloon_alert(user, "folded") qdel(src) user.put_in_hands(result) - -/obj/item/storage/box/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/stack/package_wrap)) - return FALSE - return ..() diff --git a/code/game/objects/items/storage/boxes/food_boxes.dm b/code/game/objects/items/storage/boxes/food_boxes.dm index c49fa288eb3..45de0e58ff6 100644 --- a/code/game/objects/items/storage/boxes/food_boxes.dm +++ b/code/game/objects/items/storage/boxes/food_boxes.dm @@ -94,16 +94,16 @@ desc = "A paper sack with a crude smile etched onto the side." return ..() -/obj/item/storage/box/papersack/attackby(obj/item/attacking_item, mob/user, params) - if(istype(attacking_item, /obj/item/pen)) - var/choice = show_radial_menu(user, src , papersack_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user, attacking_item), radius = 36, require_near = TRUE) +/obj/item/storage/box/papersack/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(istype(inserted, /obj/item/pen)) + var/choice = show_radial_menu(user, src , papersack_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user, inserted), radius = 36, require_near = TRUE) if(!choice || choice == design_choice) return FALSE design_choice = choice balloon_alert(user, "modified") update_appearance() return FALSE - if(attacking_item.get_sharpness() && !contents.len) + if(inserted.get_sharpness() && !contents.len) if(design_choice == "None") user.show_message(span_notice("You cut eyeholes into [src]."), MSG_VISUAL) new /obj/item/clothing/head/costume/papersack(drop_location()) @@ -114,7 +114,7 @@ new /obj/item/clothing/head/costume/papersack/smiley(drop_location()) qdel(src) return FALSE - return ..() + return TRUE /** * check_menu: Checks if we are allowed to interact with a radial menu diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm index 8960470bb79..1f6c957234a 100644 --- a/code/game/objects/items/storage/boxes/job_boxes.dm +++ b/code/game/objects/items/storage/boxes/job_boxes.dm @@ -42,7 +42,7 @@ if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA)) new /obj/item/storage/pill_bottle/potassiodide(src) - + if(SSmapping.is_planetary() && LAZYLEN(SSmapping.multiz_levels)) new /obj/item/climbing_hook/emergency(src) @@ -178,20 +178,20 @@ desc = "A colorful cardboard box for the clown" illustration = "clown" -/obj/item/storage/box/clown/attackby(obj/item/I, mob/user, params) - if((istype(I, /obj/item/bodypart/arm/left/robot)) || (istype(I, /obj/item/bodypart/arm/right/robot))) +/obj/item/storage/box/clown/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(istype(inserted, /obj/item/bodypart/arm/left/robot) || istype(inserted, /obj/item/bodypart/arm/right/robot)) if(contents.len) //prevent accidently deleting contents balloon_alert(user, "items inside!") - return - if(!user.temporarilyRemoveItemFromInventory(I)) - return - qdel(I) - balloon_alert(user, "wheels added, honk!") + return FALSE + if(!user.temporarilyRemoveItemFromInventory(inserted)) + return FALSE + qdel(inserted) + loc.balloon_alert(user, "wheels added, honk!") var/obj/item/bot_assembly/honkbot/A = new qdel(src) user.put_in_hands(A) - else - return ..() + return FALSE + return TRUE /obj/item/storage/box/clown/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] opens [src] and gets consumed by [p_them()]! It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/game/objects/items/storage/boxes/service_boxes.dm b/code/game/objects/items/storage/boxes/service_boxes.dm index 6dc790cc495..e4d6a86553f 100644 --- a/code/game/objects/items/storage/boxes/service_boxes.dm +++ b/code/game/objects/items/storage/boxes/service_boxes.dm @@ -92,13 +92,18 @@ atom_storage.max_slots = 10 atom_storage.set_holdable(/obj/item/match) +/obj/item/storage/box/matches/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + return !istype(inserted, /obj/item/match) + /obj/item/storage/box/matches/PopulateContents() for(var/i in 1 to 10) new /obj/item/match(src) -/obj/item/storage/box/matches/attackby(obj/item/match/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/match)) - W.matchignite() +/obj/item/storage/box/matches/item_interaction(mob/living/user, obj/item/match/match, list/modifiers) + if(istype(match)) + match.matchignite() + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/storage/box/matches/update_icon_state() . = ..() diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 730f2e07c4c..4b261b0a7a9 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -23,12 +23,12 @@ register_context() -/obj/item/storage/lockbox/attackby(obj/item/W, mob/user, params) +/obj/item/storage/lockbox/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) var/locked = atom_storage.locked - if(W.GetID()) + if(inserted.GetID()) if(broken) balloon_alert(user, "broken!") - return + return FALSE if(allowed(user)) if(atom_storage.locked) atom_storage.locked = STORAGE_NOT_LOCKED @@ -42,15 +42,16 @@ icon_state = icon_closed balloon_alert(user, locked ? "locked" : "unlocked") - return + return FALSE - else - balloon_alert(user, "access denied!") - return - if(!locked) - return ..() - else + balloon_alert(user, "access denied!") + return FALSE + + if(locked) balloon_alert(user, "locked!") + return FALSE + + return TRUE /obj/item/storage/lockbox/emag_act(mob/user, obj/item/card/emag/emag_card) if(!broken) @@ -98,7 +99,6 @@ /obj/item/storage/lockbox/medal name = "medal box" desc = "A locked box used to store medals of honor." - icon = 'icons/obj/storage/case.dmi' icon_state = "medalbox+l" inhand_icon_state = "syringe_kit" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' @@ -235,7 +235,6 @@ /obj/item/storage/lockbox/order name = "order lockbox" desc = "A box used to secure small cargo orders from being looted by those who didn't order it. Yeah, cargo tech, that means you." - icon = 'icons/obj/storage/case.dmi' icon_state = "secure" icon_closed = "secure" icon_locked = "secure_locked" @@ -252,24 +251,20 @@ buyer_account = _buyer_account ADD_TRAIT(src, TRAIT_NO_MISSING_ITEM_ERROR, TRAIT_GENERIC) ADD_TRAIT(src, TRAIT_NO_MANIFEST_CONTENTS_ERROR, TRAIT_GENERIC) - - //NOVA EDIT START + //NOVA EDIT ADDITION START if(istype(buyer_account, /datum/bank_account/department)) department_purchase = TRUE department_account = buyer_account - //NOVA EDIT END + //NOVA EDIT ADDITION END -/obj/item/storage/lockbox/order/attackby(obj/item/W, mob/user, params) - var/obj/item/card/id/id_card = W.GetID() +/obj/item/storage/lockbox/order/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + var/obj/item/card/id/id_card = inserted.GetID() if(!id_card) return ..() - if(iscarbon(user)) - add_fingerprint(user) - - if((id_card.registered_account != buyer_account) && !(department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id))) //NOVA EDIT + if((id_card.registered_account != buyer_account) && !(department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id))) //NOVA EDIT CHANGE - ORIGINAL: if(id_card.registered_account != buyer_account) balloon_alert(user, "incorrect bank account!") - return + return FALSE if(privacy_lock) atom_storage.locked = STORAGE_NOT_LOCKED @@ -278,8 +273,11 @@ atom_storage.locked = STORAGE_FULLY_LOCKED icon_state = icon_closed privacy_lock = atom_storage.locked - user.visible_message(span_notice("[user] [privacy_lock ? "" : "un"]locks [src]'s privacy lock."), - span_notice("You [privacy_lock ? "" : "un"]lock [src]'s privacy lock.")) + user.visible_message( + span_notice("[user] [privacy_lock ? "" : "un"]locks [src]'s privacy lock."), + span_notice("You [privacy_lock ? "" : "un"]lock [src]'s privacy lock."), + ) + return FALSE ///screentips for lockboxes /obj/item/storage/lockbox/add_context(atom/source, list/context, obj/item/held_item, mob/user) diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index 5b09b5e0605..b1ca307e939 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -399,14 +399,13 @@ generate_items_inside(items_inside,src) //medibot assembly -/obj/item/storage/medkit/attackby(obj/item/bodypart/bodypart, mob/user, params) - if((!istype(bodypart, /obj/item/bodypart/arm/left/robot)) && (!istype(bodypart, /obj/item/bodypart/arm/right/robot))) - return ..() - +/obj/item/storage/medkit/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(!istype(inserted, /obj/item/bodypart/arm/left/robot) && !istype(inserted, /obj/item/bodypart/arm/right/robot)) + return TRUE //Making a medibot! if(contents.len >= 1) balloon_alert(user, "items inside!") - return + return FALSE ///if you add a new one don't forget to update /datum/crafting_recipe/medbot/on_craft_completion() var/obj/item/bot_assembly/medbot/medbot_assembly = new @@ -424,10 +423,11 @@ medbot_assembly.set_skin("bezerk") user.put_in_hands(medbot_assembly) medbot_assembly.balloon_alert(user, "arm added") - medbot_assembly.robot_arm = bodypart.type + medbot_assembly.robot_arm = inserted.type medbot_assembly.medkit_type = type - qdel(bodypart) + qdel(inserted) qdel(src) + return FALSE /* * Pill Bottles @@ -733,20 +733,28 @@ icon_state = "[base_icon_state][cooling ? "-working" : null]" return ..() -/obj/item/storage/organbox/attackby(obj/item/I, mob/user, params) - if(is_reagent_container(I) && I.is_open_container()) - var/obj/item/reagent_containers/RC = I +/obj/item/storage/organbox/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(is_reagent_container(inserted) && inserted.is_open_container()) + return FALSE + if(istype(inserted, /obj/item/plunger)) + return FALSE + return TRUE + +/obj/item/storage/organbox/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(is_reagent_container(tool) && tool.is_open_container()) + var/obj/item/reagent_containers/RC = tool var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this, transferred_by = user) if(units) balloon_alert(user, "[units]u transferred") - return - if(istype(I, /obj/item/plunger)) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + if(istype(tool, /obj/item/plunger)) balloon_alert(user, "plunging...") if(do_after(user, 1 SECONDS, target = src)) balloon_alert(user, "plunged") reagents.clear_reagents() - return - return ..() + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/storage/organbox/suicide_act(mob/living/carbon/user) if(HAS_TRAIT(user, TRAIT_RESISTCOLD)) //if they're immune to cold, just do the box suicide diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 97d6305eacc..d218a5edc1d 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -275,22 +275,23 @@ new /obj/item/gun_maintenance_supplies(src) //floorbot assembly -/obj/item/storage/toolbox/attackby(obj/item/stack/tile/iron/T, mob/user, params) - var/list/allowed_toolbox = list(/obj/item/storage/toolbox/emergency, //which toolboxes can be made into floorbots - /obj/item/storage/toolbox/electrical, - /obj/item/storage/toolbox/mechanical, - /obj/item/storage/toolbox/artistic, - /obj/item/storage/toolbox/syndicate) - - if(!istype(T, /obj/item/stack/tile/iron)) - ..() - return +/obj/item/storage/toolbox/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(!istype(inserted, /obj/item/stack/tile/iron)) + return TRUE + var/static/list/allowed_toolbox = list( + /obj/item/storage/toolbox/artistic, + /obj/item/storage/toolbox/electrical, + /obj/item/storage/toolbox/emergency, + /obj/item/storage/toolbox/mechanical, + /obj/item/storage/toolbox/syndicate, + ) + if(!is_type_in_list(src, allowed_toolbox) && (type != /obj/item/storage/toolbox)) - return + return TRUE if(contents.len >= 1) balloon_alert(user, "not empty!") - return - if(T.use(10)) + return FALSE + if(inserted.use(10)) var/obj/item/bot_assembly/floorbot/B = new B.toolbox = type switch(B.toolbox) @@ -308,9 +309,9 @@ B.update_appearance() B.balloon_alert(user, "tiles added") qdel(src) - else - balloon_alert(user, "needs 10 tiles!") - return + return FALSE + balloon_alert(user, "needs 10 tiles!") + return FALSE /obj/item/storage/toolbox/haunted name = "old toolbox" diff --git a/code/game/objects/items/syndie_spraycan.dm b/code/game/objects/items/syndie_spraycan.dm index 774219fa122..1b7e0d9c402 100644 --- a/code/game/objects/items/syndie_spraycan.dm +++ b/code/game/objects/items/syndie_spraycan.dm @@ -19,28 +19,27 @@ /// Set to true if we finished drawing something, this spraycan is now useless var/expended = FALSE -/obj/item/traitor_spraycan/afterattack(atom/target, mob/user, proximity, params) - . = ..() +/obj/item/traitor_spraycan/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (!check_allowed_items(interacting_with) || !isliving(user)) + return NONE + if (expended) user.balloon_alert(user, "all out of paint...") - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if (drawing_rune) user.balloon_alert(user, "already busy!") - return COMPONENT_CANCEL_ATTACK_CHAIN - - . |= AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING - if (!proximity || !check_allowed_items(target) || !isliving(user)) - return + if (isturf(interacting_with)) + try_draw_new_rune(user, interacting_with) + return ITEM_INTERACT_SUCCESS - if (isturf(target)) - try_draw_new_rune(user, target) - return COMPONENT_CANCEL_ATTACK_CHAIN + if (istype(interacting_with, /obj/effect/decal/cleanable/traitor_rune)) + try_complete_rune(user, interacting_with) + return ITEM_INTERACT_SUCCESS - if (istype(target, /obj/effect/decal/cleanable/traitor_rune)) - try_complete_rune(user, target) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /** * Attempt to draw a rune on [target_turf]. diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index c37a501271f..45c20e9908b 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -137,9 +137,9 @@ return INITIALIZE_HINT_QDEL reagents = loc.reagents //This mister is really just a proxy for the tank's reagents -/obj/item/reagent_containers/spray/mister/afterattack(obj/target, mob/user, proximity) +/obj/item/reagent_containers/spray/mister/try_spray(atom/target, mob/user) if(target.loc == loc) //Safety check so you don't fill your mister with mutagen or something and then blast yourself in the face with it - return + return FALSE return ..() //Janitor tank @@ -287,49 +287,53 @@ return return -/obj/item/extinguisher/mini/nozzle/afterattack(atom/target, mob/user) - if(AttemptRefill(target, user)) - return +/obj/item/extinguisher/mini/nozzle/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(AttemptRefill(interacting_with, user)) + return NONE if(nozzle_mode == EXTINGUISHER) return ..() - var/Adj = user.Adjacent(target) + + var/Adj = user.Adjacent(interacting_with) if(nozzle_mode == RESIN_LAUNCHER) if(Adj) - return //Safety check so you don't blast yourself trying to refill your tank + return ITEM_INTERACT_BLOCKING //Safety check so you don't blast yourself trying to refill your tank var/datum/reagents/R = reagents if(R.total_volume < 100) balloon_alert(user, "not enough water!") - return + return ITEM_INTERACT_BLOCKING if(!COOLDOWN_FINISHED(src, resin_cooldown)) balloon_alert(user, "still recharging!") - return + return ITEM_INTERACT_BLOCKING COOLDOWN_START(src, resin_cooldown, 10 SECONDS) R.remove_all(100) var/obj/effect/resin_container/resin = new (get_turf(src)) user.log_message("used Resin Launcher", LOG_GAME) playsound(src,'sound/items/syringeproj.ogg',40,TRUE) var/delay = 2 - var/datum/move_loop/loop = GLOB.move_manager.move_towards(resin, target, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) + var/datum/move_loop/loop = GLOB.move_manager.move_towards(resin, interacting_with, delay, timeout = delay * 5, priority = MOVEMENT_ABOVE_SPACE_PRIORITY) RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(resin_stop_check)) RegisterSignal(loop, COMSIG_QDELETING, PROC_REF(resin_landed)) - return + return ITEM_INTERACT_SUCCESS if(nozzle_mode == RESIN_FOAM) - if(!Adj || !isturf(target)) + if(!Adj || !isturf(interacting_with)) balloon_alert(user, "too far!") - return - for(var/S in target) - if(istype(S, /obj/effect/particle_effect/fluid/foam/metal/resin) || istype(S, /obj/structure/foamedmetal/resin)) + return ITEM_INTERACT_BLOCKING + for(var/thing in interacting_with) + if(istype(thing, /obj/effect/particle_effect/fluid/foam/metal/resin) || istype(thing, /obj/structure/foamedmetal/resin)) balloon_alert(user, "already has resin!") - return + return ITEM_INTERACT_BLOCKING if(metal_synthesis_cooldown < 5) - var/obj/effect/particle_effect/fluid/foam/metal/resin/foam = new (get_turf(target)) + var/obj/effect/particle_effect/fluid/foam/metal/resin/foam = new (get_turf(interacting_with)) foam.group.target_size = 0 metal_synthesis_cooldown++ addtimer(CALLBACK(src, PROC_REF(reduce_metal_synth_cooldown)), 10 SECONDS) - else - balloon_alert(user, "still being synthesized!") - return + return ITEM_INTERACT_SUCCESS + + balloon_alert(user, "still being synthesized!") + return ITEM_INTERACT_BLOCKING + + return NONE /obj/item/extinguisher/mini/nozzle/proc/resin_stop_check(datum/move_loop/source, result) SIGNAL_HANDLER diff --git a/code/game/objects/items/taster.dm b/code/game/objects/items/taster.dm index eaa65967f97..599b78971db 100644 --- a/code/game/objects/items/taster.dm +++ b/code/game/objects/items/taster.dm @@ -8,17 +8,12 @@ var/taste_sensitivity = 15 -/obj/item/taster/afterattack(atom/O, mob/user, proximity) - . = ..() - if(!proximity) - return - - . |= AFTERATTACK_PROCESSED_ITEM - - if(!O.reagents) - to_chat(user, span_notice("[src] cannot taste [O], since [O.p_they()] [O.p_have()] have no reagents.")) - else if(O.reagents.total_volume == 0) - to_chat(user, "[src] cannot taste [O], since [O.p_they()] [O.p_are()] empty.") +/obj/item/taster/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!interacting_with.reagents) + to_chat(user, span_notice("[src] cannot taste [interacting_with], since [interacting_with.p_they()] [interacting_with.p_have()] have no reagents.")) + else if(interacting_with.reagents.total_volume == 0) + to_chat(user, span_notice("[src] cannot taste [interacting_with], since [interacting_with.p_they()] [interacting_with.p_are()] empty.")) else - var/message = O.reagents.generate_taste_message(user, taste_sensitivity) - to_chat(user, "[src] tastes [message] in [O].") + var/message = interacting_with.reagents.generate_taste_message(user, taste_sensitivity) + to_chat(user, span_notice("[src] tastes [message] in [interacting_with].")) + return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index 4af38b86b8b..fd5c1741e17 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -134,11 +134,6 @@ . = ..() active_portal_pairs = list() -/obj/item/hand_tele/pre_attack(atom/target, mob/user, params) - if(try_dispel_portal(target, user)) - return TRUE - return ..() - /obj/item/hand_tele/proc/try_dispel_portal(atom/target, mob/user) if(is_parent_of_portal(target)) qdel(target) @@ -147,11 +142,15 @@ return TRUE return FALSE -/obj/item/hand_tele/afterattack(atom/target, mob/user) - try_dispel_portal(target, user) - . = ..() +/obj/item/hand_tele/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(try_dispel_portal(interacting_with, user)) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/hand_tele/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) -/obj/item/hand_tele/pre_attack_secondary(atom/target, mob/user, proximity_flag, click_parameters) +/obj/item/hand_tele/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) var/portal_location = last_portal_location if (isweakref(portal_location)) @@ -160,12 +159,13 @@ if (isnull(portal_location)) to_chat(user, span_warning("[src] flashes briefly. No target is locked in.")) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING try_create_portal_to(user, portal_location) + return ITEM_INTERACT_SUCCESS - - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/hand_tele/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) /obj/item/hand_tele/attack_self(mob/user) if (!can_teleport_notifies(user)) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index 5f0404c3423..41edfaea37e 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -293,16 +293,13 @@ inhand_icon_state = "supermatter_tongs[sliver ? "_loaded" : null]" return ..() -/obj/item/hemostat/supermatter/afterattack(atom/O, mob/user, proximity) - . = ..() +/obj/item/hemostat/supermatter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!sliver) - return - if (!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(ismovable(O) && O != sliver) - Consume(O, user) - return . + return NONE + if(ismovable(interacting_with) && interacting_with != sliver) + Consume(interacting_with, user) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/hemostat/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins if(sliver) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 7d2b7fcb802..87ca1486c0c 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -135,6 +135,11 @@ target.cut_overlay(sparks) /obj/item/weldingtool/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!status && interacting_with.is_refillable()) + reagents.trans_to(interacting_with, reagents.total_volume, transferred_by = user) + to_chat(user, span_notice("You empty [src]'s fuel tank into [interacting_with].")) + update_appearance() + return ITEM_INTERACT_SUCCESS if(!ishuman(interacting_with)) return NONE if(user.combat_mode) @@ -162,29 +167,18 @@ item_heal_robotic(attacked_humanoid, user, 15, 0) return ITEM_INTERACT_SUCCESS -/obj/item/weldingtool/afterattack(atom/attacked_atom, mob/user, proximity) - . = ..() - if(!proximity) +/obj/item/weldingtool/afterattack(atom/target, mob/user, click_parameters) + if(!isOn()) return - - if(isOn() && ismovable(attacked_atom)) - use(1) - var/turf/location = get_turf(user) - location.hotspot_expose(700, 50, 1) - . |= AFTERATTACK_PROCESSED_ITEM - if (!QDELETED(attacked_atom) && isliving(attacked_atom)) // can't ignite something that doesn't exist - var/mob/living/attacked_mob = attacked_atom - if(attacked_mob.ignite_mob()) - message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)]") - user.log_message("set [key_name(attacked_mob)] on fire with [src].", LOG_ATTACK) - - if(!status && attacked_atom.is_refillable()) - . |= AFTERATTACK_PROCESSED_ITEM - reagents.trans_to(attacked_atom, reagents.total_volume, transferred_by = user) - to_chat(user, span_notice("You empty [src]'s fuel tank into [attacked_atom].")) - update_appearance() - - return . + use(1) + var/turf/location = get_turf(user) + location.hotspot_expose(700, 50, 1) + if(QDELETED(target) || !isliving(target)) // can't ignite something that doesn't exist + return + var/mob/living/attacked_mob = target + if(attacked_mob.ignite_mob()) + message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(attacked_mob)] on fire with [src] at [AREACOORD(user)]") + user.log_message("set [key_name(attacked_mob)] on fire with [src].", LOG_ATTACK) /obj/item/weldingtool/attack_self(mob/user) if(src.reagents.has_reagent(/datum/reagent/toxin/plasma)) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index faf8862e116..1c82bffbf7c 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -51,21 +51,21 @@ /obj/item/toy/waterballoon/attack(mob/living/carbon/human/M, mob/user) return -/obj/item/toy/waterballoon/afterattack(atom/A as mob|obj, mob/user, proximity) - . = ..() - if(!proximity) - return - if (istype(A, /obj/structure/reagent_dispensers)) - var/obj/structure/reagent_dispensers/RD = A - if(RD.reagents.total_volume <= 0) - to_chat(user, span_warning("[RD] is empty.")) - else if(reagents.total_volume >= 10) - to_chat(user, span_warning("[src] is full.")) - else - A.reagents.trans_to(src, 10, transferred_by = user) - to_chat(user, span_notice("You fill the balloon with the contents of [A].")) - desc = "A translucent balloon with some form of liquid sloshing around in it." - update_appearance() +/obj/item/toy/waterballoon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (!istype(interacting_with, /obj/structure/reagent_dispensers)) + return NONE + var/obj/structure/reagent_dispensers/RD = interacting_with + if(RD.reagents.total_volume <= 0) + to_chat(user, span_warning("[RD] is empty.")) + else if(reagents.total_volume >= 10) + to_chat(user, span_warning("[src] is full.")) + else + interacting_with.reagents.trans_to(src, 10, transferred_by = user) + to_chat(user, span_notice("You fill the balloon with the contents of [interacting_with].")) + desc = "A translucent balloon with some form of liquid sloshing around in it." + update_appearance() + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/toy/waterballoon/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/reagent_containers/cup)) @@ -524,23 +524,21 @@ else return ..() -/obj/item/toy/gun/afterattack(atom/target as mob|obj|turf|area, mob/user, flag) - . = ..() - if (flag) - return - if (!ISADVANCEDTOOLUSER(user)) +/obj/item/toy/gun/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ISADVANCEDTOOLUSER(user)) to_chat(user, span_warning("You don't have the dexterity to do this!")) - return + return ITEM_INTERACT_BLOCKING src.add_fingerprint(user) if (src.bullets < 1) user.show_message(span_warning("*click*"), MSG_AUDIBLE) playsound(src, 'sound/weapons/gun/revolver/dry_fire.ogg', 30, TRUE) - return + return ITEM_INTERACT_SUCCESS playsound(user, 'sound/weapons/gun/revolver/shot.ogg', 100, TRUE) src.bullets-- - user.visible_message(span_danger("[user] fires [src] at [target]!"), \ - span_danger("You fire [src] at [target]!"), \ + user.visible_message(span_danger("[user] fires [src] at [interacting_with]!"), \ + span_danger("You fire [src] at [interacting_with]!"), \ span_hear("You hear a gunshot!")) + return ITEM_INTERACT_SUCCESS /obj/item/toy/ammo/gun name = "capgun ammo" @@ -1055,11 +1053,9 @@ throwforce = 20 //the same damage as a disabler shot damtype = STAMINA //maybe someday we can add stuffing rocks (or perhaps ore?) into snowballs to make them deal brute damage -/obj/item/toy/snowball/afterattack(atom/target as mob|obj|turf|area, mob/user) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - if(user.dropItemToGround(src)) - throw_at(target, throw_range, throw_speed) +/obj/item/toy/snowball/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + user.throw_item(interacting_with) + return ITEM_INTERACT_SUCCESS /obj/item/toy/snowball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) diff --git a/code/game/objects/items/v8_engine.dm b/code/game/objects/items/v8_engine.dm index c3e5f311461..c75f1ebc13a 100644 --- a/code/game/objects/items/v8_engine.dm +++ b/code/game/objects/items/v8_engine.dm @@ -70,34 +70,33 @@ AddComponent(/datum/component/two_handed, force_unwielded = 12, force_wielded = 22, attacksound = active_hitsound) RegisterSignals(src, list(COMSIG_ITEM_DROPPED, COMSIG_MOVABLE_PRE_THROW, COMSIG_ITEM_ATTACK_SELF), PROC_REF(reset_charges)) -/obj/item/house_edge/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() +/obj/item/house_edge/afterattack(atom/target, mob/user, click_parameters) if(!ismob(target)) return if(HAS_TRAIT(src, TRAIT_WIELDED)) //Add a fire charge to a max of 3, updates icon_state. fire_charges = clamp((fire_charges + 1), HOUSE_EDGE_ICONS_MIN, HOUSE_EDGE_ICONS_MAX) - icon_state = "house_edge[fire_charges]" COOLDOWN_RESET(src, fire_charge_cooldown) else //Lose a fire charge to a min of 0, updates icon_state. fire_charges = clamp((fire_charges - 1), HOUSE_EDGE_ICONS_MIN, HOUSE_EDGE_ICONS_MAX) - icon_state = "house_edge[fire_charges]" do_sparks(number = 0, cardinal_only = TRUE, source = src) + update_appearance(UPDATE_ICON_STATE) -/obj/item/house_edge/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) +/obj/item/house_edge/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, fire_charge_cooldown)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(fire_charges <= 0) balloon_alert(user, "no fire charges!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - user.throw_at(target = get_turf(target), range = 2 * fire_charges, speed = 5, thrower = user, spin = FALSE, gentle = FALSE, quickstart = TRUE) + return ITEM_INTERACT_BLOCKING + user.throw_at(target = get_turf(interacting_with), range = 2 * fire_charges, speed = 5, thrower = user, spin = FALSE, gentle = FALSE, quickstart = TRUE) COOLDOWN_START(src, fire_charge_cooldown, DASH_COOLDOWN) reset_charges(on_dash = TRUE) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /obj/item/house_edge/update_icon_state() inhand_icon_state = HAS_TRAIT(src, TRAIT_WIELDED) ? "house_edge1" : "house_edge0" + icon_state = "house_edge[fire_charges]" return ..() /obj/item/house_edge/proc/reset_charges(on_dash = FALSE) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index bb87ab7fd84..3eea2400aa2 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -951,15 +951,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 )) -/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag || HAS_TRAIT(user, TRAIT_PACIFISM)) - return - +/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, click_parameters) if(is_type_in_typecache(target, splattable)) - new /obj/effect/decal/cleanable/insectguts(target.drop_location()) to_chat(user, span_warning("You easily splat [target].")) if(isliving(target)) + new /obj/effect/decal/cleanable/insectguts(target.drop_location()) var/mob/living/bug = target bug.investigate_log("has been splatted by a flyswatter.", INVESTIGATE_DEATHS) bug.gib(DROP_ALL_REMAINS) @@ -1089,24 +1085,18 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 if(prob(final_block_chance * (HAS_TRAIT(src, TRAIT_WIELDED) ? 2 : 1))) owner.visible_message(span_danger("[owner] parries [attack_text] with [src]!")) return TRUE + return FALSE -/obj/item/highfrequencyblade/attack(mob/living/target, mob/living/user, params) - if(!HAS_TRAIT(src, TRAIT_WIELDED) || HAS_TRAIT(src, TRAIT_PACIFISM)) - return ..() - slash(target, user, params) - -/obj/item/highfrequencyblade/attack_atom(atom/target, mob/living/user, params) - if(HAS_TRAIT(src, TRAIT_WIELDED)) - return - return ..() - -/obj/item/highfrequencyblade/afterattack(atom/target, mob/user, proximity_flag, params) +/obj/item/highfrequencyblade/pre_attack(atom/A, mob/living/user, params) + . = ..() + if(.) + return . if(!HAS_TRAIT(src, TRAIT_WIELDED)) - return ..() - if(!proximity_flag || !(isclosedturf(target) || isitem(target) || ismachinery(target) || isstructure(target) || isvehicle(target))) - return - slash(target, user, params) - return AFTERATTACK_PROCESSED_ITEM + return . // Default attack + if(isliving(A) && HAS_TRAIT(src, TRAIT_PACIFISM)) + return . // Default attack (ultimately nothing) + + return slash(A, user, params) /// triggered on wield of two handed item /obj/item/highfrequencyblade/proc/on_wield(obj/item/source, mob/user) @@ -1141,14 +1131,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 living_target.investigate_log("has been gibbed by [src].", INVESTIGATE_DEATHS) living_target.gib(DROP_ALL_REMAINS) log_combat(user, living_target, "gibbed", src) + return TRUE else if(target.uses_integrity) target.take_damage(force*damage_mod*3, BRUTE, MELEE, FALSE, null, 50) + return TRUE else if(iswallturf(target) && prob(force*damage_mod*0.5)) var/turf/closed/wall/wall_target = target wall_target.dismantle_wall() + return TRUE else if(ismineralturf(target) && prob(force*damage_mod)) var/turf/closed/mineral/mineral_target = target mineral_target.gets_drilled() + return TRUE + return FALSE /obj/effect/temp_visual/slash icon_state = "highfreq_slash" diff --git a/code/game/objects/items/wizard_weapons.dm b/code/game/objects/items/wizard_weapons.dm index 8c2677d3ee3..34676e18bf0 100644 --- a/code/game/objects/items/wizard_weapons.dm +++ b/code/game/objects/items/wizard_weapons.dm @@ -39,9 +39,6 @@ icon_state = "[base_icon_state]0" return ..() -/obj/item/singularityhammer/proc/recharge() - charged = TRUE - /obj/item/singularityhammer/proc/vortex(turf/pull, mob/wielder) for(var/atom/X in orange(5,pull)) if(ismovable(X)) @@ -59,22 +56,19 @@ step_towards(A,pull) step_towards(A,pull) -/obj/item/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/living/user, proximity) - . = ..() - if(!proximity) +/obj/item/singularityhammer/afterattack(atom/target, mob/user, click_parameters) + if(!HAS_TRAIT(src, TRAIT_WIELDED)) return - . |= AFTERATTACK_PROCESSED_ITEM - if(HAS_TRAIT(src, TRAIT_WIELDED)) - if(charged) - charged = FALSE - if(isliving(A)) - var/mob/living/Z = A - Z.take_bodypart_damage(20,0) - playsound(user, 'sound/weapons/marauder.ogg', 50, TRUE) - var/turf/target = get_turf(A) - vortex(target,user) - addtimer(CALLBACK(src, PROC_REF(recharge)), 10 SECONDS) - return . + if(!charged) + return + + charged = FALSE + if(isliving(target)) + var/mob/living/smacked = target + smacked.take_bodypart_damage(20, 0) + playsound(user, 'sound/weapons/marauder.ogg', 50, TRUE) + vortex(get_turf(target), user) + addtimer(VARSET_CALLBACK(src, charged, TRUE), 10 SECONDS) /obj/item/mjollnir name = "Mjollnir" diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index c3555b8802d..a5b37929750 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -372,17 +372,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/chair/stool/bar, 0) return TRUE return FALSE -/obj/item/chair/afterattack(atom/target, mob/living/carbon/user, proximity) - . = ..() - if(!proximity) +/obj/item/chair/afterattack(atom/target, mob/user, click_parameters) + if(!prob(break_chance)) return - if(prob(break_chance)) - user.visible_message(span_danger("[user] smashes \the [src] to pieces against \the [target]")) - if(iscarbon(target)) - var/mob/living/carbon/C = target - if(C.health < C.maxHealth*0.5) - C.Paralyze(20) - smash(user) + user.visible_message(span_danger("[user] smashes [src] to pieces against [target]")) + if(iscarbon(target)) + var/mob/living/carbon/C = target + if(C.health < C.maxHealth*0.5) + C.Paralyze(20) + smash(user) /obj/item/chair/greyscale material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index e6c0ef7504f..f98b29e1932 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -988,7 +988,7 @@ GLOBAL_LIST_EMPTY(roundstart_station_closets) // tk grab then use on self /obj/structure/closet/attack_self_tk(mob/user) if(attack_hand(user)) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /obj/structure/closet/verb/verb_toggleopen() set src in view(1) diff --git a/code/game/objects/structures/deployable_turret.dm b/code/game/objects/structures/deployable_turret.dm index b2bb5fe51c5..f24df392ded 100644 --- a/code/game/objects/structures/deployable_turret.dm +++ b/code/game/objects/structures/deployable_turret.dm @@ -259,11 +259,11 @@ M.attacked_by(src, user) add_fingerprint(user) -/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user, flag, params) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - var/modifiers = params2list(params) +/obj/item/gun_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/obj/machinery/deployable_turret/E = user.buckled - E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, targeted_atom, modifiers) - E.direction_track(user, targeted_atom) - E.checkfire(targeted_atom, user) + E.calculated_projectile_vars = calculate_projectile_angle_and_pixel_offsets(user, interacting_with, modifiers) + E.direction_track(user, interacting_with) + E.checkfire(interacting_with, user) + +/obj/item/gun_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) diff --git a/code/game/objects/structures/plaques/_plaques.dm b/code/game/objects/structures/plaques/_plaques.dm index 4a1684434dc..1277869dbf6 100644 --- a/code/game/objects/structures/plaques/_plaques.dm +++ b/code/game/objects/structures/plaques/_plaques.dm @@ -185,11 +185,10 @@ return return ..() -/obj/item/plaque/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!iswallturf(target) || !proximity) - return - var/turf/target_turf = target +/obj/item/plaque/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!iswallturf(interacting_with)) + return NONE + var/turf/target_turf = interacting_with var/turf/user_turf = get_turf(user) var/obj/structure/plaque/placed_plaque = new plaque_path(user_turf) //We place the plaque on the turf the user is standing, and pixel shift it to the target wall, as below. //This is to mimic how signs and other wall objects are usually placed by mappers, and so they're only visible from one side of a wall. @@ -213,3 +212,4 @@ placed_plaque.update_integrity(get_integrity()) placed_plaque.setDir(dir) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index b8709334c37..eefbe49ef32 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -209,11 +209,10 @@ return return ..() -/obj/item/sign/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!iswallturf(target) || !proximity) - return - var/turf/target_turf = target +/obj/item/sign/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!iswallturf(interacting_with)) + return NONE + var/turf/target_turf = interacting_with var/turf/user_turf = get_turf(user) var/obj/structure/sign/placed_sign = new sign_path(user_turf) //We place the sign on the turf the user is standing, and pixel shift it to the target wall, as below. //This is to mimic how signs and other wall objects are usually placed by mappers, and so they're only visible from one side of a wall. @@ -233,6 +232,7 @@ placed_sign.setDir(dir) placed_sign.find_and_hang_on_wall(TRUE, placed_sign.knock_down_callback) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/sign/welder_act(mob/living/user, obj/item/I) . = ..() diff --git a/code/game/objects/structures/training_machine.dm b/code/game/objects/structures/training_machine.dm index c2f4d3a18ae..bed4c4805cc 100644 --- a/code/game/objects/structures/training_machine.dm +++ b/code/game/objects/structures/training_machine.dm @@ -360,12 +360,17 @@ ///Number of hits made since the Lap button (alt-click) was last pushed var/lap_hits = 0 -/obj/item/training_toolbox/afterattack(atom/target, mob/living/user, proximity) +/obj/item/training_toolbox/pre_attack(atom/A, mob/living/user, params) . = ..() - if (!proximity || target == user || !user.combat_mode) - return - if (check_hit(target)) - user.changeNext_move(CLICK_CD_MELEE) + if(.) + return . + if(A == user || !user.combat_mode) + return . + if(!check_hit(A)) + return . + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(A) + return TRUE /** * Check if we should increment the hit counter diff --git a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm index 2fb5d526045..d3f162f5fb5 100644 --- a/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm +++ b/code/modules/antagonists/abductor/equipment/gear/abductor_items.dm @@ -63,14 +63,8 @@ return ITEM_INTERACT_SUCCESS -/obj/item/abductor/gizmo/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - // Proximity is already handled via the interact_with_atom proc - if(proximity_flag) - return - - . |= AFTERATTACK_PROCESSED_ITEM - interact_with_atom(target, user) +/obj/item/abductor/gizmo/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) /obj/item/abductor/gizmo/proc/scan(atom/target, mob/living/user) if(ishuman(target)) @@ -117,14 +111,8 @@ radio_off(interacting_with, user) return ITEM_INTERACT_SUCCESS -/obj/item/abductor/silencer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - // Proximity is already handled via the interact_with_atom proc - if(proximity_flag) - return - - . |= AFTERATTACK_PROCESSED_ITEM - interact_with_atom(target, user) +/obj/item/abductor/silencer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) /obj/item/abductor/silencer/proc/radio_off(atom/target, mob/living/user) if( !(user in (viewers(7,target))) ) @@ -167,17 +155,19 @@ icon_state = "mind_device_message" to_chat(user, span_notice("You switch the device to [mode == MIND_DEVICE_MESSAGE? "TRANSMISSION": "COMMAND"] MODE")) -/obj/item/abductor/mind_device/afterattack(atom/target, mob/living/user, flag, params) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/abductor/mind_device/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/abductor/mind_device/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ScientistCheck(user)) - return + return ITEM_INTERACT_BLOCKING switch(mode) if(MIND_DEVICE_CONTROL) - mind_control(target, user) + mind_control(interacting_with, user) if(MIND_DEVICE_MESSAGE) - mind_message(target, user) + mind_message(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/abductor/mind_device/proc/mind_control(atom/target, mob/living/user) if(iscarbon(target)) diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index d82ec1d1318..1c4fa8c501c 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -218,17 +218,13 @@ effectiveness = 80, \ ) -/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/melee/arm_blade/afterattack(atom/target, mob/user, click_parameters) if(istype(target, /obj/structure/table)) - var/obj/structure/table/T = target - T.deconstruct(FALSE) + var/obj/smash = target + smash.deconstruct(FALSE) else if(istype(target, /obj/machinery/computer)) - var/obj/machinery/computer/C = target - C.attack_alien(user) //muh copypasta + target.attack_alien(user) //muh copypasta else if(istype(target, /obj/machinery/door/airlock)) var/obj/machinery/door/airlock/opening = target diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index d62fdd5bf5f..c93c0907c0d 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -376,7 +376,7 @@ return ..() /obj/item/melee/blood_magic/attack_self(mob/living/user) - afterattack(user, user, TRUE) + cast_spell(user, user) /obj/item/melee/blood_magic/attack(mob/living/M, mob/living/carbon/user) if(!iscarbon(user) || !IS_CULTIST(user)) @@ -387,16 +387,25 @@ SSblackbox.record_feedback("tally", "cult_spell_invoke", 1, "[name]") M.lastattacker = user.real_name M.lastattackerckey = user.ckey + cast_spell(M, user) -/obj/item/melee/blood_magic/afterattack(atom/target, mob/living/carbon/user, proximity) - . = ..() +/obj/item/melee/blood_magic/attack_atom(atom/attacked_atom, mob/living/user, params) + if(!iscarbon(user) || !IS_CULTIST(user)) + uses = 0 + qdel(src) + return + log_combat(user, attacked_atom, "used a cult spell on", source.name, "") + SSblackbox.record_feedback("tally", "cult_spell_invoke", 1, "[name]") + cast_spell(attacked_atom, user) + +/obj/item/melee/blood_magic/proc/cast_spell(atom/target, mob/living/carbon/user) if(invocation) user.whisper(invocation, language = /datum/language/common) if(health_cost) if(user.active_hand_index == 1) - user.apply_damage(health_cost, BRUTE, BODY_ZONE_L_ARM) + user.apply_damage(health_cost, BRUTE, BODY_ZONE_L_ARM, wound_bonus = CANT_WOUND) else - user.apply_damage(health_cost, BRUTE, BODY_ZONE_R_ARM) + user.apply_damage(health_cost, BRUTE, BODY_ZONE_R_ARM, wound_bonus = CANT_WOUND) if(uses <= 0) qdel(src) else if(source) @@ -411,51 +420,49 @@ color = RUNE_COLOR_RED invocation = "Fuu ma'jin!" -/obj/item/melee/blood_magic/stun/afterattack(mob/living/target, mob/living/carbon/user, proximity) - if(!isliving(target) || !proximity) - return - if(IS_CULTIST(target)) +/obj/item/melee/blood_magic/stun/cast_spell(mob/living/target, mob/living/carbon/user) + if(!istype(target) || IS_CULTIST(target)) return var/datum/antagonist/cult/cultist = IS_CULTIST(user) - if(!isnull(cultist)) - var/datum/team/cult/cult_team = cultist.get_team() - var/effect_coef = 1 - (cult_team.cult_risen ? 0.4 : 0) - (cult_team.cult_ascendent ? 0.5 : 0) - user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \ - span_cult_italic("You attempt to stun [target] with the spell!")) - user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) - if(IS_HERETIC(target)) - to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!")) - to_chat(target, span_warning("You are protected by your faith to the Forgotten Gods.")) - var/old_color = target.color - target.color = rgb(0, 128, 0) - animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN) - - // NOVA EDIT START - if(IS_CLOCK(target)) - to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the heretic Ratvar!")) - to_chat(target, span_warning("You are protected by your faith to Ratvar!")) - var/old_color = target.color - target.color = rgb(190, 135, 0) - animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN) - // NOVA EDIT END - - else if(target.can_block_magic()) - to_chat(user, span_warning("The spell had no effect!")) - else - to_chat(user, span_cult_italic("In a brilliant flash of red, [target] falls to the ground!")) - target.Paralyze(16 SECONDS * effect_coef) - target.flash_act(1, TRUE) - if(issilicon(target)) - var/mob/living/silicon/silicon_target = target - silicon_target.emp_act(EMP_HEAVY) - else if(iscarbon(target)) - var/mob/living/carbon/carbon_target = target - carbon_target.adjust_silence(12 SECONDS * effect_coef) - carbon_target.adjust_stutter(30 SECONDS * effect_coef) - carbon_target.adjust_timed_status_effect(30 SECONDS * effect_coef, /datum/status_effect/speech/slurring/cult) - carbon_target.set_jitter_if_lower(30 SECONDS * effect_coef) - uses-- - ..() + var/datum/team/cult/cult_team = cultist.get_team() + var/effect_coef = 1 - (cult_team.cult_risen ? 0.4 : 0) - (cult_team.cult_ascendent ? 0.5 : 0) + user.visible_message( + span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), + span_cult_italic("You attempt to stun [target] with the spell!"), + visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE, + ) + user.mob_light(range = 1.1, power = 2, color = LIGHT_COLOR_BLOOD_MAGIC, duration = 0.2 SECONDS) + if(IS_HERETIC(target)) + to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the Forgotten Gods!")) + to_chat(target, span_warning("You are protected by your faith to the Forgotten Gods.")) + var/old_color = target.color + target.color = rgb(0, 128, 0) + animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN) + // NOVA EDIT ADDITION START + if(IS_CLOCK(target)) + to_chat(user, span_warning("Some force greater than you intervenes! [target] is protected by the heretic Ratvar!")) + to_chat(target, span_warning("You are protected by your faith to Ratvar!")) + var/old_color = target.color + target.color = rgb(190, 135, 0) + animate(target, color = old_color, time = 1 SECONDS, easing = EASE_IN) + // NOVA EDIT ADDITION END + else if(target.can_block_magic()) + to_chat(user, span_warning("The spell had no effect!")) + else + to_chat(user, span_cult_italic("In a brilliant flash of red, [target] falls to the ground!")) + target.Paralyze(16 SECONDS * effect_coef) + target.flash_act(1, TRUE) + if(issilicon(target)) + var/mob/living/silicon/silicon_target = target + silicon_target.emp_act(EMP_HEAVY) + else if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + carbon_target.adjust_silence(12 SECONDS * effect_coef) + carbon_target.adjust_stutter(30 SECONDS * effect_coef) + carbon_target.adjust_timed_status_effect(30 SECONDS * effect_coef, /datum/status_effect/speech/slurring/cult) + carbon_target.set_jitter_if_lower(30 SECONDS * effect_coef) + uses-- + return ..() //Teleportation /obj/item/melee/blood_magic/teleport @@ -464,47 +471,50 @@ desc = "Will teleport a cultist to a teleport rune on contact." invocation = "Sas'so c'arta forbici!" -/obj/item/melee/blood_magic/teleport/afterattack(atom/target, mob/living/carbon/user, proximity) - var/mob/mob_target = target - if(istype(mob_target) && !IS_CULTIST(mob_target) || !proximity) - to_chat(user, span_warning("You can only teleport adjacent cultists with this spell!")) +/obj/item/melee/blood_magic/teleport/cast_spell(mob/living/target, mob/living/carbon/user) + if(!istype(target) || !IS_CULTIST(target)) + to_chat(user, span_warning("You can only teleport cultists with this spell!")) return - if(IS_CULTIST(user)) - var/list/potential_runes = list() - var/list/teleportnames = list() - for(var/obj/effect/rune/teleport/teleport_rune as anything in GLOB.teleport_runes) - potential_runes[avoid_assoc_duplicate_keys(teleport_rune.listkey, teleportnames)] = teleport_rune - - if(!length(potential_runes)) - to_chat(user, span_warning("There are no valid runes to teleport to!")) - return - var/turf/T = get_turf(src) - if(is_away_level(T.z)) - to_chat(user, span_cult_italic("You are not in the right dimension!")) - return + var/list/potential_runes = list() + var/list/teleportnames = list() + for(var/obj/effect/rune/teleport/teleport_rune as anything in GLOB.teleport_runes) + potential_runes[avoid_assoc_duplicate_keys(teleport_rune.listkey, teleportnames)] = teleport_rune - var/input_rune_key = tgui_input_list(user, "Rune to teleport to", "Teleportation Target", potential_runes) //we know what key they picked - if(isnull(input_rune_key)) - return - if(isnull(potential_runes[input_rune_key])) - to_chat(user, span_warning("You must pick a valid rune!")) - return - var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to? - if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune || !proximity) - return - var/turf/dest = get_turf(actual_selected_rune) - if(dest.is_blocked_turf(TRUE)) - to_chat(user, span_warning("The target rune is blocked. You cannot teleport there.")) - return - uses-- - var/turf/origin = get_turf(user) - var/mob/living/L = target - if(do_teleport(L, dest, channel = TELEPORT_CHANNEL_CULT)) - origin.visible_message(span_warning("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!"), \ - span_cult_italic("You speak the words of the talisman and find yourself somewhere else!"), "You hear a sharp crack.") - dest.visible_message(span_warning("There is a boom of outrushing air as something appears above the rune!"), null, "You hear a boom.") - ..() + if(!length(potential_runes)) + to_chat(user, span_warning("There are no valid runes to teleport to!")) + return + var/turf/T = get_turf(src) + if(is_away_level(T.z)) + to_chat(user, span_cult_italic("You are not in the right dimension!")) + return + var/input_rune_key = tgui_input_list(user, "Rune to teleport to", "Teleportation Target", potential_runes) //we know what key they picked + if(isnull(input_rune_key)) + return + if(isnull(potential_runes[input_rune_key])) + to_chat(user, span_warning("You must pick a valid rune!")) + return + var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to? + if(QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated() || !actual_selected_rune) + return + var/turf/dest = get_turf(actual_selected_rune) + if(dest.is_blocked_turf(TRUE)) + to_chat(user, span_warning("The target rune is blocked. You cannot teleport there.")) + return + uses-- + var/turf/origin = get_turf(user) + if(do_teleport(target, dest, channel = TELEPORT_CHANNEL_CULT)) + origin.visible_message( + span_warning("Dust flows from [user]'s hand, and [user.p_they()] disappear[user.p_s()] with a sharp crack!"), + span_cult_italic("You speak the words of the talisman and find yourself somewhere else!"), + span_hear("You hear a sharp crack."), + ) + dest.visible_message( + span_warning("There is a boom of outrushing air as something appears above the rune!"), + null, + span_hear("You hear a boom."), + ) + return ..() //Shackles /obj/item/melee/blood_magic/shackles @@ -513,15 +523,17 @@ invocation = "In'totum Lig'abis!" color = COLOR_BLACK // black -/obj/item/melee/blood_magic/shackles/afterattack(atom/target, mob/living/carbon/user, proximity) - if(IS_CULTIST(user) && iscarbon(target) && proximity) - var/mob/living/carbon/C = target - if(C.canBeHandcuffed()) - CuffAttack(C, user) - else - user.visible_message(span_cult_italic("This victim doesn't have enough arms to complete the restraint!")) - return - ..() +/obj/item/melee/blood_magic/shackles/cast_spell(atom/target, mob/living/carbon/user) + if(!iscarbon(target)) + return + var/mob/living/carbon/C = target + if(IS_CULTIST(C)) + return + if(!C.canBeHandcuffed()) + user.visible_message(span_cult_italic("This victim doesn't have enough arms to complete the restraint!")) + return + CuffAttack(C, user) + return ..() /obj/item/melee/blood_magic/shackles/proc/CuffAttack(mob/living/carbon/C, mob/living/user) if(!C.handcuffed) @@ -574,90 +586,95 @@ Purified soulstones (and any shades inside) into cultist soulstones\n Airlocks into brittle runed airlocks after a delay (harm intent)"} -/obj/item/melee/blood_magic/construction/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(proximity_flag && IS_CULTIST(user)) - if(channeling) - to_chat(user, span_cult_italic("You are already invoking twisted construction!")) +/obj/item/melee/blood_magic/construction/cast_spell(atom/target, mob/living/carbon/user) + if(channeling) + to_chat(user, span_cult_italic("You are already invoking twisted construction!")) + return + + var/turf/T = get_turf(target) + if(istype(target, /obj/item/stack/sheet/iron)) + var/obj/item/stack/sheet/candidate = target + if(!candidate.use(IRON_TO_CONSTRUCT_SHELL_CONVERSION)) + to_chat(user, span_warning("You need [IRON_TO_CONSTRUCT_SHELL_CONVERSION] iron to produce a construct shell!")) return - . |= AFTERATTACK_PROCESSED_ITEM - var/turf/T = get_turf(target) - if(istype(target, /obj/item/stack/sheet/iron)) - var/obj/item/stack/sheet/candidate = target - if(candidate.use(IRON_TO_CONSTRUCT_SHELL_CONVERSION)) - uses-- - to_chat(user, span_warning("A dark cloud emanates from your hand and swirls around the iron, twisting it into a construct shell!")) - new /obj/structure/constructshell(T) - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - else - to_chat(user, span_warning("You need [IRON_TO_CONSTRUCT_SHELL_CONVERSION] iron to produce a construct shell!")) - return - else if(istype(target, /obj/item/stack/sheet/plasteel)) - var/obj/item/stack/sheet/plasteel/candidate = target - var/quantity = candidate.amount - if(candidate.use(quantity)) - uses -- - new /obj/item/stack/sheet/runed_metal(T,quantity) - to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!")) - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - else if(istype(target,/mob/living/silicon/robot)) - var/mob/living/silicon/robot/candidate = target - if(candidate.mmi || candidate.shell) - channeling = TRUE - user.visible_message(span_danger("A dark cloud emanates from [user]'s hand and swirls around [candidate]!")) - playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, TRUE) - var/prev_color = candidate.color - candidate.color = "black" - if(do_after(user, 9 SECONDS, target = candidate)) - candidate.undeploy() - candidate.emp_act(EMP_HEAVY) - var/construct_class = show_radial_menu(user, src, GLOB.construct_radial_images, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) - if(!check_menu(user)) - return - if(QDELETED(candidate)) - channeling = FALSE - return - candidate.grab_ghost() - user.visible_message(span_danger("The dark cloud recedes from what was formerly [candidate], revealing a\n [construct_class]!")) - make_new_construct_from_class(construct_class, THEME_CULT, candidate, user, FALSE, T) - uses-- - qdel(candidate) - channeling = FALSE - else - channeling = FALSE - candidate.color = prev_color - return - else - uses-- - to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!")) - new /obj/structure/constructshell(T) - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - qdel(candidate) - else if(istype(target,/obj/machinery/door/airlock)) + uses-- + to_chat(user, span_warning("A dark cloud emanates from your hand and swirls around the iron, twisting it into a construct shell!")) + new /obj/structure/constructshell(T) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + return ..() + + if(istype(target, /obj/item/stack/sheet/plasteel)) + var/obj/item/stack/sheet/plasteel/candidate = target + var/quantity = candidate.amount + if(!candidate.use(quantity)) + return + + uses-- + new /obj/item/stack/sheet/runed_metal(T,quantity) + to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around the plasteel, transforming it into runed metal!")) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + return ..() + + if(istype(target,/mob/living/silicon/robot)) + var/mob/living/silicon/robot/candidate = target + if(candidate.mmi || candidate.shell) channeling = TRUE - playsound(T, 'sound/machines/airlockforced.ogg', 50, TRUE) - do_sparks(5, TRUE, target) - if(do_after(user, 5 SECONDS, target = user)) - if(QDELETED(target)) - channeling = FALSE - return - target.narsie_act() - uses-- - user.visible_message(span_warning("Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!")) - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + user.visible_message(span_danger("A dark cloud emanates from [user]'s hand and swirls around [candidate]!")) + playsound(T, 'sound/machines/airlock_alien_prying.ogg', 80, TRUE) + var/prev_color = candidate.color + candidate.color = "black" + if(!do_after(user, 9 SECONDS, target = candidate)) channeling = FALSE - else + candidate.color = prev_color + return + candidate.undeploy() + candidate.emp_act(EMP_HEAVY) + var/construct_class = show_radial_menu(user, src, GLOB.construct_radial_images, custom_check = CALLBACK(src, PROC_REF(check_menu), user), require_near = TRUE, tooltips = TRUE) + if(!check_menu(user) || QDELETED(candidate)) channeling = FALSE + candidate.color = prev_color return - else if(istype(target,/obj/item/soulstone)) - var/obj/item/soulstone/candidate = target - if(candidate.corrupt()) - uses-- - to_chat(user, span_warning("You corrupt [candidate]!")) - SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) - else - to_chat(user, span_warning("The spell will not work on [target]!")) + candidate.grab_ghost() + user.visible_message(span_danger("The dark cloud recedes from what was formerly [candidate], revealing a\n [construct_class]!")) + make_new_construct_from_class(construct_class, THEME_CULT, candidate, user, FALSE, T) + uses-- + qdel(candidate) + channeling = FALSE + return ..() + + uses-- + to_chat(user, span_warning("A dark cloud emanates from you hand and swirls around [candidate] - twisting it into a construct shell!")) + new /obj/structure/constructshell(T) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + qdel(candidate) + return ..() + + if(istype(target,/obj/machinery/door/airlock)) + channeling = TRUE + playsound(T, 'sound/machines/airlockforced.ogg', 50, TRUE) + do_sparks(5, TRUE, target) + if(!do_after(user, 5 SECONDS, target = user) && !QDELETED(target)) + channeling = FALSE return - return . | ..() + + target.narsie_act() + uses-- + user.visible_message(span_warning("Black ribbons suddenly emanate from [user]'s hand and cling to the airlock - twisting and corrupting it!")) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + channeling = FALSE + return ..() + + if(istype(target,/obj/item/soulstone)) + var/obj/item/soulstone/candidate = target + if(!candidate.corrupt()) + return + + uses-- + to_chat(user, span_warning("You corrupt [candidate]!")) + SEND_SOUND(user, sound('sound/effects/magic.ogg',0,1,25)) + return ..() + + to_chat(user, span_warning("The spell will not work on [target]!")) /obj/item/melee/blood_magic/construction/proc/check_menu(mob/user) if(!istype(user)) @@ -673,21 +690,21 @@ desc = "Will equip cult combat gear onto a cultist on contact." color = "#33cc33" // green -/obj/item/melee/blood_magic/armor/afterattack(atom/target, mob/living/carbon/user, proximity) +/obj/item/melee/blood_magic/armor/cast_spell(mob/living/target, mob/living/carbon/user) + if(!iscarbon(target) || !IS_CULTIST(target)) + return + uses-- var/mob/living/carbon/carbon_target = target - if(istype(carbon_target) && IS_CULTIST(carbon_target) && proximity) - uses-- - var/mob/living/carbon/C = target - C.visible_message(span_warning("Otherworldly armor suddenly appears on [C]!")) - C.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,ITEM_SLOT_ICLOTHING) - C.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), ITEM_SLOT_OCLOTHING) - C.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), ITEM_SLOT_FEET) - C.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), ITEM_SLOT_BACK) - if(C == user) - qdel(src) //Clears the hands - C.put_in_hands(new /obj/item/melee/cultblade/dagger(user)) - C.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user)) - ..() + carbon_target.visible_message(span_warning("Otherworldly armor suddenly appears on [carbon_target]!")) + carbon_target.equip_to_slot_or_del(new /obj/item/clothing/under/color/black,ITEM_SLOT_ICLOTHING) + carbon_target.equip_to_slot_or_del(new /obj/item/clothing/suit/hooded/cultrobes/alt(user), ITEM_SLOT_OCLOTHING) + carbon_target.equip_to_slot_or_del(new /obj/item/clothing/shoes/cult/alt(user), ITEM_SLOT_FEET) + carbon_target.equip_to_slot_or_del(new /obj/item/storage/backpack/cultpack(user), ITEM_SLOT_BACK) + if(carbon_target == user) + qdel(src) //Clears the hands + carbon_target.put_in_hands(new /obj/item/melee/cultblade/dagger(user)) + carbon_target.put_in_hands(new /obj/item/restraints/legcuffs/bola/cult(user)) + return ..() /obj/item/melee/blood_magic/manipulator name = "Blood Rite Aura" @@ -708,10 +725,7 @@ * * '/obj/item/melee/blood_magic/manipulator/proc/blood_draw' handles blood pools/trails and does not affect parent proc */ -/obj/item/melee/blood_magic/manipulator/afterattack(atom/target, mob/living/carbon/human/user, proximity) - if(!proximity) - return - +/obj/item/melee/blood_magic/manipulator/cast_spell(mob/living/target, mob/living/carbon/user) if((isconstruct(target) || isshade(target)) && !heal_construct(target, user)) return if(istype(target, /obj/effect/decal/cleanable/blood) || istype(target, /obj/effect/decal/cleanable/trail_holder) || isturf(target)) @@ -724,12 +738,11 @@ if(human_bloodbag.stat == DEAD) human_bloodbag.balloon_alert(user, "dead!") return - if(IS_CULTIST(human_bloodbag) && !heal_cultist(human_bloodbag, user)) return if(!IS_CULTIST(human_bloodbag) && !drain_victim(human_bloodbag, user)) return - ..() + return ..() /** * handles blood rites usage on constructs diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 41350fdadf4..b39a534755c 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -639,49 +639,49 @@ Striking a noncultist, however, will tear their flesh."} var/charges = 5 start_on = TRUE -/obj/item/flashlight/flare/culttorch/afterattack(atom/movable/A, mob/user, proximity) - if(!proximity) - return - if(!IS_CULTIST(user)) - to_chat(user, "That doesn't seem to do anything useful.") - return +/obj/item/flashlight/flare/culttorch/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/datum/antagonist/cult/cult = user.mind.has_antag_datum(/datum/antagonist/cult) + var/datum/team/cult/cult_team = cult?.get_team() + if(isnull(cult_team)) + to_chat(user, span_warning("That doesn't seem to do anything useful.")) + return ITEM_INTERACT_BLOCKING + + if(!isitem(interacting_with)) + to_chat(user, span_warning("[src] can only transport items!")) + return ITEM_INTERACT_BLOCKING + + var/list/mob/living/cultists = list() + for(var/datum/mind/cult_mind as anything in cult_team.members) + if(cult_mind == user.mind) + continue + if(cult_mind.current?.stat != DEAD) + cultists |= cult_mind.current - if(!isitem(A)) - ..() - to_chat(user, span_warning("\The [src] can only transport items!")) - return - - . |= AFTERATTACK_PROCESSED_ITEM - - var/list/cultists = list() - for(var/datum/mind/M as anything in get_antag_minds(/datum/antagonist/cult)) - if(M.current && M.current.stat != DEAD) - cultists |= M.current var/mob/living/cultist_to_receive = tgui_input_list(user, "Who do you wish to call to [src]?", "Followers of the Geometer", (cultists - user)) - if(!Adjacent(user) || !src || QDELETED(src) || user.incapacitated()) - return + if(QDELETED(src) || loc != user || user.incapacitated()) + return ITEM_INTERACT_BLOCKING if(isnull(cultist_to_receive)) - to_chat(user, "You require a destination!") - log_game("[key_name(user)]'s Void torch failed - no target.") - return + to_chat(user, span_cult_italic("You require a destination!")) + return ITEM_INTERACT_BLOCKING if(cultist_to_receive.stat == DEAD) - to_chat(user, "[cultist_to_receive] has died!") - log_game("[key_name(user)]'s Void torch failed - target died.") - return - if(!IS_CULTIST(cultist_to_receive)) - to_chat(user, "[cultist_to_receive] is not a follower of the Geometer!") - log_game("[key_name(user)]'s Void torch failed - target was deconverted.") - return - if(A in user.get_all_contents()) - to_chat(user, "[A] must be on a surface in order to teleport it!") - return - to_chat(user, "You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!") - user.log_message("teleported [A] to [cultist_to_receive] with \the [src].", LOG_GAME) - cultist_to_receive.put_in_hands(A) + to_chat(user, span_cult_italic("[cultist_to_receive] has died!")) + return ITEM_INTERACT_BLOCKING + if(!(cultist_to_receive.mind in cult_team.members)) + to_chat(user, span_cult_italic("[cultist_to_receive] is not a follower of the Geometer!")) + return ITEM_INTERACT_BLOCKING + if(!isturf(interacting_with.loc)) + to_chat(user, span_cult_italic("[interacting_with] must be on a surface in order to teleport it!")) + return ITEM_INTERACT_BLOCKING + + to_chat(user, span_cult_italic("You ignite [interacting_with] with [src], turning it to ash, \ + but through the torch's flames you see that [interacting_with] has reached [cultist_to_receive]!")) + user.log_message("teleported [interacting_with] to [cultist_to_receive] with [src].", LOG_GAME) + cultist_to_receive.put_in_hands(interacting_with) charges-- - to_chat(user, "\The [src] now has [charges] charge\s.") - if(charges == 0) + to_chat(user, span_notice("[src] now has [charges] charge\s.")) + if(charges <= 0) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/melee/cultblade/halberd name = "bloody halberd" @@ -859,31 +859,33 @@ Striking a noncultist, however, will tear their flesh."} ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT) -/obj/item/blood_beam/afterattack(atom/A, mob/living/user, proximity_flag, clickparams) - . = ..() +/obj/item/blood_beam/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/blood_beam/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(firing || charging) - return - if(ishuman(user)) - angle = get_angle(user, A) - else - qdel(src) - return . | AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + if(!ishuman(user)) + return ITEM_INTERACT_BLOCKING + angle = get_angle(user, interacting_with) charging = TRUE INVOKE_ASYNC(src, PROC_REF(charge), user) if(do_after(user, 9 SECONDS, target = user)) firing = TRUE ADD_TRAIT(user, TRAIT_IMMOBILIZED, CULT_TRAIT) - INVOKE_ASYNC(src, PROC_REF(pewpew), user, clickparams) + var/params = list2params(modifiers) + INVOKE_ASYNC(src, PROC_REF(pewpew), user, params) var/obj/structure/emergency_shield/cult/weak/N = new(user.loc) if(do_after(user, 9 SECONDS, target = user)) user.Paralyze(40) - to_chat(user, "You have exhausted the power of this spell!") + to_chat(user, span_cult_italic("You have exhausted the power of this spell!")) REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, CULT_TRAIT) firing = FALSE if(N) qdel(N) qdel(src) charging = FALSE + return ITEM_INTERACT_SUCCESS /obj/item/blood_beam/proc/charge(mob/user) var/obj/O diff --git a/code/modules/antagonists/heretic/heretic_antag.dm b/code/modules/antagonists/heretic/heretic_antag.dm index 01d7c33f718..81bd8e8ccea 100644 --- a/code/modules/antagonists/heretic/heretic_antag.dm +++ b/code/modules/antagonists/heretic/heretic_antag.dm @@ -230,7 +230,7 @@ GLOB.reality_smash_track.add_tracked_mind(owner) RegisterSignals(our_mob, list(COMSIG_MOB_BEFORE_SPELL_CAST, COMSIG_MOB_SPELL_ACTIVATED), PROC_REF(on_spell_cast)) - RegisterSignal(our_mob, COMSIG_MOB_ITEM_AFTERATTACK, PROC_REF(on_item_afterattack)) + RegisterSignal(our_mob, COMSIG_USER_ITEM_INTERACTION, PROC_REF(on_item_use)) RegisterSignal(our_mob, COMSIG_MOB_LOGIN, PROC_REF(fix_influence_network)) RegisterSignal(our_mob, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(after_fully_healed)) @@ -245,7 +245,7 @@ UnregisterSignal(our_mob, list( COMSIG_MOB_BEFORE_SPELL_CAST, COMSIG_MOB_SPELL_ACTIVATED, - COMSIG_MOB_ITEM_AFTERATTACK, + COMSIG_USER_ITEM_INTERACTION, COMSIG_MOB_LOGIN, COMSIG_LIVING_POST_FULLY_HEAL, )) @@ -286,26 +286,25 @@ return SPELL_CANCEL_CAST /* - * Signal proc for [COMSIG_MOB_ITEM_AFTERATTACK]. + * Signal proc for [COMSIG_USER_ITEM_INTERACTION]. * * If a heretic is holding a pen in their main hand, * and have mansus grasp active in their offhand, * they're able to draw a transmutation rune. */ -/datum/antagonist/heretic/proc/on_item_afterattack(mob/living/source, atom/target, obj/item/weapon, proximity_flag, click_parameters) +/datum/antagonist/heretic/proc/on_item_use(mob/living/source, atom/target, obj/item/weapon, click_parameters) SIGNAL_HANDLER - if(!is_type_in_typecache(weapon, scribing_tools)) - return - if(!isturf(target) || !isliving(source) || !proximity_flag) - return + return NONE + if(!isturf(target) || !isliving(source)) + return NONE var/obj/item/offhand = source.get_inactive_held_item() if(QDELETED(offhand) || !istype(offhand, /obj/item/melee/touch_attack/mansus_fist)) - return + return NONE try_draw_rune(source, target, additional_checks = CALLBACK(src, PROC_REF(check_mansus_grasp_offhand), source)) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /** * Attempt to draw a rune on [target_turf]. diff --git a/code/modules/antagonists/heretic/items/forbidden_book.dm b/code/modules/antagonists/heretic/items/forbidden_book.dm index 06f091c77e7..6a6a799183a 100644 --- a/code/modules/antagonists/heretic/items/forbidden_book.dm +++ b/code/modules/antagonists/heretic/items/forbidden_book.dm @@ -45,20 +45,16 @@ AddElement(/datum/element/heretic_focus) update_weight_class(WEIGHT_CLASS_NORMAL) -/obj/item/codex_cicatrix/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag) - return - +/obj/item/codex_cicatrix/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(user) if(!heretic_datum) - return - - if(isopenturf(target)) - var/obj/effect/heretic_influence/influence = locate(/obj/effect/heretic_influence) in target + return NONE + if(isopenturf(interacting_with)) + var/obj/effect/heretic_influence/influence = locate(/obj/effect/heretic_influence) in interacting_with if(!influence?.drain_influence_with_codex(user, src)) - heretic_datum.try_draw_rune(user, target, drawing_time = 8 SECONDS) - return TRUE + heretic_datum.try_draw_rune(user, interacting_with, drawing_time = 8 SECONDS) + return ITEM_INTERACT_BLOCKING + return NONE /// Plays a little animation that shows the book opening and closing. /obj/item/codex_cicatrix/proc/open_animation() diff --git a/code/modules/antagonists/heretic/items/heretic_blades.dm b/code/modules/antagonists/heretic/items/heretic_blades.dm index edcf5e15368..675f5f87b0a 100644 --- a/code/modules/antagonists/heretic/items/heretic_blades.dm +++ b/code/modules/antagonists/heretic/items/heretic_blades.dm @@ -24,14 +24,19 @@ attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "rend") var/after_use_message = "" -/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user) +/obj/item/melee/sickly_blade/pre_attack(atom/A, mob/living/user, params) + . = ..() + if(.) + return . if(!IS_HERETIC_OR_MONSTER(user)) to_chat(user, span_danger("You feel a pulse of alien intellect lash out at your mind!")) - var/mob/living/carbon/human/human_user = user - human_user.AdjustParalyzed(5 SECONDS) + user.AdjustParalyzed(5 SECONDS) return TRUE + return . - return ..() +/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, click_parameters) + if(isliving(target)) + SEND_SIGNAL(user, COMSIG_HERETIC_BLADE_ATTACK, target, src) /obj/item/melee/sickly_blade/attack_self(mob/user) var/turf/safe_turf = find_safe_turf(zlevel = z, extended_safety_checks = TRUE) @@ -45,15 +50,10 @@ playsound(src, SFX_SHATTER, 70, TRUE) //copied from the code for smashing a glass sheet onto the ground to turn it into a shard qdel(src) -/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!isliving(target)) - return - - if(proximity_flag) - SEND_SIGNAL(user, COMSIG_HERETIC_BLADE_ATTACK, target, src) - else - SEND_SIGNAL(user, COMSIG_HERETIC_RANGED_BLADE_ATTACK, target, src) +/obj/item/melee/sickly_blade/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isliving(interacting_with)) + SEND_SIGNAL(user, COMSIG_HERETIC_RANGED_BLADE_ATTACK, interacting_with, src) + return ITEM_INTERACT_BLOCKING /obj/item/melee/sickly_blade/examine(mob/user) . = ..() diff --git a/code/modules/antagonists/heretic/items/keyring.dm b/code/modules/antagonists/heretic/items/keyring.dm index 16566c0a8bf..dc1291bc034 100644 --- a/code/modules/antagonists/heretic/items/keyring.dm +++ b/code/modules/antagonists/heretic/items/keyring.dm @@ -171,20 +171,17 @@ playsound(drop_location(),'sound/items/eatfood.ogg', rand(10,50), TRUE) access += card.access -/obj/item/card/id/advanced/heretic/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !IS_HERETIC(user)) - return +/obj/item/card/id/advanced/heretic/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!IS_HERETIC(user)) + return NONE if(istype(target, /obj/effect/lock_portal)) clear_portals() - return - + return ITEM_INTERACT_SUCCESS if(!istype(target, /obj/machinery/door)) - return - + return NONE var/reference_resolved = link?.resolve() if(reference_resolved == target) - return + return ITEM_INTERACT_BLOCKING if(reference_resolved) make_portal(user, reference_resolved, target) @@ -194,6 +191,7 @@ else link = WEAKREF(target) balloon_alert(user, "link 1/2") + return ITEM_INTERACT_SUCCESS /obj/item/card/id/advanced/heretic/Destroy() QDEL_LIST_ASSOC(fused_ids) diff --git a/code/modules/antagonists/heretic/items/labyrinth_handbook.dm b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm index b3e3649763f..8555b60f0c3 100644 --- a/code/modules/antagonists/heretic/items/labyrinth_handbook.dm +++ b/code/modules/antagonists/heretic/items/labyrinth_handbook.dm @@ -41,24 +41,29 @@ . += span_hypnophrase("Materializes a barrier upon any tile in sight, which only you can pass through. Lasts 8 seconds.") . += span_hypnophrase("It has [uses] uses left.") -/obj/item/heretic_labyrinth_handbook/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(IS_HERETIC(user)) - var/turf/turf_target = get_turf(target) - if(locate(barrier_type) in turf_target) - user.balloon_alert(user, "already occupied!") - return - turf_target.visible_message(span_warning("A storm of paper materializes!")) - new /obj/effect/temp_visual/paper_scatter(turf_target) - playsound(turf_target, 'sound/magic/smoke.ogg', 30) - new barrier_type(turf_target, user) - uses-- - if(uses <= 0) - to_chat(user, span_warning("[src] falls apart, turning into ash and dust!")) - qdel(src) - return - var/mob/living/carbon/human/human_user = user - to_chat(human_user, span_userdanger("Your mind burns as you stare deep into the book, a headache setting in like your brain is on fire!")) - human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30, 190) - human_user.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) - human_user.dropItemToGround(src) +/obj/item/heretic_labyrinth_handbook/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/heretic_labyrinth_handbook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!IS_HERETIC(user)) + if(ishuman(user)) + var/mob/living/carbon/human/human_user = user + to_chat(human_user, span_userdanger("Your mind burns as you stare deep into the book, a headache setting in like your brain is on fire!")) + human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30, 190) + human_user.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) + human_user.dropItemToGround(src) + return ITEM_INTERACT_BLOCKING + + var/turf/turf_target = get_turf(interacting_with) + if(locate(barrier_type) in turf_target) + user.balloon_alert(user, "already occupied!") + return ITEM_INTERACT_BLOCKING + turf_target.visible_message(span_warning("A storm of paper materializes!")) + new /obj/effect/temp_visual/paper_scatter(turf_target) + playsound(turf_target, 'sound/magic/smoke.ogg', 30) + new barrier_type(turf_target, user) + uses-- + if(uses <= 0) + to_chat(user, span_warning("[src] falls apart, turning into ash and dust!")) + qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm index b9afe643240..9bdad0ea5fc 100644 --- a/code/modules/antagonists/heretic/structures/carving_knife.dm +++ b/code/modules/antagonists/heretic/structures/carving_knife.dm @@ -45,21 +45,14 @@ var/potion_string = span_info("\tThe " + initial(trap.name) + " - " + initial(trap.carver_tip)) . += potion_string -/obj/item/melee/rune_carver/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag) - return - +/obj/item/melee/rune_carver/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!IS_HERETIC_OR_MONSTER(user)) - return - - if(!isopenturf(target)) - return - - if(is_type_in_typecache(target, blacklisted_turfs)) - return + return NONE + if(!isopenturf(interacting_with) || is_type_in_typecache(interacting_with, blacklisted_turfs)) + return NONE - INVOKE_ASYNC(src, PROC_REF(try_carve_rune), target, user) + INVOKE_ASYNC(src, PROC_REF(try_carve_rune), interacting_with, user) + return ITEM_INTERACT_SUCCESS /* * Begin trying to carve a rune. Go through a few checks, then call do_carve_rune if successful. diff --git a/code/modules/antagonists/ninja/energy_katana.dm b/code/modules/antagonists/ninja/energy_katana.dm index dadd07bf947..fd3a4df7e59 100644 --- a/code/modules/antagonists/ninja/energy_katana.dm +++ b/code/modules/antagonists/ninja/energy_katana.dm @@ -44,12 +44,11 @@ spark_system.set_up(5, 0, src) spark_system.attach(src) -/obj/item/energy_katana/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return - if(!target.density) - jaunt?.teleport(user, target) +/obj/item/energy_katana/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!interacting_with.density) + jaunt?.teleport(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/energy_katana/equipped(mob/user, slot, initial) . = ..() diff --git a/code/modules/antagonists/ninja/ninja_explosive.dm b/code/modules/antagonists/ninja/ninja_explosive.dm index 4c014da1863..6e61ad68761 100644 --- a/code/modules/antagonists/ninja/ninja_explosive.dm +++ b/code/modules/antagonists/ninja/ninja_explosive.dm @@ -47,15 +47,16 @@ return detonation_area = objective.detonation_location -/obj/item/grenade/c4/ninja/afterattack(atom/movable/target, mob/ninja, flag) - if(!IS_SPACE_NINJA(ninja)) +/obj/item/grenade/c4/ninja/plant_c4(atom/bomb_target, mob/living/user) + if(!IS_SPACE_NINJA(user)) say("Access denied.") - return - . |= AFTERATTACK_PROCESSED_ITEM - if (!check_loc(ninja)) - return . - detonator = WEAKREF(ninja) - return . | ..() + return FALSE + if(!check_loc(user)) + return FALSE + if(!..()) + return FALSE + detonator = WEAKREF(user) + return TRUE /obj/item/grenade/c4/ninja/detonate(mob/living/lanced_by) if(!check_loc(detonator.resolve())) // if its moved, deactivate the c4 diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm index 2ed8787316f..4275c807ea8 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/beer_nuke.dm @@ -29,7 +29,7 @@ /obj/machinery/nuclearbomb/beer/attackby(obj/item/weapon, mob/user, params) if(weapon.is_refillable()) - weapon.afterattack(keg, user, TRUE) // redirect refillable containers to the keg, allowing them to be filled + weapon.interact_with_atom(keg, user) // redirect refillable containers to the keg, allowing them to be filled return TRUE // pretend we handled the attack, too. if(istype(weapon, /obj/item/nuke_core_container)) diff --git a/code/modules/antagonists/traitor/objectives/locate_weakpoint.dm b/code/modules/antagonists/traitor/objectives/locate_weakpoint.dm index 1976fd38fc8..4acfe712048 100644 --- a/code/modules/antagonists/traitor/objectives/locate_weakpoint.dm +++ b/code/modules/antagonists/traitor/objectives/locate_weakpoint.dm @@ -243,28 +243,24 @@ objective_weakref = null return ..() -/obj/item/grenade/c4/es8/afterattack(atom/movable/target, mob/user, flag) - if(!user.mind) - return - +/obj/item/grenade/c4/es8/plant_c4(atom/bomb_target, mob/living/user) if(!IS_TRAITOR(user)) to_chat(user, span_warning("You can't seem to find a way to detonate the charge.")) - return + return FALSE var/datum/traitor_objective/locate_weakpoint/objective = objective_weakref.resolve() - if(!objective || objective.objective_state == OBJECTIVE_STATE_INACTIVE || objective.handler.owner != user.mind) to_chat(user, span_warning("You don't think it would be wise to use [src].")) - return + return FALSE - var/area/target_area = get_area(target) + var/area/target_area = get_area(bomb_target) if (target_area.type != objective.weakpoint_area) to_chat(user, span_warning("[src] can only be detonated in [initial(objective.weakpoint_area.name)].")) - return + return FALSE - if(!isfloorturf(target) && !iswallturf(target)) + if(!isfloorturf(bomb_target) && !iswallturf(bomb_target)) to_chat(user, span_warning("[src] can only be planted on a wall or the floor!")) - return + return FALSE return ..() diff --git a/code/modules/antagonists/traitor/objectives/steal.dm b/code/modules/antagonists/traitor/objectives/steal.dm index 22d8ed7d39c..b8e62beefea 100644 --- a/code/modules/antagonists/traitor/objectives/steal.dm +++ b/code/modules/antagonists/traitor/objectives/steal.dm @@ -273,28 +273,26 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) . += span_notice("This device must be placed by clicking on the [initial(target_object_type.name)] with it.") . += span_notice("Remember, you may leave behind fingerprints or fibers on the device. Use soap or similar to scrub it clean to be safe!") -/obj/item/traitor_bug/afterattack(atom/movable/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!target_object_type) - return - if(!user.Adjacent(target)) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/traitor_bug/interact_with_atom(atom/movable/target, mob/living/user, list/modifiers) + if(!target_object_type || !ismovable(target)) + return NONE + var/result = SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PRE_PLANTED_OBJECT, target) if(!(result & COMPONENT_FORCE_PLACEMENT)) if(result & COMPONENT_FORCE_FAIL_PLACEMENT || !istype(target, target_object_type)) balloon_alert(user, "you can't attach this onto here!") - return + return ITEM_INTERACT_BLOCKING if(!do_after(user, deploy_time, src, hidden = TRUE)) - return + return ITEM_INTERACT_BLOCKING if(planted_on) - return + return ITEM_INTERACT_BLOCKING forceMove(target) target.vis_contents += src vis_flags |= VIS_INHERIT_PLANE planted_on = target RegisterSignal(planted_on, COMSIG_QDELETING, PROC_REF(handle_planted_on_deletion)) SEND_SIGNAL(src, COMSIG_TRAITOR_BUG_PLANTED_OBJECT, target) + return ITEM_INTERACT_SUCCESS /obj/item/traitor_bug/proc/handle_planted_on_deletion() planted_on = null @@ -314,5 +312,5 @@ GLOBAL_DATUM_INIT(steal_item_handler, /datum/objective_item_handler, new()) UnregisterSignal(planted_on, COMSIG_QDELETING) planted_on = null -/obj/item/traitor_bug/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/obj/item/traitor_bug/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) return !istype(storage_holder, target_object_type) diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 5c606958948..9176558c7a1 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -431,43 +431,45 @@ COMSIG_ITEM_MAGICALLY_CHARGED = PROC_REF(on_magic_charge), ) -/obj/item/runic_vendor_scepter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) +/obj/item/runic_vendor_scepter/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/runic_vendor_scepter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(scepter_is_busy_recharging) user.balloon_alert(user, "busy!") - return - if(!check_allowed_items(target, not_inside = TRUE)) - return - . |= AFTERATTACK_PROCESSED_ITEM - var/turf/afterattack_turf = get_turf(target) - if(istype(target, /obj/machinery/vending/runic_vendor)) - var/obj/machinery/vending/runic_vendor/runic_explosion_target = target + return ITEM_INTERACT_BLOCKING + if(!check_allowed_items(interacting_with, not_inside = TRUE)) + return NONE + if(istype(interacting_with, /obj/machinery/vending/runic_vendor)) + var/obj/machinery/vending/runic_vendor/runic_explosion_target = interacting_with runic_explosion_target.runic_explosion() - return + return ITEM_INTERACT_SUCCESS + var/turf/afterattack_turf = get_turf(interacting_with) var/obj/machinery/vending/runic_vendor/vendor_on_turf = locate() in afterattack_turf if(vendor_on_turf) vendor_on_turf.runic_explosion() - return + return ITEM_INTERACT_SUCCESS if(!summon_vendor_charges) user.balloon_alert(user, "no charges!") - return + return ITEM_INTERACT_BLOCKING if(get_dist(afterattack_turf,src) > max_summon_range) user.balloon_alert(user, "too far!") - return + return ITEM_INTERACT_BLOCKING if(get_turf(src) == afterattack_turf) user.balloon_alert(user, "too close!") - return + return ITEM_INTERACT_BLOCKING if(scepter_is_busy_summoning) user.balloon_alert(user, "already summoning!") - return + return ITEM_INTERACT_BLOCKING if(afterattack_turf.is_blocked_turf(TRUE)) user.balloon_alert(user, "blocked!") - return + return ITEM_INTERACT_BLOCKING if(summoning_time) scepter_is_busy_summoning = TRUE user.balloon_alert(user, "summoning...") - if(!do_after(user, summoning_time, target = target)) + if(!do_after(user, summoning_time, target = interacting_with)) scepter_is_busy_summoning = FALSE - return + return ITEM_INTERACT_BLOCKING scepter_is_busy_summoning = FALSE if(summon_vendor_charges) playsound(src,'sound/weapons/resonator_fire.ogg',50,TRUE) @@ -475,8 +477,8 @@ new /obj/machinery/vending/runic_vendor(afterattack_turf) summon_vendor_charges-- user.changeNext_move(CLICK_CD_MELEE) - return - return ..() + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/runic_vendor_scepter/attack_self(mob/user, modifiers) . = ..() @@ -489,17 +491,20 @@ scepter_is_busy_recharging = FALSE summon_vendor_charges = RUNIC_SCEPTER_MAX_CHARGES -/obj/item/runic_vendor_scepter/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - var/turf/afterattack_secondary_turf = get_turf(target) +/obj/item/runic_vendor_scepter/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) + +/obj/item/runic_vendor_scepter/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/afterattack_secondary_turf = get_turf(interacting_with) var/obj/machinery/vending/runic_vendor/vendor_on_turf = locate() in afterattack_secondary_turf - if(istype(target, /obj/machinery/vending/runic_vendor)) - var/obj/machinery/vending/runic_vendor/vendor_being_throw = target - vendor_being_throw.throw_at(get_edge_target_turf(target, get_cardinal_dir(src, target)), 4, 20, user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(istype(interacting_with, /obj/machinery/vending/runic_vendor)) + var/obj/machinery/vending/runic_vendor/vendor_being_throw = interacting_with + vendor_being_throw.throw_at(get_edge_target_turf(interacting_with, get_cardinal_dir(src, interacting_with)), 4, 20, user) + return ITEM_INTERACT_SUCCESS if(vendor_on_turf) - vendor_on_turf.throw_at(get_edge_target_turf(target, get_cardinal_dir(src, target)), 4, 20, user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + vendor_on_turf.throw_at(get_edge_target_turf(interacting_with, get_cardinal_dir(src, interacting_with)), 4, 20, user) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/runic_vendor_scepter/proc/on_magic_charge(datum/source, datum/action/cooldown/spell/charge/spell, mob/living/caster) SIGNAL_HANDLER diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 6b76a628c1b..04b5d366918 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -77,7 +77,7 @@ whatever spark it once held long extinguished." ///signal called whenever a soulstone is smacked by a bible -/obj/item/soulstone/proc/on_bible_smacked(datum/source, mob/living/user, direction) +/obj/item/soulstone/proc/on_bible_smacked(datum/source, mob/living/user, ...) SIGNAL_HANDLER INVOKE_ASYNC(src, PROC_REF(attempt_exorcism), user) diff --git a/code/modules/antagonists/wizard/equipment/teleport_rod.dm b/code/modules/antagonists/wizard/equipment/teleport_rod.dm index a1d9904ddb2..c15b66da6ff 100644 --- a/code/modules/antagonists/wizard/equipment/teleport_rod.dm +++ b/code/modules/antagonists/wizard/equipment/teleport_rod.dm @@ -55,28 +55,21 @@ var/datum/status_effect/teleport_flux/perma/permaflux = user.has_status_effect(/datum/status_effect/teleport_flux/perma) permaflux?.delayed_remove(src) -/obj/item/teleport_rod/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters) - . = ..() - if(!isliving(user)) - return - if(proximity_flag) // assuming you don't want to teleport 1 tile away - return - - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/teleport_rod/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + . = ITEM_INTERACT_BLOCKING var/turf/start_turf = get_turf(user) - var/turf/target_turf = get_turf(target) + var/turf/target_turf = get_turf(interacting_with) if(get_dist(start_turf, target_turf) > max_tp_range) user.balloon_alert(user, "too far!") - return + return . if(!(target_turf in view(user, user.client?.view || world.view))) user.balloon_alert(user, "out of view!") - return + return . if(target_turf.is_blocked_turf(exclude_mobs = TRUE, source_atom = user)) user.balloon_alert(user, "obstructed!") - return + return . var/tp_result = do_teleport( teleatom = user, @@ -88,7 +81,9 @@ if(!tp_result) user.balloon_alert(user, "teleport failed!") - return + return . + + . = ITEM_INTERACT_SUCCESS var/sound/teleport_sound = sound('sound/magic/summonitems_generic.ogg') teleport_sound.pitch = 0.5 @@ -101,7 +96,7 @@ user.changeNext_move(CLICK_CD_SLOW * 1.2) if(!apply_debuffs) - return + return . // Teleporting leaves some of your reagents behind! // (Primarily a way to prevent cheese with damage healing chem mixes, @@ -110,13 +105,14 @@ user.reagents?.remove_all(0.33, relative = TRUE) user_stomach?.reagents?.remove_all(0.33, relative = TRUE) if(user.has_status_effect(/datum/status_effect/teleport_flux/perma)) - return + return . if(user.has_status_effect(/datum/status_effect/teleport_flux)) // The status effect handles the damage, but we'll add a special pop up for rod usage specifically user.balloon_alert(user, "too soon!") user.apply_status_effect(/datum/status_effect/teleport_flux) + return . /// Temp visual displayed on both sides of a teleport rod teleport /obj/effect/temp_visual/teleport_flux diff --git a/code/modules/art/statues.dm b/code/modules/art/statues.dm index 8ed46a5bf81..fd64d212f3e 100644 --- a/code/modules/art/statues.dm +++ b/code/modules/art/statues.dm @@ -310,12 +310,11 @@ Point with the chisel at the target to choose what to sculpt or hit block to cho Hit block again to start sculpting. Moving interrupts */ -/obj/item/chisel/pre_attack(atom/target, mob/living/user, params) - . = ..() +/obj/item/chisel/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(sculpting) - return TRUE - if(istype(target, /obj/structure/carving_block)) - var/obj/structure/carving_block/sculpt_block = target + return ITEM_INTERACT_BLOCKING + if(istype(interacting_with, /obj/structure/carving_block)) + var/obj/structure/carving_block/sculpt_block = interacting_with if(sculpt_block.completion) // someone already started sculpting this so just finish set_block(sculpt_block, user, silent = TRUE) @@ -326,19 +325,20 @@ Moving interrupts set_block(sculpt_block, user) else if(sculpt_block == prepared_block) show_generic_statues_prompt(user) - return TRUE - else if(prepared_block) //We're aiming at something next to us with block prepared - prepared_block.set_target(target, user) - return TRUE + return ITEM_INTERACT_SUCCESS -// We aim at something distant. -/obj/item/chisel/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() + else if(prepared_block) //We're aiming at something next to us with block prepared + prepared_block.set_target(interacting_with, user) + return ITEM_INTERACT_SUCCESS - if (!sculpting && prepared_block && ismovable(target) && prepared_block.completion == 0) - prepared_block.set_target(target,user) + return NONE - return . | AFTERATTACK_PROCESSED_ITEM +// We aim at something distant. +/obj/item/chisel/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if (!sculpting && prepared_block && ismovable(interacting_with) && prepared_block.completion == 0) + prepared_block.set_target(interacting_with, user) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /// Starts or continues the sculpting action on the carving block material /obj/item/chisel/proc/start_sculpting(mob/living/user) diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm index c12893cb137..6e0490e25ef 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm @@ -5,29 +5,27 @@ icon_state = "hypernoblium_crystal" var/uses = 1 -/obj/item/hypernoblium_crystal/afterattack(obj/target_object, mob/user, proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/machinery/portable_atmospherics/atmos_device = target_object +/obj/item/hypernoblium_crystal/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/obj/machinery/portable_atmospherics/atmos_device = interacting_with + var/obj/item/clothing/worn_item = interacting_with + if(!istype(worn_item) && !istype(atmos_device)) + to_chat(user, span_warning("The crystal can only be used on clothing and portable atmospheric devices!")) + return ITEM_INTERACT_BLOCKING + if(istype(atmos_device)) if(atmos_device.nob_crystal_inserted) to_chat(user, span_warning("[atmos_device] already has a hypernoblium crystal inserted in it!")) - return + return ITEM_INTERACT_BLOCKING atmos_device.nob_crystal_inserted = TRUE to_chat(user, span_notice("You insert the [src] into [atmos_device].")) - var/obj/item/clothing/worn_item = target_object - if(!istype(worn_item) && !istype(atmos_device)) - to_chat(user, span_warning("The crystal can only be used on clothing and portable atmospheric devices!")) - return + if(istype(worn_item)) if(istype(worn_item, /obj/item/clothing/suit/space)) to_chat(user, span_warning("The [worn_item] is already pressure-resistant!")) - return + return ITEM_INTERACT_BLOCKING if(worn_item.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && worn_item.clothing_flags & STOPSPRESSUREDAMAGE) to_chat(user, span_warning("[worn_item] is already pressure-resistant!")) - return + return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You see how the [worn_item] changes color, it's now pressure proof.")) worn_item.name = "pressure-resistant [worn_item.name]" worn_item.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) @@ -35,6 +33,8 @@ worn_item.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT worn_item.cold_protection = worn_item.body_parts_covered worn_item.clothing_flags |= STOPSPRESSUREDAMAGE + uses-- - if(!uses) + if(uses <= 0) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/basketball/basketball.dm b/code/modules/basketball/basketball.dm index 77c3214fe56..35579dc4482 100644 --- a/code/modules/basketball/basketball.dm +++ b/code/modules/basketball/basketball.dm @@ -173,31 +173,37 @@ user.swap_hand(user.get_held_index_of_item(src)) playsound(src, 'sound/items/basketball_bounce.ogg', 75, FALSE) -/obj/item/toy/basketball/afterattack(atom/target, mob/living/user) - . = ..() - if(!user.combat_mode) - user.throw_item(target) +/obj/item/toy/basketball/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/toy/basketball/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(user.combat_mode) + user.throw_item(interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/toy/basketball/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) -/obj/item/toy/basketball/afterattack_secondary(atom/aim_target, mob/living/baller, proximity_flag, click_parameters) - // dunking negates shooting - if(istype(aim_target, /obj/structure/hoop) && baller.Adjacent(aim_target)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/toy/basketball/interact_with_atom_secondary(atom/interacting_with, mob/living/baller, list/modifiers) + if(istype(interacting_with, /obj/structure/hoop) && baller.Adjacent(interacting_with)) + return NONE // Do hoop stuff baller.adjustStaminaLoss(STAMINA_COST_SHOOTING) - var/dunk_dir = get_dir(baller, aim_target) + var/dunk_dir = get_dir(baller, interacting_with) var/dunk_pixel_y = dunk_dir & SOUTH ? -16 : 16 var/dunk_pixel_x = dunk_dir & EAST && 16 || dunk_dir & WEST && -16 || 0 animate(baller, pixel_x = dunk_pixel_x, pixel_y = dunk_pixel_y, time = 5, easing = BOUNCE_EASING|EASE_IN|EASE_OUT) if(do_after(baller, 0.5 SECONDS)) pass_flags |= PASSMOB - baller.throw_item(aim_target) + baller.throw_item(interacting_with) animate(baller, pixel_x = 0, pixel_y = 0, time = 3) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_SUCCESS animate(baller, pixel_x = 0, pixel_y = 0, time = 3) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /obj/item/toy/basketball/throw_impact(mob/living/carbon/target, datum/thrownthing/throwingdatum) playsound(src, 'sound/items/basketball_bounce.ogg', 75, FALSE) diff --git a/code/modules/cargo/universal_scanner.dm b/code/modules/cargo/universal_scanner.dm index a52ad9ce5be..fdcbc9ba2bb 100644 --- a/code/modules/cargo/universal_scanner.dm +++ b/code/modules/cargo/universal_scanner.dm @@ -58,17 +58,16 @@ icon_state = "[choice]" playsound(src, 'sound/machines/click.ogg', 40, TRUE) -/obj/item/universal_scanner/afterattack(obj/object, mob/user, proximity) - . = ..() - if(!istype(object) || !proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/universal_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isobj(interacting_with)) + return NONE if(scanning_mode == SCAN_EXPORTS) - export_scan(object, user) - return . + export_scan(interacting_with, user) + return ITEM_INTERACT_SUCCESS if(scanning_mode == SCAN_PRICE_TAG) - price_tag(target = object, user = user) - return . + price_tag(interacting_with, user) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/universal_scanner/attackby(obj/item/attacking_item, mob/user, params) . = ..() diff --git a/code/modules/clothing/chameleon/chameleon_scanner.dm b/code/modules/clothing/chameleon/chameleon_scanner.dm index 5023997cefe..2ea0958a0cc 100644 --- a/code/modules/clothing/chameleon/chameleon_scanner.dm +++ b/code/modules/clothing/chameleon/chameleon_scanner.dm @@ -43,25 +43,24 @@ . += span_red("Left click will stealthily scan a target up to [scan_range] meters away and upload their getup as a custom outfit for you to use.") . += span_red("Right click will do the same, but instantly equip the outfit you obtain.") -/obj/item/chameleon_scanner/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(scan_target(target, user)) - . |= AFTERATTACK_PROCESSED_ITEM - return . +/obj/item/chameleon_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return scan_target(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING -/obj/item/chameleon_scanner/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) - return . +/obj/item/chameleon_scanner/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) - var/list/scanned_outfit = scan_target(target, user) +/obj/item/chameleon_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + var/list/scanned_outfit = scan_target(interacting_with, user) if(length(scanned_outfit)) var/datum/outfit/empty_outfit = new() var/datum/action/chameleon_outfit/outfit_action = locate() in user.actions outfit_action?.apply_outfit(empty_outfit, scanned_outfit.Copy()) qdel(empty_outfit) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING - return SECONDARY_ATTACK_CONTINUE_CHAIN // no normal afterattack +/obj/item/chameleon_scanner/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) /** * Attempts to scan a human's outfit diff --git a/code/modules/clothing/gloves/insulated.dm b/code/modules/clothing/gloves/insulated.dm index 99a1ed04355..19109d68b9c 100644 --- a/code/modules/clothing/gloves/insulated.dm +++ b/code/modules/clothing/gloves/insulated.dm @@ -39,18 +39,20 @@ icon = 'icons/obj/clothing/gloves.dmi' icon_state = "sprayoncan" -/obj/item/toy/sprayoncan/afterattack(atom/target, mob/living/carbon/user, proximity) - if(iscarbon(target) && proximity) - var/mob/living/carbon/C = target - var/mob/living/carbon/U = user - var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, qdel_on_fail = TRUE, disable_warning = TRUE) - if(success) - if(C == user) - C.visible_message(span_notice("[U] sprays their hands with glittery rubber!")) - else - C.visible_message(span_warning("[U] sprays glittery rubber on the hands of [C]!")) +/obj/item/toy/sprayoncan/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!iscarbon(interacting_with)) + return NONE + var/mob/living/carbon/C = interacting_with + var/mob/living/carbon/U = user + var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, qdel_on_fail = TRUE, disable_warning = TRUE) + if(success) + if(C == user) + C.visible_message(span_notice("[U] sprays their hands with glittery rubber!")) else - C.visible_message(span_warning("The rubber fails to stick to [C]'s hands!")) + C.visible_message(span_warning("[U] sprays glittery rubber on the hands of [C]!")) + else + C.visible_message(span_warning("The rubber fails to stick to [C]'s hands!")) + return ITEM_INTERACT_SUCCESS /obj/item/clothing/gloves/color/yellow/sprayon desc = "How're you gonna get 'em off, nerd?" diff --git a/code/modules/clothing/head/wig.dm b/code/modules/clothing/head/wig.dm index 5ab2bcad214..2614d57fd6f 100644 --- a/code/modules/clothing/head/wig.dm +++ b/code/modules/clothing/head/wig.dm @@ -60,20 +60,22 @@ add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY) update_appearance() -/obj/item/clothing/head/wig/afterattack(mob/living/carbon/human/target, mob/user) - . = ..() - if(!istype(target)) - return +/obj/item/clothing/head/wig/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) +/obj/item/clothing/head/wig/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ishuman(interacting_with) || interacting_with == user) + return NONE + var/mob/living/carbon/human/target = interacting_with if(target.head) var/obj/item/clothing/head = target.head if((head.flags_inv & HIDEHAIR) && !istype(head, /obj/item/clothing/head/wig)) to_chat(user, span_warning("You can't get a good look at [target.p_their()] hair!")) - return + return ITEM_INTERACT_BLOCKING var/obj/item/bodypart/head/noggin = target.get_bodypart(BODY_ZONE_HEAD) if(!noggin) to_chat(user, span_warning("[target.p_They()] have no head!")) - return + return ITEM_INTERACT_BLOCKING var/selected_hairstyle = null var/selected_hairstyle_color = null @@ -90,6 +92,7 @@ add_atom_colour(selected_hairstyle_color, FIXED_COLOUR_PRIORITY) hairstyle = selected_hairstyle update_appearance() + return ITEM_INTERACT_SUCCESS /obj/item/clothing/head/wig/random/Initialize(mapload) hairstyle = pick(GLOB.hairstyles_list - "Bald") //Don't want invisible wig diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 28c872519dc..72a819d62e3 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -474,25 +474,21 @@ selling = !selling to_chat(user, span_notice("[src] has been set to [selling ? "'Sell'" : "'Get Price'"] mode.")) -/obj/item/clothing/neck/necklace/dope/merchant/afterattack(obj/item/I, mob/user, proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - var/datum/export_report/ex = export_item_and_contents(I, delete_unsold = selling, dry_run = !selling) +/obj/item/clothing/neck/necklace/dope/merchant/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/datum/export_report/ex = export_item_and_contents(interacting_with, delete_unsold = selling, dry_run = !selling) var/price = 0 for(var/x in ex.total_amount) price += ex.total_value[x] if(price) var/true_price = round(price*profit_scaling) - to_chat(user, span_notice("[selling ? "Sold" : "Getting the price of"] [I], value: [true_price] credits[I.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "[round(price-true_price)] credit\s taken as processing fee\s." : ""]")) + to_chat(user, span_notice("[selling ? "Sold" : "Getting the price of"] [interacting_with], value: [true_price] credits[interacting_with.contents.len ? " (exportable contents included)" : ""].[profit_scaling < 1 && selling ? "[round(price-true_price)] credit\s taken as processing fee\s." : ""]")) if(selling) new /obj/item/holochip(get_turf(user), true_price) else - to_chat(user, span_warning("There is no export value for [I] or any items within it.")) - - return . + to_chat(user, span_warning("There is no export value for [interacting_with] or any items within it.")) + + return ITEM_INTERACT_BLOCKING /obj/item/clothing/neck/beads name = "plastic bead necklace" diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm index c10648e3315..4f8d8c74cb1 100644 --- a/code/modules/detectivework/evidence.dm +++ b/code/modules/detectivework/evidence.dm @@ -8,12 +8,11 @@ inhand_icon_state = "" w_class = WEIGHT_CLASS_TINY -/obj/item/evidencebag/afterattack(obj/item/I, mob/user,proximity) - . = ..() - if(!proximity || loc == I) - return - evidencebagEquip(I, user) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/evidencebag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(interacting_with == loc) + return NONE + evidencebagEquip(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/evidencebag/attackby(obj/item/I, mob/user, params) if(evidencebagEquip(I, user)) diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 82c77839da7..57987eda621 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -74,14 +74,16 @@ // Clear the logs log = list() -/obj/item/detective_scanner/pre_attack_secondary(atom/A, mob/user, params) - safe_scan(user, atom_to_scan = A) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/detective_scanner/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/living/user) + return !user.combat_mode -/obj/item/detective_scanner/afterattack(atom/A, mob/user, params) - . = ..() - safe_scan(user, atom_to_scan = A) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/detective_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + safe_scan(user, interacting_with) + return ITEM_INTERACT_SUCCESS + +/obj/item/detective_scanner/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + safe_scan(user, interacting_with) + return ITEM_INTERACT_SUCCESS /** * safe_scan - a wrapper proc for scan() diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index d1482c61c98..622d84551a2 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -89,16 +89,12 @@ /** * Provides feedback when an item isn't related to an experiment, and has fully passed the attack chain */ -/datum/component/experiment_handler/proc/ignored_handheld_experiment_attempt(datum/source, atom/target, mob/user, proximity_flag, params) +/datum/component/experiment_handler/proc/ignored_handheld_experiment_attempt(datum/source, atom/target, mob/user, params) SIGNAL_HANDLER - if (!proximity_flag) + if ((isnull(selected_experiment) && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || (config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) return - . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - if ((selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || config_flags & EXPERIMENT_CONFIG_SILENT_FAIL) - return . playsound(user, 'sound/machines/buzz-sigh.ogg', 25) to_chat(user, span_notice("[target] is not related to your currently selected experiment.")) - return . /** * Checks that an experiment can be run using the provided target, used for preventing the cancellation of the attack chain inappropriately diff --git a/code/modules/explorer_drone/loot.dm b/code/modules/explorer_drone/loot.dm index 901b87e1018..b616f4dbf99 100644 --- a/code/modules/explorer_drone/loot.dm +++ b/code/modules/explorer_drone/loot.dm @@ -167,19 +167,18 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index()) /obj/item/firelance/get_cell() return cell -/obj/item/firelance/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - if(!HAS_TRAIT(src,TRAIT_WIELDED)) - to_chat(user,span_notice("You need to wield [src] in two hands before you can fire it.")) - return +/obj/item/firelance/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + . = ITEM_INTERACT_BLOCKING + if(!HAS_TRAIT(src, TRAIT_WIELDED)) + to_chat(user, span_notice("You need to wield [src] in two hands before you can fire it.")) + return . if(LAZYACCESS(user.do_afters, "firelance")) - return + return . if(!cell.use(0.2 * STANDARD_CELL_CHARGE)) - to_chat(user,span_warning("[src] battery ran dry!")) - return + to_chat(user,span_warning("[src]'s battery ran dry!")) + return . ADD_TRAIT(user, TRAIT_IMMOBILIZED, REF(src)) - to_chat(user,span_notice("You begin to charge [src]")) + to_chat(user,span_notice("You begin to charge [src]...")) inhand_icon_state = "firelance_charging" user.update_held_items() if(do_after(user,windup_time,interaction_key="firelance",extra_checks = CALLBACK(src, PROC_REF(windup_checks)))) @@ -189,9 +188,11 @@ GLOBAL_LIST_INIT(adventure_loot_generator_index,generate_generator_index()) for(var/turf/turf_to_melt in get_line(start_turf,last_turf)) if(turf_to_melt.density) turf_to_melt.Melt() + . = ITEM_INTERACT_SUCCESS inhand_icon_state = initial(inhand_icon_state) user.update_held_items() REMOVE_TRAIT(user, TRAIT_IMMOBILIZED, REF(src)) + return . /// Additional windup checks /obj/item/firelance/proc/windup_checks() diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index 2706da8e967..2038f1960f9 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -78,31 +78,29 @@ return CONTEXTUAL_SCREENTIP_SET return NONE -/obj/item/fish_analyzer/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !user.can_read(src) || user.is_blind()) - return +/obj/item/fish_analyzer/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!isfish(target) && !isaquarium(target)) + return NONE + if(!user.can_read(src) || user.is_blind()) + return ITEM_INTERACT_BLOCKING if(isfish(target)) balloon_alert(user, "analyzing stats") - user.visible_message(span_notice("[user] analyzes [target]."), span_notice("You analyze [target].")) analyze_status(target, user) else if(istype(target, /obj/structure/aquarium)) scan_aquarium(target, user) + return ITEM_INTERACT_SUCCESS - -/obj/item/fish_analyzer/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if(!isfish(target)) - return - - if(!proximity_flag || !user.can_read(src) || user.is_blind()) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/fish_analyzer/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!isfish(interacting_with)) + return NONE + if(!user.can_read(src) || user.is_blind()) + return ITEM_INTERACT_BLOCKING balloon_alert(user, "analyzing traits") - - analyze_traits(target, user) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + analyze_traits(interacting_with, user) + return ITEM_INTERACT_SUCCESS ///Instantiates the radial menu, populates the list of choices, shows it and register signals on the aquarium. /obj/item/fish_analyzer/proc/scan_aquarium(obj/structure/aquarium/aquarium, mob/user) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 98ac7f8ff72..9cc564df6f4 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -145,16 +145,6 @@ . = ..() ui_interact(user) -/obj/item/fishing_rod/pre_attack(atom/targeted_atom, mob/living/user, params) - . = ..() - /// Reel in if able - if(currently_hooked) - reel(user) - return TRUE - if(!hook) - balloon_alert(user, "install a hook first!") - SEND_SIGNAL(targeted_atom, COMSIG_PRE_FISHING) - /// Generates the fishing line visual from the current user to the target and updates inhands /obj/item/fishing_rod/proc/create_fishing_line(atom/movable/target, target_py = null) if(!display_fishing_line) @@ -205,22 +195,26 @@ qdel(source) return BEAM_CANCEL_DRAW -/obj/item/fishing_rod/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/fishing_rod/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/fishing_rod/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!hook) + balloon_alert(user, "install a hook first!") + return ITEM_INTERACT_BLOCKING - /// Reel in if able + // Reel in if able if(currently_hooked) reel(user) - return . - - cast_line(target, user, proximity_flag) + return ITEM_INTERACT_BLOCKING - return . + SEND_SIGNAL(interacting_with, COMSIG_PRE_FISHING) + cast_line(interacting_with, user) + return ITEM_INTERACT_SUCCESS -///Called by afterattack(). If the line to whatever that is is clear and we're not already busy, try fishing in it -/obj/item/fishing_rod/proc/cast_line(atom/target, mob/user, proximity_flag) - if(casting || currently_hooked || proximity_flag) +/// If the line to whatever that is is clear and we're not already busy, try fishing in it +/obj/item/fishing_rod/proc/cast_line(atom/target, mob/user) + if(casting || currently_hooked) return if(!hook) balloon_alert(user, "install a hook first!") @@ -230,8 +224,6 @@ return if(!COOLDOWN_FINISHED(src, casting_cd)) return - /// Annoyingly pre attack is only called in melee - SEND_SIGNAL(target, COMSIG_PRE_FISHING) casting = TRUE var/obj/projectile/fishing_cast/cast_projectile = new(get_turf(src)) cast_projectile.range = cast_range diff --git a/code/modules/hydroponics/beekeeping/bee_smoker.dm b/code/modules/hydroponics/beekeeping/bee_smoker.dm index fc296339a9f..91195dacc84 100644 --- a/code/modules/hydroponics/beekeeping/bee_smoker.dm +++ b/code/modules/hydroponics/beekeeping/bee_smoker.dm @@ -36,40 +36,33 @@ user.balloon_alert(user, "[activated ? "activated" : "deactivated"]") return TRUE -/obj/item/bee_smoker/afterattack(atom/attacked_atom, mob/living/user, proximity) - . = ..() - - if(!proximity) - return - - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/bee_smoker/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!activated) user.balloon_alert(user, "not activated!") - return + return ITEM_INTERACT_BLOCKING if(current_herb_fuel < single_use_cost) user.balloon_alert(user, "not enough fuel!") - return + return ITEM_INTERACT_BLOCKING current_herb_fuel -= single_use_cost playsound(src, 'sound/effects/spray2.ogg', 100, TRUE) - var/turf/target_turf = get_turf(attacked_atom) + var/turf/target_turf = get_turf(interacting_with) new /obj/effect/temp_visual/mook_dust(target_turf) - for(var/mob/living/basic/bee/friend in target_turf) if(friend.flags_1 & HOLOGRAM_1) continue friend.befriend(user) - if(!istype(attacked_atom, /obj/structure/beebox)) - return + if(!istype(interacting_with, /obj/structure/beebox)) + return ITEM_INTERACT_BLOCKING - var/obj/structure/beebox/hive = attacked_atom + var/obj/structure/beebox/hive = interacting_with for(var/mob/living/bee as anything in hive.bees) if(bee.flags_1 & HOLOGRAM_1) continue bee.befriend(user) + return ITEM_INTERACT_SUCCESS /obj/item/bee_smoker/attackby(obj/item/herb, mob/living/carbon/human/user, list/modifiers) . = ..() diff --git a/code/modules/hydroponics/unique_plant_genes.dm b/code/modules/hydroponics/unique_plant_genes.dm index 99c877cdfbe..c3855ff6939 100644 --- a/code/modules/hydroponics/unique_plant_genes.dm +++ b/code/modules/hydroponics/unique_plant_genes.dm @@ -76,24 +76,9 @@ return /// Signal proc for [COMSIG_ITEM_AFTERATTACK] that allows for effects after an attack is done -/datum/plant_gene/trait/attack/proc/after_plant_attack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) +/datum/plant_gene/trait/attack/proc/after_plant_attack(obj/item/source, atom/target, mob/user, click_parameters) SIGNAL_HANDLER - - if(!proximity_flag) - return - - if(!ismovable(target)) - return - - . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - - if(isobj(target)) - var/obj/object_target = target - if(!(object_target.obj_flags & CAN_BE_HIT)) - return . - INVOKE_ASYNC(src, PROC_REF(after_attack_effect), source, target, user) - return . /* * Effects done when we hit people with our plant, AFTER the attack is done. diff --git a/code/modules/library/bibles.dm b/code/modules/library/bibles.dm index 31630c550a1..8c2ad28fead 100644 --- a/code/modules/library/bibles.dm +++ b/code/modules/library/bibles.dm @@ -269,49 +269,48 @@ GLOBAL_LIST_INIT(bibleitemstates, list( playsound(target_mob, SFX_PUNCH, 25, TRUE, -1) log_combat(user, target_mob, "attacked", src) -/obj/item/book/bible/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/obj/item/book/bible/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) return !istype(storage_holder, /obj/item/book/bible) -/obj/item/book/bible/afterattack(atom/bible_smacked, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag) - return - if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user, proximity_flag, click_parameters) & COMSIG_END_BIBLE_CHAIN) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/book/bible/interact_with_atom(atom/bible_smacked, mob/living/user, list/modifiers) + if(SEND_SIGNAL(bible_smacked, COMSIG_BIBLE_SMACKED, user) & COMSIG_END_BIBLE_CHAIN) + return ITEM_INTERACT_SUCCESS if(isfloorturf(bible_smacked)) if(user.mind?.holy_role) var/area/current_area = get_area(bible_smacked) if(!GLOB.chaplain_altars.len && istype(current_area, /area/station/service/chapel)) make_new_altar(bible_smacked, user) - return + return ITEM_INTERACT_SUCCESS for(var/obj/effect/rune/nearby_runes in range(2, user)) nearby_runes.SetInvisibility(INVISIBILITY_NONE, id=type, priority=INVISIBILITY_PRIORITY_BASIC_ANTI_INVISIBILITY) bible_smacked.balloon_alert(user, "floor smacked!") + return ITEM_INTERACT_SUCCESS if(user.mind?.holy_role) - if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/water)) // blesses all the water in the holder - . |= AFTERATTACK_PROCESSED_ITEM + if(bible_smacked.reagents?.has_reagent(/datum/reagent/water)) // blesses all the water in the holder bible_smacked.balloon_alert(user, "blessed") var/water2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/water) bible_smacked.reagents.del_reagent(/datum/reagent/water) bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,water2holy) - if(bible_smacked.reagents && bible_smacked.reagents.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me - . |= AFTERATTACK_PROCESSED_ITEM + . = ITEM_INTERACT_SUCCESS + if(bible_smacked.reagents?.has_reagent(/datum/reagent/fuel/unholywater)) // yeah yeah, copy pasted code - sue me bible_smacked.balloon_alert(user, "purified") var/unholy2holy = bible_smacked.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater) bible_smacked.reagents.del_reagent(/datum/reagent/fuel/unholywater) bible_smacked.reagents.add_reagent(/datum/reagent/water/holywater,unholy2holy) + . = ITEM_INTERACT_SUCCESS if(istype(bible_smacked, /obj/item/book/bible) && !istype(bible_smacked, /obj/item/book/bible/syndicate)) - . |= AFTERATTACK_PROCESSED_ITEM bible_smacked.balloon_alert(user, "converted") var/obj/item/book/bible/other_bible = bible_smacked other_bible.name = name other_bible.icon_state = icon_state other_bible.inhand_icon_state = inhand_icon_state other_bible.deity_name = deity_name + . = ITEM_INTERACT_SUCCESS + if(.) + return . if(istype(bible_smacked, /obj/item/cult_bastard) && !IS_CULTIST(user)) - . |= AFTERATTACK_PROCESSED_ITEM var/obj/item/cult_bastard/sword = bible_smacked bible_smacked.balloon_alert(user, "exorcising...") playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,TRUE) @@ -333,6 +332,9 @@ GLOBAL_LIST_INIT(bibleitemstates, list( new /obj/item/nullrod/claymore(get_turf(sword)) user.visible_message(span_notice("[user] exorcises [sword]!")) qdel(sword) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + return NONE /obj/item/book/bible/booze desc = "To be applied to the head repeatedly." diff --git a/code/modules/mapfluff/ruins/lavalandruin_code/puzzle.dm b/code/modules/mapfluff/ruins/lavalandruin_code/puzzle.dm index 1ec15d01345..ef6dc902c9f 100644 --- a/code/modules/mapfluff/ruins/lavalandruin_code/puzzle.dm +++ b/code/modules/mapfluff/ruins/lavalandruin_code/puzzle.dm @@ -320,21 +320,23 @@ icon = 'icons/obj/mining_zones/artefacts.dmi' icon_state = "prison_cube" -/obj/item/prisoncube/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !isliving(target)) - return - var/mob/living/victim = target - var/mob/living/carbon/carbon_victim = victim +/obj/item/prisoncube/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isliving(interacting_with)) + return NONE + + var/mob/living/carbon/carbon_victim = interacting_with //Handcuffed or unconscious - if(istype(carbon_victim) && carbon_victim.handcuffed || victim.stat != CONSCIOUS) - if(!puzzle_imprison(target)) - to_chat(user,span_warning("[src] does nothing.")) - return - to_chat(user,span_warning("You trap [victim] in the prison cube!")) + if(istype(carbon_victim) && (carbon_victim.handcuffed || carbon_victim.stat != CONSCIOUS)) + user.do_attack_animation(carbon_victim) + if(!puzzle_imprison(carbon_victim)) + to_chat(user, span_warning("[src] does nothing.")) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_warning("You trap [carbon_victim] in the prison cube!")) qdel(src) - else - to_chat(user,span_notice("[src] only accepts restrained or unconscious prisoners.")) + return ITEM_INTERACT_SUCCESS + + to_chat(user, span_notice("[src] only accepts restrained or unconscious prisoners.")) + return ITEM_INTERACT_BLOCKING /proc/puzzle_imprison(mob/living/prisoner) var/turf/T = get_turf(prisoner) diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/mapfluff/ruins/objects_and_mobs/sin_ruins.dm index 713aa260df9..15566603a93 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/sin_ruins.dm @@ -36,18 +36,17 @@ w_class = WEIGHT_CLASS_NORMAL hitsound = 'sound/weapons/bladeslice.ogg' -/obj/item/knife/envy/afterattack(atom/movable/AM, mob/living/carbon/human/user, proximity) - . = ..() - if(!proximity) +/obj/item/knife/envy/afterattack(atom/target, mob/living/carbon/human/user, click_parameters) + if(!istype(user) || !ishuman(target)) return - if(!istype(user)) + + var/mob/living/carbon/human/H = target + if(user.real_name == H.dna.real_name) return - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(user.real_name != H.dna.real_name) - user.real_name = H.dna.real_name - H.dna.transfer_identity(user, transfer_SE=1) - user.updateappearance(mutcolor_update=1) - user.domutcheck() - user.visible_message(span_warning("[user]'s appearance shifts into [H]'s!"), \ - span_boldannounce("[H.p_They()] think[H.p_s()] [H.p_theyre()] sooo much better than you. Not anymore, [H.p_they()] won't.")) + + user.real_name = H.dna.real_name + H.dna.transfer_identity(user, transfer_SE=1) + user.updateappearance(mutcolor_update=1) + user.domutcheck() + user.visible_message(span_warning("[user]'s appearance shifts into [H]'s!"), \ + span_boldannounce("[H.p_They()] think[H.p_s()] [H.p_theyre()] sooo much better than you. Not anymore, [H.p_they()] won't.")) diff --git a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm index b341b8d5073..059d9c8aa9e 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/hilbertshotel.dm @@ -549,14 +549,12 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999)) icon_state = "hilbertsanalyzer" worn_icon_state = "analyzer" -/obj/item/analyzer/hilbertsanalyzer/afterattack(atom/target, mob/user, proximity) - . = ..() - if(istype(target, /obj/item/hilbertshotel)) - . |= AFTERATTACK_PROCESSED_ITEM - if(!proximity) +/obj/item/analyzer/hilbertsanalyzer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/item/hilbertshotel)) + if(!Adjacent(interacting_with)) to_chat(user, span_warning("It's to far away to scan!")) - return . - var/obj/item/hilbertshotel/sphere = target + return ITEM_INTERACT_BLOCKING + var/obj/item/hilbertshotel/sphere = interacting_with if(sphere.activeRooms.len) to_chat(user, "Currently Occupied Rooms:") for(var/roomnumber in sphere.activeRooms) @@ -569,7 +567,8 @@ GLOBAL_VAR_INIT(hhMysteryRoomNumber, rand(1, 999999)) to_chat(user, roomnumber) else to_chat(user, "No vacated rooms.") - return . + return ITEM_INTERACT_SUCCESS + return ..() /obj/effect/landmark/transport/transport_id/hilbert specific_transport_id = HILBERT_LINE_1 diff --git a/code/modules/mining/equipment/grapple_gun.dm b/code/modules/mining/equipment/grapple_gun.dm index c7c91ede73e..6a8b2ec3053 100644 --- a/code/modules/mining/equipment/grapple_gun.dm +++ b/code/modules/mining/equipment/grapple_gun.dm @@ -35,26 +35,22 @@ zipline_sound = new(src) update_appearance() -/obj/item/grapple_gun/afterattack(atom/target, mob/living/user, proximity) - . = ..() - +/obj/item/grapple_gun/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers) if(isgroundlessturf(target)) - return + return NONE + if(target == user || !hooked) + return NONE if(!lavaland_equipment_pressure_check(get_turf(user))) user.balloon_alert(user, "gun mechanism wont work here!") - return - - if(target == user || !hooked) - return - + return ITEM_INTERACT_BLOCKING if(get_dist(user, target) > 9) user.balloon_alert(user, "too far away!") - return + return ITEM_INTERACT_BLOCKING var/turf/attacked_atom = get_turf(target) if(isnull(attacked_atom)) - return + return ITEM_INTERACT_BLOCKING var/list/turf_list = (get_line(user, attacked_atom) - get_turf(src)) for(var/turf/singular_turf as anything in turf_list) @@ -66,9 +62,7 @@ break if(user.CanReach(attacked_atom)) - return - - . |= AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING var/atom/bullet = fire_projectile(/obj/projectile/grapple_hook, attacked_atom, 'sound/weapons/zipline_fire.ogg') zipline = user.Beam(bullet, icon_state = "zipline_hook", maxdistance = 9, layer = BELOW_MOB_LAYER) @@ -77,6 +71,7 @@ RegisterSignal(bullet, COMSIG_PREQDELETED, PROC_REF(on_grapple_fail)) zipliner = WEAKREF(user) update_appearance() + return ITEM_INTERACT_SUCCESS /obj/item/grapple_gun/proc/on_grapple_hit(datum/source, atom/movable/firer, atom/target, Angle) SIGNAL_HANDLER diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 1ff620c141e..f31e522812e 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -84,27 +84,24 @@ crusher_trophy.remove_from(src, user) return ITEM_INTERACT_SUCCESS -/obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) +/obj/item/kinetic_crusher/pre_attack(atom/A, mob/living/user, params) + . = ..() + if(.) + return TRUE if(!HAS_TRAIT(src, TRAIT_WIELDED) && !acts_as_if_wielded) // NOVA EDIT CHANGE - Original: if(!HAS_TRAIT(src, TRAIT_WIELDED)) user.balloon_alert(user, "must be wielded!") - return - var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) - if(!crusher_damage_effect) - crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage) - var/target_health = target.health - ..() - for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) - if(!QDELETED(target)) - crusher_trophy.on_melee_hit(target, user) - if(!QDELETED(crusher_damage_effect) && !QDELETED(target)) - crusher_damage_effect.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did + return TRUE + return . -/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, proximity_flag, clickparams) - . = ..() - if(.) +/obj/item/kinetic_crusher/afterattack(mob/living/target, mob/living/user, clickparams) + if(!isliving(target)) return - if(!proximity_flag || !isliving(target)) + // Melee effect + for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) + crusher_trophy.on_melee_hit(target, user) + if(QDELETED(target)) return + // Clear existing marks var/valid_crusher_attack = FALSE for(var/datum/status_effect/crusher_mark/crusher_mark_effect as anything in target.get_all_status_effect_of_id(/datum/status_effect/crusher_mark)) //this will erase ALL crusher marks, not only ones by you. @@ -114,9 +111,8 @@ break if(!valid_crusher_attack) return - var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) - if(!crusher_damage_effect) - crusher_damage_effect = target.apply_status_effect(/datum/status_effect/crusher_damage) + // Detonation effect + var/datum/status_effect/crusher_damage/crusher_damage_effect = target.has_status_effect(/datum/status_effect/crusher_damage) || target.apply_status_effect(/datum/status_effect/crusher_damage) var/target_health = target.health for(var/obj/item/crusher_trophy/crusher_trophy as anything in trophies) crusher_trophy.on_mark_detonation(target, user) @@ -129,6 +125,7 @@ var/combined_damage = detonation_damage var/backstab_dir = get_dir(user, target) var/def_check = target.getarmor(type = BOMB) + // Backstab bonus if((user.dir & backstab_dir) && (target.dir & backstab_dir)) backstabbed = TRUE combined_damage += backstab_bonus @@ -138,24 +135,23 @@ SEND_SIGNAL(user, COMSIG_LIVING_CRUSHER_DETONATE, target, src, backstabbed) target.apply_damage(combined_damage, BRUTE, blocked = def_check) -/obj/item/kinetic_crusher/attack_secondary(atom/target, mob/living/user, clickparams) - return SECONDARY_ATTACK_CONTINUE_CHAIN - -/obj/item/kinetic_crusher/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters) +/obj/item/kinetic_crusher/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(!HAS_TRAIT(src, TRAIT_WIELDED) && !acts_as_if_wielded) // NOVA EDIT CHANGE - Original: if(!HAS_TRAIT(src, TRAIT_WIELDED)) balloon_alert(user, "wield it first!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(target == user) + return ITEM_INTERACT_BLOCKING + if(interacting_with == user) balloon_alert(user, "can't aim at yourself!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - fire_kinetic_blast(target, user, click_parameters) + return ITEM_INTERACT_BLOCKING + fire_kinetic_blast(interacting_with, user, modifiers) user.changeNext_move(CLICK_CD_MELEE) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS + +/obj/item/kinetic_crusher/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom_secondary(interacting_with, user, modifiers) -/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, click_parameters) +/obj/item/kinetic_crusher/proc/fire_kinetic_blast(atom/target, mob/living/user, list/modifiers) if(!charged) return - var/modifiers = params2list(click_parameters) var/turf/proj_turf = user.loc if(!isturf(proj_turf)) return @@ -188,7 +184,7 @@ return COMSIG_SABOTEUR_SUCCESS /obj/item/kinetic_crusher/update_icon_state() - inhand_icon_state = "crusher[HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent + inhand_icon_state = "crusher[HAS_TRAIT(src, TRAIT_WIELDED)]" // this is not icon_state and not supported by 2hcomponent return ..() /obj/item/kinetic_crusher/update_overlays() diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index ff90c418c88..4e82c03d373 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -25,27 +25,25 @@ ///So you can't revive boss monsters or robots with it var/revive_type = SENTIENCE_ORGANIC -/obj/item/lazarus_injector/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!loaded || !proximity_flag) - return - +/obj/item/lazarus_injector/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!loaded) + return NONE if(SEND_SIGNAL(target, COMSIG_ATOM_ON_LAZARUS_INJECTOR, src, user) & LAZARUS_INJECTOR_USED) - return - + return ITEM_INTERACT_SUCCESS if(!isliving(target)) - return + return NONE var/mob/living/target_animal = target if(!target_animal.compare_sentience_type(revive_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway balloon_alert(user, "invalid creature!") - return + return ITEM_INTERACT_BLOCKING if(target_animal.stat != DEAD) balloon_alert(user, "it's not dead!") - return + return ITEM_INTERACT_BLOCKING target_animal.lazarus_revive(user, malfunctioning) expend(target_animal, user) + return ITEM_INTERACT_SUCCESS /obj/item/lazarus_injector/proc/expend(atom/revived_target, mob/user) user.visible_message(span_notice("[user] injects [revived_target] with [src], reviving it.")) diff --git a/code/modules/mining/equipment/monster_organs/monster_organ.dm b/code/modules/mining/equipment/monster_organs/monster_organ.dm index 135373469d8..a854f113740 100644 --- a/code/modules/mining/equipment/monster_organs/monster_organ.dm +++ b/code/modules/mining/equipment/monster_organs/monster_organ.dm @@ -8,24 +8,21 @@ desc = "Inject certain types of monster organs with this stabilizer to prevent their rapid decay." w_class = WEIGHT_CLASS_TINY -/obj/item/mining_stabilizer/afterattack(obj/item/organ/target_organ, mob/user, proximity) - . = ..() - if (!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - - var/obj/item/organ/internal/monster_core/target_core = target_organ - if (!istype(target_core, /obj/item/organ/internal/monster_core)) +/obj/item/mining_stabilizer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isorgan(interacting_with)) + return NONE + var/obj/item/organ/internal/monster_core/target_core = interacting_with + if (!istype(target_core)) balloon_alert(user, "invalid target!") - return . + return ITEM_INTERACT_BLOCKING if (!target_core.preserve()) balloon_alert(user, "organ decayed!") - return . + return ITEM_INTERACT_BLOCKING balloon_alert(user, "organ stabilized") qdel(src) - return . + return ITEM_INTERACT_SUCCESS /** * Useful organs which drop as loot from a mining creature. @@ -135,12 +132,9 @@ icon_state = initial(icon_state) return ..() -/obj/item/organ/internal/monster_core/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if (!proximity_flag) - return - try_apply(target, user) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/organ/internal/monster_core/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + try_apply(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/organ/internal/monster_core/attack_self(mob/user) if (!user.can_perform_action(src, FORBID_TELEKINESIS_REACH|ALLOW_RESTING)) diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index 035bbb24fc4..56b65c45619 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -51,36 +51,33 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) beacon_ref = WEAKREF(chosen_beacon) balloon_alert(user, "linked!") -/obj/item/extraction_pack/afterattack(atom/movable/thing, mob/living/carbon/human/user, proximity_flag, params) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/extraction_pack/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ismovable(interacting_with)) + return NONE + if(!isturf(interacting_with.loc)) // no extracting stuff inside other stuff + return NONE + var/atom/movable/thing = interacting_with + if(thing.anchored) + return NONE + + . = ITEM_INTERACT_BLOCKING var/obj/structure/extraction_point/beacon = beacon_ref?.resolve() if(isnull(beacon)) - balloon_alert(user, "not linked") + balloon_alert(user, "not linked!") beacon_ref = null - return - + return . if(!can_use_indoors) var/area/area = get_area(thing) if(!area.outdoors) - balloon_alert(user, "not outdoors") - return - - if(!proximity_flag || !istype(thing)) - return - + balloon_alert(user, "not outdoors!") + return . if(!safe_for_living_creatures && check_for_living_mobs(thing)) to_chat(user, span_warning("[src] is not safe for use with living creatures, they wouldn't survive the trip back!")) balloon_alert(user, "not safe!") - return - - if(!isturf(thing.loc)) // no extracting stuff inside other stuff - return - if(thing.anchored || (thing.move_resist > max_force_fulton)) + return . + if(thing.move_resist > max_force_fulton) balloon_alert(user, "too heavy!") - return - + return . balloon_alert_to_viewers("attaching...") playsound(thing, 'sound/items/zip.ogg', vol = 50, vary = TRUE) if(isliving(thing)) @@ -89,11 +86,12 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) to_chat(thing, span_userdanger("You are being extracted! Stand still to proceed.")) if(!do_after(user, 5 SECONDS, target = thing)) - return + return . balloon_alert_to_viewers("extracting!") - if(loc == user) - user.back?.atom_storage?.attempt_insert(src, user, force = STORAGE_SOFT_LOCKED) + if(loc == user && ishuman(user)) + var/mob/living/carbon/human/human_user = user + human_user.back?.atom_storage?.attempt_insert(src, user, force = STORAGE_SOFT_LOCKED) uses_left-- if(uses_left <= 0) @@ -180,6 +178,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) qdel(holder_obj) if(uses_left <= 0) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/fulton_core name = "extraction beacon assembly kit" diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 99f04ce5498..5e3cdcf6a2b 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -99,14 +99,14 @@ blink_activated = !blink_activated to_chat(user, span_notice("You [blink_activated ? "enable" : "disable"] the blink function on [src].")) -/obj/item/hierophant_club/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/hierophant_club/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) // If our target is the beacon and the hierostaff is next to the beacon, we're trying to pick it up. - if((target == beacon) && target.Adjacent(src)) - return + if(interacting_with == beacon) + return NONE if(blink_activated) - blink.teleport(user, target) + blink.teleport(user, interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/hierophant_club/update_icon_state() icon_state = inhand_icon_state = "hierophant_club[blink?.current_charges > 0 ? "_ready":""][(!QDELETED(beacon)) ? "":"_beacon"]" @@ -797,40 +797,43 @@ var/timer = 0 var/static/list/banned_turfs = typecacheof(list(/turf/open/space, /turf/closed)) -/obj/item/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() +/obj/item/lava_staff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return interact_with_atom(interacting_with, user, modifiers) + +/obj/item/lava_staff/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(timer > world.time) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(is_type_in_typecache(target, banned_turfs)) - return - if(target in view(user.client.view, get_turf(user))) - var/turf/open/T = get_turf(target) - if(!istype(T)) - return - if(!islava(T)) - var/obj/effect/temp_visual/lavastaff/L = new /obj/effect/temp_visual/lavastaff(T) - L.alpha = 0 - animate(L, alpha = 255, time = create_delay) - user.visible_message(span_danger("[user] points [src] at [T]!")) - timer = world.time + create_delay + 1 - if(do_after(user, create_delay, target = T)) - var/old_name = T.name - if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR)) - user.visible_message(span_danger("[user] turns \the [old_name] into [transform_string]!")) - message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]") - user.log_message("fired the lava staff at [AREACOORD(T)].", LOG_ATTACK) - timer = world.time + create_cooldown - playsound(T,'sound/magic/fireball.ogg', 200, TRUE) - else - timer = world.time - qdel(L) - else + return NONE + if(is_type_in_typecache(interacting_with, banned_turfs)) + return NONE + if(!(interacting_with in view(user.client.view, get_turf(user)))) + return NONE + var/turf/open/T = get_turf(interacting_with) + if(!istype(T)) + return NONE + if(!islava(T)) + var/obj/effect/temp_visual/lavastaff/L = new /obj/effect/temp_visual/lavastaff(T) + L.alpha = 0 + animate(L, alpha = 255, time = create_delay) + user.visible_message(span_danger("[user] points [src] at [T]!")) + timer = world.time + create_delay + 1 + if(do_after(user, create_delay, target = T)) var/old_name = T.name - if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR)) - user.visible_message(span_danger("[user] turns \the [old_name] into [reset_string]!")) - timer = world.time + reset_cooldown + if(T.TerraformTurf(turf_type, flags = CHANGETURF_INHERIT_AIR)) + user.visible_message(span_danger("[user] turns \the [old_name] into [transform_string]!")) + message_admins("[ADMIN_LOOKUPFLW(user)] fired the lava staff at [ADMIN_VERBOSEJMP(T)]") + user.log_message("fired the lava staff at [AREACOORD(T)].", LOG_ATTACK) + timer = world.time + create_cooldown playsound(T,'sound/magic/fireball.ogg', 200, TRUE) + else + timer = world.time + qdel(L) + else + var/old_name = T.name + if(T.TerraformTurf(reset_turf_type, flags = CHANGETURF_INHERIT_AIR)) + user.visible_message(span_danger("[user] turns \the [old_name] into [reset_string]!")) + timer = world.time + reset_cooldown + playsound(T,'sound/magic/fireball.ogg', 200, TRUE) + return ITEM_INTERACT_SUCCESS /obj/effect/temp_visual/lavastaff icon_state = "lavastaff_warn" @@ -1030,23 +1033,27 @@ affected_weather.wind_down() user.log_message("has dispelled a storm at [AREACOORD(user_turf)].", LOG_GAME) -/obj/item/storm_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/storm_staff/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return thunder_blast(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + +/obj/item/storm_staff/afterattack(atom/target, mob/user, click_parameters) + thunder_blast(target, user) + +/obj/item/storm_staff/proc/thunder_blast(atom/target, mob/user) if(!thunder_charges) balloon_alert(user, "needs to charge!") - return + return FALSE var/turf/target_turf = get_turf(target) var/area/target_area = get_area(target) if(!target_turf || !target_area || (is_type_in_list(target_area, excluded_areas))) balloon_alert(user, "can't bolt here!") - return + return FALSE if(target_turf in targeted_turfs) balloon_alert(user, "already targeted!") - return + return FALSE if(HAS_TRAIT(user, TRAIT_PACIFISM)) balloon_alert(user, "you don't want to harm!") - return + return FALSE var/power_boosted = FALSE for(var/datum/weather/weather as anything in SSweather.processing) if(weather.stage != MAIN_STAGE) @@ -1062,6 +1069,7 @@ thunder_charges-- addtimer(CALLBACK(src, PROC_REF(recharge)), thunder_charge_time) user.log_message("fired the staff of storms at [AREACOORD(target_turf)].", LOG_ATTACK) + return TRUE /obj/item/storm_staff/proc/recharge(mob/user) thunder_charges = min(thunder_charges + 1, max_thunder_charges) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index f5d6f6b62b2..d2a9af576ce 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -649,20 +649,18 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ continue target_airlock.lock() -/obj/item/coin/eldritch/afterattack(atom/target_atom, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/coin/eldritch/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/machinery/door/airlock)) + return NONE if(!IS_HERETIC(user)) - var/mob/living/living_user = user - living_user.adjustBruteLoss(5) - living_user.adjustFireLoss(5) - return - if(istype(target_atom, /obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/target_airlock = target_atom - to_chat(user, span_warning("You insert [src] into the airlock.")) - target_airlock.emag_act(user, src) - qdel(src) + user.adjustBruteLoss(5) + user.adjustFireLoss(5) + return ITEM_INTERACT_BLOCKING + var/obj/machinery/door/airlock/target_airlock = interacting_with + to_chat(user, span_warning("You insert [src] into the airlock.")) + target_airlock.emag_act(user, src) + qdel(src) + return ITEM_INTERACT_SUCCESS #undef GIBTONITE_QUALITY_HIGH #undef GIBTONITE_QUALITY_LOW diff --git a/code/modules/mob/living/basic/minebots/minebot.dm b/code/modules/mob/living/basic/minebots/minebot.dm index 32f0ed80121..54fe9a07367 100644 --- a/code/modules/mob/living/basic/minebots/minebot.dm +++ b/code/modules/mob/living/basic/minebots/minebot.dm @@ -215,10 +215,10 @@ balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]") return CLICK_ACTION_SUCCESS -/mob/living/basic/mining_drone/RangedAttack(atom/target) +/mob/living/basic/mining_drone/RangedAttack(atom/target, list/modifiers) if(!combat_mode) return - stored_gun.afterattack(target, src) + stored_gun.try_fire_gun(target, src, list2params(modifiers)) /mob/living/basic/mining_drone/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers) . = ..() diff --git a/code/modules/mob/living/basic/minebots/minebot_remote_control.dm b/code/modules/mob/living/basic/minebots/minebot_remote_control.dm index 618edc3d0b6..36019409123 100644 --- a/code/modules/mob/living/basic/minebots/minebot_remote_control.dm +++ b/code/modules/mob/living/basic/minebots/minebot_remote_control.dm @@ -43,22 +43,22 @@ user.client?.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi' user.update_mouse_pointer() -/obj/item/minebot_remote_control/afterattack(atom/attacked_atom, mob/living/user, proximity) - . = ..() - - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/minebot_remote_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) +/obj/item/minebot_remote_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!primed) user.balloon_alert(user, "not primed!") - return - var/turf/target_turf = get_turf(attacked_atom) + return ITEM_INTERACT_BLOCKING + var/turf/target_turf = get_turf(interacting_with) if(isnull(target_turf) || isclosedturf(target_turf) || isgroundlessturf(target_turf)) user.balloon_alert(user, "invalid target!") - return + return ITEM_INTERACT_BLOCKING playsound(src, 'sound/machines/beep.ogg', 30) clear_priming() new /obj/effect/temp_visual/minebot_target(target_turf) COOLDOWN_START(src, bomb_timer, BOMB_COOLDOWN) + return ITEM_INTERACT_SUCCESS /obj/effect/temp_visual/minebot_target name = "Rocket Target" diff --git a/code/modules/mob/living/basic/minebots/minebot_upgrades.dm b/code/modules/mob/living/basic/minebots/minebot_upgrades.dm index 14c62f7fefc..881342bcf66 100644 --- a/code/modules/mob/living/basic/minebots/minebot_upgrades.dm +++ b/code/modules/mob/living/basic/minebots/minebot_upgrades.dm @@ -5,11 +5,11 @@ icon = 'icons/obj/devices/circuitry_n_data.dmi' item_flags = NOBLUDGEON -/obj/item/mine_bot_upgrade/afterattack(mob/living/basic/mining_drone/minebot, mob/user, proximity) - . = ..() - if(!istype(minebot) || !proximity) - return - upgrade_bot(minebot, user) +/obj/item/mine_bot_upgrade/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /mob/living/basic/mining_drone)) + return NONE + upgrade_bot(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/mine_bot_upgrade/proc/upgrade_bot(mob/living/basic/mining_drone/minebot, mob/user) if(minebot.melee_damage_upper != initial(minebot.melee_damage_upper)) @@ -90,4 +90,3 @@ icon = 'icons/mob/silicon/aibots.dmi' icon_state = "minebot_shield_bottom_layer" layer = BELOW_MOB_LAYER - diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm index 04d52cf6212..f936caa1d51 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm @@ -18,18 +18,17 @@ /mob/living/basic/guardian, )) -/obj/item/fugu_gland/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag || !isanimal_or_basicmob(target) || fugu_blacklist[target.type]) - return - var/mob/living/animal = target +/obj/item/fugu_gland/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isanimal_or_basicmob(interacting_with) || fugu_blacklist[interacting_with.type]) + return NONE + var/mob/living/animal = interacting_with if(animal.stat == DEAD || HAS_TRAIT(animal, TRAIT_FAKEDEATH)) balloon_alert(user, "it's dead!") - return + return ITEM_INTERACT_BLOCKING if(HAS_TRAIT(animal, TRAIT_FUGU_GLANDED)) balloon_alert(user, "already large!") - return + return ITEM_INTERACT_BLOCKING ADD_TRAIT(animal, TRAIT_FUGU_GLANDED, type) animal.AddComponent(/datum/component/seethrough_mob) @@ -41,3 +40,4 @@ animal.AddElement(/datum/element/wall_tearer) to_chat(user, span_info("You increase the size of [animal], giving [animal.p_them()] a surge of strength!")) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index cf12c2b4083..f951b8c4898 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -352,18 +352,18 @@ return ..() -/obj/item/food/deadmouse/afterattack(obj/target, mob/living/user, proximity_flag) - . = ..() - if(proximity_flag && reagents && target.is_open_container()) - . |= AFTERATTACK_PROCESSED_ITEM - // is_open_container will not return truthy if target.reagents doesn't exist - var/datum/reagents/target_reagents = target.reagents - var/trans_amount = reagents.maximum_volume - reagents.total_volume * (4 / 3) - if(target_reagents.has_reagent(/datum/reagent/fuel) && target_reagents.trans_to(src, trans_amount)) - to_chat(user, span_notice("You dip [src] into [target].")) - else - to_chat(user, span_warning("That's a terrible idea.")) - return . +/obj/item/food/deadmouse/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isnull(reagents) || !interacting_with.is_open_container()) + return NONE + + // is_open_container will not return truthy if target.reagents doesn't exist + var/datum/reagents/target_reagents = interacting_with.reagents + var/trans_amount = reagents.maximum_volume - reagents.total_volume * (4 / 3) + if(target_reagents.has_reagent(/datum/reagent/fuel) && target_reagents.trans_to(src, trans_amount)) + to_chat(user, span_notice("You dip [src] into [interacting_with].")) + else + to_chat(user, span_warning("That's a terrible idea.")) + return ITEM_INTERACT_BLOCKING /obj/item/food/deadmouse/moldy name = "moldy dead mouse" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index d154bcc6706..31b2ac8e2d5 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -23,15 +23,14 @@ QDEL_NULL(dna) GLOB.carbon_list -= src -/mob/living/carbon/item_tending(mob/living/user, obj/item/tool, list/modifiers) +/mob/living/carbon/item_interaction(mob/living/user, obj/item/tool, list/modifiers) . = ..() if(. & ITEM_INTERACT_ANY_BLOCKER) return . - + // Needs to happen after parent call otherwise wounds are prioritized over surgery for(var/datum/wound/wound as anything in shuffle(all_wounds)) if(wound.try_treating(tool, user)) return ITEM_INTERACT_SUCCESS - return . /mob/living/carbon/click_ctrl_shift(mob/user) diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index f4487bfc9d9..db883e9141b 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -82,7 +82,7 @@ if(!can_unarmed_attack()) return if(internal_ext) - internal_ext.afterattack(A, src) + internal_ext.interact_with_atom(A, src, modifiers) else return ..() @@ -90,7 +90,7 @@ if(!(bot_mode_flags & BOT_MODE_ON)) return if(internal_ext) - internal_ext.afterattack(A, src) + internal_ext.interact_with_atom(A, src, modifiers) else return ..() @@ -289,7 +289,7 @@ flick("firebots_use", user) else flick("firebot1_use", user) - internal_ext.afterattack(target, user, null) + internal_ext.interact_with_atom(target, src) /mob/living/simple_animal/bot/firebot/update_icon_state() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 71801a44c95..7139f6a92bf 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -368,26 +368,26 @@ While using this makes the system rely on OnFire, it still gives options for tim throw_speed = 3 throw_range = 5 -/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag) - var/mob/living/simple_animal/hostile/asteroid/elite/E = target - if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key) - user.visible_message(span_notice("It appears [E] is unable to be revived right now. Perhaps try again later.")) - return - E.faction = list("[REF(user)]") - E.revive(HEAL_ALL) - user.visible_message(span_notice("[user] stabs [E] with [src], reviving it.")) - E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0) - to_chat(E, "You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.") - to_chat(E, "Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!") - E.maxHealth = E.maxHealth * 0.4 - E.health = E.maxHealth - E.desc = "[E.desc] However, this one appears to be less wild in nature, and calmer around people." - E.sentience_type = SENTIENCE_ORGANIC - qdel(src) - else - to_chat(user, span_info("[src] only works on the corpse of a sentient lavaland elite.")) +/obj/item/tumor_shard/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /mob/living/simple_animal/hostile/asteroid/elite)) + return NONE + + var/mob/living/simple_animal/hostile/asteroid/elite/E = interacting_with + if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key) + user.visible_message(span_notice("It appears [E] is unable to be revived right now. Perhaps try again later.")) + return ITEM_INTERACT_BLOCKING + E.faction = list("[REF(user)]") + E.revive(HEAL_ALL) + user.visible_message(span_notice("[user] stabs [E] with [src], reviving it.")) + E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0) + to_chat(E, "You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.") + to_chat(E, "Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!") + E.maxHealth = E.maxHealth * 0.4 + E.health = E.maxHealth + E.desc = "[E.desc] However, this one appears to be less wild in nature, and calmer around people." + E.sentience_type = SENTIENCE_ORGANIC + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/effect/temp_visual/elite_tumor_wall name = "magic wall" diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 69ce474ab91..a82f91d8353 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -147,6 +147,9 @@ if(active) . += span_notice("Charge: [core ? "[get_charge_percent()]%" : "No core"].") . += span_notice("Selected module: [selected_module || "None"].") + if(atom_storage) + . += span_notice("While the suit's panel is open, \ + being on combat mode will prevent you from inserting items into it when clicking on it.") if(!open && !active) if(!wearer) . += span_notice("You could equip it to turn it on.") @@ -253,33 +256,28 @@ add_fingerprint(user) /obj/item/mod/control/wrench_act(mob/living/user, obj/item/wrench) - if(..()) - return TRUE if(seconds_electrified && get_charge() && shock(user)) - return TRUE + return ITEM_INTERACT_BLOCKING if(open) if(!core) balloon_alert(user, "no core!") - return TRUE + return ITEM_INTERACT_BLOCKING balloon_alert(user, "removing core...") wrench.play_tool_sound(src, 100) if(!wrench.use_tool(src, user, 3 SECONDS) || !open) balloon_alert(user, "interrupted!") - return TRUE + return ITEM_INTERACT_BLOCKING wrench.play_tool_sound(src, 100) balloon_alert(user, "core removed") core.forceMove(drop_location()) - return TRUE - return ..() + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/mod/control/screwdriver_act(mob/living/user, obj/item/screwdriver) - . = ..() - if(.) - return TRUE if(active || activating || ai_controller) balloon_alert(user, "deactivate suit first!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING balloon_alert(user, "[open ? "closing" : "opening"] cover...") screwdriver.play_tool_sound(src, 100) if(screwdriver.use_tool(src, user, 1 SECONDS)) @@ -290,21 +288,21 @@ open = !open else balloon_alert(user, "interrupted!") - return TRUE + return ITEM_INTERACT_SUCCESS /obj/item/mod/control/crowbar_act(mob/living/user, obj/item/crowbar) . = ..() if(!open) balloon_alert(user, "open the cover first!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING if(!allowed(user)) balloon_alert(user, "insufficient access!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return + return ITEM_INTERACT_BLOCKING if(SEND_SIGNAL(src, COMSIG_MOD_MODULE_REMOVAL, user) & MOD_CANCEL_REMOVAL) playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING if(length(modules)) var/list/removable_modules = list() for(var/obj/item/mod/module/module as anything in modules) @@ -313,52 +311,64 @@ removable_modules += module var/obj/item/mod/module/module_to_remove = tgui_input_list(user, "Which module to remove?", "Module Removal", removable_modules) if(!module_to_remove?.mod) - return FALSE + return ITEM_INTERACT_BLOCKING uninstall(module_to_remove) module_to_remove.forceMove(drop_location()) crowbar.play_tool_sound(src, 100) SEND_SIGNAL(src, COMSIG_MOD_MODULE_REMOVED, user) - return TRUE + return ITEM_INTERACT_SUCCESS balloon_alert(user, "no modules!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING + +/obj/item/mod/control/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + if(user.combat_mode) + // Block all item-click-inserts when we're open + // Other form of insertion will still function (mousedrop, hotkey) + if(open) + return FALSE + // ...You have to open it up somehow though + if(inserted.tool_behaviour == TOOL_SCREWDRIVER) + return FALSE + return TRUE -/obj/item/mod/control/attackby(obj/item/attacking_item, mob/living/user, params) +/obj/item/mod/control/item_interaction(mob/living/user, obj/item/attacking_item, list/modifiers) if(istype(attacking_item, /obj/item/pai_card)) if(!open) balloon_alert(user, "open the cover first!") - return FALSE + return ITEM_INTERACT_BLOCKING insert_pai(user, attacking_item) - return TRUE + return ITEM_INTERACT_SUCCESS if(istype(attacking_item, /obj/item/mod/module)) if(!open) balloon_alert(user, "open the cover first!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING install(attacking_item, user) SEND_SIGNAL(src, COMSIG_MOD_MODULE_ADDED, user) - return TRUE - else if(istype(attacking_item, /obj/item/mod/core)) + return ITEM_INTERACT_SUCCESS + if(istype(attacking_item, /obj/item/mod/core)) if(!open) balloon_alert(user, "open the cover first!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING if(core) balloon_alert(user, "core already installed!") playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE) - return FALSE + return ITEM_INTERACT_BLOCKING var/obj/item/mod/core/attacking_core = attacking_item attacking_core.install(src) balloon_alert(user, "core installed") playsound(src, 'sound/machines/click.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE) - return TRUE - else if(is_wire_tool(attacking_item) && open) - wires.interact(user) - return TRUE - else if(open && attacking_item.GetID()) - update_access(user, attacking_item.GetID()) - return TRUE - return ..() + return ITEM_INTERACT_SUCCESS + if(open) + if(is_wire_tool(attacking_item)) + wires.interact(user) + return ITEM_INTERACT_SUCCESS + if(attacking_item.GetID()) + update_access(user, attacking_item.GetID()) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/mod/control/get_cell() var/obj/item/stock_parts/cell/cell = get_charge_source() diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 70e930ca31e..46b9b8f31fd 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -104,7 +104,7 @@ return ..() /obj/structure/filingcabinet/attack_self_tk(mob/user) - . = COMPONENT_CANCEL_ATTACK_CHAIN + . = ITEM_INTERACT_BLOCKING if(contents.len) if(prob(40 + contents.len * 5)) var/obj/item/I = pick(contents) @@ -203,4 +203,3 @@ GLOBAL_LIST_EMPTY(employmentCabinets) fillCurrent() virgin = FALSE return ..() - diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 7a2d2c837f6..7cc468f88d6 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -116,7 +116,7 @@ labels_left = initial(labels_left) //Yes, it's capped at its initial value return ITEM_INTERACT_SUCCESS -/obj/item/hand_labeler/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/obj/item/hand_labeler/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) return !mode /obj/item/hand_labeler/borg diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index ec71eda2e46..53df8dbd35b 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -501,22 +501,22 @@ . += span_notice("To initiate the surrender prompt, simply click on an individual within your proximity.") //Code from the medical penlight -/obj/item/pen/red/security/afterattack(atom/target, mob/living/user, proximity) - . = ..() +/obj/item/pen/red/security/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, holosign_cooldown)) balloon_alert(user, "not ready!") - return + return ITEM_INTERACT_BLOCKING - var/target_turf = get_turf(target) + var/turf/target_turf = get_turf(interacting_with) var/mob/living/living_target = locate(/mob/living) in target_turf if(!living_target || (living_target == user)) - return + return ITEM_INTERACT_BLOCKING living_target.apply_status_effect(/datum/status_effect/surrender_timed) to_chat(living_target, span_userdanger("[user] requests your immediate surrender! You are given 30 seconds to comply!")) new /obj/effect/temp_visual/security_holosign(target_turf, user) //produce a holographic glow COOLDOWN_START(src, holosign_cooldown, 30 SECONDS) + return ITEM_INTERACT_SUCCESS /obj/effect/temp_visual/security_holosign name = "security holosign" diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 00cb86446bb..5814750dab1 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -107,7 +107,7 @@ . += "It has [pictures_left] photos left." //user can be atom or mob -/obj/item/camera/proc/can_target(atom/target, mob/user, prox_flag) +/obj/item/camera/proc/can_target(atom/target, mob/user) if(!on || blending || !pictures_left) return FALSE var/turf/T = get_turf(target) @@ -128,24 +128,30 @@ return FALSE return TRUE -/obj/item/camera/afterattack(atom/target, mob/user, flag) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/camera/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) +/obj/item/camera/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if (disk) - if(ismob(target)) + if(ismob(interacting_with)) if (disk.record) QDEL_NULL(disk.record) disk.record = new - var/mob/M = target + var/mob/M = interacting_with disk.record.caller_name = M.name disk.record.set_caller_image(M) else to_chat(user, span_warning("Invalid holodisk target.")) - return + return ITEM_INTERACT_BLOCKING - if(!can_target(target, user, flag)) - return + if(!can_target(interacting_with, user)) + return ITEM_INTERACT_BLOCKING + if(!photo_taken(interacting_with, user)) + return ITEM_INTERACT_BLOCKING + return ITEM_INTERACT_SUCCESS + +/obj/item/camera/proc/photo_taken(atom/target, mob/user) on = FALSE addtimer(CALLBACK(src, PROC_REF(cooldown)), cooldown) @@ -153,7 +159,7 @@ icon_state = state_off INVOKE_ASYNC(src, PROC_REF(captureimage), target, user, picture_size_x - 1, picture_size_y - 1) - + return TRUE /obj/item/camera/proc/cooldown() UNTIL(!blending) diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm index 0e5342af599..de4a9005792 100644 --- a/code/modules/plumbing/ducts.dm +++ b/code/modules/plumbing/ducts.dm @@ -354,24 +354,23 @@ All the important duct code: duct_color = new_color add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY) -/obj/item/stack/ducts/afterattack(atom/target, user, proximity) - . = ..() - if(!proximity) - return - if(istype(target, /obj/machinery/duct)) - var/obj/machinery/duct/duct = target +/obj/item/stack/ducts/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/machinery/duct)) + var/obj/machinery/duct/duct = interacting_with if(duct.anchored) to_chat(user, span_warning("The duct must be unanchored before it can be picked up.")) - return + return ITEM_INTERACT_BLOCKING // Turn into a duct stack and then merge to the in-hand stack. var/obj/item/stack/ducts/stack = new(duct.loc, 1, FALSE) qdel(duct) if(stack.can_merge(src)) stack.merge(src) - return + return ITEM_INTERACT_SUCCESS + + check_attach_turf(interacting_with) + return ITEM_INTERACT_SUCCESS - check_attach_turf(target) /obj/item/stack/ducts/proc/check_attach_turf(atom/target) if(isopenturf(target) && use(1)) diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 2b5595fe16d..3988a14c19a 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -304,10 +304,6 @@ /obj/item/stock_parts/cell/get_part_rating() return maxcharge * 10 + charge -/obj/item/stock_parts/cell/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) - var/obj/item/mod/control/mod = storage_holder - return !(istype(mod) && mod.open) - /* Cell variants*/ /obj/item/stock_parts/cell/empty empty = TRUE diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 86e1235bce1..a8bf81ce37d 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -503,11 +503,12 @@ . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) -/obj/item/turret_control/afterattack(atom/targeted_atom, mob/user, proxflag, clickparams) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/turret_control/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return ranged_interact_with_atom(interacting_with, user, modifiers) + +/obj/item/turret_control/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/obj/machinery/power/emitter/emitter = user.buckled - emitter.setDir(get_dir(emitter,targeted_atom)) + emitter.setDir(get_dir(emitter, interacting_with)) user.setDir(emitter.dir) switch(emitter.dir) if(NORTH) @@ -543,7 +544,7 @@ user.pixel_x = 8 user.pixel_y = -12 - emitter.last_projectile_params = calculate_projectile_angle_and_pixel_offsets(user, null, clickparams) + emitter.last_projectile_params = calculate_projectile_angle_and_pixel_offsets(user, null, list2params(modifiers)) if(emitter.charge >= 10 && world.time > delay) emitter.charge -= 10 @@ -551,6 +552,7 @@ delay = world.time + 10 else if (emitter.charge < 10) playsound(src,'sound/machines/buzz-sigh.ogg', 50, TRUE) + return ITEM_INTERACT_SUCCESS /obj/machinery/power/emitter/ctf name = "Energy Cannon" diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 8076350514b..cf796c3d042 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -249,30 +249,66 @@ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/gun/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters) - if(!isliving(victim) || !IN_GIVEN_RANGE(user, victim, GUNPOINT_SHOOTER_STRAY_RANGE)) - return ..() //if they're out of range, just shootem. - if(!can_hold_up) - return ..() +/obj/item/gun/pre_attack(atom/A, mob/living/user, params) + . = ..() + if(.) + return . + if(isnull(bayonet) || !user.combat_mode) + return . + return bayonet.melee_attack_chain(user, A, params) + +/obj/item/gun/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(user.combat_mode) + return NONE + + if(istype(tool, /obj/item/knife)) + var/obj/item/knife/new_stabber = tool + if(!can_bayonet || !new_stabber.bayonet || !isnull(bayonet)) //ensure the gun has an attachment point available, and that the knife is compatible with it. + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(new_stabber, src)) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You attach [new_stabber] to [src]'s bayonet lug.")) + bayonet = new_stabber + update_appearance() + return ITEM_INTERACT_SUCCESS + + return NONE + +/obj/item/gun/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(user.combat_mode && isliving(interacting_with)) + return ITEM_INTERACT_SKIP_TO_ATTACK // Gun bash / bayonet attack + if(try_fire_gun(interacting_with, user, list2params(modifiers))) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/gun/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_hold_up || !isliving(interacting_with)) + return interact_with_atom(interacting_with, user, modifiers) + var/datum/component/gunpoint/gunpoint_component = user.GetComponent(/datum/component/gunpoint) if (gunpoint_component) - if(gunpoint_component.target == victim) - balloon_alert(user, "already holding them up!") - else - balloon_alert(user, "already holding someone up!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if (user == victim) + balloon_alert(user, "already holding [gunpoint_component.target == interacting_with ? "them" : "someone"] up!") + return ITEM_INTERACT_BLOCKING + if (user == interacting_with) balloon_alert(user, "can't hold yourself up!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING - if(do_after(user, 0.5 SECONDS, victim)) - user.AddComponent(/datum/component/gunpoint, victim, src) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + if(do_after(user, 0.5 SECONDS, interacting_with)) + user.AddComponent(/datum/component/gunpoint, interacting_with, src) + return ITEM_INTERACT_SUCCESS + +/obj/item/gun/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(try_fire_gun(interacting_with, user, list2params(modifiers))) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING -/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params) - ..() - fire_gun(target, user, flag, params) - return AFTERATTACK_PROCESSED_ITEM +/obj/item/gun/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(IN_GIVEN_RANGE(user, interacting_with, GUNPOINT_SHOOTER_STRAY_RANGE)) + return interact_with_atom_secondary(interacting_with, user, modifiers) + return ..() + +/obj/item/gun/proc/try_fire_gun(atom/target, mob/living/user, params) + return fire_gun(target, user, user.Adjacent(target), params) /obj/item/gun/proc/fire_gun(atom/target, mob/living/user, flag, params) if(QDELETED(target)) @@ -467,39 +503,6 @@ /obj/item/gun/proc/reset_semicd() semicd = FALSE -/obj/item/gun/attack(mob/M, mob/living/user) - if(user.combat_mode) //Flogging - if(bayonet) - M.attackby(bayonet, user) - return - else - return ..() - return - -/obj/item/gun/attack_atom(obj/O, mob/living/user, params) - if(user.combat_mode) - if(bayonet) - O.attackby(bayonet, user) - return - return ..() - -/obj/item/gun/attackby(obj/item/I, mob/living/user, params) - if(user.combat_mode) - return ..() - - else if(istype(I, /obj/item/knife)) - var/obj/item/knife/K = I - if(!can_bayonet || !K.bayonet || bayonet) //ensure the gun has an attachment point available, and that the knife is compatible with it. - return ..() - if(!user.transferItemToLoc(I, src)) - return - to_chat(user, span_notice("You attach [K] to [src]'s bayonet lug.")) - bayonet = K - update_appearance() - - else - return ..() - /obj/item/gun/screwdriver_act(mob/living/user, obj/item/I) . = ..() if(.) diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 8c6e2ae7cbd..30ba65dc94a 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -159,17 +159,18 @@ underbarrel = new /obj/item/gun/ballistic/revolver/grenadelauncher/unrestricted(src) update_appearance() -/obj/item/gun/ballistic/automatic/m90/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters) - underbarrel.afterattack(target, user, proximity_flag, click_parameters) - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/gun/ballistic/automatic/m90/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + return underbarrel.try_fire_gun(target, user, params) + return ..() -/obj/item/gun/ballistic/automatic/m90/attackby(obj/item/A, mob/user, params) - if(isammocasing(A)) - if(istype(A, underbarrel.magazine.ammo_type)) +/obj/item/gun/ballistic/automatic/m90/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(isammocasing(tool)) + if(istype(tool, underbarrel.magazine.ammo_type)) underbarrel.attack_self(user) - underbarrel.attackby(A, user, params) - else - ..() + underbarrel.attackby(tool, user, list2params(modifiers)) + return ITEM_INTERACT_BLOCKING + return ..() /obj/item/gun/ballistic/automatic/tommygun name = "\improper Thompson SMG" @@ -276,15 +277,15 @@ . += "l6_door_[cover_open ? "open" : "closed"]" -/obj/item/gun/ballistic/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/gun/ballistic/automatic/l6_saw/try_fire_gun(atom/target, mob/living/user, params) if(cover_open) balloon_alert(user, "close the cover!") - return - else - . |= ..() + return FALSE + + . = ..() + if(.) update_appearance() + return . //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/item/gun/ballistic/automatic/l6_saw/attack_hand(mob/user, list/modifiers) diff --git a/code/modules/projectiles/guns/ballistic/bows/_bow.dm b/code/modules/projectiles/guns/ballistic/bows/_bow.dm index 86094d0fe17..15c89ddb855 100644 --- a/code/modules/projectiles/guns/ballistic/bows/_bow.dm +++ b/code/modules/projectiles/guns/ballistic/bows/_bow.dm @@ -63,14 +63,13 @@ playsound(src, 'sound/weapons/gun/bow/bow_draw.ogg', 25, TRUE) update_appearance() -/obj/item/gun/ballistic/bow/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/gun/ballistic/bow/try_fire_gun(atom/target, mob/living/user, params) if(!chambered) - return + return FALSE if(!drawn) to_chat(user, span_warning("Without drawing the bow, the arrow uselessly falls to the ground.")) drop_arrow() - return + return FALSE return ..() //fires, removing the arrow /obj/item/gun/ballistic/bow/equipped(mob/user, slot, initial) diff --git a/code/modules/projectiles/guns/ballistic/launchers.dm b/code/modules/projectiles/guns/ballistic/launchers.dm index c293f7c5c6f..d3b74e21728 100644 --- a/code/modules/projectiles/guns/ballistic/launchers.dm +++ b/code/modules/projectiles/guns/ballistic/launchers.dm @@ -88,8 +88,10 @@ This one has been fitted with a special backblast diverter to prevent 'friendly' fire 'accidents' during use." backblast = FALSE -/obj/item/gun/ballistic/rocketlauncher/afterattack() +/obj/item/gun/ballistic/rocketlauncher/try_fire_gun(atom/target, mob/living/user, params) . = ..() + if(!.) + return magazine.get_round(FALSE) //Hack to clear the mag after it's fired /obj/item/gun/ballistic/rocketlauncher/attack_self_tk(mob/user) diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index a40e99882ff..cfee84f1a6a 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -86,21 +86,20 @@ QDEL_NULL(underbarrel) return ..() -/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters) - underbarrel.afterattack(target, user, proximity_flag, click_parameters) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + return underbarrel.try_fire_gun(target, user, params) + return ..() -/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack(atom/target, mob/living/user, flag, params) - // mirrors what the standalone fisher does when you hit people with it - . = ..() - if(user.Adjacent(target)) - var/obj/projectile/energy/fisher/melee/simulated_hit = new - simulated_hit.firer = user - simulated_hit.on_hit(target) +/obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/afterattack(atom/target, mob/user, click_parameters) + var/obj/projectile/energy/fisher/melee/simulated_hit = new + simulated_hit.firer = user + simulated_hit.on_hit(target) /obj/item/gun/ballistic/automatic/pistol/clandestine/fisher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - // as above comment, mirrors what the standalone fisher does when you hit people with it . = ..() + if(.) + return var/obj/projectile/energy/fisher/melee/simulated_hit = new simulated_hit.firer = throwingdatum.get_thrower() simulated_hit.on_hit(hit_atom) diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 069da214da5..eb7d800f822 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -218,26 +218,24 @@ toggle_magazine() return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN -/obj/item/gun/ballistic/shotgun/bulldog/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters) +/obj/item/gun/ballistic/shotgun/bulldog/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(secondary_magazine) toggle_magazine() - return SECONDARY_ATTACK_CALL_NORMAL - -/obj/item/gun/ballistic/shotgun/bulldog/attackby_secondary(obj/item/weapon, mob/user, params) - if(!istype(weapon, secondary_magazine_type)) - balloon_alert(user, "[weapon.name] doesn't fit!") - return SECONDARY_ATTACK_CALL_NORMAL - if(!user.transferItemToLoc(weapon, src)) - to_chat(user, span_warning("You cannot seem to get [src] out of your hands!")) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ..() + +/obj/item/gun/ballistic/shotgun/bulldog/item_interaction_secondary(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, secondary_magazine_type)) + return ..() + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING var/obj/item/ammo_box/magazine/old_mag = secondary_magazine - secondary_magazine = weapon + secondary_magazine = tool if(old_mag) user.put_in_hands(old_mag) balloon_alert(user, "secondary [magazine_wording] loaded") playsound(src, load_empty_sound, load_sound_volume, load_sound_vary) update_appearance() - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /obj/item/gun/ballistic/shotgun/bulldog/click_alt_secondary(mob/user) if(secondary_magazine) @@ -338,6 +336,7 @@ . = ..() . += span_notice("Right-click to shoot the hook.") -/obj/item/gun/ballistic/shotgun/hook/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - hook.afterattack(target, user, proximity_flag, click_parameters) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/gun/ballistic/shotgun/hook/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + return hook.try_fire_gun(target, user, params) + return ..() diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index 11399e9c24d..e29e1ef4878 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -328,26 +328,27 @@ sync_ammo() var/atom/target = source.mouse_object_ref?.resolve() if(target) - INVOKE_ASYNC(src, PROC_REF(afterattack), target, source.mob, FALSE, source.mouseParams, passthrough = TRUE) + INVOKE_ASYNC(src, PROC_REF(try_fire_gun), target, source.mob, source.mouseParams, TRUE) stop_aiming() QDEL_LIST(current_tracers) -/obj/item/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE) - . |= AFTERATTACK_PROCESSED_ITEM - if(flag) //It's adjacent, is the user, or is on the user's person +/obj/item/gun/energy/beam_rifle/try_fire_gun(atom/target, mob/living/user, params, passthrough = FALSE) + if(user.Adjacent(target)) //It's adjacent, is the user, or is on the user's person if(target in user.contents) //can't shoot stuff inside us. - return + return FALSE if(!ismob(target) || user.combat_mode) //melee attack - return + return FALSE if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) - return + return FALSE if(!passthrough && (aiming_time > aiming_time_fire_threshold)) - return + return FALSE if(lastfire > world.time + delay) - return + return FALSE + if(!..()) + return FALSE lastfire = world.time - . = ..() stop_aiming() + return TRUE /obj/item/gun/energy/beam_rifle/proc/sync_ammo() for(var/obj/item/ammo_casing/energy/beam_rifle/AC in contents) diff --git a/code/modules/projectiles/guns/energy/laser_gatling.dm b/code/modules/projectiles/guns/energy/laser_gatling.dm index 3d64e6b700a..0f5e7d3deac 100644 --- a/code/modules/projectiles/guns/energy/laser_gatling.dm +++ b/code/modules/projectiles/guns/energy/laser_gatling.dm @@ -142,10 +142,11 @@ cell.give(transferred) -/obj/item/gun/energy/minigun/afterattack(atom/target, mob/living/user, flag, params) +/obj/item/gun/energy/minigun/try_fire_gun(atom/target, mob/living/user, params) if(!ammo_pack || ammo_pack.loc != user) to_chat(user, span_warning("You need the backpack power source to fire the gun!")) - . = ..() + return FALSE + return ..() /obj/item/stock_parts/cell/minigun name = "gatling gun fusion core" diff --git a/code/modules/projectiles/guns/energy/recharge.dm b/code/modules/projectiles/guns/energy/recharge.dm index 71d14348608..1b9409478cd 100644 --- a/code/modules/projectiles/guns/energy/recharge.dm +++ b/code/modules/projectiles/guns/energy/recharge.dm @@ -156,13 +156,13 @@ While some would argue that this is a really terrible design choice, others argue that it is very funny to be able to shoot at light sources.
\ Caveat emptor.") -/obj/item/gun/energy/recharge/fisher/afterattack(atom/target, mob/living/user, flag, params) - // you should just shoot them, but in case you can't/wont +/obj/item/gun/energy/recharge/fisher/attack(mob/living/target_mob, mob/living/user, params) . = ..() - if(user.Adjacent(target)) - var/obj/projectile/energy/fisher/melee/simulated_hit = new - simulated_hit.firer = user - simulated_hit.on_hit(target) + if(.) + return + var/obj/projectile/energy/fisher/melee/simulated_hit = new + simulated_hit.firer = user + simulated_hit.on_hit(target_mob) /obj/item/gun/energy/recharge/fisher/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // ...you reeeeeally just shoot them, but in case you can't/won't diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index c04c86d7579..4b7d9dfcc51 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -231,17 +231,15 @@ if(istype(WH)) WH.gun = WEAKREF(src) -/obj/item/gun/energy/wormhole_projector/afterattack(atom/target, mob/living/user, flag, params) - if(select == AMMO_SELECT_ORANGE) //Last fired in right click mode. Switch to blue wormhole (left click). - select_fire() +/obj/item/gun/energy/wormhole_projector/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + if(select == AMMO_SELECT_BLUE) //Last fired in left click mode. Switch to orange wormhole (right click). + select_fire() + else + if(select == AMMO_SELECT_ORANGE) //Last fired in right click mode. Switch to blue wormhole (left click). + select_fire() return ..() -/obj/item/gun/energy/wormhole_projector/afterattack_secondary(atom/target, mob/living/user, flag, params) - if(select == AMMO_SELECT_BLUE) //Last fired in left click mode. Switch to orange wormhole (right click). - select_fire() - fire_gun(target, user, flag, params) - return SECONDARY_ATTACK_CONTINUE_CHAIN - /obj/item/gun/energy/wormhole_projector/proc/on_portal_destroy(obj/effect/portal/P) SIGNAL_HANDLER if(P == p_blue) @@ -408,13 +406,15 @@ coin_count++ COOLDOWN_START(src, coin_regen_cd, coin_regen_rate) -/obj/item/gun/energy/marksman_revolver/afterattack_secondary(atom/target, mob/living/user, params) - if(!CAN_THEY_SEE(target, user)) +/obj/item/gun/energy/marksman_revolver/try_fire_gun(atom/target, mob/living/user, params) + if(!LAZYACCESS(params2list(params), RIGHT_CLICK)) return ..() + if(!CAN_THEY_SEE(target, user)) + return ITEM_INTERACT_BLOCKING if(max_coins && coin_count <= 0) to_chat(user, span_warning("You don't have any coins right now!")) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(max_coins) START_PROCESSING(SSobj, src) @@ -426,5 +426,4 @@ var/obj/projectile/bullet/coin/new_coin = new(get_turf(user), target_turf, user) new_coin.preparePixelProjectile(target_turf, user) new_coin.fire() - - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 99b60b2107e..e8f41ef0b48 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -33,24 +33,23 @@ return ..() -/obj/item/gun/magic/wand/afterattack(atom/target, mob/living/user) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/gun/magic/wand/try_fire_gun(atom/target, mob/living/user, params) if(!charges) shoot_with_empty_chamber(user) - return + return FALSE if(target == user) - if(no_den_usage) - var/area/A = get_area(user) - if(istype(A, /area/centcom/wizard_station)) - to_chat(user, span_warning("You know better than to violate the security of The Den, best wait until you leave to use [src].")) - return - else - no_den_usage = 0 + if(no_den_usage && istype(get_area(user), /area/centcom/wizard_station)) + to_chat(user, span_warning("You know better than to violate the security of The Den, best wait until you leave to use [src].")) + return FALSE zap_self(user) + . = TRUE + else - . |= ..() - update_appearance() + . = ..() + if(.) + update_appearance() + return . /obj/item/gun/magic/wand/proc/zap_self(mob/living/user) user.visible_message(span_danger("[user] zaps [user.p_them()]self with [src].")) diff --git a/code/modules/projectiles/guns/special/blastcannon.dm b/code/modules/projectiles/guns/special/blastcannon.dm index f9a8abf7ae3..d867ca09c04 100644 --- a/code/modules/projectiles/guns/special/blastcannon.dm +++ b/code/modules/projectiles/guns/special/blastcannon.dm @@ -110,10 +110,8 @@ update_appearance() return TRUE -/obj/item/gun/blastcannon/afterattack(atom/target, mob/user, flag, params) - . |= AFTERATTACK_PROCESSED_ITEM - - if((!bomb && bombcheck) || !target || (get_dist(get_turf(target), get_turf(user)) <= 2)) +/obj/item/gun/blastcannon/try_fire_gun(atom/target, mob/living/user, params) + if((!bomb && bombcheck) || isnull(target) || (get_dist(get_turf(target), get_turf(user)) <= 2)) return ..() cached_target = WEAKREF(target) @@ -123,12 +121,12 @@ span_danger("[user] points [src] at [target]!"), span_danger("You point [src] at [target]!") ) - return + return FALSE cached_firer = WEAKREF(user) if(!bomb) - fire_debug(target, user, flag, params) - return + fire_debug(target, user, params) + return TRUE playsound(src, dry_fire_sound, 30, TRUE) // *click user.visible_message( @@ -141,8 +139,7 @@ user.log_message("opened blastcannon transfer valve at [AREACOORD(current_turf)] while aiming at [AREACOORD(target_turf)] (target).", LOG_GAME) bomb.toggle_valve() update_appearance() - return - + return TRUE /** * Channels an internal explosion into a blastwave projectile. diff --git a/code/modules/projectiles/guns/special/hand_of_midas.dm b/code/modules/projectiles/guns/special/hand_of_midas.dm index 6a5ccf2dea1..68b8158c32d 100644 --- a/code/modules/projectiles/guns/special/hand_of_midas.dm +++ b/code/modules/projectiles/guns/special/hand_of_midas.dm @@ -37,29 +37,36 @@ balloon_alert(user, "not enough gold") // Siphon gold from a victim, recharging our gun & removing their Midas Blight debuff in the process. -/obj/item/gun/magic/midas_hand/afterattack_secondary(mob/living/victim, mob/living/user, proximity_flag, click_parameters) - if(!isliving(victim) || !IN_GIVEN_RANGE(user, victim, gold_suck_range)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(victim == user) - balloon_alert(user, "can't siphon from self") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - if(!victim.reagents) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - - var/gold_amount = victim.reagents.get_reagent_amount(/datum/reagent/gold, type_check = REAGENT_SUB_TYPE) +/obj/item/gun/magic/midas_hand/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!isliving(interacting_with) || !IN_GIVEN_RANGE(user, interacting_with, gold_suck_range)) + return ITEM_INTERACT_BLOCKING + if(interacting_with == user) + balloon_alert(user, "can't siphon from self!") + return ITEM_INTERACT_BLOCKING + if(!interacting_with.reagents) + return ITEM_INTERACT_BLOCKING + + var/gold_amount = interacting_with.reagents.get_reagent_amount(/datum/reagent/gold, type_check = REAGENT_SUB_TYPE) if(!gold_amount) - balloon_alert(user, "no gold in bloodstream") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - var/gold_beam = user.Beam(victim, icon_state="drain_gold") - if(!do_after(user = user, delay = 1 SECONDS, target = victim, timed_action_flags = (IGNORE_USER_LOC_CHANGE | IGNORE_TARGET_LOC_CHANGE), extra_checks = CALLBACK(src, PROC_REF(check_gold_range), user, victim))) + balloon_alert(user, "no gold in bloodstream!") + return ITEM_INTERACT_BLOCKING + var/mob/living/victim = interacting_with + var/gold_beam = user.Beam(victim, icon_state = "drain_gold") + if(!do_after( + user = user, + delay = 1 SECONDS, + target = victim, + timed_action_flags = (IGNORE_USER_LOC_CHANGE | IGNORE_TARGET_LOC_CHANGE), + extra_checks = CALLBACK(src, PROC_REF(check_gold_range), user, victim), + )) qdel(gold_beam) - balloon_alert(user, "link broken") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + balloon_alert(user, "link broken!") + return ITEM_INTERACT_BLOCKING handle_gold_charges(user, gold_amount) victim.reagents.remove_reagent(/datum/reagent/gold, gold_amount, include_subtypes = TRUE) victim.remove_status_effect(/datum/status_effect/midas_blight) qdel(gold_beam) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS // If we botch a shot, we have to start over again by inserting gold coins into the gun. Can only be done if it has no charges or gold. /obj/item/gun/magic/midas_hand/attackby(obj/item/I, mob/living/user, params) diff --git a/code/modules/projectiles/guns/special/syringe_gun.dm b/code/modules/projectiles/guns/special/syringe_gun.dm index 97a31a7c813..4006d55298e 100644 --- a/code/modules/projectiles/guns/special/syringe_gun.dm +++ b/code/modules/projectiles/guns/special/syringe_gun.dm @@ -83,23 +83,23 @@ return TRUE -/obj/item/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = TRUE) - if(istype(A, /obj/item/reagent_containers/syringe/bluespace)) - balloon_alert(user, "[A.name] is too big!") - return TRUE - if(istype(A, /obj/item/reagent_containers/syringe)) +/obj/item/gun/syringe/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/reagent_containers/syringe/bluespace)) + balloon_alert(user, "[tool.name] is too big!") + return ITEM_INTERACT_BLOCKING + if(istype(tool, /obj/item/reagent_containers/syringe)) if(syringes.len < max_syringes) - if(!user.transferItemToLoc(A, src)) - return FALSE - balloon_alert(user, "[A.name] loaded") - syringes += A + if(!user.transferItemToLoc(tool, src)) + return ITEM_INTERACT_BLOCKING + balloon_alert(user, "[tool.name] loaded") + syringes += tool recharge_newshot() update_appearance() - playsound(loc, load_sound, 40) - return TRUE - else - balloon_alert(user, "it's already full!") - return FALSE + playsound(src, load_sound, 40) + return ITEM_INTERACT_SUCCESS + balloon_alert(user, "it's full!") + return ITEM_INTERACT_BLOCKING + return NONE /obj/item/gun/syringe/update_overlays() . = ..() @@ -164,24 +164,24 @@ . = ..() chambered = new /obj/item/ammo_casing/dnainjector(src) -/obj/item/gun/syringe/dna/attackby(obj/item/A, mob/user, params, show_msg = TRUE) - if(istype(A, /obj/item/dnainjector)) - var/obj/item/dnainjector/D = A +/obj/item/gun/syringe/dna/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/dnainjector)) + var/obj/item/dnainjector/D = tool if(D.used) balloon_alert(user, "[D.name] is used up!") - return + return ITEM_INTERACT_BLOCKING if(syringes.len < max_syringes) if(!user.transferItemToLoc(D, src)) - return FALSE + return ITEM_INTERACT_BLOCKING balloon_alert(user, "[D.name] loaded") syringes += D recharge_newshot() update_appearance() playsound(loc, load_sound, 40) - return TRUE - else - balloon_alert(user, "it's already full!") - return FALSE + return ITEM_INTERACT_SUCCESS + balloon_alert(user, "it's already full!") + return ITEM_INTERACT_BLOCKING + return NONE /obj/item/gun/syringe/blowgun name = "blowgun" diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm index 77d6a702b49..0c4dc094159 100644 --- a/code/modules/projectiles/pins.dm +++ b/code/modules/projectiles/pins.dm @@ -25,32 +25,31 @@ if(isgun(newloc)) gun = newloc -/obj/item/firing_pin/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(proximity_flag) - if(isgun(target)) - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/gun/targeted_gun = target - var/obj/item/firing_pin/old_pin = targeted_gun.pin - if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable)) - if(Adjacent(user)) - user.put_in_hands(old_pin) - else - old_pin.forceMove(targeted_gun.drop_location()) - old_pin.gun_remove(user) - - if(!targeted_gun.pin) - if(!user.temporarilyRemoveItemFromInventory(src)) - return . - if(gun_insert(user, targeted_gun)) - if(old_pin) - balloon_alert(user, "swapped firing pin") - else - balloon_alert(user, "inserted firing pin") +/obj/item/firing_pin/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isgun(interacting_with)) + return NONE + + var/obj/item/gun/targeted_gun = interacting_with + var/obj/item/firing_pin/old_pin = targeted_gun.pin + if(old_pin?.pin_removable && (force_replace || old_pin.pin_hot_swappable)) + if(Adjacent(user)) + user.put_in_hands(old_pin) + else + old_pin.forceMove(targeted_gun.drop_location()) + old_pin.gun_remove(user) + + if(!targeted_gun.pin) + if(!user.temporarilyRemoveItemFromInventory(src)) + return . + if(gun_insert(user, targeted_gun)) + if(old_pin) + balloon_alert(user, "swapped firing pin") else - to_chat(user, span_notice("This firearm already has a firing pin installed.")) + balloon_alert(user, "inserted firing pin") + else + to_chat(user, span_notice("This firearm already has a firing pin installed.")) - return . + return ITEM_INTERACT_SUCCESS /obj/item/firing_pin/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) @@ -190,13 +189,15 @@ fail_message = "dna check failed!" var/unique_enzymes = null -/obj/item/firing_pin/dna/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(proximity_flag && iscarbon(target)) - var/mob/living/carbon/M = target +/obj/item/firing_pin/dna/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(iscarbon(interacting_with)) + var/mob/living/carbon/M = interacting_with if(M.dna && M.dna.unique_enzymes) unique_enzymes = M.dna.unique_enzymes balloon_alert(user, "dna lock set") + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING + return ..() /obj/item/firing_pin/dna/pin_auth(mob/living/carbon/user) if(user && user.dna && user.dna.unique_enzymes) diff --git a/code/modules/reagents/chemistry/items.dm b/code/modules/reagents/chemistry/items.dm index 5b6fbefef79..d307f96dc26 100644 --- a/code/modules/reagents/chemistry/items.dm +++ b/code/modules/reagents/chemistry/items.dm @@ -77,20 +77,20 @@ ///If the paper was used, and therefore cannot change color again var/used = FALSE -/obj/item/ph_paper/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!is_reagent_container(target)) - return - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/reagent_containers/cont = target - if(used == TRUE) - to_chat(user, span_warning("[src] has already been used!")) +/obj/item/ph_paper/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!is_reagent_container(interacting_with)) return + var/obj/item/reagent_containers/cont = interacting_with if(!LAZYLEN(cont.reagents.reagent_list)) - return + return NONE + if(used) + to_chat(user, span_warning("[src] has already been used!")) + return ITEM_INTERACT_BLOCKING CONVERT_PH_TO_COLOR(round(cont.reagents.ph, 1), color) desc += " The paper looks to be around a pH of [round(cont.reagents.ph, 1)]" name = "used [name]" used = TRUE + return ITEM_INTERACT_SUCCESS /* * pH meter that will give a detailed or truncated analysis of all the reagents in of an object with a reagents datum attached to it. Only way of detecting purity for now. @@ -112,18 +112,16 @@ to_chat(user, span_notice("You switch the chemical analyzer to not include reagent descriptions in it's report.")) scanmode = SHORTENED_CHEM_OUTPUT -/obj/item/ph_meter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!is_reagent_container(target)) - return - . |= AFTERATTACK_PROCESSED_ITEM - var/obj/item/reagent_containers/cont = target - if(LAZYLEN(cont.reagents.reagent_list) == null) - return +/obj/item/ph_meter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!is_reagent_container(interacting_with)) + return NONE + var/obj/item/reagent_containers/cont = interacting_with + if(!LAZYLEN(cont.reagents.reagent_list)) + return NONE var/list/out_message = list() to_chat(user, "The chemistry meter beeps and displays:") out_message += "Total volume: [round(cont.volume, 0.01)] Current temperature: [round(cont.reagents.chem_temp, 0.1)]K Total pH: [round(cont.reagents.ph, 0.01)]\n" - out_message += "Chemicals found in [target.name]:\n" + out_message += "Chemicals found in [interacting_with.name]:
\n" if(cont.reagents.is_reacting) out_message += "[span_warning("A reaction appears to be occuring currently.")]\n" for(var/datum/reagent/reagent in cont.reagents.reagent_list) @@ -136,6 +134,7 @@ out_message += "Analysis: [reagent.description]\n" to_chat(user, "[out_message.Join()]") desc = "An electrode attached to a small circuit box that will display details of a solution. Can be toggled to provide a description of each of the reagents. The screen currently displays detected vol: [round(cont.volume, 0.01)] detected pH:[round(cont.reagents.ph, 0.1)]." + return ITEM_INTERACT_SUCCESS /obj/item/burner name = "burner" @@ -186,24 +185,25 @@ set_lit(TRUE) user.visible_message(span_notice("[user] lights up the [src].")) -/obj/item/burner/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(lit) - . |= AFTERATTACK_PROCESSED_ITEM - if(is_reagent_container(target)) - var/obj/item/reagent_containers/container = target - container.reagents.expose_temperature(get_temperature()) - to_chat(user, span_notice("You heat up the [src].")) - playsound(user.loc, 'sound/chemistry/heatdam.ogg', 50, TRUE) - return . - else if(isitem(target)) - var/obj/item/item = target - if(item.heat > 1000) - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/burner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!lit) + return NONE + + if(is_reagent_container(interacting_with)) + var/obj/item/reagent_containers/container = interacting_with + container.reagents.expose_temperature(get_temperature()) + user.visible_message(span_notice("[user] heats up [src]."), span_notice("You heat up [src].")) + playsound(user, 'sound/chemistry/heatdam.ogg', 50, TRUE) + return ITEM_INTERACT_SUCCESS + + else if(isitem(interacting_with)) + var/obj/item/item = interacting_with + if(item.get_temperature() > 1000) set_lit(TRUE) - user.visible_message(span_notice("[user] lights up the [src].")) + user.visible_message(span_notice("[user] lights up [src]."), span_notice("You light up [src].")) + return ITEM_INTERACT_SUCCESS - return . + return ITEM_INTERACT_BLOCKING /obj/item/burner/update_icon_state() . = ..() @@ -280,7 +280,7 @@ /obj/item/thermometer name = "thermometer" - desc = "A thermometer for checking a beaker's temperature" + desc = "A thermometer for checking a something's temperature." icon_state = "thermometer" icon = 'icons/obj/medical/chemical.dmi' item_flags = NOBLUDGEON @@ -290,19 +290,18 @@ var/datum/reagents/attached_to_reagents /obj/item/thermometer/Destroy() - QDEL_NULL(attached_to_reagents) //I have no idea how you can destroy this, but not the beaker, but here we go + attached_to_reagents = null return ..() -/obj/item/thermometer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM - if(target.reagents) - if(!user.transferItemToLoc(src, target)) - return . - attached_to_reagents = target.reagents - to_chat(user, span_notice("You add the [src] to the [target].")) - ui_interact(usr, null) - return . +/obj/item/thermometer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isnull(interacting_with.reagents)) + return NONE + if(!user.transferItemToLoc(src, interacting_with)) + return ITEM_INTERACT_BLOCKING + attached_to_reagents = interacting_with.reagents + to_chat(user, span_notice("You add the [src] to [interacting_with].")) + ui_interact(user) + return ITEM_INTERACT_SUCCESS /obj/item/thermometer/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -315,7 +314,7 @@ INVOKE_ASYNC(src, PROC_REF(remove_thermometer), user) /obj/item/thermometer/ui_status(mob/user, datum/ui_state/state) - if(!(in_range(src, user))) + if(!in_range(src, user)) return UI_CLOSE return UI_INTERACTIVE @@ -325,7 +324,9 @@ /obj/item/thermometer/ui_data(mob/user) if(!attached_to_reagents) ui_close(user) - var/data = list() + return + + var/list/data = list() data["Temperature"] = round(attached_to_reagents.chem_temp) return data @@ -334,8 +335,8 @@ attached_to_reagents = null /obj/item/thermometer/proc/try_put_in_hand(obj/object, mob/living/user) - to_chat(user, span_notice("You remove the [src] from the [attached_to_reagents.my_atom].")) - if(!issilicon(user) && in_range(src.loc, user)) + to_chat(user, span_notice("You remove the [src] from [attached_to_reagents.my_atom].")) + if(!issilicon(user) && in_range(loc, user)) user.put_in_hands(object) else object.forceMove(drop_location()) diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 3cf5b752400..dd4e0dff626 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -96,7 +96,7 @@ if(!QDELETED(beaker)) if(istype(held_item, /obj/item/reagent_containers/dropper) || istype(held_item, /obj/item/reagent_containers/syringe)) var/obj/item/reagent_containers/injector = held_item - injector.afterattack(beaker, user, proximity_flag = TRUE) + injector.interact_with_atom(beaker, user, modifiers) return ITEM_INTERACT_SUCCESS if(is_reagent_container(held_item) && held_item.is_open_container()) diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index f08989390a2..dca2b603ca4 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -87,9 +87,9 @@ return ..() var/list/modifiers = params2list(params) if(istype(held_item, /obj/item/reagent_containers/syringe) && LAZYACCESS(modifiers, RIGHT_CLICK)) - held_item.afterattack_secondary(beaker, user, Adjacent(user), params) + held_item.interact_with_atom_secondary(beaker, user) else - held_item.afterattack(beaker, user, Adjacent(user), params) + held_item.interact_with_atom(beaker, user) SStgui.update_uis(src) return TRUE diff --git a/code/modules/reagents/reagent_containers/condiment.dm b/code/modules/reagents/reagent_containers/condiment.dm index d70dbc547a7..24886d87850 100644 --- a/code/modules/reagents/reagent_containers/condiment.dm +++ b/code/modules/reagents/reagent_containers/condiment.dm @@ -68,34 +68,33 @@ playsound(M.loc,'sound/items/drink.ogg', rand(10,50), TRUE) return TRUE -/obj/item/reagent_containers/condiment/afterattack(obj/target, mob/user , proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/condiment/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(istype(target, /obj/structure/reagent_dispensers)) //A dispenser. Transfer FROM it TO us. - if(!target.reagents.total_volume) to_chat(user, span_warning("[target] is empty!")) - return + return ITEM_INTERACT_BLOCKING if(reagents.total_volume >= reagents.maximum_volume) to_chat(user, span_warning("[src] is full!")) - return + return ITEM_INTERACT_BLOCKING var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) to_chat(user, span_notice("You fill [src] with [trans] units of the contents of [target].")) + return ITEM_INTERACT_SUCCESS //Something like a glass or a food item. Player probably wants to transfer TO it. else if(target.is_drainable() || IS_EDIBLE(target)) if(!reagents.total_volume) to_chat(user, span_warning("[src] is empty!")) - return + return ITEM_INTERACT_BLOCKING if(target.reagents.total_volume >= target.reagents.maximum_volume) to_chat(user, span_warning("you can't add anymore to [target]!")) - return + return ITEM_INTERACT_BLOCKING var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user) to_chat(user, span_notice("You transfer [trans] units of the condiment to [target].")) + return ITEM_INTERACT_SUCCESS + + return NONE /obj/item/reagent_containers/condiment/enzyme name = "universal enzyme" @@ -151,11 +150,10 @@ desc = "Salt. From dead crew, presumably." return TOXLOSS -/obj/item/reagent_containers/condiment/saltshaker/afterattack(obj/target, mob/living/user, proximity) +/obj/item/reagent_containers/condiment/saltshaker/interact_with_atom(atom/target, mob/living/user, list/modifiers) . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . if(isturf(target)) if(!reagents.has_reagent(/datum/reagent/consumable/salt, 2)) to_chat(user, span_warning("You don't have enough salt to make a pile!")) @@ -163,7 +161,8 @@ user.visible_message(span_notice("[user] shakes some salt onto [target]."), span_notice("You shake some salt onto [target].")) reagents.remove_reagent(/datum/reagent/consumable/salt, 2) new/obj/effect/decal/cleanable/food/salt(target) - return + return ITEM_INTERACT_SUCCESS + return . /obj/item/reagent_containers/condiment/peppermill name = "pepper mill" @@ -443,26 +442,22 @@ /obj/item/reagent_containers/condiment/pack/attack(mob/M, mob/user, def_zone) //Can't feed these to people directly. return -/obj/item/reagent_containers/condiment/pack/afterattack(obj/target, mob/user , proximity) - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/condiment/pack/interact_with_atom(atom/target, mob/living/user, list/modifiers) //You can tear the bag open above food to put the condiments on it, obviously. if(IS_EDIBLE(target)) if(!reagents.total_volume) to_chat(user, span_warning("You tear open [src], but there's nothing in it.")) qdel(src) - return + return ITEM_INTERACT_BLOCKING if(target.reagents.total_volume >= target.reagents.maximum_volume) to_chat(user, span_warning("You tear open [src], but [target] is stacked so high that it just drips off!") ) qdel(src) - return - else - to_chat(user, span_notice("You tear open [src] above [target] and the condiments drip onto it.")) - src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user) - qdel(src) - return - return . | ..() + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You tear open [src] above [target] and the condiments drip onto it.")) + src.reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user) + qdel(src) + return ITEM_INTERACT_SUCCESS + return ..() /// Handles reagents getting added to the condiment pack. /obj/item/reagent_containers/condiment/pack/proc/on_reagent_add(datum/reagents/reagents) diff --git a/code/modules/reagents/reagent_containers/cups/_cup.dm b/code/modules/reagents/reagent_containers/cups/_cup.dm index 7e48c441808..e0ba956f303 100644 --- a/code/modules/reagents/reagent_containers/cups/_cup.dm +++ b/code/modules/reagents/reagent_containers/cups/_cup.dm @@ -102,68 +102,66 @@ if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) -/obj/item/reagent_containers/cup/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag) - return - - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/reagent_containers/cup/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(!check_allowed_items(target, target_self = TRUE)) - return - + return NONE if(!spillable) - return + return NONE if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it. if(!reagents.total_volume) to_chat(user, span_warning("[src] is empty!")) - return + return ITEM_INTERACT_BLOCKING if(target.reagents.holder_full()) to_chat(user, span_warning("[target] is full.")) - return + return ITEM_INTERACT_BLOCKING var/trans = reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user) to_chat(user, span_notice("You transfer [trans] unit\s of the solution to [target].")) SEND_SIGNAL(src, COMSIG_REAGENTS_CUP_TRANSFER_TO, target) target.update_appearance() + return ITEM_INTERACT_SUCCESS - else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. + if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. if(!target.reagents.total_volume) to_chat(user, span_warning("[target] is empty and can't be refilled!")) - return + return ITEM_INTERACT_BLOCKING if(reagents.holder_full()) to_chat(user, span_warning("[src] is full.")) - return + return ITEM_INTERACT_BLOCKING var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) to_chat(user, span_notice("You fill [src] with [trans] unit\s of the contents of [target].")) SEND_SIGNAL(src, COMSIG_REAGENTS_CUP_TRANSFER_FROM, target) target.update_appearance() + return ITEM_INTERACT_SUCCESS -/obj/item/reagent_containers/cup/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if((!proximity_flag) || !check_allowed_items(target, target_self = TRUE)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return NONE +/obj/item/reagent_containers/cup/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers) + if(user.combat_mode) + return ITEM_INTERACT_SKIP_TO_ATTACK + if(!check_allowed_items(target, target_self = TRUE)) + return NONE if(!spillable) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(target.is_drainable()) //A dispenser. Transfer FROM it TO us. if(!target.reagents.total_volume) to_chat(user, span_warning("[target] is empty!")) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(reagents.holder_full()) to_chat(user, span_warning("[src] is full.")) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) to_chat(user, span_notice("You fill [src] with [trans] unit\s of the contents of [target].")) target.update_appearance() - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_SUCCESS /obj/item/reagent_containers/cup/attackby(obj/item/attacking_item, mob/user, params) var/hotness = attacking_item.get_temperature() diff --git a/code/modules/reagents/reagent_containers/cups/drinks.dm b/code/modules/reagents/reagent_containers/cups/drinks.dm index 5a3ed446f60..2f326accb90 100644 --- a/code/modules/reagents/reagent_containers/cups/drinks.dm +++ b/code/modules/reagents/reagent_containers/cups/drinks.dm @@ -291,20 +291,18 @@ return ..() -/obj/item/reagent_containers/cup/glass/waterbottle/afterattack(obj/target, mob/living/user, proximity) - . |= AFTERATTACK_PROCESSED_ITEM - +/obj/item/reagent_containers/cup/glass/waterbottle/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(cap_on && (target.is_refillable() || target.is_drainable() || (reagents.total_volume && !user.combat_mode))) to_chat(user, span_warning("You must remove the cap before you can do that!")) - return + return ITEM_INTERACT_BLOCKING - else if(istype(target, /obj/item/reagent_containers/cup/glass/waterbottle)) + if(istype(target, /obj/item/reagent_containers/cup/glass/waterbottle)) var/obj/item/reagent_containers/cup/glass/waterbottle/other_bottle = target if(other_bottle.cap_on) to_chat(user, span_warning("[other_bottle] has a cap firmly twisted on!")) - return + return ITEM_INTERACT_BLOCKING - return . | ..() + return ..() // heehoo bottle flipping /obj/item/reagent_containers/cup/glass/waterbottle/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index beb6f3e6314..76ab1166c08 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -11,22 +11,18 @@ reagent_flags = TRANSPARENT custom_price = PAYCHECK_CREW -/obj/item/reagent_containers/dropper/afterattack(obj/target, mob/user , proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/dropper/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(!target.reagents) - return + return NONE if(reagents.total_volume > 0) if(target.reagents.holder_full()) to_chat(user, span_notice("[target] is full.")) - return + return ITEM_INTERACT_BLOCKING if(!target.is_injectable(user)) to_chat(user, span_warning("You cannot transfer reagents to [target]!")) - return + return ITEM_INTERACT_BLOCKING var/trans = 0 var/fraction = min(amount_per_transfer_from_this / reagents.total_volume, 1) @@ -48,10 +44,10 @@ to_chat(user, span_notice("You transfer [trans] unit\s of the solution.")) update_appearance() - return + return ITEM_INTERACT_BLOCKING else if(isalien(target)) //hiss-hiss has no eyes! to_chat(target, span_danger("[target] does not seem to have any eyes!")) - return + return ITEM_INTERACT_BLOCKING target.visible_message(span_danger("[user] squirts something into [target]'s eyes!"), \ span_userdanger("[user] squirts something into your eyes!")) @@ -69,23 +65,23 @@ to_chat(user, span_notice("You transfer [trans] unit\s of the solution.")) update_appearance() target.update_appearance() + return ITEM_INTERACT_SUCCESS - else + if(!target.is_drawable(user, FALSE)) //No drawing from mobs here + to_chat(user, span_warning("You cannot directly remove reagents from [target]!")) + return ITEM_INTERACT_BLOCKING - if(!target.is_drawable(user, FALSE)) //No drawing from mobs here - to_chat(user, span_warning("You cannot directly remove reagents from [target]!")) - return + if(!target.reagents.total_volume) + to_chat(user, span_warning("[target] is empty!")) + return ITEM_INTERACT_BLOCKING - if(!target.reagents.total_volume) - to_chat(user, span_warning("[target] is empty!")) - return + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) + to_chat(user, span_notice("You fill [src] with [trans] unit\s of the solution.")) - to_chat(user, span_notice("You fill [src] with [trans] unit\s of the solution.")) - - update_appearance() - target.update_appearance() + update_appearance() + target.update_appearance() + return ITEM_INTERACT_SUCCESS /obj/item/reagent_containers/dropper/update_overlays() . = ..() diff --git a/code/modules/reagents/reagent_containers/misc.dm b/code/modules/reagents/reagent_containers/misc.dm index 4e55cce99a1..f7152204f9e 100644 --- a/code/modules/reagents/reagent_containers/misc.dm +++ b/code/modules/reagents/reagent_containers/misc.dm @@ -138,15 +138,13 @@ user.visible_message(span_suicide("[user] is smothering [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!")) return OXYLOSS -/obj/item/reagent_containers/cup/rag/afterattack(atom/target, mob/living/user, proximity_flag, click_parameters) - if(!proximity_flag) - return - if(!iscarbon(target) || !reagents?.total_volume) +/obj/item/reagent_containers/cup/rag/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!iscarbon(interacting_with) || !reagents?.total_volume) return ..() - var/mob/living/carbon/carbon_target = target + var/mob/living/carbon/carbon_target = interacting_with var/reagentlist = pretty_string_from_reagent_list(reagents.reagent_list) var/log_object = "containing [reagentlist]" - if(user.combat_mode && !carbon_target.is_mouth_covered()) + if(!carbon_target.is_mouth_covered()) reagents.trans_to(carbon_target, reagents.total_volume, transferred_by = user, methods = INGEST) carbon_target.visible_message(span_danger("[user] smothers \the [carbon_target] with \the [src]!"), span_userdanger("[user] smothers you with \the [src]!"), span_hear("You hear some struggling and muffled cries of surprise.")) log_combat(user, carbon_target, "smothered", src, log_object) @@ -155,7 +153,12 @@ reagents.clear_reagents() carbon_target.visible_message(span_notice("[user] touches \the [carbon_target] with \the [src].")) log_combat(user, carbon_target, "touched", src, log_object) + return ITEM_INTERACT_SUCCESS ///Checks whether or not we should clean. /obj/item/reagent_containers/cup/rag/proc/should_clean(datum/cleaning_source, atom/atom_to_clean, mob/living/cleaner) - return (src in cleaner) + if(cleaner.combat_mode && ismob(atom_to_clean)) + return CLEAN_BLOCKED|CLEAN_DONT_BLOCK_INTERACTION + if(loc == cleaner) + return CLEAN_ALLOWED + return CLEAN_ALLOWED|CLEAN_NO_XP diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 6a8df092d5d..74538ae79de 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -59,24 +59,20 @@ return TRUE -/obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity) - . = ..() - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/pill/interact_with_atom(atom/target, mob/living/user, list/modifiers) if(!dissolvable || !target.is_refillable()) - return + return NONE if(target.is_drainable() && !target.reagents.total_volume) to_chat(user, span_warning("[target] is empty! There's nothing to dissolve [src] in.")) - return - + return ITEM_INTERACT_BLOCKING if(target.reagents.holder_full()) to_chat(user, span_warning("[target] is full.")) - return + return ITEM_INTERACT_BLOCKING user.visible_message(span_warning("[user] slips something into [target]!"), span_notice("You dissolve [src] in [target]."), null, 2) reagents.trans_to(target, reagents.total_volume, transferred_by = user) qdel(src) + return ITEM_INTERACT_SUCCESS /* * On accidental consumption, consume the pill diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index c6723b8554e..2b0be09ed71 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -26,31 +26,38 @@ possible_transfer_amounts = list(5,10) var/spray_sound = 'sound/effects/spray2.ogg' -/obj/item/reagent_containers/spray/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(istype(target, /obj/structure/sink) || istype(target, /obj/structure/mop_bucket/janitorialcart) || istype(target, /obj/machinery/hydroponics)) - return +/obj/item/reagent_containers/spray/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + return try_spray(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + +/obj/item/reagent_containers/spray/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + // This is a hack to make spray bottles fillable from / transferable to these sources + // However it can be completely removed when these objects are updated to use the new interaction system + // (because the desired effect will just work out of the box) + if(istype(interacting_with, /obj/structure/sink) || istype(interacting_with, /obj/structure/mop_bucket/janitorialcart) || istype(interacting_with, /obj/machinery/hydroponics)) + return NONE - . |= AFTERATTACK_PROCESSED_ITEM + return try_spray(interacting_with, user) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING - if((target.is_drainable() && !target.is_refillable()) && (get_dist(src, target) <= 1) && can_fill_from_container) +/obj/item/reagent_containers/spray/proc/try_spray(atom/target, mob/user) + var/adjacent = user.Adjacent(target) + if((target.is_drainable() && !target.is_refillable()) && adjacent && can_fill_from_container) if(!target.reagents.total_volume) to_chat(user, span_warning("[target] is empty.")) - return + return FALSE if(reagents.holder_full()) to_chat(user, span_warning("[src] is full.")) - return + return FALSE var/trans = target.reagents.trans_to(src, 50, transferred_by = user) //transfer 50u , using the spray's transfer amount would take too long to refill to_chat(user, span_notice("You fill \the [src] with [trans] units of the contents of \the [target].")) - return + return FALSE if(reagents.total_volume < amount_per_transfer_from_this) to_chat(user, span_warning("Not enough left!")) - return + return FALSE - if(proximity_flag && (target.density || ismob(target))) + if(adjacent && (target.density || ismob(target))) // If we're spraying an adjacent mob or a dense object, we start the spray on ITS tile rather than OURs // This is so we can use a spray bottle to clean stuff like windows without getting blocked by passflags spray(target, user, get_turf(target)) @@ -58,9 +65,9 @@ spray(target, user) playsound(src, spray_sound, 50, TRUE, -6) - user.changeNext_move(CLICK_CD_RANGE*2) + user.changeNext_move(CLICK_CD_RANGE * 2) user.newtonian_move(get_dir(target, user)) - return + return TRUE /// Handles creating a chem puff that travels towards the target atom, exposing reagents to everything it hits on the way. /obj/item/reagent_containers/spray/proc/spray(atom/target, mob/user, turf/start_turf = get_turf(src)) @@ -232,10 +239,10 @@ return OXYLOSS // Fix pepperspraying yourself -/obj/item/reagent_containers/spray/pepper/afterattack(atom/A as mob|obj, mob/user) - if (A.loc == user) - return - return ..() | AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/spray/pepper/try_spray(atom/target, mob/user) + if (target.loc == user) + return FALSE + return ..() //water flower /obj/item/reagent_containers/spray/waterflower @@ -320,11 +327,10 @@ amount_per_transfer_from_this = 10 volume = 600 -/obj/item/reagent_containers/spray/chemsprayer/afterattack(atom/A as mob|obj, mob/user) - // Make it so the bioterror spray doesn't spray yourself when you click your inventory items - if (A.loc == user) - return - return ..() | AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/spray/chemsprayer/try_spray(atom/target, mob/user) + if (target.loc == user) + return FALSE + return ..() /obj/item/reagent_containers/spray/chemsprayer/spray(atom/A, mob/user) var/direction = get_dir(src, A) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 83f71ff69b0..9fffd5ccc7c 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -25,9 +25,7 @@ /obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params) return -/obj/item/reagent_containers/syringe/proc/try_syringe(atom/target, mob/user, proximity) - if(!proximity) - return FALSE +/obj/item/reagent_containers/syringe/proc/try_syringe(atom/target, mob/user) if(!target.reagents) return FALSE @@ -36,49 +34,50 @@ if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags)) return FALSE - // chance of monkey retaliation - SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE, user) return TRUE -/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user, proximity) - . = ..() - . |= AFTERATTACK_PROCESSED_ITEM +/obj/item/reagent_containers/syringe/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(!target.reagents) + return NONE + if(!try_syringe(target, user)) + return ITEM_INTERACT_BLOCKING - if (!try_syringe(target, user, proximity)) - return + SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE_INJECT, user) var/contained = reagents.get_reagent_log_string() log_combat(user, target, "attempted to inject", src, addition="which had [contained]") if(!reagents.total_volume) to_chat(user, span_warning("[src] is empty! Right-click to draw.")) - return + return ITEM_INTERACT_BLOCKING if(!isliving(target) && !target.is_injectable(user)) to_chat(user, span_warning("You cannot directly fill [target]!")) - return + return ITEM_INTERACT_BLOCKING if(target.reagents.total_volume >= target.reagents.maximum_volume) to_chat(user, span_notice("[target] is full.")) - return + return ITEM_INTERACT_BLOCKING if(isliving(target)) var/mob/living/living_target = target - if(!living_target.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags)) - return if(living_target != user) - living_target.visible_message(span_danger("[user] is trying to inject [living_target]!"), \ - span_userdanger("[user] is trying to inject you!")) - if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), living_target, extra_checks = CALLBACK(living_target, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags))) - return + living_target.visible_message( + span_danger("[user] is trying to inject [living_target]!"), + span_userdanger("[user] is trying to inject you!"), + ) + if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), living_target, extra_checks = CALLBACK(src, PROC_REF(try_syringe), living_target, user))) + return ITEM_INTERACT_BLOCKING if(!reagents.total_volume) - return + return ITEM_INTERACT_BLOCKING if(living_target.reagents.total_volume >= living_target.reagents.maximum_volume) - return - living_target.visible_message(span_danger("[user] injects [living_target] with the syringe!"), \ - span_userdanger("[user] injects you with the syringe!")) + return ITEM_INTERACT_BLOCKING + living_target.visible_message( + span_danger("[user] injects [living_target] with the syringe!"), + span_userdanger("[user] injects you with the syringe!"), + ) - if (living_target == user) + if(living_target == user) living_target.log_message("injected themselves ([contained]) with [name]", LOG_ATTACK, color="orange") else log_combat(user, living_target, "injected", src, addition="which had [contained]") @@ -86,44 +85,53 @@ if(reagents.trans_to(target, amount_per_transfer_from_this, transferred_by = user, methods = INJECT)) to_chat(user, span_notice("You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units.")) target.update_appearance() + return ITEM_INTERACT_SUCCESS -/obj/item/reagent_containers/syringe/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if (!try_syringe(target, user, proximity_flag)) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING + +/obj/item/reagent_containers/syringe/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers) + if (!target.reagents) + return NONE + if (!try_syringe(target, user)) + return ITEM_INTERACT_BLOCKING + + SEND_SIGNAL(target, COMSIG_LIVING_TRY_SYRINGE_WITHDRAW, user) if(reagents.total_volume >= reagents.maximum_volume) to_chat(user, span_notice("[src] is full.")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING if(isliving(target)) var/mob/living/living_target = target var/drawn_amount = reagents.maximum_volume - reagents.total_volume if(target != user) - target.visible_message(span_danger("[user] is trying to take a blood sample from [target]!"), \ - span_userdanger("[user] is trying to take a blood sample from you!")) - if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target, extra_checks = CALLBACK(living_target, TYPE_PROC_REF(/mob/living, try_inject), user, null, INJECT_TRY_SHOW_ERROR_MESSAGE|inject_flags))) - return SECONDARY_ATTACK_CONTINUE_CHAIN + target.visible_message( + span_danger("[user] is trying to take a blood sample from [target]!"), + span_userdanger("[user] is trying to take a blood sample from you!"), + ) + if(!do_after(user, CHEM_INTERACT_DELAY(3 SECONDS, user), target, extra_checks = CALLBACK(src, PROC_REF(try_syringe), living_target, user))) + return ITEM_INTERACT_BLOCKING if(reagents.total_volume >= reagents.maximum_volume) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING if(living_target.transfer_blood_to(src, drawn_amount)) user.visible_message(span_notice("[user] takes a blood sample from [living_target].")) else to_chat(user, span_warning("You are unable to draw any blood from [living_target]!")) - else - if(!target.reagents.total_volume) - to_chat(user, span_warning("[target] is empty!")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_SUCCESS - if(!target.is_drawable(user)) - to_chat(user, span_warning("You cannot directly remove reagents from [target]!")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + if(!target.reagents.total_volume) + to_chat(user, span_warning("[target] is empty!")) + return ITEM_INTERACT_BLOCKING - var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) // transfer from, transfer to - who cares? + if(!target.is_drawable(user)) + to_chat(user, span_warning("You cannot directly remove reagents from [target]!")) + return ITEM_INTERACT_BLOCKING - to_chat(user, span_notice("You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")) - target.update_appearance() + var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) // transfer from, transfer to - who cares? - return SECONDARY_ATTACK_CONTINUE_CHAIN + to_chat(user, span_notice("You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")) + target.update_appearance() + return ITEM_INTERACT_SUCCESS /* * On accidental consumption, inject the eater with 2/3rd of the syringe and reveal it diff --git a/code/modules/recycling/conveyor.dm b/code/modules/recycling/conveyor.dm index c4409263887..c5dfdc39d3e 100644 --- a/code/modules/recycling/conveyor.dm +++ b/code/modules/recycling/conveyor.dm @@ -543,10 +543,9 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) belt.id = id to_chat(user, span_notice("You have linked all nearby conveyor belt assemblies to this switch.")) -/obj/item/conveyor_switch_construct/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || user.stat || !isfloorturf(target) || istype(target, /area/shuttle)) - return +/obj/item/conveyor_switch_construct/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isfloorturf(interacting_with)) + return NONE var/found = FALSE for(var/obj/machinery/conveyor/belt in view()) @@ -555,10 +554,11 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) break if(!found) to_chat(user, "[icon2html(src, user)]" + span_notice("The conveyor switch did not detect any linked conveyor belts in range.")) - return - var/obj/machinery/conveyor_switch/built_switch = new/obj/machinery/conveyor_switch(target, id) + return ITEM_INTERACT_BLOCKING + var/obj/machinery/conveyor_switch/built_switch = new/obj/machinery/conveyor_switch(interacting_with, id) transfer_fingerprints_to(built_switch) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/stack/conveyor name = "conveyor belt assembly" @@ -576,17 +576,17 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) . = ..() id = _id -/obj/item/stack/conveyor/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || user.stat || !isfloorturf(target) || istype(target, /area/shuttle)) - return - var/belt_dir = get_dir(target, user) - if(target == user.loc) +/obj/item/stack/conveyor/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isfloorturf(interacting_with)) + return NONE + var/belt_dir = get_dir(interacting_with, user) + if(interacting_with == user.loc) to_chat(user, span_warning("You cannot place a conveyor belt under yourself!")) - return - var/obj/machinery/conveyor/belt = new/obj/machinery/conveyor(target, belt_dir, id) + return ITEM_INTERACT_BLOCKING + var/obj/machinery/conveyor/belt = new/obj/machinery/conveyor(interacting_with, belt_dir, id) transfer_fingerprints_to(belt) use(1) + return ITEM_INTERACT_SUCCESS /obj/item/stack/conveyor/attackby(obj/item/item_used, mob/user, params) ..() diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index c4f4e975fb8..f02bfff4a09 100644 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -252,7 +252,7 @@ unwrap_contents() post_unwrap_contents(user) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING /obj/item/dest_tagger name = "destination tagger" diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm index 51e7dd69e81..7700c5300ff 100644 --- a/code/modules/research/stock_parts.dm +++ b/code/modules/research/stock_parts.dm @@ -37,19 +37,24 @@ If you create T5+ please take a pass at mech_fabricator.dm. The parts being good user.Beam(attacked_machinery, icon_state = "rped_upgrade", time = 0.5 SECONDS) return TRUE -/obj/item/storage/part_replacer/afterattack(obj/attacked_object, mob/living/user, adjacent, params) - . = ..() - if(!works_from_distance || adjacent) // Adjacent things = already handled by pre-attack - return . - - if(part_replace_action(attacked_object, user)) - user.Beam(attacked_object, icon_state = "rped_upgrade", time = 0.5 SECONDS) - return . | AFTERATTACK_PROCESSED_ITEM - - if(istype(attacked_object, /obj/structure/frame)) - attacked_object.item_interaction(user, src) // Cursed snowflake but we need to handle frame ranged interaction here - user.Beam(attacked_object, icon_state = "rped_upgrade", time = 0.5 SECONDS) - return . | AFTERATTACK_PROCESSED_ITEM +/obj/item/storage/part_replacer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(part_replace_action(interacting_with, user)) + return ITEM_INTERACT_SUCCESS + return NONE + +/obj/item/storage/part_replacer/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!works_from_distance) + return NONE + if(part_replace_action(interacting_with, user)) + user.Beam(interacting_with, icon_state = "rped_upgrade", time = 0.5 SECONDS) + return ITEM_INTERACT_SUCCESS + if(istype(interacting_with, /obj/structure/frame)) + // Cursed snowflake but we need to handle frame ranged interaction here + // Likely no longer necessary with the new framework, revisit later + interacting_with.item_interaction(user, src) + user.Beam(interacting_with, icon_state = "rped_upgrade", time = 0.5 SECONDS) + return ITEM_INTERACT_SUCCESS + return NONE /obj/item/storage/part_replacer/proc/play_rped_sound() //Plays the sound for RPED exhanging or installing parts. diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 7f8f835e8d9..75fabc77cf1 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -52,11 +52,10 @@ Slimecrossing Items ret[part.body_zone] = saved_part return ret -/obj/item/camera/rewind/afterattack(atom/target, mob/user, flag) - . |= AFTERATTACK_PROCESSED_ITEM - - if(!on || !pictures_left || !isturf(target.loc)) - return . +/obj/item/camera/rewind/photo_taken(atom/target, mob/user) + . = ..() + if(!.) + return if(user == target) to_chat(user, span_notice("You take a selfie!")) @@ -66,9 +65,6 @@ Slimecrossing Items to_chat(target, span_boldnotice("You'll remember this moment forever!")) target.AddComponent(/datum/component/dejavu, 2) - return . | ..() - - //Timefreeze camera - Old Burning Sepia result. Kept in case admins want to spawn it /obj/item/camera/timefreeze @@ -77,13 +73,11 @@ Slimecrossing Items pictures_left = 1 pictures_max = 1 -/obj/item/camera/timefreeze/afterattack(atom/target, mob/user, flag) - . |= AFTERATTACK_PROCESSED_ITEM - - if(!on || !pictures_left || !isturf(target.loc)) - return . +/obj/item/camera/timefreeze/photo_taken(atom/target, mob/user) + . = ..() + if(!.) + return new /obj/effect/timestop(get_turf(target), 2, 50, list(user)) - return . | ..() //Hypercharged slime cell - Charged Yellow /obj/item/stock_parts/cell/high/slime_hypercharged diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm index ecf76357e20..16203cd3462 100644 --- a/code/modules/research/xenobiology/crossbreeding/_potions.dm +++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm @@ -11,27 +11,25 @@ Slimecrossing Potions icon = 'icons/obj/medical/chemical.dmi' icon_state = "potpurple" -/obj/item/slimepotion/extract_cloner/afterattack(obj/item/target, mob/user , proximity) - if(!proximity) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(is_reagent_container(target)) - return ..(target, user, proximity) - if(istype(target, /obj/item/slimecross)) - to_chat(user, span_warning("[target] is too complex for the potion to clone!")) - return - if(!istype(target, /obj/item/slime_extract)) - return - var/obj/item/slime_extract/S = target +/obj/item/slimepotion/extract_cloner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + . = ..() + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(istype(interacting_with, /obj/item/slimecross)) + to_chat(user, span_warning("[interacting_with] is too complex for the potion to clone!")) + return ITEM_INTERACT_BLOCKING + if(!istype(interacting_with, /obj/item/slime_extract)) + return ITEM_INTERACT_BLOCKING + var/obj/item/slime_extract/S = interacting_with if(S.recurring) - to_chat(user, span_warning("[target] is too complex for the potion to clone!")) - return + to_chat(user, span_warning("[interacting_with] is too complex for the potion to clone!")) + return ITEM_INTERACT_BLOCKING var/path = S.type - var/obj/item/slime_extract/C = new path(get_turf(target)) + var/obj/item/slime_extract/C = new path(get_turf(interacting_with)) C.extract_uses = S.extract_uses - to_chat(user, span_notice("You pour the potion onto [target], and the fluid solidifies into a copy of it!")) + to_chat(user, span_notice("You pour the potion onto [interacting_with], and the fluid solidifies into a copy of it!")) qdel(src) - return + return ITEM_INTERACT_SUCCESS //Peace potion - Charged Light Pink /obj/item/slimepotion/peacepotion @@ -107,34 +105,34 @@ Slimecrossing Potions icon_state = "potblue" var/uses = 2 -/obj/item/slimepotion/spaceproof/afterattack(obj/item/clothing/C, mob/user, proximity) +/obj/item/slimepotion/spaceproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) . = ..() - if(!uses) + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(uses <= 0) qdel(src) - return - if(!proximity) - return - if(!istype(C)) + return ITEM_INTERACT_BLOCKING + var/obj/item/clothing/clothing = interacting_with + if(!istype(clothing)) to_chat(user, span_warning("The potion can only be used on clothing!")) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(istype(C, /obj/item/clothing/suit/space)) - to_chat(user, span_warning("The [C] is already pressure-resistant!")) - return . | ..() - if(C.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && C.clothing_flags & STOPSPRESSUREDAMAGE) - to_chat(user, span_warning("The [C] is already pressure-resistant!")) - return . | ..() - to_chat(user, span_notice("You slather the blue gunk over the [C], making it airtight.")) - C.name = "pressure-resistant [C.name]" - C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - C.add_atom_colour(COLOR_NAVY, FIXED_COLOUR_PRIORITY) - C.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - C.cold_protection = C.body_parts_covered - C.clothing_flags |= STOPSPRESSUREDAMAGE + return ITEM_INTERACT_BLOCKING + if(istype(clothing, /obj/item/clothing/suit/space)) + to_chat(user, span_warning("The [interacting_with] is already pressure-resistant!")) + return ITEM_INTERACT_BLOCKING + if(clothing.min_cold_protection_temperature == SPACE_SUIT_MIN_TEMP_PROTECT && (clothing.clothing_flags & STOPSPRESSUREDAMAGE)) + to_chat(user, span_warning("The [interacting_with] is already pressure-resistant!")) + return ITEM_INTERACT_BLOCKING + to_chat(user, span_notice("You slather the blue gunk over the [clothing], making it airtight.")) + clothing.name = "pressure-resistant [clothing.name]" + clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + clothing.add_atom_colour(COLOR_NAVY, FIXED_COLOUR_PRIORITY) + clothing.min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + clothing.cold_protection = clothing.body_parts_covered + clothing.clothing_flags |= STOPSPRESSUREDAMAGE uses-- - if(!uses) + if(uses <= 0) qdel(src) - return . + return ITEM_INTERACT_SUCCESS //Enhancer potion - Charged Cerulean /obj/item/slimepotion/enhancer/max @@ -152,29 +150,30 @@ Slimecrossing Potions resistance_flags = LAVA_PROOF | FIRE_PROOF var/uses = 2 -/obj/item/slimepotion/lavaproof/afterattack(obj/item/C, mob/user, proximity) +/obj/item/slimepotion/lavaproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) . = ..() - if(!uses) + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(uses <= 0) qdel(src) - return ..() - if(!proximity) - return ..() - if(!istype(C)) + return ITEM_INTERACT_BLOCKING + if(!isitem(interacting_with)) to_chat(user, span_warning("You can't coat this with lavaproofing fluid!")) - return ..() - . |= AFTERATTACK_PROCESSED_ITEM - to_chat(user, span_notice("You slather the red gunk over the [C], making it lavaproof.")) - C.name = "lavaproof [C.name]" - C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - C.add_atom_colour(COLOR_MAROON, FIXED_COLOUR_PRIORITY) - C.resistance_flags |= LAVA_PROOF - if (isclothing(C)) - var/obj/item/clothing/CL = C - CL.clothing_flags |= LAVAPROTECT + return ITEM_INTERACT_BLOCKING + + var/obj/item/clothing = interacting_with + to_chat(user, span_notice("You slather the red gunk over the [clothing], making it lavaproof.")) + clothing.name = "lavaproof [clothing.name]" + clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + clothing.add_atom_colour(COLOR_MAROON, FIXED_COLOUR_PRIORITY) + clothing.resistance_flags |= LAVA_PROOF + if (isclothing(clothing)) + var/obj/item/clothing/clothing_real = clothing + clothing_real.clothing_flags |= LAVAPROTECT uses-- - if(!uses) + if(uses <= 0) qdel(src) - return . + return ITEM_INTERACT_SUCCESS //Revival potion - Charged Grey /obj/item/slimepotion/slime_reviver @@ -183,15 +182,21 @@ Slimecrossing Potions icon = 'icons/obj/medical/chemical.dmi' icon_state = "potsilver" -/obj/item/slimepotion/slime_reviver/attack(mob/living/basic/slime/revive_target, mob/user) +/obj/item/slimepotion/slime_reviver/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + . = ..() + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + var/mob/living/basic/slime/revive_target = interacting_with if(!isslime(revive_target)) to_chat(user, span_warning("The potion only works on slimes!")) - return ..() + return ITEM_INTERACT_BLOCKING if(revive_target.stat != DEAD) to_chat(user, span_warning("The slime is still alive!")) - return + return ITEM_INTERACT_BLOCKING if(revive_target.maxHealth <= 0) to_chat(user, span_warning("The slime is too unstable to return!")) + return ITEM_INTERACT_BLOCKING + user.do_attack_animation(interacting_with) revive_target.revive(HEAL_ALL) revive_target.set_stat(CONSCIOUS) revive_target.visible_message(span_notice("[revive_target] is filled with renewed vigor and blinks awake!")) @@ -199,6 +204,7 @@ Slimecrossing Potions revive_target.health -= 10 revive_target.regenerate_icons() qdel(src) + return ITEM_INTERACT_SUCCESS //Stabilizer potion - Charged Blue /obj/item/slimepotion/slime/chargedstabilizer diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index bae83e311a6..658d0734f4e 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -1079,7 +1079,7 @@ var/obj/item/slimecross/stabilized/rainbow/X = linked_extract if(istype(X)) if(X.regencore) - X.regencore.afterattack(owner,owner,TRUE) + X.regencore.interact_with_atom(owner, owner) X.regencore = null owner.visible_message(span_warning("[owner] flashes a rainbow of colors, and [owner.p_their()] skin is coated in a milky regenerative goo!")) qdel(src) diff --git a/code/modules/research/xenobiology/crossbreeding/_weapons.dm b/code/modules/research/xenobiology/crossbreeding/_weapons.dm index 1ad9ce683e4..c5136baafb1 100644 --- a/code/modules/research/xenobiology/crossbreeding/_weapons.dm +++ b/code/modules/research/xenobiology/crossbreeding/_weapons.dm @@ -27,8 +27,8 @@ Slimecrossing Weapons throwforce = 15 damtype = BRUTE -/obj/item/knife/rainbowknife/afterattack(atom/O, mob/user, proximity) - if(proximity && isliving(O)) +/obj/item/knife/rainbowknife/afterattack(atom/target, mob/user, params) + if(isliving(target)) damtype = pick(BRUTE, BURN, TOX, OXY) switch(damtype) if(BRUTE) @@ -47,7 +47,6 @@ Slimecrossing Weapons hitsound = 'sound/effects/space_wind.ogg' attack_verb_continuous = string_list(list("suffocates", "winds", "vacuums")) attack_verb_simple = string_list(list("suffocate", "wind", "vacuum")) - return ..() //Adamantine shield - Chilling Adamantine /obj/item/shield/adamantineshield diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index d8cf3456ed2..70784f5b90f 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -151,19 +151,20 @@ Chilling extracts: var/list/allies = list() var/active = FALSE -/obj/item/slimecross/chilling/bluespace/afterattack(atom/target, mob/user, proximity) - if(!proximity || !isliving(target) || active) - return - if(HAS_TRAIT(target, TRAIT_NO_TELEPORT)) - to_chat(user, span_warning("[target] resists being linked with [src]!")) - return - if(target in allies) - allies -= target - to_chat(user, span_notice("You unlink [src] with [target].")) +/obj/item/slimecross/chilling/bluespace/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isliving(interacting_with) || active) + return NONE + user.do_attack_animation(interacting_with) + if(HAS_TRAIT(interacting_with, TRAIT_NO_TELEPORT)) + to_chat(user, span_warning("[interacting_with] resists being linked with [src]!")) + return ITEM_INTERACT_BLOCKING + if(interacting_with in allies) + allies -= interacting_with + to_chat(user, span_notice("You unlink [src] with [interacting_with].")) else - allies |= target - to_chat(user, span_notice("You link [src] with [target].")) - return + allies += interacting_with + to_chat(user, span_notice("You link [src] with [interacting_with].")) + return ITEM_INTERACT_SUCCESS /obj/item/slimecross/chilling/bluespace/do_effect(mob/user) if(allies.len <= 0) @@ -193,16 +194,17 @@ Chilling extracts: effect_desc = "Touching someone with it adds/removes them from a list. Activating the extract stops time for 30 seconds, and everyone on the list is immune, except the user." var/list/allies = list() -/obj/item/slimecross/chilling/sepia/afterattack(atom/target, mob/user, proximity) - if(!proximity || !isliving(target)) - return - if(target in allies) - allies -= target - to_chat(user, span_notice("You unlink [src] with [target].")) +/obj/item/slimecross/chilling/sepia/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isliving(interacting_with)) + return NONE + user.do_attack_animation(interacting_with) + if(interacting_with in allies) + allies -= interacting_with + to_chat(user, span_notice("You unlink [src] with [interacting_with].")) else - allies |= target - to_chat(user, span_notice("You link [src] with [target].")) - return + allies += interacting_with + to_chat(user, span_notice("You link [src] with [interacting_with].")) + return ITEM_INTERACT_SUCCESS /obj/item/slimecross/chilling/sepia/do_effect(mob/user) user.visible_message(span_warning("[src] shatters, freezing time itself!")) diff --git a/code/modules/research/xenobiology/crossbreeding/prismatic.dm b/code/modules/research/xenobiology/crossbreeding/prismatic.dm index 3f8509c1a7c..947323b0e47 100644 --- a/code/modules/research/xenobiology/crossbreeding/prismatic.dm +++ b/code/modules/research/xenobiology/crossbreeding/prismatic.dm @@ -10,25 +10,25 @@ Prismatic extracts: icon_state = "prismatic" var/paintcolor = COLOR_WHITE -/obj/item/slimecross/prismatic/afterattack(turf/target, mob/user, proximity) - if(!proximity) - return - if(!istype(target) || isspaceturf(target)) - return - target.add_atom_colour(paintcolor, WASHABLE_COLOUR_PRIORITY) - playsound(target, 'sound/effects/slosh.ogg', 20, TRUE) - -/obj/item/slimecross/prismatic/grey/ +/obj/item/slimecross/prismatic/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isturf(interacting_with) || isspaceturf(interacting_with)) + return NONE + user.do_attack_animation(interacting_with) + interacting_with.add_atom_colour(paintcolor, WASHABLE_COLOUR_PRIORITY) + playsound(interacting_with, 'sound/effects/slosh.ogg', 20, TRUE) + return ITEM_INTERACT_SUCCESS + +/obj/item/slimecross/prismatic/grey colour = SLIME_TYPE_GREY desc = "It's constantly wet with a pungent-smelling, clear chemical." -/obj/item/slimecross/prismatic/grey/afterattack(turf/target, mob/user, proximity) - . = ..() - if(!proximity) - return - if(istype(target) && target.color != initial(target.color)) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - playsound(target, 'sound/effects/slosh.ogg', 20, TRUE) +/obj/item/slimecross/prismatic/grey/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isturf(interacting_with) && interacting_with.color != initial(interacting_with.color)) + user.do_attack_animation(interacting_with) + interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + playsound(interacting_with, 'sound/effects/slosh.ogg', 20, TRUE) + return ITEM_INTERACT_SUCCESS + return ..() /obj/item/slimecross/prismatic/orange paintcolor = "#FFA500" diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm index ee02a18f11f..e46290bef28 100644 --- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm +++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm @@ -14,14 +14,13 @@ Regenerative extracts: /obj/item/slimecross/regenerative/proc/core_effect_before(mob/living/carbon/human/target, mob/user) return -/obj/item/slimecross/regenerative/afterattack(atom/target,mob/user,prox) - . = ..() - if(!prox || !isliving(target)) +/obj/item/slimecross/regenerative/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isliving(interacting_with)) return - var/mob/living/H = target + var/mob/living/H = interacting_with if(H.stat == DEAD) to_chat(user, span_warning("[src] will not work on the dead!")) - return + return ITEM_INTERACT_BLOCKING if(H != user) user.visible_message(span_notice("[user] crushes [src] over [H], the milky goo quickly regenerating all of [H.p_their()] injuries!"), span_notice("You squeeze [src], and it bursts over [H], the milky goo regenerating [H.p_their()] injuries.")) @@ -29,10 +28,12 @@ Regenerative extracts: user.visible_message(span_notice("[user] crushes [src] over [user.p_them()]self, the milky goo quickly regenerating all of [user.p_their()] injuries!"), span_notice("You squeeze [src], and it bursts in your hand, splashing you with milky goo which quickly regenerates your injuries!")) core_effect_before(H, user) + user.do_attack_animation(interacting_with) H.revive(HEAL_ALL) core_effect(H, user) - playsound(target, 'sound/effects/splat.ogg', 40, TRUE) + playsound(H, 'sound/effects/splat.ogg', 40, TRUE) qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/slimecross/regenerative/grey colour = SLIME_TYPE_GREY //Has no bonus effect. diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 4f4a85b1b60..34d7f4d507a 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -644,13 +644,12 @@ desc = "A hard yet gelatinous capsule excreted by a slime, containing mysterious substances." w_class = WEIGHT_CLASS_TINY -/obj/item/slimepotion/afterattack(obj/item/reagent_containers/target, mob/user , proximity) - . = ..() - if(!proximity) - return - if (istype(target)) - to_chat(user, span_warning("You cannot transfer [src] to [target]! It appears the potion must be given directly to a slime to absorb.") ) - return +/obj/item/slimepotion/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(is_reagent_container(interacting_with)) + to_chat(user, span_warning("You cannot transfer [src] to [interacting_with]! \ + It appears the potion must be given directly to a slime to absorb.") ) + return ITEM_INTERACT_BLOCKING + return NONE /obj/item/slimepotion/slime/docility name = "docility potion" @@ -778,33 +777,36 @@ var/prompted = 0 var/animal_type = SENTIENCE_ORGANIC -/obj/item/slimepotion/transference/afterattack(mob/living/switchy_mob, mob/living/user, proximity) - if(!proximity) - return +/obj/item/slimepotion/transference/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + . = ..() + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + var/mob/living/switchy_mob = interacting_with if(prompted || !isliving(switchy_mob)) - return + return ITEM_INTERACT_BLOCKING if(switchy_mob.ckey) //much like sentience, these will not work on something that is already player controlled balloon_alert(user, "already sentient!") - return ..() + return ITEM_INTERACT_BLOCKING if(switchy_mob.stat) balloon_alert(user, "it's dead!") - return ..() + return ITEM_INTERACT_BLOCKING if(!switchy_mob.compare_sentience_type(animal_type)) balloon_alert(user, "invalid creature!") - return ..() + return ITEM_INTERACT_BLOCKING var/job_banned = is_banned_from(user.ckey, ROLE_MIND_TRANSFER) if(QDELETED(src) || QDELETED(switchy_mob) || QDELETED(user)) - return + return ITEM_INTERACT_BLOCKING if(job_banned) balloon_alert(user, "you're banned!") - return + return ITEM_INTERACT_BLOCKING + user.do_attack_animation(interacting_with) prompted = 1 if(tgui_alert(usr,"This will permanently transfer your consciousness to [switchy_mob]. Are you sure you want to do this?",,list("Yes","No")) == "No") prompted = 0 - return + return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You drink the potion then place your hands on [switchy_mob]...")) @@ -820,6 +822,7 @@ if(isanimal(switchy_mob)) var/mob/living/simple_animal/switchy_animal= switchy_mob switchy_animal.sentience_act() + return ITEM_INTERACT_SUCCESS /obj/item/slimepotion/slime/steroid name = "slime steroid" @@ -903,29 +906,29 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = "potyellow" -/obj/item/slimepotion/speed/afterattack(obj/C, mob/user, proximity) +/obj/item/slimepotion/speed/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) . = ..() - if(!proximity) - return - if(!istype(C)) + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(!isobj(interacting_with)) to_chat(user, span_warning("The potion can only be used on objects!")) - return - . |= AFTERATTACK_PROCESSED_ITEM - if(SEND_SIGNAL(C, COMSIG_SPEED_POTION_APPLIED, src, user) & SPEED_POTION_STOP) - return - if(isitem(C)) - var/obj/item/I = C - if(I.slowdown <= 0 || (I.item_flags & IMMUTABLE_SLOW)) - to_chat(user, span_warning("The [C] can't be made any faster!")) - return ..() - I.slowdown = 0 - - to_chat(user, span_notice("You slather the red gunk over the [C], making it faster.")) - C.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - C.add_atom_colour(COLOR_RED, FIXED_COLOUR_PRIORITY) + return ITEM_INTERACT_BLOCKING + if(SEND_SIGNAL(interacting_with, COMSIG_SPEED_POTION_APPLIED, src, user) & SPEED_POTION_STOP) + return ITEM_INTERACT_SUCCESS + if(isitem(interacting_with)) + var/obj/item/apply_to = interacting_with + if(apply_to.slowdown <= 0 || (apply_to.item_flags & IMMUTABLE_SLOW)) + to_chat(user, span_warning("The [apply_to] can't be made any faster!")) + return ITEM_INTERACT_BLOCKING + apply_to.slowdown = 0 + + to_chat(user, span_notice("You slather the red gunk over the [interacting_with], making it faster.")) + interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + interacting_with.add_atom_colour(COLOR_RED, FIXED_COLOUR_PRIORITY) qdel(src) + return ITEM_INTERACT_SUCCESS -/obj/item/slimepotion/speed/attackby_storage_insert(datum/storage, atom/storage_holder, mob/user) +/obj/item/slimepotion/speed/storage_insert_on_interaction(datum/storage, atom/storage_holder, mob/user) if(!isitem(storage_holder)) return TRUE if(istype(storage_holder, /obj/item/mod/control)) @@ -942,20 +945,20 @@ resistance_flags = FIRE_PROOF var/uses = 3 -/obj/item/slimepotion/fireproof/afterattack(obj/item/clothing/clothing, mob/user, proximity) +/obj/item/slimepotion/fireproof/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) . = ..() - if(!proximity) - return - if(!uses) + if(. & ITEM_INTERACT_ANY_BLOCKER) + return . + if(uses <= 0) qdel(src) - return - . |= AFTERATTACK_PROCESSED_ITEM + return ITEM_INTERACT_BLOCKING + var/obj/item/clothing/clothing = interacting_with if(!istype(clothing)) to_chat(user, span_warning("The potion can only be used on clothing!")) - return + return ITEM_INTERACT_BLOCKING if(clothing.max_heat_protection_temperature >= FIRE_IMMUNITY_MAX_TEMP_PROTECT) to_chat(user, span_warning("The [clothing] is already fireproof!")) - return + return ITEM_INTERACT_BLOCKING to_chat(user, span_notice("You slather the blue gunk over the [clothing], fireproofing it.")) clothing.name = "fireproofed [clothing.name]" clothing.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) @@ -964,8 +967,9 @@ clothing.heat_protection = clothing.body_parts_covered clothing.resistance_flags |= FIRE_PROOF uses -- - if(!uses) + if(uses <= 0) qdel(src) + return ITEM_INTERACT_BLOCKING /obj/item/slimepotion/genderchange name = "gender change potion" @@ -1080,4 +1084,3 @@ max_amount = 60 turf_type = /turf/open/floor/sepia merge_type = /obj/item/stack/tile/sepia - diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index ca2618a7525..38199785878 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -804,14 +804,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/item/storage/pod, 32) new /obj/item/bodybag/environmental(src) new /obj/item/bodybag/environmental(src) -/obj/item/storage/pod/attackby(obj/item/W, mob/user, params) - if (can_interact(user)) - return ..() - -/obj/item/storage/pod/attackby_secondary(obj/item/weapon, mob/user, params) - if (!can_interact(user)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - return ..() +/obj/item/storage/pod/storage_insert_on_interacted_with(datum/storage, obj/item/inserted, mob/living/user) + return can_interact(user) /obj/item/storage/pod/attack_hand(mob/user, list/modifiers) if (can_interact(user)) diff --git a/code/modules/spells/spell_types/self/sanguine_strike.dm b/code/modules/spells/spell_types/self/sanguine_strike.dm index afb5860c6a6..7afa3deb8d9 100644 --- a/code/modules/spells/spell_types/self/sanguine_strike.dm +++ b/code/modules/spells/spell_types/self/sanguine_strike.dm @@ -58,7 +58,7 @@ RegisterSignal(enchanted, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped)) /// signal called from attacking with the enchanted item -/datum/action/cooldown/spell/sanguine_strike/proc/on_enchanted_afterattack(obj/item/enchanted, atom/target, mob/user, proximity_flag, click_parameters) +/datum/action/cooldown/spell/sanguine_strike/proc/on_enchanted_afterattack(obj/item/enchanted, atom/target, mob/user, click_parameters) SIGNAL_HANDLER end_enchantment(enchanted) if(!isliving(target)) diff --git a/code/modules/spells/spell_types/touch/_touch.dm b/code/modules/spells/spell_types/touch/_touch.dm index 29a6f28e4f5..a28b339dcff 100644 --- a/code/modules/spells/spell_types/touch/_touch.dm +++ b/code/modules/spells/spell_types/touch/_touch.dm @@ -128,7 +128,6 @@ SHOULD_CALL_PARENT(TRUE) RegisterSignal(attached_hand, COMSIG_ITEM_AFTERATTACK, PROC_REF(on_hand_hit)) - RegisterSignal(attached_hand, COMSIG_ITEM_AFTERATTACK_SECONDARY, PROC_REF(on_secondary_hand_hit)) RegisterSignal(attached_hand, COMSIG_ITEM_DROPPED, PROC_REF(on_hand_dropped)) RegisterSignal(attached_hand, COMSIG_QDELETING, PROC_REF(on_hand_deleted)) @@ -142,7 +141,6 @@ UnregisterSignal(attached_hand, list( COMSIG_ITEM_AFTERATTACK, - COMSIG_ITEM_AFTERATTACK_SECONDARY, COMSIG_ITEM_DROPPED, COMSIG_QDELETING, COMSIG_ITEM_OFFER_TAKEN, @@ -165,33 +163,17 @@ * * When our hand hits an atom, we can cast do_hand_hit() on them. */ -/datum/action/cooldown/spell/touch/proc/on_hand_hit(datum/source, atom/victim, mob/caster, proximity_flag, click_parameters) +/datum/action/cooldown/spell/touch/proc/on_hand_hit(datum/source, atom/victim, mob/caster, click_parameters) SIGNAL_HANDLER SHOULD_NOT_OVERRIDE(TRUE) // DEFINITELY don't put effects here, put them in cast_on_hand_hit - if(!proximity_flag) - return - if(!can_hit_with_hand(victim, caster)) - return - - INVOKE_ASYNC(src, PROC_REF(do_hand_hit), source, victim, caster) - -/** - * Signal proc for [COMSIG_ITEM_AFTERATTACK_SECONDARY] from our attached hand. - * - * Same as on_hand_hit, but for if right-click was used on hit. - */ -/datum/action/cooldown/spell/touch/proc/on_secondary_hand_hit(datum/source, atom/victim, mob/caster, proximity_flag, click_parameters) - SIGNAL_HANDLER - SHOULD_NOT_OVERRIDE(TRUE) // DEFINITELY don't put effects here, put them in cast_on_secondary_hand_hit - - if(!proximity_flag) - return if(!can_hit_with_hand(victim, caster)) return - INVOKE_ASYNC(src, PROC_REF(do_secondary_hand_hit), source, victim, caster) - return COMPONENT_SECONDARY_CANCEL_ATTACK_CHAIN + if(LAZYACCESS(params2list(click_parameters), RIGHT_CLICK)) + INVOKE_ASYNC(src, PROC_REF(do_secondary_hand_hit), source, victim, caster) + else + INVOKE_ASYNC(src, PROC_REF(do_hand_hit), source, victim, caster) /// Checks if the passed victim can be cast on by the caster. /datum/action/cooldown/spell/touch/proc/can_hit_with_hand(atom/victim, mob/caster) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 85c1beab0a3..be4bdb6db5d 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -341,11 +341,9 @@ . = ..() UnregisterSignal(user, COMSIG_SURGERY_STARTING) -/obj/item/surgical_processor/afterattack(atom/design_holder, mob/user, proximity) - if(!proximity) - return ..() +/obj/item/surgical_processor/interact_with_atom(atom/design_holder, mob/living/user, list/modifiers) if(!istype(design_holder, /obj/item/disk/surgery) && !istype(design_holder, /obj/machinery/computer/operating)) - return ..() + return NONE balloon_alert(user, "copying designs...") playsound(src, 'sound/machines/terminal_processing.ogg', 25, TRUE) if(do_after(user, 1 SECONDS, target = design_holder)) @@ -358,7 +356,8 @@ playsound(src, 'sound/machines/terminal_success.ogg', 25, TRUE) downloaded = TRUE update_appearance(UPDATE_OVERLAYS) - return TRUE + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/surgical_processor/update_overlays() . = ..() diff --git a/code/modules/unit_tests/projectiles.dm b/code/modules/unit_tests/projectiles.dm index fad9250cba3..7b19e0c506e 100644 --- a/code/modules/unit_tests/projectiles.dm +++ b/code/modules/unit_tests/projectiles.dm @@ -31,7 +31,7 @@ gunner.set_combat_mode(FALSE) // just to make sure we know we're not trying to pistol-whip them var/expected_damage = loaded_bullet.damage loaded_bullet.def_zone = BODY_ZONE_CHEST - var/did_we_shoot = test_gun.afterattack(victim, gunner) + var/did_we_shoot = test_gun.melee_attack_chain(gunner, victim) TEST_ASSERT(did_we_shoot, "Gun does not appeared to have successfully fired.") TEST_ASSERT_EQUAL(victim.getBruteLoss(), expected_damage, "Victim took incorrect amount of damage, expected [expected_damage], got [victim.getBruteLoss()].") diff --git a/code/modules/unit_tests/reagent_mob_expose.dm b/code/modules/unit_tests/reagent_mob_expose.dm index 51c35520daf..844b863c037 100644 --- a/code/modules/unit_tests/reagent_mob_expose.dm +++ b/code/modules/unit_tests/reagent_mob_expose.dm @@ -30,7 +30,7 @@ // TOUCH dropper.reagents.add_reagent(/datum/reagent/water, 5) - dropper.afterattack(human, human, TRUE) + dropper.melee_attack_chain(human, human) TEST_ASSERT(human.fire_stacks < 0, "Human still has fire stacks after touching water") // VAPOR diff --git a/code/modules/wiremod/components/admin/signal_handler/signal_list.dm b/code/modules/wiremod/components/admin/signal_handler/signal_list.dm index 8fbff3dcfaa..7d6571484b7 100644 --- a/code/modules/wiremod/components/admin/signal_handler/signal_list.dm +++ b/code/modules/wiremod/components/admin/signal_handler/signal_list.dm @@ -41,7 +41,6 @@ GLOBAL_LIST_INIT(integrated_circuit_signal_ids, generate_circuit_signal_list()) COMSIG_ITEM_AFTERATTACK = list(cancel_attack, target, user), COMSIG_ITEM_ATTACK_SECONDARY = list(secondary_cancel_attack, secondary_continue_attack, target, user), COMSIG_ITEM_PRE_ATTACK_SECONDARY = list(secondary_cancel_attack, secondary_continue_attack, target, user), - COMSIG_ITEM_AFTERATTACK_SECONDARY = list(secondary_cancel_attack, secondary_continue_attack, target, user), COMSIG_ITEM_ATTACK_SELF = list(cancel_attack, user), COMSIG_ITEM_ATTACK_SELF_SECONDARY = list(cancel_attack, user), ) diff --git a/code/modules/wiremod/shell/scanner.dm b/code/modules/wiremod/shell/scanner.dm index c88d7b1fb5f..f32f91fa76f 100644 --- a/code/modules/wiremod/shell/scanner.dm +++ b/code/modules/wiremod/shell/scanner.dm @@ -41,22 +41,19 @@ signal = add_output_port("Scanned", PORT_TYPE_SIGNAL) /obj/item/circuit_component/wiremod_scanner/register_shell(atom/movable/shell) - RegisterSignal(shell, COMSIG_ITEM_AFTERATTACK, PROC_REF(handle_afterattack)) + RegisterSignal(shell, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(handle_interaction)) /obj/item/circuit_component/wiremod_scanner/unregister_shell(atom/movable/shell) - UnregisterSignal(shell, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(shell, COMSIG_ITEM_INTERACTING_WITH_ATOM) /** * Called when the shell item attacks something */ -/obj/item/circuit_component/wiremod_scanner/proc/handle_afterattack(atom/source, atom/target, mob/user, proximity_flag) +/obj/item/circuit_component/wiremod_scanner/proc/handle_interaction(atom/source, mob/user, atom/target, ...) SIGNAL_HANDLER - if(!proximity_flag) - return source.balloon_alert(user, "scanned object") - playsound(source, get_sfx(SFX_TERMINAL_TYPE), 25, FALSE) + playsound(source, SFX_TERMINAL_TYPE, 25, FALSE) attacker.set_output(user) attacking.set_output(target) signal.set_output(COMPONENT_SIGNAL) - return COMPONENT_AFTERATTACK_PROCESSED_ITEM - + return ITEM_INTERACT_SUCCESS diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 1d5caf8e909..14dc6edee11 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -11,16 +11,11 @@ bare_wound_bonus = 15 sharpness = SHARP_EDGED -/obj/item/mutant_hand/zombie/afterattack(atom/target, mob/living/user, proximity_flag) - . = ..() - if(!proximity_flag) - return +/obj/item/mutant_hand/zombie/afterattack(atom/target, mob/user, click_parameters) + if(ishuman(target)) + try_to_zombie_infect(target, user, user.zone_selected) else if(isliving(target)) - if(ishuman(target)) - try_to_zombie_infect(target, user, user.zone_selected) - else - . |= AFTERATTACK_PROCESSED_ITEM - check_feast(target, user) + check_feast(target, user) /proc/try_to_zombie_infect(mob/living/carbon/human/target, mob/living/user, def_zone = BODY_ZONE_CHEST) CHECK_DNA_AND_SPECIES(target) diff --git a/modular_nova/master_files/code/game/objects/items/RCD.dm b/modular_nova/master_files/code/game/objects/items/RCD.dm index 7f380539591..8dbb00da644 100644 --- a/modular_nova/master_files/code/game/objects/items/RCD.dm +++ b/modular_nova/master_files/code/game/objects/items/RCD.dm @@ -20,16 +20,15 @@ return ..() // Drain deconstruction -/obj/item/construction/plumbing/afterattack(atom/target, mob/user, proximity) - if(!proximity) - return - if(istype(target, /obj/structure/drain)) - var/obj/structure/drain/drain_target = target - if(do_after(user, 2 SECONDS, target = target)) - drain_target.deconstruct() //Let's not substract matter - playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) - else +/obj/item/construction/plumbing/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/structure/drain)) return ..() + var/obj/structure/drain/drain_target = interacting_with + if(do_after(user, 2 SECONDS, target = interacting_with)) + drain_target.deconstruct() //Let's not substract matter + playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) + return ITEM_INTERACT_SUCCESS + return ITEM_INTERACT_BLOCKING /obj/item/construction/plumbing/mining name = "mining plumbing constructor" diff --git a/modular_nova/modules/ashwalkers/code/buildings/railroad.dm b/modular_nova/modules/ashwalkers/code/buildings/railroad.dm index 1220db529ce..dd9a92b7429 100644 --- a/modular_nova/modules/ashwalkers/code/buildings/railroad.dm +++ b/modular_nova/modules/ashwalkers/code/buildings/railroad.dm @@ -12,15 +12,16 @@ /obj/item/stack/rail_track/fifty amount = 50 -/obj/item/stack/rail_track/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!isopenturf(target) || !proximity_flag) - return ..() - var/turf/target_turf = get_turf(target) +/obj/item/stack/rail_track/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isopenturf(interacting_with)) + return NONE + var/turf/open/target_turf = get_turf(interacting_with) var/obj/structure/railroad/check_rail = locate() in target_turf if(check_rail || !use(1)) - return ..() + return NONE to_chat(user, span_notice("You place [src] on [target_turf].")) - new /obj/structure/railroad(get_turf(target)) + new /obj/structure/railroad(target_turf) + return ITEM_INTERACT_SUCCESS /obj/structure/railroad name = "railroad track" diff --git a/modular_nova/modules/ashwalkers/code/items/ashwalker_shaman.dm b/modular_nova/modules/ashwalkers/code/items/ashwalker_shaman.dm index 8c051578689..bcac6a17418 100644 --- a/modular_nova/modules/ashwalkers/code/items/ashwalker_shaman.dm +++ b/modular_nova/modules/ashwalkers/code/items/ashwalker_shaman.dm @@ -12,32 +12,30 @@ ///If the world.time is above this, it wont work. Charging requires whacking the necropolis nest var/staff_time = 0 -/obj/item/ash_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) - return ..() +/obj/item/ash_staff/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!user.mind.has_antag_datum(/datum/antagonist/ashwalker)) - return ..() - if(istype(target, /obj/structure/lavaland/ash_walker)) - return - if(isopenturf(target)) - var/turf/target_turf = target - if(istype(target, /turf/open/misc/asteroid/basalt/lava_land_surface)) - to_chat(user, span_warning("You begin to corrupt the land even further...")) - if(!do_after(user, 4 SECONDS, target = target_turf)) - to_chat(user, span_warning("[src] had their casting cut short!")) - return - target_turf.ChangeTurf(/turf/open/lava/smooth/lava_land_surface) - to_chat(user, span_notice("[src] sparks, corrupting the area too far!")) - return - if(world.time > staff_time) - to_chat(user, span_warning("[src] has had its permission expire from the necropolis!")) - return - if(!do_after(user, 2 SECONDS, target = target_turf)) + return NONE + if(istype(interacting_with, /obj/structure/lavaland/ash_walker)) + return NONE + if(!isopenturf(interacting_with)) + return NONE + var/turf/target_turf = interacting_with + if(istype(interacting_with, /turf/open/misc/asteroid/basalt/lava_land_surface)) + to_chat(user, span_warning("You begin to corrupt the land even further...")) + if(!do_after(user, 4 SECONDS, target = target_turf)) to_chat(user, span_warning("[src] had their casting cut short!")) - return - target_turf.ChangeTurf(/turf/open/misc/asteroid/basalt/lava_land_surface) + return ITEM_INTERACT_BLOCKING + target_turf.ChangeTurf(/turf/open/lava/smooth/lava_land_surface) + to_chat(user, span_notice("[src] sparks, corrupting the area too far!")) return - return ..() + if(world.time > staff_time) + to_chat(user, span_warning("[src] has had its permission expire from the necropolis!")) + return ITEM_INTERACT_BLOCKING + if(!do_after(user, 2 SECONDS, target = target_turf)) + to_chat(user, span_warning("[src] had their casting cut short!")) + return ITEM_INTERACT_BLOCKING + target_turf.ChangeTurf(/turf/open/misc/asteroid/basalt/lava_land_surface) + return ITEM_INTERACT_SUCCESS /obj/structure/lavaland/ash_walker/attackby(obj/item/I, mob/living/user, params) if(istype(I, /obj/item/ash_staff) && user.mind.has_antag_datum(/datum/antagonist/ashwalker)) diff --git a/modular_nova/modules/borg_buffs/code/snack_dispensor.dm b/modular_nova/modules/borg_buffs/code/snack_dispensor.dm index fbf81e7b412..85cec6b3939 100644 --- a/modular_nova/modules/borg_buffs/code/snack_dispensor.dm +++ b/modular_nova/modules/borg_buffs/code/snack_dispensor.dm @@ -88,52 +88,59 @@ var/snack_name = initial(selected_snack.name) to_chat(user, span_notice("[src] is now dispensing [snack_name].")) -/obj/item/borg_snack_dispenser/attack(mob/living/patron, mob/living/silicon/robot/user, params) +/obj/item/borg_snack_dispenser/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/mob/living/patron = interacting_with + if(!istype(patron)) + return NONE var/empty_hand = LAZYACCESS(patron.get_empty_held_indexes(), 1) if(!empty_hand) to_chat(user, span_warning("[patron] has no free hands!")) - return + return ITEM_INTERACT_BLOCKING if(!selected_snack) to_chat(user, span_warning("No snack selected.")) - return - if(!istype(user)) - CRASH("[src] being used by non borg [user]") - if(user.cell.charge < borg_charge_cutoff) - to_chat(user, span_danger("Automated Safety Measures restrict the operation of [src] while under [borg_charge_cutoff]!")) - return - if(!user.cell.use(borg_charge_usage)) - to_chat(user, span_danger("Failure printing snack: power failure!")) - return + return ITEM_INTERACT_BLOCKING + var/mob/living/silicon/robot/borg = user + if(!istype(borg)) + CRASH("[src] being used by non borg [borg]") + if(borg.cell.charge < borg_charge_cutoff) + to_chat(borg, span_danger("Automated Safety Measures restrict the operation of [src] while under [borg_charge_cutoff]!")) + return ITEM_INTERACT_BLOCKING + if(!borg.cell.use(borg_charge_usage)) + to_chat(borg, span_danger("Failure printing snack: power failure!")) + return ITEM_INTERACT_BLOCKING var/atom/snack = new selected_snack(src) patron.put_in_hand(snack, empty_hand) - user.do_item_attack_animation(patron, null, snack) + borg.do_item_attack_animation(patron, null, snack) playsound(loc, 'sound/machines/click.ogg', 10, TRUE) - to_chat(patron, span_notice("[user] dispenses [snack] into your empty hand and you reflexively grasp it.")) - to_chat(user, span_notice("You dispense [snack] into the hand of [user].")) + to_chat(patron, span_notice("[borg] dispenses [snack] into your empty hand and you reflexively grasp it.")) + to_chat(borg, span_notice("You dispense [snack] into the hand of [borg].")) + return ITEM_INTERACT_SUCCESS /obj/item/borg_snack_dispenser/click_alt(mob/user) launch_mode = !launch_mode to_chat(user, span_notice("[src] is [(launch_mode ? "now" : "no longer")] launching snacks at a distance.")) return CLICK_ACTION_SUCCESS -/obj/item/borg_snack_dispenser/afterattack(atom/target, mob/living/silicon/robot/user, proximity_flag, click_parameters) - if(Adjacent(target) || !launch_mode) - return ..() +/obj/item/borg_snack_dispenser/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!launch_mode) + return NONE if(!selected_snack) to_chat(user, span_warning("No snack selected.")) - return - if(!istype(user)) - CRASH("[src] being used by non borg [user]") - if(user.cell.charge < borg_charge_cutoff) - to_chat(user, span_danger("Automated Safety Measures restrict the operation of [src] while under [borg_charge_cutoff]!")) - return - if(!user.cell.use(borg_charge_usage)) - to_chat(user, span_danger("Failure printing snack: power failure!")) - return + return ITEM_INTERACT_BLOCKING + var/mob/living/silicon/robot/borg = user + if(!istype(borg)) + CRASH("[src] being used by non borg [borg]") + if(borg.cell.charge < borg_charge_cutoff) + to_chat(borg, span_danger("Automated Safety Measures restrict the operation of [src] while under [borg_charge_cutoff]!")) + return ITEM_INTERACT_BLOCKING + if(!borg.cell.use(borg_charge_usage)) + to_chat(borg, span_danger("Failure printing snack: power failure!")) + return ITEM_INTERACT_BLOCKING var/atom/movable/snack = new selected_snack(get_turf(src)) - snack.throw_at(target, 7, 2, user, TRUE, FALSE) + snack.throw_at(interacting_with, 7, 2, borg, TRUE, FALSE) playsound(loc, 'sound/machines/click.ogg', 10, TRUE) - user.visible_message(span_notice("[src] launches [snack] at [target]!")) + borg.visible_message(span_notice("[src] launches [snack] at [interacting_with]!")) + return ITEM_INTERACT_SUCCESS /obj/item/food/cookie/bacon name = "strip of bacon" diff --git a/modular_nova/modules/borgs/code/robot_items.dm b/modular_nova/modules/borgs/code/robot_items.dm index 0bcc09ac813..107f4f40585 100644 --- a/modular_nova/modules/borgs/code/robot_items.dm +++ b/modular_nova/modules/borgs/code/robot_items.dm @@ -355,12 +355,12 @@ /// A proc for shooting a projectile at the target, it's just that simple, really. -/obj/item/borg/paperplane_crossbow/proc/shoot(atom/target, mob/living/user, params) +/obj/item/borg/paperplane_crossbow/proc/shoot(atom/target, mob/living/user) if(!COOLDOWN_FINISHED(src, shooting_cooldown)) - return + return ITEM_INTERACT_BLOCKING if(planes <= 0) to_chat(user, span_warning("Not enough paper planes left!")) - return FALSE + return ITEM_INTERACT_BLOCKING planes-- var/obj/item/paperplane/syndicate/hardlight/plane_to_fire = new /obj/item/paperplane/syndicate/hardlight(get_turf(src.loc)) @@ -370,18 +370,19 @@ COOLDOWN_START(src, shooting_cooldown, shooting_delay) user.visible_message(span_warning("[user] shoots a paper plane at [target]!")) check_amount() + return ITEM_INTERACT_SUCCESS -/obj/item/borg/paperplane_crossbow/afterattack(atom/target, mob/living/user, proximity, click_params) - . = ..() +/obj/item/borg/paperplane_crossbow/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) check_amount() - if(iscyborg(user)) - var/mob/living/silicon/robot/robot_user = user - if(!robot_user.cell.use(10)) - to_chat(user, span_warning("Not enough power.")) - return FALSE - shoot(target, user, click_params) + if(!iscyborg(user)) + return ITEM_INTERACT_BLOCKING + var/mob/living/silicon/robot/robot_user = user + if(!robot_user.cell.use(10)) + to_chat(user, span_warning("Not enough power.")) + return ITEM_INTERACT_BLOCKING + return shoot(interacting_with, user) /// Holders for the package wrap and the wrapping paper synthetizers. diff --git a/modular_nova/modules/borgs/code/robot_upgrade.dm b/modular_nova/modules/borgs/code/robot_upgrade.dm index 9a51254472f..8d5d2b1900f 100644 --- a/modular_nova/modules/borgs/code/robot_upgrade.dm +++ b/modular_nova/modules/borgs/code/robot_upgrade.dm @@ -353,22 +353,20 @@ desc = "For giving affectionate kisses." item_flags = NOBLUDGEON -/obj/item/quadborg_tongue/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !isliving(target)) - return +/obj/item/quadborg_tongue/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) var/mob/living/silicon/robot/borg = user - var/mob/living/mob = target - - if(!HAS_TRAIT(target, TRAIT_AFFECTION_AVERSION)) // Checks for Affection Aversion trait - if(check_zone(borg.zone_selected) == "head") - borg.visible_message(span_warning("\the [borg] affectionally licks \the [mob]'s face!"), span_notice("You affectionally lick \the [mob]'s face!")) - playsound(borg, 'sound/effects/attackblob.ogg', 50, 1) - else - borg.visible_message(span_warning("\the [borg] affectionally licks \the [mob]!"), span_notice("You affectionally lick \the [mob]!")) - playsound(borg, 'sound/effects/attackblob.ogg', 50, 1) + var/mob/living/mob = interacting_with + if(!istype(mob)) + return ITEM_INTERACT_BLOCKING + if(HAS_TRAIT(interacting_with, TRAIT_AFFECTION_AVERSION)) // Checks for Affection Aversion trait + to_chat(user, span_warning("ERROR: [interacting_with] is on the Do Not Lick registry!")) + return ITEM_INTERACT_BLOCKING + if(check_zone(borg.zone_selected) == "head") + borg.visible_message(span_warning("\the [borg] affectionally licks \the [mob]'s face!"), span_notice("You affectionally lick \the [mob]'s face!")) else - to_chat(user, span_warning("ERROR: [target] is on the Do Not Lick registry!")) + borg.visible_message(span_warning("\the [borg] affectionally licks \the [mob]!"), span_notice("You affectionally lick \the [mob]!")) + playsound(borg, 'sound/effects/attackblob.ogg', 50, 1) + return ITEM_INTERACT_SUCCESS // Quadruped nose - Boop /obj/item/quadborg_nose @@ -380,16 +378,14 @@ item_flags = NOBLUDGEON force = 0 -/obj/item/quadborg_nose/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return +/obj/item/quadborg_nose/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(HAS_TRAIT(interacting_with, TRAIT_AFFECTION_AVERSION)) // Checks for Affection Aversion trait + to_chat(user, span_warning("ERROR: [interacting_with] is on the No Nosing registry!")) + return ITEM_INTERACT_BLOCKING - if(!HAS_TRAIT(target, TRAIT_AFFECTION_AVERSION)) // Checks for Affection Aversion trait - do_attack_animation(target, null, src) - user.visible_message(span_notice("[user] [pick("nuzzles", "pushes", "boops")] \the [target.name] with their nose!")) - else - to_chat(user, span_warning("ERROR: [target] is on the No Nosing registry!")) + do_attack_animation(interacting_with, null, src) + user.visible_message(span_notice("[user] [pick("nuzzles", "pushes", "boops")] \the [interacting_with.name] with their nose!")) + return ITEM_INTERACT_SUCCESS /// The Shrinkening /mob/living/silicon/robot diff --git a/modular_nova/modules/bsrpd/code/bsrpd.dm b/modular_nova/modules/bsrpd/code/bsrpd.dm index 11ee9422587..51391d50870 100644 --- a/modular_nova/modules/bsrpd/code/bsrpd.dm +++ b/modular_nova/modules/bsrpd/code/bsrpd.dm @@ -54,21 +54,21 @@ playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) return CLICK_ACTION_SUCCESS -/obj/item/pipe_dispenser/bluespace/afterattack(atom/target, mob/user, prox) - if(prox || !remote_piping_toggle) // If we are in proximity to the target or have our safety on, don't use charge and don't call this shitcode. - return ..() +/obj/item/pipe_dispenser/bluespace/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!remote_piping_toggle) // If we are in proximity to the target or have our safety on, don't use charge and don't call this shitcode. + return NONE if(current_capacity < ranged_use_cost) to_chat(user, span_warning("The [src] lacks the charge to do that.")) - return FALSE + return ITEM_INTERACT_BLOCKING if(!in_use) - user.Beam(target, icon_state = "rped_upgrade", time = 1 SECONDS) + user.Beam(interacting_with, icon_state = "rped_upgrade", time = 1 SECONDS) in_use = TRUE // So people can't just spam click and get more uses addtimer(VARSET_CALLBACK(src, in_use, FALSE), 1 SECONDS, TIMER_UNIQUE) - if(pre_attack(target, user)) + if(pre_attack(interacting_with, user)) current_capacity -= ranged_use_cost - return TRUE + return ITEM_INTERACT_SUCCESS - return FALSE + return ITEM_INTERACT_BLOCKING #undef BSRPD_CAPACITY_MAX #undef BSRPD_CAPACITY_USE diff --git a/modular_nova/modules/cargo_teleporter/code/cargo_teleporter.dm b/modular_nova/modules/cargo_teleporter/code/cargo_teleporter.dm index 9c9475f79ca..418c64f99a6 100644 --- a/modular_nova/modules/cargo_teleporter/code/cargo_teleporter.dm +++ b/modular_nova/modules/cargo_teleporter/code/cargo_teleporter.dm @@ -38,21 +38,17 @@ GLOBAL_LIST_EMPTY(cargo_marks) qdel(destroy_children) return CLICK_ACTION_SUCCESS -/obj/item/cargo_teleporter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) - return ..() - if(target == src) - return ..() +/obj/item/cargo_teleporter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!COOLDOWN_FINISHED(src, use_cooldown)) to_chat(user, span_warning("[src] is still on cooldown!")) - return + return ITEM_INTERACT_BLOCKING var/choice = tgui_input_list(user, "Select which cargo mark to teleport the items to?", "Cargo Mark Selection", GLOB.cargo_marks) if(!choice) - return ..() - if(get_dist(user, target) > 1) - return + return ITEM_INTERACT_BLOCKING + if(get_dist(user, interacting_with) > 1) + return ITEM_INTERACT_BLOCKING var/turf/moving_turf = get_turf(choice) - var/turf/target_turf = get_turf(target) + var/turf/target_turf = get_turf(interacting_with) for(var/check_content in target_turf.contents) if(isobserver(check_content)) continue @@ -68,6 +64,7 @@ GLOBAL_LIST_EMPTY(cargo_marks) do_teleport(movable_content, moving_turf, asoundout = 'sound/magic/Disable_Tech.ogg') new /obj/effect/decal/cleanable/ash(target_turf) COOLDOWN_START(src, use_cooldown, 8 SECONDS) + return ITEM_INTERACT_SUCCESS /datum/design/cargo_teleporter name = "Cargo Teleporter" diff --git a/modular_nova/modules/clock_cult/code/items/replica_fabricator.dm b/modular_nova/modules/clock_cult/code/items/replica_fabricator.dm index 2fa882d0885..62bc382f675 100644 --- a/modular_nova/modules/clock_cult/code/items/replica_fabricator.dm +++ b/modular_nova/modules/clock_cult/code/items/replica_fabricator.dm @@ -46,45 +46,45 @@ . += span_brass("Right Click in-hand to fabricate bronze sheets.") -/obj/item/clockwork/replica_fabricator/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !IS_CLOCK(user)) - return +/obj/item/clockwork/replica_fabricator/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!IS_CLOCK(user)) + return NONE - if(istype(target, /obj/item/stack/sheet)) // If it's an item, handle it seperately - attempt_convert_materials(target, user) - return + if(istype(interacting_with, /obj/item/stack/sheet)) // If it's an item, handle it seperately + attempt_convert_materials(interacting_with, user) + return ITEM_INTERACT_SUCCESS - if(!selected_output || !isopenturf(target)) // Now we handle objects - return + if(!selected_output || !isopenturf(interacting_with)) // Now we handle objects + return ITEM_INTERACT_BLOCKING - var/turf/creation_turf = get_turf(target) + var/turf/creation_turf = get_turf(interacting_with) if(locate(selected_output.to_create_path) in creation_turf) to_chat(user, span_clockyellow("There is already one of these on this tile!")) - return + return ITEM_INTERACT_BLOCKING if(power < selected_output.cost) to_chat(user, span_clockyellow("[src] needs at least [selected_output.cost]W of power to create this.")) - return + return ITEM_INTERACT_BLOCKING var/obj/effect/temp_visual/ratvar/constructing_effect/effect = new(creation_turf, selected_output.creation_delay) - if(!do_after(user, selected_output.creation_delay, target)) + if(!do_after(user, selected_output.creation_delay, interacting_with)) qdel(effect) - return + return ITEM_INTERACT_BLOCKING if(power < selected_output.cost) // Just in case - return + return ITEM_INTERACT_BLOCKING power -= selected_output.cost var/atom/created if(selected_output.to_create_path) - created = new selected_output.to_create_path(get_turf(target)) + created = new selected_output.to_create_path(get_turf(interacting_with)) selected_output.on_create(created, creation_turf, user) + return ITEM_INTERACT_SUCCESS /obj/item/clockwork/replica_fabricator/attackby(obj/item/attacking_item, mob/user, params) diff --git a/modular_nova/modules/clock_cult/code/items/weaponry.dm b/modular_nova/modules/clock_cult/code/items/weaponry.dm index 419efdd38e4..c79891e5ef6 100644 --- a/modular_nova/modules/clock_cult/code/items/weaponry.dm +++ b/modular_nova/modules/clock_cult/code/items/weaponry.dm @@ -168,11 +168,10 @@ AddElement(/datum/element/clockwork_description, "Firing from brass tiles will halve the time that it takes to recharge a bolt.") AddElement(/datum/element/clockwork_pickup) -/obj/item/gun/ballistic/bow/clockwork/afterattack(atom/target, mob/living/user, flag, params, passthrough) +/obj/item/gun/ballistic/bow/clockwork/try_fire_gun(atom/target, mob/living/user, params) if(!drawn || !chambered) to_chat(user, span_notice("[src] must be drawn to fire a shot!")) - return - + return FALSE return ..() /obj/item/gun/ballistic/bow/clockwork/shoot_live_shot(mob/living/user, pointblank, atom/pbtarget, message) diff --git a/modular_nova/modules/clock_cult/code/structures/traps/trap.dm b/modular_nova/modules/clock_cult/code/structures/traps/trap.dm index c891f4c6204..8815a22e960 100644 --- a/modular_nova/modules/clock_cult/code/structures/traps/trap.dm +++ b/modular_nova/modules/clock_cult/code/structures/traps/trap.dm @@ -18,12 +18,12 @@ place_trap(get_turf(src), user) -/obj/item/clockwork/trap_placer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!IS_CLOCK(user) || !isturf(target) || !proximity_flag) - return +/obj/item/clockwork/trap_placer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!IS_CLOCK(user) || !isturf(interacting_with)) + return NONE - place_trap(target, user) + place_trap(interacting_with, user) + return ITEM_INTERACT_SUCCESS /obj/item/clockwork/trap_placer/proc/place_trap(atom/target, mob/user) diff --git a/modular_nova/modules/colony_fabricator/code/construction/turfs.dm b/modular_nova/modules/colony_fabricator/code/construction/turfs.dm index 9fb40beda97..6aac65ee2ed 100644 --- a/modular_nova/modules/colony_fabricator/code/construction/turfs.dm +++ b/modular_nova/modules/colony_fabricator/code/construction/turfs.dm @@ -41,31 +41,29 @@ GLOBAL_LIST_INIT(plastic_wall_panel_recipes, list( . = ..() . += span_notice("You can build a prefabricated wall by right clicking on an empty floor.") -/obj/item/stack/sheet/plastic_wall_panel/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if(!isopenturf(target)) - return SECONDARY_ATTACK_CONTINUE_CHAIN - var/turf/open/build_on = target - if(!user.Adjacent(build_on)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/stack/sheet/plastic_wall_panel/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!isopenturf(interacting_with)) + return NONE + var/turf/open/build_on = interacting_with if(isgroundlessturf(build_on)) user.balloon_alert(user, "can't place it here!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(build_on.is_blocked_turf()) user.balloon_alert(user, "something is blocking the tile!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(get_amount() < 1) user.balloon_alert(user, "not enough material!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(!do_after(user, 3 SECONDS, build_on)) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(build_on.is_blocked_turf()) user.balloon_alert(user, "something is blocking the tile!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING if(!use(1)) user.balloon_alert(user, "not enough material!") - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_BLOCKING build_on.place_on_top(walltype, flags = CHANGETURF_INHERIT_AIR) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS /obj/item/stack/sheet/plastic_wall_panel/get_main_recipes() . = ..() diff --git a/modular_nova/modules/conveyor_sorter/code/conveyor_sorter.dm b/modular_nova/modules/conveyor_sorter/code/conveyor_sorter.dm index 277dad54faf..2e94dccf47d 100644 --- a/modular_nova/modules/conveyor_sorter/code/conveyor_sorter.dm +++ b/modular_nova/modules/conveyor_sorter/code/conveyor_sorter.dm @@ -35,23 +35,20 @@ new_cs.sorting_list = current_sort spawned_sorters += new_cs -/obj/item/conveyor_sorter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(target == src) - return ..() - if(!proximity_flag) - return ..() - if(!ismovable(target)) - return ..() - if(istype(target, /obj/effect/decal/conveyor_sorter)) - return - if(is_type_in_list(target, current_sort)) - to_chat(user, span_warning("[target] is already in [src]'s sorting list!")) - return +/obj/item/conveyor_sorter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ismovable(interacting_with)) + return NONE + if(istype(interacting_with, /obj/effect/decal/conveyor_sorter)) + return NONE + if(is_type_in_list(interacting_with, current_sort)) + to_chat(user, span_warning("[interacting_with] is already in [src]'s sorting list!")) + return ITEM_INTERACT_BLOCKING if(length(current_sort) >= max_items) to_chat(user, span_warning("[src] already has [max_items] things within the sorting list!")) - return - current_sort += target.type - to_chat(user, span_notice("[target] has been added to [src]'s sorting list.")) + return ITEM_INTERACT_BLOCKING + current_sort += interacting_with.type + to_chat(user, span_notice("[interacting_with] has been added to [src]'s sorting list.")) + return ITEM_INTERACT_SUCCESS /obj/item/conveyor_sorter/click_alt(mob/user) visible_message("[src] pings, resetting its sorting list!") diff --git a/modular_nova/modules/customization/game/objects/items/conversion_kits.dm b/modular_nova/modules/customization/game/objects/items/conversion_kits.dm index e0248b1e1f9..e42abb70af9 100644 --- a/modular_nova/modules/customization/game/objects/items/conversion_kits.dm +++ b/modular_nova/modules/customization/game/objects/items/conversion_kits.dm @@ -8,21 +8,20 @@ /// The object to turn it into. var/obj/item/to_obj -/obj/item/device/custom_kit/afterattack(obj/target_obj, mob/user, proximity_flag) - if(!proximity_flag) //Gotta be adjacent to your target - return - if(isturf(target_obj)) //This shouldn't be needed, but apparently it throws runtimes otherwise. - return - else if(target_obj.type == from_obj) //Checks whether the item is eligible to be converted - if(!pre_convert_check(target_obj, user)) - return FALSE - var/obj/item/converted_item = new to_obj(get_turf(src)) - user.put_in_hands(converted_item) - user.visible_message(span_notice("[user] modifies [target_obj] into [converted_item]."), span_notice("You modify [target_obj] into [converted_item].")) - qdel(target_obj) - qdel(src) - else - to_chat(user, span_warning("It looks like this kit won't work on [target_obj]...")) +/obj/item/device/custom_kit/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(isturf(interacting_with)) //This shouldn't be needed, but apparently it throws runtimes otherwise. + return NONE + if(interacting_with.type != from_obj) //Checks whether the item is eligible to be converted + to_chat(user, span_warning("It looks like this kit won't work on [interacting_with]...")) + return ITEM_INTERACT_BLOCKING + if(!pre_convert_check(interacting_with, user)) + return ITEM_INTERACT_BLOCKING + var/obj/item/converted_item = new to_obj + user.visible_message(span_notice("[user] modifies [interacting_with] into [converted_item]."), span_notice("You modify [interacting_with] into [converted_item].")) + qdel(interacting_with) + qdel(src) + user.put_in_hands(converted_item) + return ITEM_INTERACT_SUCCESS /// Override this if you have some condition you want fulfilled before allowing the conversion. Return TRUE to allow it to convert, return FALSE to prevent it. /obj/item/device/custom_kit/proc/pre_convert_check(obj/target_obj, mob/user) diff --git a/modular_nova/modules/customization/modules/surgery/organs/wings.dm b/modular_nova/modules/customization/modules/surgery/organs/wings.dm index 072509b0377..2b9014301d2 100644 --- a/modular_nova/modules/customization/modules/surgery/organs/wings.dm +++ b/modular_nova/modules/customization/modules/surgery/organs/wings.dm @@ -136,24 +136,24 @@ . += span_notice("Firstly, look upwards by holding [english_list(look_binds, nothing_text = "(nothing bound)", and_text = " or ", comma_text = ", or ")]!") . += span_notice("Then, click solid ground adjacent to the hole above you.") -/obj/item/climbing_moth_wings/afterattack(turf/open/target, mob/living/user, proximity_flag, click_parameters) - . = ..() +/obj/item/climbing_moth_wings/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/open/target = interacting_with if(target.z == user.z) - return + return NONE if(!istype(target) || isopenspaceturf(target)) - return + return NONE var/turf/user_turf = get_turf(user) var/datum/gas_mixture/environment = user_turf.return_air() var/turf/above = GET_TURF_ABOVE(user_turf) if(target_blocked(target, above)) - return + return NONE if(environment.return_pressure() < (HAZARD_LOW_PRESSURE)) to_chat(user, span_warning("There's far too little air for your wings to work against!")) - return + return ITEM_INTERACT_BLOCKING if(!isopenspaceturf(above) || !above.Adjacent(target)) //are we below a hole, is the target blocked, is the target adjacent to our hole user.balloon_alert(user, "blocked!") - return + return ITEM_INTERACT_BLOCKING var/away_dir = get_dir(above, target) user.visible_message(span_notice("[user] begins pushing themselves upwards with their wings!"), span_notice("Your wings start fluttering violently as you begin going upwards.")) @@ -165,7 +165,9 @@ user.forceMove(target) user.adjustStaminaLoss(100) playsound(user_turf, 'sound/voice/moth/moth_flutter.ogg', 50) //a third time for seasoning + . = ITEM_INTERACT_SUCCESS QDEL_LIST(effects) + return . || ITEM_INTERACT_BLOCKING /obj/item/climbing_moth_wings/proc/target_blocked(turf/target, turf/above) if(target.density || above.density) diff --git a/modular_nova/modules/faction/code/id.dm b/modular_nova/modules/faction/code/id.dm index c7b858989d0..26fed121421 100644 --- a/modular_nova/modules/faction/code/id.dm +++ b/modular_nova/modules/faction/code/id.dm @@ -18,15 +18,16 @@ icon_state = "data_1" var/list/extra_access -/obj/item/card/faction_access/afterattack(atom/movable/AM, mob/user, proximity) - . = ..() - if(istype(AM, /obj/item/card/id) && proximity) - var/obj/item/card/id/I = AM - if(extra_access) - for(var/acs in extra_access) - I.access |= acs - to_chat(user, span_notice("You upgrade [I] with extra access.")) - qdel(src) +/obj/item/card/faction_access/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/obj/item/card/id/id = interacting_with + if(!istype(id)) + return NONE + if(extra_access) + for(var/acs in extra_access) + id.access |= acs + to_chat(user, span_notice("You upgrade [id] with extra access.")) + qdel(src) + return ITEM_INTERACT_SUCCESS /obj/item/card/faction_access/guest name = "faction guest access card" diff --git a/modular_nova/modules/gladiator/code/game/objects/items/gladiator_items.dm b/modular_nova/modules/gladiator/code/game/objects/items/gladiator_items.dm index 00b532a8f8c..bdfcf2cdb78 100644 --- a/modular_nova/modules/gladiator/code/game/objects/items/gladiator_items.dm +++ b/modular_nova/modules/gladiator/code/game/objects/items/gladiator_items.dm @@ -154,17 +154,17 @@ if(is_nemesis_faction) force -= faction_bonus_force -/obj/item/claymore/dragonslayer/afterattack_secondary(atom/target, mob/living/user, params) // dark souls +/obj/item/claymore/dragonslayer/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) if(user.IsImmobilized()) // no free dodgerolls - return - var/turf/where_to = get_turf(target) + return NONE + var/turf/where_to = get_turf(interacting_with) user.apply_damage(damage = roll_stamcost, damagetype = STAMINA) user.Immobilize(0.1 SECONDS) // you dont get to adjust your roll user.throw_at(where_to, range = roll_range, speed = 1, force = MOVE_FORCE_NORMAL) user.apply_status_effect(/datum/status_effect/dodgeroll_iframes) playsound(user, SFX_BODYFALL, 50, TRUE) playsound(user, SFX_RUSTLE, 50, TRUE) - return ..() + return ITEM_INTERACT_SUCCESS /datum/status_effect/dodgeroll_iframes id = "dodgeroll_dodging" diff --git a/modular_nova/modules/gunpoint/code/gunpoint_datum.dm b/modular_nova/modules/gunpoint/code/gunpoint_datum.dm index 00c91fc7f0b..729040b99cc 100644 --- a/modular_nova/modules/gunpoint/code/gunpoint_datum.dm +++ b/modular_nova/modules/gunpoint/code/gunpoint_datum.dm @@ -76,7 +76,7 @@ /datum/gunpoint/Destroy() UnregisterSignal(aimed_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED)) - UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED)) + UnregisterSignal(target, list(COMSIG_QDELETING, COMSIG_ITEM_ATTACK_SELF, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ITEM_ATTACK_SELF, COMSIG_MOVABLE_RADIO_TALK_INTO, COMSIG_MOB_FIRED_GUN, COMSIG_MOVABLE_MOVED)) UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_STATUS_STUN, COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_LIVING_STATUS_PARALYZE, COMSIG_LIVING_UPDATED_RESTING)) REMOVE_TRAIT(source, TRAIT_NORUNNING, "gunpoint") diff --git a/modular_nova/modules/hyposprays/code/hyposprays_II.dm b/modular_nova/modules/hyposprays/code/hyposprays_II.dm index 1c9090aad1f..55e6ac2a0a8 100644 --- a/modular_nova/modules/hyposprays/code/hyposprays_II.dm +++ b/modular_nova/modules/hyposprays/code/hyposprays_II.dm @@ -26,8 +26,6 @@ var/list/allowed_containers = list(/obj/item/reagent_containers/cup/vial/small) /// Is the hypospray only able to use small vials. Relates to the loaded overlays var/small_only = TRUE - /// Inject or spray? - var/mode = HYPO_INJECT /// The presently-inserted vial. var/obj/item/reagent_containers/cup/vial/vial /// If the Hypospray starts with a vial, which vial does it start with? @@ -189,18 +187,14 @@ else current_vial.forceMove(old_loc) -/obj/item/hypospray/mkii/attackby(obj/item/used_item, mob/living/user) - if((istype(used_item, /obj/item/reagent_containers/cup/vial) && vial != null)) - if(!quickload) - to_chat(user, span_warning("[src] can not hold more than one vial!")) - return FALSE - else - insert_vial(used_item, user, vial) - return TRUE - - if((istype(used_item, /obj/item/reagent_containers/cup/vial))) - insert_vial(used_item, user) - return TRUE +/obj/item/hypospray/mkii/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!istype(tool, /obj/item/reagent_containers/cup/vial)) + return NONE + if(isnull(vial) || quickload) + insert_vial(tool, user, vial) + return ITEM_INTERACT_SUCCESS + to_chat(user, span_warning("[src] can not hold more than one vial!")) + return ITEM_INTERACT_BLOCKING /obj/item/hypospray/mkii/attack_self(mob/user) . = ..() @@ -229,41 +223,37 @@ obj_flags |= EMAGGED return TRUE -/obj/item/hypospray/mkii/attack(obj/item/hypo, mob/user, params) - mode = HYPO_INJECT - return +/obj/item/hypospray/mkii/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/item/reagent_containers/cup/vial)) + insert_vial(interacting_with, user, interacting_with) + return ITEM_INTERACT_SUCCESS + return do_inject(interacting_with, user, mode=HYPO_INJECT) -/obj/item/hypospray/mkii/attack_secondary(obj/item/hypo, mob/user, params) - mode = HYPO_SPRAY - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/hypospray/mkii/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + return do_inject(interacting_with, user, mode=HYPO_SPRAY) -/obj/item/hypospray/mkii/afterattack(atom/target, mob/living/user, proximity) - if(istype(target, /obj/item/reagent_containers/cup/vial)) - insert_vial(target, user, vial) - return TRUE - - if(!vial || !proximity || !isliving(target)) - return - var/mob/living/injectee = target +/obj/item/hypospray/mkii/proc/do_inject(mob/living/injectee, mob/living/user, mode) + if(!isliving(injectee)) + return NONE if(!injectee.reagents || !injectee.can_inject(user, user.zone_selected, penetrates)) - return + return NONE if(iscarbon(injectee)) var/obj/item/bodypart/affecting = injectee.get_bodypart(check_zone(user.zone_selected)) if(!affecting) to_chat(user, span_warning("The limb is missing!")) - return + return ITEM_INTERACT_BLOCKING //Always log attemped injections for admins var/contained = vial.reagents.get_reagent_log_string() log_combat(user, injectee, "attemped to inject", src, addition="which had [contained]") if(!vial) to_chat(user, span_notice("[src] doesn't have any vial installed!")) - return + return ITEM_INTERACT_BLOCKING if(!vial.reagents.total_volume) to_chat(user, span_notice("[src]'s vial is empty!")) - return + return ITEM_INTERACT_BLOCKING var/fp_verb = mode == HYPO_SPRAY ? "spray" : "inject" @@ -272,15 +262,15 @@ span_userdanger("[user] is trying to [fp_verb] you with [src]!")) var/selected_wait_time - if(target == user) + if(injectee == user) selected_wait_time = (mode == HYPO_INJECT) ? inject_self : spray_self else selected_wait_time = (mode == HYPO_INJECT) ? inject_wait : spray_wait if(!do_after(user, selected_wait_time, injectee, extra_checks = CALLBACK(injectee, /mob/living/proc/can_inject, user, user.zone_selected, penetrates))) - return - if(!vial.reagents.total_volume) - return + return ITEM_INTERACT_BLOCKING + if(!vial || !vial.reagents.total_volume) + return ITEM_INTERACT_BLOCKING log_attack("[user.name] ([user.ckey]) applied [src] to [injectee.name] ([injectee.ckey]), which had [contained] (COMBAT MODE: [uppertext(user.combat_mode)]) (MODE: [mode])") if(injectee != user) injectee.visible_message(span_danger("[user] uses the [src] on [injectee]!"), \ @@ -298,9 +288,7 @@ playsound(loc, long_sound ? 'modular_nova/modules/hyposprays/sound/hypospray_long.ogg' : pick('modular_nova/modules/hyposprays/sound/hypospray.ogg','modular_nova/modules/hyposprays/sound/hypospray2.ogg'), 50, 1, -1) to_chat(user, span_notice("You [fp_verb] [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")) update_appearance() - -/obj/item/hypospray/mkii/afterattack_secondary(atom/target, mob/living/user, proximity) - return SECONDARY_ATTACK_CALL_NORMAL + return ITEM_INTERACT_SUCCESS /obj/item/hypospray/mkii/attack_hand(mob/living/user) if(user && loc == user && user.is_holding(src)) diff --git a/modular_nova/modules/icemoon_additions/code/icecat_recipes.dm b/modular_nova/modules/icemoon_additions/code/icecat_recipes.dm index 6dd65abef5c..7a2ad588af7 100644 --- a/modular_nova/modules/icemoon_additions/code/icecat_recipes.dm +++ b/modular_nova/modules/icemoon_additions/code/icecat_recipes.dm @@ -152,15 +152,15 @@ throwforce = 0 w_class = WEIGHT_CLASS_TINY -/obj/item/frozen_breath/afterattack(atom/target, mob/living/carbon/user) +/obj/item/frozen_breath/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if (!is_species(user, /datum/species/human/felinid/primitive)) to_chat(user, span_warning("You have no idea how to use this freezing concoction.")) return - if(istype(target, /obj/item/organ/internal/lungs)) - var/obj/item/organ/internal/lungs/target_lungs = target + if(istype(interacting_with, /obj/item/organ/internal/lungs)) + var/obj/item/organ/internal/lungs/target_lungs = interacting_with if(IS_ROBOTIC_ORGAN(target_lungs)) - target.balloon_alert(user, "The lungs have to be organic!") + user.balloon_alert(user, "The lungs have to be organic!") return var/location = get_turf(target_lungs) playsound(location, 'sound/effects/slosh.ogg', 25, TRUE) diff --git a/modular_nova/modules/liquids/code/liquid_systems/liquid_interaction.dm b/modular_nova/modules/liquids/code/liquid_systems/liquid_interaction.dm index 1ec199f890c..ccabef3654f 100644 --- a/modular_nova/modules/liquids/code/liquid_systems/liquid_interaction.dm +++ b/modular_nova/modules/liquids/code/liquid_systems/liquid_interaction.dm @@ -12,16 +12,17 @@ interaction_callback = CALLBACK(parent, on_interaction_callback) /datum/component/liquids_interaction/RegisterWithParent() - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(AfterAttack)) //The only signal allowing item -> turf interaction + RegisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM, PROC_REF(item_interaction)) //The only signal allowing item -> turf interaction /datum/component/liquids_interaction/UnregisterFromParent() - UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) + UnregisterSignal(parent, COMSIG_ITEM_INTERACTING_WITH_ATOM) -/datum/component/liquids_interaction/proc/AfterAttack(obj/item/target, turf/turf_target, mob/user) +/datum/component/liquids_interaction/proc/item_interaction(datum/source, mob/living/user, atom/target, modifiers) SIGNAL_HANDLER - if(!isturf(turf_target) || !turf_target.liquids) + var/turf/turf_target = target + if(!isturf(target) || !turf_target.liquids) return NONE if(interaction_callback.Invoke(turf_target, user, turf_target.liquids)) - return COMPONENT_CANCEL_ATTACK_CHAIN + return ITEM_INTERACT_SUCCESS diff --git a/modular_nova/modules/liquids/code/mop.dm b/modular_nova/modules/liquids/code/mop.dm index d07a59ebaae..fb86b4c6ed3 100644 --- a/modular_nova/modules/liquids/code/mop.dm +++ b/modular_nova/modules/liquids/code/mop.dm @@ -8,7 +8,7 @@ // Disable normal cleaning if there are liquids. if(isturf(atom_to_clean) && turf_to_clean.liquids) - return DO_NOT_CLEAN + return CLEAN_BLOCKED|CLEAN_DONT_BLOCK_INTERACTION return ..() diff --git a/modular_nova/modules/magfed_turret/code/turret_framework.dm b/modular_nova/modules/magfed_turret/code/turret_framework.dm index af1833d0e07..1ecc025b567 100644 --- a/modular_nova/modules/magfed_turret/code/turret_framework.dm +++ b/modular_nova/modules/magfed_turret/code/turret_framework.dm @@ -18,12 +18,12 @@ #define TURRET_FLAG_SHOOT_NOONE 3 // Turrets will not fire at any player-type mob. #define TURRET_FLAG_SHOOT_EVERYONE 4 // Turrets will shoot at all player-type mobs. -#define TURRET_THREAT_PASSIVE 0 +#define TURRET_THREAT_PASSIVE 0 #define TURRET_THREAT_LOW 2 #define TURRET_THREAT_MEDIUM 4 #define TURRET_THREAT_HIGH 6 #define TURRET_THREAT_SEVERE 8 -#define TURRET_THREAT_PRIORITY 10 +#define TURRET_THREAT_PRIORITY 10 DEFINE_BITFIELD(turret_flags, list( "TURRET_FLAG_SHOOT_ALL_REACT" = TURRET_FLAG_SHOOT_ALL_REACT, @@ -190,30 +190,29 @@ DEFINE_BITFIELD(turret_flags, list( sync_turrets() return -/obj/item/target_designator/afterattack(atom/movable/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!can_see(user,target,scan_range)) //if outside range, dont bother. - return +/obj/item/target_designator/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_see(user, interacting_with, scan_range)) //if outside range, dont bother. + return NONE - if(target in linked_turrets) //to stop issues with linking turrets. - return + if(interacting_with in linked_turrets) //to stop issues with linking turrets. + return NONE if(acquired_target) //if there's a target already, cant designate one. - return + return ITEM_INTERACT_BLOCKING - designate_enemy(target, user) + designate_enemy(interacting_with, user) addtimer(CALLBACK(src, PROC_REF(clear_target), user), acquisition_duration) //clears after 5 seconds. to avoid issues. - return + return ITEM_INTERACT_SUCCESS -/obj/item/target_designator/afterattack_secondary(atom/movable/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(!can_see(user,target,scan_range)) //if outside range, dont bother. - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN +/obj/item/target_designator/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_see(user, interacting_with, scan_range)) //if outside range, dont bother. + return ITEM_INTERACT_BLOCKING - if(istype(target, /mob/living)) + if(istype(interacting_with, /mob/living)) for(var/obj/machinery/porta_turret/syndicate/toolbox/mag_fed/turret in linked_turrets) - turret.toggle_ally(target) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + turret.toggle_ally(interacting_with) + return ITEM_INTERACT_SUCCESS + return NONE /// designates a manual target to turrets /obj/item/target_designator/proc/designate_enemy(atom/movable/target, mob/user) @@ -234,7 +233,7 @@ DEFINE_BITFIELD(turret_flags, list( balloon_alert(user, "designation cleared!") /// Sets all turrets to the same state as the controller. -/obj/item/target_designator/proc/sync_turrets() +/obj/item/target_designator/proc/sync_turrets() for(var/obj/machinery/porta_turret/syndicate/toolbox/mag_fed/turret in linked_turrets) if(target_all == TRUE && follow_flags == FALSE) if(!(turret.target_assessment == TURRET_FLAG_SHOOT_EVERYONE)) diff --git a/modular_nova/modules/marines/code/gear.dm b/modular_nova/modules/marines/code/gear.dm index 5b68607d600..fb32d21c415 100644 --- a/modular_nova/modules/marines/code/gear.dm +++ b/modular_nova/modules/marines/code/gear.dm @@ -94,16 +94,18 @@ QDEL_NULL(underbarrel) return ..() -/obj/item/gun/ballistic/automatic/ar/modular/m44a/shotgun/afterattack_secondary(atom/target, mob/living/user, flag, params) - underbarrel.afterattack(target, user, flag, params) - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/gun/ballistic/automatic/ar/modular/m44a/shotgun/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + return underbarrel.try_fire_gun(target, user, params) + return ..() -/obj/item/gun/ballistic/automatic/ar/modular/m44a/shotgun/attackby(obj/item/attacking_item, mob/user, params) - if(!istype(attacking_item, /obj/item/ammo_casing)) - ..() - if(istype(attacking_item, underbarrel.magazine.ammo_type)) - underbarrel.attack_self(user) - underbarrel.attackby(attacking_item, user, params) +/obj/item/gun/ballistic/automatic/ar/modular/m44a/shotgun/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(isammocasing(tool)) + if(istype(tool, underbarrel.magazine.ammo_type)) + underbarrel.attackby(tool, user, list2params(modifiers)) + underbarrel.attack_self(user) + return ITEM_INTERACT_BLOCKING + return ..() /obj/item/gun/ballistic/automatic/ar/modular/m44a/grenadelauncher name = "\improper NT M44AGL Pulse Rifle" @@ -122,13 +124,15 @@ QDEL_NULL(underbarrel) return ..() -/obj/item/gun/ballistic/automatic/ar/modular/m44a/grenadelauncher/afterattack_secondary(atom/target, mob/living/user, flag, params) - underbarrel.afterattack(target, user, flag, params) - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/gun/ballistic/automatic/ar/modular/m44a/grenadelauncher/try_fire_gun(atom/target, mob/living/user, params) + if(LAZYACCESS(params2list(params), RIGHT_CLICK)) + return underbarrel.try_fire_gun(target, user, params) + return ..() -/obj/item/gun/ballistic/automatic/ar/modular/m44a/grenadelauncher/attackby(obj/item/attacking_item, mob/user, params) - if(!istype(attacking_item, /obj/item/ammo_casing)) - ..() - if(istype(attacking_item, underbarrel.magazine.ammo_type)) - underbarrel.attack_self(user) - underbarrel.attackby(attacking_item, user, params) +/obj/item/gun/ballistic/automatic/ar/modular/m44a/grenadelauncher/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(isammocasing(tool)) + if(istype(tool, underbarrel.magazine.ammo_type)) + underbarrel.attackby(tool, user, list2params(modifiers)) + underbarrel.attack_self(user) + return ITEM_INTERACT_BLOCKING + return ..() diff --git a/modular_nova/modules/medical/code/smartdarts.dm b/modular_nova/modules/medical/code/smartdarts.dm index 6c658334bf1..74d89853fc0 100644 --- a/modular_nova/modules/medical/code/smartdarts.dm +++ b/modular_nova/modules/medical/code/smartdarts.dm @@ -9,35 +9,35 @@ base_icon_state = "dart" //Code that handles the base interactions involving smartdarts -/obj/item/reagent_containers/syringe/smartdart/afterattack(atom/target, mob/user, proximity) - if(isliving(target)) +/obj/item/reagent_containers/syringe/smartdart/interact_with_atom(atom/target, mob/living/user, list/modifiers) + if(target.reagents) to_chat(user, span_warning("The [src] is unable to manually inject chemicals.")) - return + return NONE //A majority of this code is from the original syringes.dm file. -/obj/item/reagent_containers/syringe/smartdart/afterattack_secondary(atom/target, mob/user, proximity_flag, click_parameters) - if(!try_syringe(target, user, proximity_flag)) - return SECONDARY_ATTACK_CONTINUE_CHAIN +/obj/item/reagent_containers/syringe/smartdart/interact_with_atom_secondary(atom/target, mob/living/user, list/modifiers) + if(!try_syringe(target, user)) + return ITEM_INTERACT_BLOCKING if(reagents.total_volume >= reagents.maximum_volume) to_chat(user, span_notice("[src] is full.")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING if(isliving(target)) to_chat(user, span_warning("The [src] is unable to take blood.")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING if(!target.reagents.total_volume) to_chat(user, span_warning("[target] is empty!")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING if(!target.is_drawable(user)) to_chat(user, span_warning("You cannot directly remove reagents from [target]!")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_BLOCKING var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this, transferred_by = user) // transfer from, transfer to - who cares? to_chat(user, span_notice("You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")) - return SECONDARY_ATTACK_CONTINUE_CHAIN + return ITEM_INTERACT_SUCCESS //The base smartdartgun /obj/item/gun/syringe/smartdart @@ -56,12 +56,11 @@ /obj/item/gun/syringe/smartdart/give_gun_safeties() return -/obj/item/gun/syringe/smartdart/attackby(obj/item/container, mob/user, params, show_msg = TRUE) - if(istype(container, /obj/item/reagent_containers/syringe/smartdart)) - ..() - else - to_chat(user, span_notice("The [container] is unable to fit inside of the [src]! Try using a SmartDart instead.")) - return FALSE +/obj/item/gun/syringe/smartdart/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/reagent_containers/syringe/smartdart)) + return ..() + to_chat(user, span_notice("The [tool] is unable to fit inside of the [src]! Try using a SmartDart instead.")) + return ITEM_INTERACT_BLOCKING /obj/item/gun/syringe/smartdart/examine(mob/user) . = ..() diff --git a/modular_nova/modules/modular_implants/code/misc_devices.dm b/modular_nova/modules/modular_implants/code/misc_devices.dm index 12ffb77f337..02ec24fd7fe 100644 --- a/modular_nova/modules/modular_implants/code/misc_devices.dm +++ b/modular_nova/modules/modular_implants/code/misc_devices.dm @@ -144,18 +144,15 @@ return . -/obj/item/nif_hud_adapter/afterattack(obj/item/clothing/glasses/target_glasses, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !istype(target_glasses)) - return FALSE - - if(!is_type_in_list(target_glasses, glasses_whitelist)) - balloon_alert("incompatible!") - return FALSE +/obj/item/nif_hud_adapter/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/obj/item/clothing/glasses/target_glasses = interacting_with + if(!istype(target_glasses) || !is_type_in_list(target_glasses, glasses_whitelist)) + balloon_alert(user, "incompatible!") + return NONE if(HAS_TRAIT(target_glasses, TRAIT_NIFSOFT_HUD_GRANTER)) - balloon_alert("already upgraded!") - return FALSE + balloon_alert(user, "already upgraded!") + return ITEM_INTERACT_BLOCKING user.visible_message(span_notice("[user] upgrades [target_glasses] with [src]."), span_notice("You upgrade [target_glasses] to be NIF HUD compatible.")) target_glasses.name = "\improper HUD-upgraded " + target_glasses.name @@ -164,4 +161,5 @@ if(!multiple_uses) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/modular_nova/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm b/modular_nova/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm index 901f63f1dc9..9d3b7665e95 100644 --- a/modular_nova/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm +++ b/modular_nova/modules/modular_implants/code/soulcatcher/attachable_soulcatcher.dm @@ -82,21 +82,18 @@ /obj/item/attachable_soulcatcher/attack_self(mob/user, modifiers) linked_soulcatcher.ui_interact(user) -/obj/item/attachable_soulcatcher/afterattack(obj/item/target_item, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !istype(target_item)) - return FALSE +/obj/item/attachable_soulcatcher/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!isitem(interacting_with) || is_type_in_list(interacting_with, blacklisted_items)) + balloon_alert(user, "incompatible!") + return NONE - if(target_item.GetComponent(/datum/component/soulcatcher)) + if(interacting_with.GetComponent(/datum/component/soulcatcher)) balloon_alert(user, "already attached!") - return FALSE + return ITEM_INTERACT_BLOCKING - if(is_type_in_list(target_item, blacklisted_items)) - balloon_alert(user, "incompatible!") - return FALSE - var/datum/component/soulcatcher/new_soulcatcher = target_item.AddComponent(/datum/component/soulcatcher/attachable_soulcatcher) - playsound(target_item.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) + var/datum/component/soulcatcher/new_soulcatcher = interacting_with.AddComponent(/datum/component/soulcatcher/attachable_soulcatcher) + playsound(interacting_with.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) var/datum/soulcatcher_room/target_room = new_soulcatcher.soulcatcher_rooms[1] var/list/current_souls = linked_soulcatcher.get_current_souls() @@ -109,3 +106,4 @@ if(destroy_on_use) qdel(src) + return ITEM_INTERACT_SUCCESS diff --git a/modular_nova/modules/modular_items/code/summon_beacon.dm b/modular_nova/modules/modular_items/code/summon_beacon.dm index 6710c937d78..53356c477b2 100644 --- a/modular_nova/modules/modular_items/code/summon_beacon.dm +++ b/modular_nova/modules/modular_items/code/summon_beacon.dm @@ -75,29 +75,28 @@ return options -/obj/item/summon_beacon/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() +/obj/item/summon_beacon/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!selected_atom) balloon_alert(user, "no choice selected!") - return - var/turf/target_turf = get_turf(target) - var/area/target_area = get_area(target) + return NONE + var/turf/target_turf = get_turf(interacting_with) + var/area/target_area = get_area(interacting_with) if(!target_turf || !target_area || !is_type_in_list(target_area, allowed_areas)) balloon_alert(user, "can't call here!") - return + return NONE var/confirmed = tgui_alert(user, "Are you sure you want to call [initial(selected_atom.name)] here?", "Confirmation", list("Yes", "No")) if(confirmed != "Yes") - return + return ITEM_INTERACT_BLOCKING if(!uses) - return + return ITEM_INTERACT_BLOCKING uses -= 1 balloon_alert(user, "[uses] use[uses == 1 ? "" : "s"] left!") podspawn(list( - "target" = get_turf(target), + "target" = target_turf, "path" = supply_pod_stay ? /obj/structure/closet/supplypod/podspawn/no_return : /obj/structure/closet/supplypod/podspawn, "style" = STYLE_CENTCOM, "spawn" = selected_atom, @@ -113,6 +112,7 @@ if(!uses) qdel(src) + return ITEM_INTERACT_SUCCESS // Misc stuff here diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm index c831a428f92..a20ad265844 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_clothing/bdsm_mask.dm @@ -1,6 +1,7 @@ // Set up the types of items that can be placed in the mask /datum/storage/pockets/small/bdsm_mask max_slots = 1 + click_alt_open = FALSE /datum/storage/pockets/small/bdsm_mask/New() . = ..() @@ -15,6 +16,7 @@ icon_state = "mask_pink_off" base_icon_state = "mask" slot_flags = ITEM_SLOT_MASK + starting_filter_type = null var/mask_on = FALSE var/current_mask_color = "pink" var/breath_status = TRUE @@ -43,6 +45,19 @@ . = ..() create_storage(storage_type = /datum/storage/pockets/small/bdsm_mask) + new /obj/item/reagent_containers/cup/lewd_filter(src) + AddElement(/datum/element/update_icon_updates_onmob) + update_icon_state() + update_icon() + update_mob_action_buttonss() + if(!length(mask_designs)) + populate_mask_designs() + +/// Can the user reach the filter, false if equipped and active +/obj/item/clothing/mask/gas/bdsm_mask/proc/is_locked(mob/living/carbon/user) + var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) + return istype(user) && src == worn_mask && src.mask_on + /obj/item/clothing/mask/gas/bdsm_mask/proc/update_mob_action_buttonss() var/datum/action/item_action/button @@ -77,6 +92,7 @@ var/choice = show_radial_menu(user, src, mask_designs, custom_check = CALLBACK(src, PROC_REF(check_menu), user), radius = 36, require_near = TRUE) if(!choice) return CLICK_ACTION_BLOCKING + atom_storage.click_alt_open = TRUE current_mask_color = choice update_icon_state() update_icon() @@ -92,68 +108,63 @@ return FALSE return TRUE -// Initializing stuff -/obj/item/clothing/mask/gas/bdsm_mask/Initialize(mapload) - . = ..() - AddElement(/datum/element/update_icon_updates_onmob) - update_icon_state() - update_icon() - update_mob_action_buttonss() - if(!length(mask_designs)) - populate_mask_designs() - // To update icon state properly /obj/item/clothing/mask/gas/bdsm_mask/update_icon_state() . = ..() icon_state = "[base_icon_state]_[current_mask_color]_[mask_on? "on" : "off"]" inhand_icon_state = "[base_icon_state]_[current_mask_color]_[mask_on? "on" : "off"]" +/obj/item/clothing/mask/gas/bdsm_mask/proc/try_unequip(mob/user) + if(!do_after(user, 60 SECONDS, target = user)) + to_chat(user, span_warning("You fail to remove the gas mask!")) + return FALSE + to_chat(user, span_notice("You remove the gas mask.")) + return TRUE +/obj/item/clothing/mask/gas/bdsm_mask/attack_hand_secondary(mob/user, list/modifiers) + + // To make in unremovable without helping when mask is on /obj/item/clothing/mask/gas/bdsm_mask/attack_hand(mob/user) - if(iscarbon(user)) - if(mask_on == TRUE) - var/mob/living/carbon/wearer = user - if(wearer.wear_mask == src) - if(!do_after(wearer, 60 SECONDS, target = src)) - to_chat(wearer, span_warning("You fail to remove the gas mask!")) - return - else - to_chat(wearer, span_notice("You remove the gas mask.")) - add_fingerprint(usr) - . = ..() + if(!is_locked(user)) + return ..() + if(try_unequip(user)) + . = ..() + if(.) + to_chat(user, span_notice("You remove the gas mask.")) // To make in unremovable without helping when mask is on (for MouseDrop) -/obj/item/clothing/mask/gas/bdsm_mask/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params) - if(ismecha(user.loc)) // Stops inventory actions in a mech +/datum/storage/pockets/small/bdsm_mask/on_mousedrop_onto(datum/source, atom/over_object, mob/user) + var/obj/item/clothing/mask/gas/bdsm_mask/mask = source + if(!istype(mask) || ismecha(user.loc) || user.incapacitated() || !mask.is_locked(user)) + return ..() + return NONE //handled in mask mousedrop, don't allow content dumping + +/obj/item/clothing/mask/gas/bdsm_mask/mouse_drop_dragged(atom/over_object, mob/user, src_location, over_location, params) + if(ismecha(user.loc) || user.incapacitated() || !is_locked(user)) return - if(!user.incapacitated()) - if(loc == user) - if(istype(over, /atom/movable/screen/inventory/hand)) - var/atom/movable/screen/inventory/hand/hand = over - var/mob/living/carbon/human/target_carbon = user - if(istype(target_carbon)) - if(mask_on == TRUE) - if(src == target_carbon.wear_mask || . == target_carbon.wear_mask) - if(!do_after(target_carbon, 60 SECONDS, target = src)) - to_chat(target_carbon, span_warning("You fail to remove the gas mask!")) - return - else - to_chat(target_carbon, span_notice("You remove the gas mask.")) - if(user.putItemFromInventoryInHandIfPossible(src, hand.held_index)) - add_fingerprint(user) - . = ..() - -// Handler for clicking on a slot in a mask by hand with a filter -/datum/storage/pockets/small/bdsm_mask/on_attackby(datum/source, obj/item/used_item, mob/user, params) - . = ..() - var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) - if(istype(used_item, /obj/item/reagent_containers/cup/lewd_filter)) - if(worn_mask) // Null check - if(istype(worn_mask, /obj/item/clothing/mask/gas/bdsm_mask)) // Check that the mask is of the correct type - if(worn_mask.mask_on == TRUE) - // Place for text about the impossibility to attach a filter - to_chat(usr, span_warning("You can't attach a filter while the mask is locked!")) - return + if(!istype(over_object, /atom/movable/screen/inventory/hand)) + return + var/atom/movable/screen/inventory/hand/hand = over_object + if(!istype(hand)) + return + if(!try_unequip(user) || !user.putItemFromInventoryInHandIfPossible(src, hand.held_index)) + return + to_chat(user, span_notice("You remove the gas mask.")) + add_fingerprint(user) + +/datum/storage/pockets/small/bdsm_mask/remove_single(mob/removing, obj/item/thing, atom/remove_to_loc, silent) + var/obj/item/clothing/mask/gas/bdsm_mask/mask = parent + if(!istype(mask) || !mask.is_locked(removing)) + return ..() + to_chat(removing, span_warning("You can't detach the filter while the mask is locked!")) + return FALSE + +/datum/storage/pockets/small/bdsm_mask/attempt_insert(obj/item/to_insert, mob/user, override, force, messages) + var/obj/item/clothing/mask/gas/bdsm_mask/mask = parent + if(!istype(mask) || !mask.is_locked(user)) + return ..() + to_chat(user, span_warning("You can't attach a filter while the mask is locked!")) + return FALSE // Breathing valve control button /datum/action/item_action/toggle_breathcontrol @@ -164,7 +175,7 @@ /datum/action/item_action/toggle_breathcontrol/Trigger(trigger_flags) var/obj/item/clothing/mask/gas/bdsm_mask/mask = target if(istype(mask)) - mask.check() + mask.check(owner) /datum/action/item_action/toggle_gag name = "Toggle gag" @@ -173,7 +184,7 @@ /datum/action/item_action/toggle_gag/Trigger(trigger_flags) var/obj/item/clothing/mask/gas/bdsm_mask/mask = target if(istype(mask)) - mask.check_gag() + mask.check_gag(owner) /datum/action/item_action/mask_inhale name = "Inhale oxygen" @@ -191,13 +202,16 @@ mask.time_to_choke_left = mask.time_to_choke mask.breath_status = TRUE - var/mob/living/carbon/affected_mob = usr + var/mob/living/carbon/affected_mob = owner if(!istype(affected_mob)) return FALSE affected_mob.try_lewd_autoemote("inhale") + if(!length(mask.contents)) + return TRUE var/obj/item/reagent_containers/cup/lewd_filter/filter = mask.contents[1] - filter.reagent_consumption(affected_mob, filter.amount_per_transfer_from_this) + if(istype(filter)) + filter.reagent_consumption(affected_mob, filter.amount_per_transfer_from_this) return TRUE @@ -224,24 +238,22 @@ temp_check = TRUE // To check if player already have this mask on and trying to change mode -/obj/item/clothing/mask/gas/bdsm_mask/proc/check() - var/mob/living/carbon/affected_carbon = usr - if(src == affected_carbon.wear_mask) - to_chat(usr, span_notice("You can't reach the air filter switch!")) - else - toggle(affected_carbon) +/obj/item/clothing/mask/gas/bdsm_mask/proc/check(mob/living/carbon/user) + if(!istype(user) || src == user.wear_mask) + to_chat(user, span_notice("You can't reach the air filter switch!")) + return + toggle(user) // Switch the mask valve to the opposite state -/obj/item/clothing/mask/gas/bdsm_mask/proc/toggle(user) +/obj/item/clothing/mask/gas/bdsm_mask/proc/toggle(mob/living/carbon/user) mask_on = !mask_on to_chat(user, span_notice("You turn the air filter [mask_on ? "on. Use with caution!" : "off. Now it's safe to wear."]")) play_lewd_sound(user, mask_on ? 'sound/weapons/magin.ogg' : 'sound/weapons/magout.ogg', 40, TRUE) update_icon_state() update_mob_action_buttonss() update_icon() - var/mob/living/carbon/human/affected_human = usr if(mask_on) - if(src == affected_human.wear_mask && affected_human.client?.prefs?.read_preference(/datum/preference/toggle/erp/sex_toy)) + if(src == user.wear_mask && user.client?.prefs?.read_preference(/datum/preference/toggle/erp/sex_toy)) START_PROCESSING(SSobj, src) time_to_choke_left = time_to_choke else @@ -262,18 +274,17 @@ // Mask choke processor /obj/item/clothing/mask/gas/bdsm_mask/process(seconds_per_tick) - var/mob/living/affected_mob = loc - var/mob/living/carbon/affected_carbon = affected_mob + var/mob/living/carbon/affected_carbon = loc if(!istype(affected_carbon)) return FALSE if(time_to_choke_left < time_to_choke/2 && breath_status == TRUE) - if(temp_check == FALSE && affected_mob.stat == CONSCIOUS) // If user passed out while wearing this we should continue when he wakes up + if(temp_check == FALSE && affected_carbon.stat == CONSCIOUS) // If user passed out while wearing this we should continue when he wakes up breath_status = FALSE time_to_choke_left = time_to_choke temp_check = TRUE - if(affected_mob.stat == CONSCIOUS) + if(affected_carbon.stat == CONSCIOUS) affected_carbon.try_lewd_autoemote("exhale") breath_status = FALSE if(rand(0, 3) == 0) @@ -284,10 +295,9 @@ if(time_to_choke_left <= 0) if(tt <= 0) - if(affected_mob.stat == CONSCIOUS) - affected_mob.adjustOxyLoss(rand(4, 8)) // Oxy dmg - if(ispath(affected_carbon)) - affected_carbon.try_lewd_autoemote(pick("gasp", "choke", "moan")) + if(affected_carbon.stat == CONSCIOUS) + affected_carbon.adjustOxyLoss(rand(4, 8)) // Oxy dmg + affected_carbon.try_lewd_autoemote(pick("gasp", "choke", "moan")) tt = time else breath_status = TRUE @@ -317,6 +327,7 @@ volume = 50 possible_transfer_amounts = list(1, 2, 3, 4, 5, 10, 25, 50) list_reagents = list(/datum/reagent/drug/aphrodisiac/crocin = 50) + amount_per_transfer_from_this = 1 interaction_flags_click = NEED_DEXTERITY // Standard initialize code for filter @@ -331,58 +342,13 @@ // Reagent consumption process handler /obj/item/reagent_containers/cup/lewd_filter/proc/reagent_consumption(mob/living/user, amount_per_transfer_from_this) SEND_SIGNAL(src, COMSIG_GLASS_DRANK, user, user) - addtimer(CALLBACK(reagents, TYPE_PROC_REF(/datum/reagents, trans_to), user, amount_per_transfer_from_this, TRUE, TRUE, FALSE, user, FALSE, INGEST), 5) + reagents.trans_to(user, amount_per_transfer_from_this, transferred_by = user, methods = INGEST) -// I just wanted to add 2th color variation. Because. +// I just wanted to add 2nd color variation. Because. /obj/item/reagent_containers/cup/lewd_filter/click_alt(mob/user) // After reskin all clicks go normal, but we can't change the flow rate if mask on and equipped - var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) - if(worn_mask) - if(iscarbon(user)) - if(istype(worn_mask, /obj/item/clothing/mask/gas/bdsm_mask)) - if(worn_mask.mask_on == TRUE) - if(istype(src, /obj/item/reagent_containers/cup/lewd_filter)) - to_chat(user, span_warning("You can't change the flow rate of the valve while the mask is on!")) - return CLICK_ACTION_BLOCKING - return ..() - -// Filter click handling -/obj/item/reagent_containers/cup/lewd_filter/attack_hand(mob/user) - var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) - if(worn_mask) - if(iscarbon(user)) - if(istype(worn_mask, /obj/item/clothing/mask/gas/bdsm_mask)) - if(worn_mask.mask_on == TRUE) - if(istype(src, /obj/item/reagent_containers/cup/lewd_filter)) - // Place for text about the impossibility of detaching the filter - to_chat(user, span_warning("You can't detach the filter while the mask is locked!")) - return - - . = ..() - add_fingerprint(usr) - -// Processing a click with a mask filter on the mask. Needed to intercept call at the object class level. Returns automatically to attack_hand(mob/user) method. -/obj/item/clothing/mask/gas/bdsm_mask/attackby(obj/item/used_item, mob/living/user, params) - return ..() || ((obj_flags & CAN_BE_HIT) && used_item.attack_atom(src, user)) - -// Mouse drop handler -/obj/item/reagent_containers/cup/lewd_filter/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params) - var/obj/item/clothing/mask/gas/bdsm_mask/worn_mask = user.get_item_by_slot(ITEM_SLOT_MASK) - - if(ismecha(user.loc)) // Stops inventory actions in a mech - return - - if(!user.incapacitated()) - if(loc == user) - if(iscarbon(user)) - if(worn_mask.mask_on == TRUE) - if(istype(over, /atom/movable/screen/inventory/hand)) - // Place for text about the impossibility of detaching the filter - to_chat(user, span_warning("You can't detach the filter while the mask is locked!")) - return - else - // Place for text about the impossibility to attach a filter - to_chat(user, span_warning("You can't attach a filter while the mask is locked!")) - return - add_fingerprint(user) + var/obj/item/clothing/mask/gas/bdsm_mask/mask = loc + if(!istype(mask) || !mask.is_locked(user)) return ..() + to_chat(user, span_warning("You can't change the flow rate of the valve while the mask is on!")) + return CLICK_ACTION_BLOCKING diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/_masturbation_item.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/_masturbation_item.dm index 2f1c9db384e..4ad9dd3c2c8 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/_masturbation_item.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/_masturbation_item.dm @@ -8,14 +8,13 @@ inhand_icon_state = "nothing" // Jerk off into bottles and onto people. -/obj/item/hand_item/coom/afterattack(obj/target, mob/user, proximity) - . = ..() - do_masturbate(target, user, proximity) +/obj/item/hand_item/coom/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + do_masturbate(interacting_with, user) /// Handles masturbation onto a living mob, or an atom. /// Attempts to fill the atom's reagent container, if it has one, and it isn't full. -/obj/item/hand_item/coom/proc/do_masturbate(obj/target, mob/user, proximity) - if (CONFIG_GET(flag/disable_erp_preferences) || !proximity || user.stat >= DEAD) +/obj/item/hand_item/coom/proc/do_masturbate(atom/target, mob/user) + if (CONFIG_GET(flag/disable_erp_preferences) || user.stat >= DEAD) return var/mob/living/carbon/human/affected_human = user diff --git a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/serviette.dm b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/serviette.dm index 4964335cea6..2980e98f90b 100644 --- a/modular_nova/modules/modular_items/lewd_items/code/lewd_items/serviette.dm +++ b/modular_nova/modules/modular_items/lewd_items/code/lewd_items/serviette.dm @@ -17,35 +17,34 @@ icon = 'modular_nova/modules/modular_items/lewd_items/icons/obj/lewd_items/lewd_items.dmi' w_class = WEIGHT_CLASS_TINY -/obj/item/serviette/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !check_allowed_items(target)) - return +/obj/item/serviette/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!check_allowed_items(interacting_with)) + return NONE var/clean_speedies = 1 * cleanspeed if(user.mind) clean_speedies = cleanspeed * min(user.mind.get_skill_modifier(/datum/skill/cleaning, SKILL_SPEED_MODIFIER)+0.1, 1) //less scaling for soapies - if((target in user?.client.screen) && !user.is_holding(target)) - to_chat(user, span_warning("You need to take \the [target.name] off before cleaning it!")) + if((interacting_with in user?.client.screen) && !user.is_holding(interacting_with)) + to_chat(user, span_warning("You need to take \the [interacting_with.name] off before cleaning it!")) - else if(istype(target, /obj/effect/decal/cleanable)) - user.visible_message(span_notice("[user] begins to clean \the [target.name] out with [src]."), span_warning("You begin to clean \the [target.name] out with [src]...")) - if(do_after(user, clean_speedies, target = target)) - to_chat(user, span_notice("You clean \the [target.name] out.")) - var/obj/effect/decal/cleanable/cleanies = target + else if(istype(interacting_with, /obj/effect/decal/cleanable)) + user.visible_message(span_notice("[user] begins to clean \the [interacting_with.name] out with [src]."), span_warning("You begin to clean \the [interacting_with.name] out with [src]...")) + if(do_after(user, clean_speedies, target = interacting_with)) + to_chat(user, span_notice("You clean \the [interacting_with.name] out.")) + var/obj/effect/decal/cleanable/cleanies = interacting_with user.mind?.adjust_experience(/datum/skill/cleaning, max(round(cleanies.beauty/CLEAN_SKILL_BEAUTY_ADJUSTMENT), 0)) //again, intentional that this does NOT round but mops do. - qdel(target) + qdel(interacting_with) qdel(src) var/obj/item/serviette_used/used_cloth = new used_serviette remove_item_from_storage(user) user.put_in_hands(used_cloth) - else if(istype(target, /obj/structure/window)) - user.visible_message(span_notice("[user] begins to clean \the [target.name] with [src]..."), span_notice("You begin to clean \the [target.name] with [src]...")) - if(do_after(user, clean_speedies, target = target)) - to_chat(user, span_notice("You clean \the [target.name].")) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) - target.set_opacity(initial(target.opacity)) + else if(istype(interacting_with, /obj/structure/window)) + user.visible_message(span_notice("[user] begins to clean \the [interacting_with.name] with [src]..."), span_notice("You begin to clean \the [interacting_with.name] with [src]...")) + if(do_after(user, clean_speedies, target = interacting_with)) + to_chat(user, span_notice("You clean \the [interacting_with.name].")) + interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + interacting_with.set_opacity(initial(interacting_with.opacity)) user.mind?.adjust_experience(/datum/skill/cleaning, CLEAN_SKILL_GENERIC_WASH_XP) qdel(src) var/obj/item/serviette_used/used_cloth = new used_serviette @@ -53,19 +52,20 @@ user.put_in_hands(used_cloth) else - user.visible_message(span_notice("[user] begins to clean \the [target.name] with [src]..."), span_notice("You begin to clean \the [target.name] with [src]...")) - if(do_after(user, clean_speedies, target = target)) - to_chat(user, span_notice("You clean \the [target.name].")) - if(user && isturf(target)) - for(var/obj/effect/decal/cleanable/cleanable_decal in target) + user.visible_message(span_notice("[user] begins to clean \the [interacting_with.name] with [src]..."), span_notice("You begin to clean \the [interacting_with.name] with [src]...")) + if(do_after(user, clean_speedies, target = interacting_with)) + to_chat(user, span_notice("You clean \the [interacting_with.name].")) + if(user && isturf(interacting_with)) + for(var/obj/effect/decal/cleanable/cleanable_decal in interacting_with) user.mind?.adjust_experience(/datum/skill/cleaning, round(cleanable_decal.beauty / CLEAN_SKILL_BEAUTY_ADJUSTMENT)) - target.wash(CLEAN_SCRUB) - target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + interacting_with.wash(CLEAN_SCRUB) + interacting_with.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) user.mind?.adjust_experience(/datum/skill/cleaning, CLEAN_SKILL_GENERIC_WASH_XP) qdel(src) var/obj/item/serviette_used/used_cloth = new used_serviette remove_item_from_storage(user) user.put_in_hands(used_cloth) + return ITEM_INTERACT_SUCCESS /* * SERVIETTE PACK diff --git a/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/grenade_launcher.dm b/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/grenade_launcher.dm index 1721ca6227f..b4137139449 100644 --- a/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/grenade_launcher.dm +++ b/modular_nova/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/grenade_launcher.dm @@ -69,17 +69,18 @@ . += span_notice("With Right Click you can set the range that shells will detonate at.") . += span_notice("A small indicator in the sight notes the current detonation range is: [target_range].") -/obj/item/gun/ballistic/automatic/sol_grenade_launcher/afterattack_secondary(atom/target, mob/living/user, proximity_flag, click_parameters) - if(!target || !user) - return +/obj/item/gun/ballistic/automatic/sol_grenade_launcher/ranged_interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!interacting_with || !user) + return ITEM_INTERACT_BLOCKING - var/distance_ranged = get_dist(user, target) + var/distance_ranged = get_dist(user, interacting_with) if(distance_ranged > maximum_target_range) user.balloon_alert(user, "out of range") - return + return ITEM_INTERACT_BLOCKING target_range = distance_ranged user.balloon_alert(user, "range set: [target_range]") + return ITEM_INTERACT_SUCCESS /obj/item/gun/ballistic/automatic/sol_grenade_launcher/no_mag spawnwithmagazine = FALSE diff --git a/modular_nova/modules/morenarcotics/code/vapecarts.dm b/modular_nova/modules/morenarcotics/code/vapecarts.dm index b22ff596324..fcf2249161f 100644 --- a/modular_nova/modules/morenarcotics/code/vapecarts.dm +++ b/modular_nova/modules/morenarcotics/code/vapecarts.dm @@ -10,20 +10,19 @@ fill_icon_thresholds = list(0, 5, 20, 40) custom_price = PAYCHECK_CREW -/obj/item/reagent_containers/vapecart/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - if(istype(target, /obj/item/clothing/mask/vape)) - var/obj/item/clothing/mask/vape/target_vape = target - if(target_vape.screw == TRUE && !target_vape.reagents.total_volume) - src.reagents.trans_to(target_vape, src.volume, transferred_by = user) - qdel(src) - to_chat(user, span_notice("You plug the [src.name] into the vape.")) - else if(!target_vape.screw) - to_chat(user, span_warning("You need to open the cap to do that!")) - else - to_chat(user, span_warning("[target_vape] is already full!")) +/obj/item/reagent_containers/vapecart/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/obj/item/clothing/mask/vape/target_vape = interacting_with + if(!istype(target_vape)) + return NONE + if(target_vape.screw == TRUE && !target_vape.reagents.total_volume) + src.reagents.trans_to(target_vape, src.volume, transferred_by = user) + to_chat(user, span_notice("You plug the [src.name] into the vape.")) + qdel(src) + else if(!target_vape.screw) + to_chat(user, span_warning("You need to open the cap to do that!")) + else + to_chat(user, span_warning("[target_vape] is already full!")) + return ITEM_INTERACT_SUCCESS /obj/item/reagent_containers/vapecart/empty name = "customizable vape cart" diff --git a/modular_nova/modules/moretraitoritems/code/glue.dm b/modular_nova/modules/moretraitoritems/code/glue.dm index 3378ee6f6e5..80123ba1515 100644 --- a/modular_nova/modules/moretraitoritems/code/glue.dm +++ b/modular_nova/modules/moretraitoritems/code/glue.dm @@ -7,24 +7,21 @@ var/uses = 1 -/obj/item/syndie_glue/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !target) - return - else - if(!uses) - to_chat(user, span_warning("The bottle of glue is empty!")) - return - if(istype(target, /obj/item)) - var/obj/item/I = target - if(HAS_TRAIT_FROM(I, TRAIT_NODROP, TRAIT_GLUED_ITEM)) - to_chat(user, span_warning("[I] is already sticky!")) - return - uses -= 1 - ADD_TRAIT(I, TRAIT_NODROP, TRAIT_GLUED_ITEM) - I.desc += " It looks sticky." - to_chat(user, span_notice("You smear the [I] with glue, making it incredibly sticky!")) - if(uses == 0) - icon_state = "glue_used" - name = "empty bottle of super glue" - return +/obj/item/syndie_glue/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!uses) + to_chat(user, span_warning("The bottle of glue is empty!")) + return NONE + if(!isitem(interacting_with)) + return NONE + if(HAS_TRAIT_FROM(interacting_with, TRAIT_NODROP, TRAIT_GLUED_ITEM)) + to_chat(user, span_warning("[interacting_with] is already sticky!")) + return ITEM_INTERACT_BLOCKING + + uses -= 1 + ADD_TRAIT(interacting_with, TRAIT_NODROP, TRAIT_GLUED_ITEM) + interacting_with.desc += " It looks sticky." + to_chat(user, span_notice("You smear the [interacting_with] with glue, making it incredibly sticky!")) + if(uses == 0) + icon_state = "glue_used" + name = "empty bottle of super glue" + return ITEM_INTERACT_SUCCESS diff --git a/modular_nova/modules/mounted_machine_gun/code/mounted_machine_gun.dm b/modular_nova/modules/mounted_machine_gun/code/mounted_machine_gun.dm index 54d91e0d72f..8824e314e05 100644 --- a/modular_nova/modules/mounted_machine_gun/code/mounted_machine_gun.dm +++ b/modular_nova/modules/mounted_machine_gun/code/mounted_machine_gun.dm @@ -191,12 +191,12 @@ if(!istype(weapon, ammo_box_type)) return if(ammo_box) - balloon_alert("already loaded!") + balloon_alert(user, "already loaded!") return ammo_box = weapon weapon.forceMove(src) playsound(src, 'modular_nova/modules/mounted_machine_gun/sound/insert_ammobox.ogg', 100) - balloon_alert("ammo box inserted!") + balloon_alert(user, "ammo box inserted!") /obj/machinery/mounted_machine_gun/proc/remove_ammo_box(mob/living/user) ammo_box.forceMove(drop_location()) diff --git a/modular_nova/modules/mutants/code/mutant_cure.dm b/modular_nova/modules/mutants/code/mutant_cure.dm index 296ffa7826d..f18b644216e 100644 --- a/modular_nova/modules/mutants/code/mutant_cure.dm +++ b/modular_nova/modules/mutants/code/mutant_cure.dm @@ -29,32 +29,30 @@ return unload_vial(user) -/obj/item/rna_extractor/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) +/obj/item/rna_extractor/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ishuman(interacting_with)) return - if(!ishuman(target)) - return - var/mob/living/carbon/human/H = target + var/mob/living/carbon/human/target = interacting_with if(!loaded_vial) to_chat(user, span_danger("[src] is empty!")) return if(loaded_vial.contains_rna) to_chat(user, span_danger("[src] already has RNA data in it, upload it to the combinator!")) return - if(!ismutant(H)) - to_chat(user, span_danger("[H] does not register as infected!")) + if(!ismutant(target)) + to_chat(user, span_danger("[target] does not register as infected!")) return - var/datum/component/mutant_infection/ZI = H.GetComponent(/datum/component/mutant_infection) - if(!ZI) - to_chat(user, span_danger("[H] does not register as infected!")) + var/datum/component/mutant_infection/target_infection = target.GetComponent(/datum/component/mutant_infection) + if(!target_infection) + to_chat(user, span_danger("[target] does not register as infected!")) return - if(ZI.extract_rna()) - loaded_vial.load_rna(H) - to_chat(user, span_notice("[src] successfully scanned [H], and now holds a sample virus RNA data.")) + if(target_infection.extract_rna()) + loaded_vial.load_rna(target) + to_chat(user, span_notice("[src] successfully scanned [target], and now holds a sample virus RNA data.")) playsound(src.loc, 'sound/effects/spray2.ogg', 50, TRUE, -6) update_appearance() else - to_chat(user, span_warning("[H] has no useable RNA!")) + to_chat(user, span_warning("[target] has no useable RNA!")) /obj/item/rna_extractor/proc/unload_vial(mob/living/user) if(loaded_vial) diff --git a/modular_nova/modules/mutants/code/mutant_species.dm b/modular_nova/modules/mutants/code/mutant_species.dm index 9ffa7861b14..d5380c8f8fe 100644 --- a/modular_nova/modules/mutants/code/mutant_species.dm +++ b/modular_nova/modules/mutants/code/mutant_species.dm @@ -212,11 +212,8 @@ else icon_state = icon_right -/obj/item/hnz_mutant_hand/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - else if(isliving(target)) +/obj/item/hnz_mutant_hand/afterattack(atom/target, mob/user, click_parameters) + if(isliving(target)) if(ishuman(target)) try_to_mutant_infect(target, user = user) else diff --git a/modular_nova/modules/novaya_ert/code/mod_suit.dm b/modular_nova/modules/novaya_ert/code/mod_suit.dm index fb7755d227b..883a78639ec 100644 --- a/modular_nova/modules/novaya_ert/code/mod_suit.dm +++ b/modular_nova/modules/novaya_ert/code/mod_suit.dm @@ -317,7 +317,7 @@ UnregisterSignal(mod.wearer, COMSIG_LIVING_HEALTH_UPDATE) /obj/item/mod/module/auto_doc/on_install() - RegisterSignal(mod, COMSIG_ATOM_ATTACKBY, PROC_REF(on_attackby)) + RegisterSignal(mod, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(on_item_interact)) /obj/item/mod/module/auto_doc/on_uninstall(deleting) UnregisterSignal(mod, COMSIG_ATOM_ATTACKBY) @@ -327,10 +327,10 @@ return TRUE return ..() -/obj/item/mod/module/auto_doc/proc/on_attackby(datum/source, obj/item/attacking_item, mob/user) +/obj/item/mod/module/auto_doc/proc/on_item_interact(datum/source, mob/user, obj/item/thing, params) SIGNAL_HANDLER - if(charge_boost(attacking_item, user)) + if(charge_boost(thing, user)) return COMPONENT_NO_AFTERATTACK return NONE diff --git a/modular_nova/modules/polarized_windows/polarization_controller.dm b/modular_nova/modules/polarized_windows/polarization_controller.dm index 68263adaf42..a9763ba73dc 100644 --- a/modular_nova/modules/polarized_windows/polarization_controller.dm +++ b/modular_nova/modules/polarized_windows/polarization_controller.dm @@ -33,7 +33,7 @@ GLOBAL_LIST_EMPTY(polarization_controllers) // But why make it a string here? Otherwise it won't be an associative list and it kind of explodes. Shitty, I know. LAZYADDASSOC(GLOB.polarization_controllers, id, list(src)) - RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(on_window_attackby)) + RegisterSignal(parent, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(window_item_interact)) RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_window_examine)) RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(on_window_multitool_act)) @@ -81,18 +81,18 @@ GLOBAL_LIST_EMPTY(polarization_controllers) * * See: [/obj/item/proc/melee_attack_chain] */ -/datum/component/polarization_controller/proc/on_window_attackby(datum/source, obj/item/attacking_item, mob/user, params) +/datum/component/polarization_controller/proc/window_item_interact(datum/source, obj/item/attacking_item, mob/user, params) SIGNAL_HANDLER if(!istype(attacking_item, /obj/item/assembly/control/polarizer)) - return + return NONE var/obj/item/assembly/control/polarizer/polarizer = attacking_item var/atom/parent_atom = parent if(!polarizer.id) parent_atom.balloon_alert(user, "set id on controller first!") - return COMPONENT_NO_AFTERATTACK + return ITEM_INTERACT_BLOCKING if(id) LAZYREMOVEASSOC(GLOB.polarization_controllers, id, list(src)) @@ -102,7 +102,7 @@ GLOBAL_LIST_EMPTY(polarization_controllers) LAZYADDASSOC(GLOB.polarization_controllers, id, list(src)) parent_atom.balloon_alert(user, "linked polarizer!") - return COMPONENT_NO_AFTERATTACK + return ITEM_INTERACT_SUCCESS /** diff --git a/modular_nova/modules/pollution/code/air_refresher.dm b/modular_nova/modules/pollution/code/air_refresher.dm index ccd5a731320..72881a01f19 100644 --- a/modular_nova/modules/pollution/code/air_refresher.dm +++ b/modular_nova/modules/pollution/code/air_refresher.dm @@ -18,20 +18,17 @@ else . += "It is empty." -/obj/item/air_refresher/afterattack(atom/attacked, mob/user, proximity) - . = ..() - if(.) - return +/obj/item/air_refresher/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(uses_remaining <= 0) to_chat(user, span_warning("\The [src] is empty!")) - return TRUE + return NONE uses_remaining-- - var/turf/aimed_turf = get_turf(attacked) + var/turf/aimed_turf = get_turf(interacting_with) aimed_turf.pollute_turf(/datum/pollutant/fragrance/air_refresher, 200) user.visible_message(span_notice("[user] sprays the air around with \the [src]."), span_notice("You spray the air around with \the [src].")) user.changeNext_move(CLICK_CD_RANGE*2) playsound(aimed_turf, 'sound/effects/spray2.ogg', 50, TRUE, -6) - return TRUE + return ITEM_INTERACT_SUCCESS /obj/machinery/pollution_scrubber name = "Pollution Scrubber" diff --git a/modular_nova/modules/pollution/code/perfumes.dm b/modular_nova/modules/pollution/code/perfumes.dm index 72e5feefa84..1f8aa0b690c 100644 --- a/modular_nova/modules/pollution/code/perfumes.dm +++ b/modular_nova/modules/pollution/code/perfumes.dm @@ -48,11 +48,10 @@ to_chat(user, span_notice("The cap on [src] is now [cap ? "on" : "off"].")) update_appearance() -/obj/item/perfume/afterattack(atom/attacked, mob/user, proximity) - . = ..() +/obj/item/perfume/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(.) return - if(!ismovable(attacked)) + if(!ismovable(interacting_with)) return if(has_cap && cap) to_chat(user, span_warning("Take the cap off first!")) @@ -63,10 +62,10 @@ uses_remaining-- var/turf/my_turf = get_turf(user) my_turf.pollute_turf(fragrance_type, 20) - user.visible_message(span_notice("[user] sprays [attacked] with \the [src]."), span_notice("You spray [attacked] with \the [src].")) + user.visible_message(span_notice("[user] sprays [interacting_with] with \the [src]."), span_notice("You spray [interacting_with] with \the [src].")) user.changeNext_move(CLICK_CD_RANGE*2) playsound(my_turf, 'sound/effects/spray2.ogg', 50, TRUE, -6) - attacked.AddComponent(/datum/component/temporary_pollution_emission, fragrance_type, 5, 10 MINUTES) + interacting_with.AddComponent(/datum/component/temporary_pollution_emission, fragrance_type, 5, 10 MINUTES) /obj/item/perfume/cologne name = "cologne bottle" diff --git a/modular_nova/modules/primitive_catgirls/code/smelling_salts.dm b/modular_nova/modules/primitive_catgirls/code/smelling_salts.dm index 632fe557250..d05d092ff01 100644 --- a/modular_nova/modules/primitive_catgirls/code/smelling_salts.dm +++ b/modular_nova/modules/primitive_catgirls/code/smelling_salts.dm @@ -31,7 +31,7 @@ user.balloon_alert_to_viewers("trying to revive [carbon_target]") if(!do_after(user, 3 SECONDS, carbon_target)) - user.balloon_alert("stopped reviving [carbon_target]") + user.balloon_alert(user, "stopped reviving [carbon_target]") return if(carbon_target.stat != DEAD) diff --git a/modular_nova/modules/primitive_catgirls/code/spawner.dm b/modular_nova/modules/primitive_catgirls/code/spawner.dm index a36f0fe0754..b7657298c12 100644 --- a/modular_nova/modules/primitive_catgirls/code/spawner.dm +++ b/modular_nova/modules/primitive_catgirls/code/spawner.dm @@ -152,7 +152,7 @@ visible_message(span_infoplain("[user] starts putting [target] into [src]...")) if(!do_after(user, 3 SECONDS, target)) - balloon_alert("cancelled transfer!") + balloon_alert(user, "cancelled transfer!") return to_chat(user, span_danger("You put [target] into [src].")) @@ -166,7 +166,7 @@ visible_message(span_infoplain("[user] starts climbing down into [src]...")) if(!do_after(user, 3 SECONDS, target)) - balloon_alert("cancelled transfer!") + balloon_alert(user, "cancelled transfer!") return if(LAZYLEN(target.buckled_mobs) > 0) diff --git a/modular_nova/modules/primitive_production/code/glassblowing.dm b/modular_nova/modules/primitive_production/code/glassblowing.dm index 9ff03071214..a8e0ff1cd14 100644 --- a/modular_nova/modules/primitive_production/code/glassblowing.dm +++ b/modular_nova/modules/primitive_production/code/glassblowing.dm @@ -143,22 +143,20 @@ if(glass.steps_remaining[STEP_JACKS]) . += "The glass requires [glass.steps_remaining[STEP_JACKS]] more jacking actions!" -/obj/item/glassblowing/blowing_rod/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) - return ..() - if(istype(target, /obj/item/glassblowing/molten_glass)) - var/obj/item/glassblowing/molten_glass/attacking_glass = target - var/obj/item/glassblowing/molten_glass/glass = glass_ref?.resolve() - if(glass) - to_chat(user, span_warning("[src] already has some glass on it!")) - return - if(!user.transferItemToLoc(attacking_glass, src)) - return - glass_ref = WEAKREF(attacking_glass) - to_chat(user, span_notice("[src] picks up [target].")) - icon_state = "blow_pipe_full" - return - return ..() +/obj/item/glassblowing/blowing_rod/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/obj/item/glassblowing/molten_glass/attacking_glass = interacting_with + if(!istype(attacking_glass)) + return NONE + + if(glass_ref?.resolve()) + to_chat(user, span_warning("[src] already has some glass on it!")) + return ITEM_INTERACT_BLOCKING + if(!user.transferItemToLoc(attacking_glass, src)) + return ITEM_INTERACT_BLOCKING + glass_ref = WEAKREF(attacking_glass) + to_chat(user, span_notice("[src] picks up [attacking_glass].")) + icon_state = "blow_pipe_full" + return ITEM_INTERACT_SUCCESS /obj/item/glassblowing/blowing_rod/attackby(obj/item/attacking_item, mob/living/user, params) var/actioning_speed = user.mind.get_skill_modifier(/datum/skill/production, SKILL_SPEED_MODIFIER) * DEFAULT_TIMED diff --git a/modular_nova/modules/reagent_forging/code/forge_items.dm b/modular_nova/modules/reagent_forging/code/forge_items.dm index e70cc5c1ef5..f298c50b6ee 100644 --- a/modular_nova/modules/reagent_forging/code/forge_items.dm +++ b/modular_nova/modules/reagent_forging/code/forge_items.dm @@ -61,7 +61,7 @@ GLOBAL_LIST_INIT(allowed_forging_materials, list( /obj/structure/reagent_crafting_bench ) -/obj/item/forging/hammer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) +/obj/item/forging/hammer/afterattack(atom/target, mob/user, click_parameters) . = ..() if(!is_type_in_list(target, fast_attacks)) return diff --git a/modular_nova/modules/resleeving/code/rsd_interface.dm b/modular_nova/modules/resleeving/code/rsd_interface.dm index 38e31ec88f3..0d5d74d0b6d 100644 --- a/modular_nova/modules/resleeving/code/rsd_interface.dm +++ b/modular_nova/modules/resleeving/code/rsd_interface.dm @@ -8,20 +8,20 @@ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' /// Attempts to use the item on the target brain. -/obj/item/rsd_interface/afterattack(obj/item/organ/internal/brain/target_brain, mob/user, proximity_flag, click_parameters) - . = ..() - if(!proximity_flag || !istype(target_brain)) - return FALSE +/obj/item/rsd_interface/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/item/organ/internal/brain)) + return NONE - if(HAS_TRAIT(target_brain, TRAIT_NIFSOFT_HUD_GRANTER)) - balloon_alert("already upgraded!") - return FALSE + if(HAS_TRAIT(interacting_with, TRAIT_RSD_COMPATIBLE)) + user.balloon_alert(user, "already upgraded!") + return ITEM_INTERACT_BLOCKING - user.visible_message(span_notice("[user] upgrades [target_brain] with [src]."), span_notice("You upgrade [target_brain] to be RSD compatible.")) - target_brain.AddElement(/datum/element/rsd_interface) - playsound(target_brain.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) + user.visible_message(span_notice("[user] upgrades [interacting_with] with [src]."), span_notice("You upgrade [interacting_with] to be RSD compatible.")) + interacting_with.AddElement(/datum/element/rsd_interface) + playsound(interacting_with.loc, 'sound/weapons/circsawhit.ogg', 50, vary = TRUE) qdel(src) + return ITEM_INTERACT_SUCCESS /datum/element/rsd_interface/Attach(datum/target) . = ..() diff --git a/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_hammer.dm b/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_hammer.dm index 790877478dc..3d01afb16d0 100644 --- a/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_hammer.dm +++ b/modular_nova/modules/sec_haul/code/peacekeeper/peacekeeper_hammer.dm @@ -30,20 +30,19 @@ . = ..() AddElement(/datum/element/kneecapping) -/obj/item/melee/breaching_hammer/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity) - return - if(istype(target, /obj/machinery/door)) - user.changeNext_move(5 SECONDS) - if(!registered) - RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(remove_track), FALSE) - RegisterSignal(target, COMSIG_BREACHING, PROC_REF(try_breaching), TRUE) - to_chat(user, text = "You prepare to forcefully strike the door") - registered = TRUE - breacher = user - SEND_SIGNAL(target, COMSIG_BREACHING, user) - breaching_target = target +/obj/item/melee/breaching_hammer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!istype(interacting_with, /obj/machinery/door)) + return NONE + user.changeNext_move(5 SECONDS) + if(!registered) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(remove_track), FALSE) + RegisterSignal(interacting_with, COMSIG_BREACHING, PROC_REF(try_breaching), TRUE) + to_chat(user, text = "You prepare to forcefully strike the door") + registered = TRUE + breacher = user + SEND_SIGNAL(interacting_with, COMSIG_BREACHING, user) + breaching_target = interacting_with + return ITEM_INTERACT_SUCCESS /// Removes any form of tracking from the user and the item , make sure to call it on he proper item /obj/item/melee/breaching_hammer/proc/remove_track(mob/living/carbon/human/user) diff --git a/modular_nova/modules/synths/code/bodyparts/power_cord.dm b/modular_nova/modules/synths/code/bodyparts/power_cord.dm index 287c3c9a54f..f2d2db1bb81 100644 --- a/modular_nova/modules/synths/code/bodyparts/power_cord.dm +++ b/modular_nova/modules/synths/code/bodyparts/power_cord.dm @@ -24,16 +24,18 @@ )) // Attempt to charge from an object by using them on the power cord. -/obj/item/synth_powercord/attackby(obj/item/attacking_item, mob/user, params) - if(!can_power_draw(attacking_item, user)) - return ..() - try_power_draw(attacking_item, user) +/obj/item/synth_powercord/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(!can_power_draw(tool, user)) + return NONE + try_power_draw(tool, user) + return ITEM_INTERACT_SUCCESS // Attempt to charge from an object by using the power cord on them. -/obj/item/synth_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag || !can_power_draw(target, user)) - return ..() - try_power_draw(target, user) +/obj/item/synth_powercord/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!can_power_draw(interacting_with, user)) + return NONE + try_power_draw(interacting_with, user) + return ITEM_INTERACT_SUCCESS /// Returns TRUE or FALSE depending on if the target object can be used as a power source. /obj/item/synth_powercord/proc/can_power_draw(obj/target, mob/user) diff --git a/modular_nova/modules/wargame_projectors/code/projectors.dm b/modular_nova/modules/wargame_projectors/code/projectors.dm index 0b25130e4c4..d5bfe08bc0a 100644 --- a/modular_nova/modules/wargame_projectors/code/projectors.dm +++ b/modular_nova/modules/wargame_projectors/code/projectors.dm @@ -51,8 +51,8 @@ set_greyscale(holosign_color) populate_radial_choice_lists() -/obj/item/wargame_projector/handle_openspace_click(turf/target, mob/user, proximity_flag, click_parameters) - afterattack(target, user, proximity_flag, click_parameters) +/obj/item/wargame_projector/handle_openspace_click(turf/target, mob/user, click_parameters) + ranged_interact_with_atom(target, user, params2list(click_parameters)) /obj/item/wargame_projector/examine(mob/user) . = ..() @@ -104,9 +104,7 @@ return CLICK_ACTION_SUCCESS /// Can we place a hologram at the target location? -/obj/item/wargame_projector/proc/check_can_place_hologram(atom/target, mob/user, proximity_flag, team) - if(!proximity_flag) - return FALSE +/obj/item/wargame_projector/proc/check_can_place_hologram(atom/target, mob/user, team) if(!check_allowed_items(target, not_inside = TRUE)) return FALSE var/turf/target_turf = get_turf(target) @@ -118,10 +116,9 @@ return TRUE /// Spawn a hologram with pixel offset based on where the user clicked -/obj/item/wargame_projector/proc/create_hologram(atom/target, mob/user, click_parameters) +/obj/item/wargame_projector/proc/create_hologram(atom/target, mob/user, list/modifiers) var/obj/target_holosign = new holosign_type(get_turf(target), src) - var/list/modifiers = params2list(click_parameters) var/click_x var/click_y @@ -136,17 +133,14 @@ playsound(loc, 'sound/machines/click.ogg', 20, TRUE) -/obj/item/wargame_projector/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - . = ..() - if(istype(target, /obj/structure/wargame_hologram)) - qdel(target) - return - if(!check_can_place_hologram(target, user, proximity_flag, 1)) - return - create_hologram(target, user, click_parameters) - -/obj/item/wargame_projector/attack(mob/living/carbon/human/M, mob/user) //Jesse what the fuck is happening with that var, I'm scared to change it from M - return +/obj/item/wargame_projector/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(istype(interacting_with, /obj/structure/wargame_hologram)) + qdel(interacting_with) + return ITEM_INTERACT_SUCCESS + if(!check_can_place_hologram(interacting_with, user, 1)) + return NONE + create_hologram(interacting_with, user, modifiers) + return ITEM_INTERACT_SUCCESS /obj/item/wargame_projector/Destroy() QDEL_LAZYLIST(projections) diff --git a/modular_nova/modules/xenoarch/code/modules/research/xenoarch/xenoarch_tool.dm b/modular_nova/modules/xenoarch/code/modules/research/xenoarch/xenoarch_tool.dm index 7d19a2c8880..c0e4fbd050d 100644 --- a/modular_nova/modules/xenoarch/code/modules/research/xenoarch/xenoarch_tool.dm +++ b/modular_nova/modules/xenoarch/code/modules/research/xenoarch/xenoarch_tool.dm @@ -128,49 +128,48 @@ desc = "An item that has the capabilities to recover items lost due to time." icon_state = "recoverer" -/obj/item/xenoarch/handheld_recoverer/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!proximity_flag) - return - var/turf/target_turf = get_turf(target) - if(istype(target, /obj/item/xenoarch/broken_item/tech)) +/obj/item/xenoarch/handheld_recoverer/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + var/turf/target_turf = get_turf(interacting_with) + . = ITEM_INTERACT_SUCCESS + if(istype(interacting_with, /obj/item/xenoarch/broken_item/tech)) var/spawn_item = pick_weight(GLOB.tech_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/weapon)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/weapon)) var/spawn_item = pick_weight(GLOB.weapon_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/illegal)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/illegal)) var/spawn_item = pick_weight(GLOB.illegal_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/alien)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/alien)) var/spawn_item = pick_weight(GLOB.alien_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/plant)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/plant)) var/spawn_item = pick_weight(GLOB.plant_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/clothing)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/clothing)) var/spawn_item = pick_weight(GLOB.clothing_reward) new spawn_item(target_turf) - qdel(target) + qdel(interacting_with) return - if(istype(target, /obj/item/xenoarch/broken_item/animal)) + if(istype(interacting_with, /obj/item/xenoarch/broken_item/animal)) var/spawn_item var/turf/src_turf = get_turf(src) for(var/looptime in 1 to rand(1,4)) spawn_item = pick_weight(GLOB.animal_reward) new spawn_item(src_turf) - qdel(target) + qdel(interacting_with) return - return ..() + return NONE /obj/item/storage/belt/utility/xenoarch name = "xenoarch toolbelt"