Skip to content

Commit

Permalink
Merge branch 'tg-interaction-20240920' of https://github.com/DopplerS…
Browse files Browse the repository at this point in the history
…hift13/DopplerShift into themostextreme
  • Loading branch information
Nerev4r committed Sep 20, 2024
2 parents 2541f3e + 1c22e15 commit 4baa3c7
Show file tree
Hide file tree
Showing 129 changed files with 1,730 additions and 377 deletions.
3 changes: 2 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
/SQL/ @kannthus

# Maintainers
/modular_doppler/ @CliffracerX @Ephemeralis
/modular_doppler/ @CliffracerX @Ephemeralis @honkpocket
/code/ @CliffracerX @Ephemeralis @honkpocket

# Maptainers
/_maps/ @SylvetteSylph @Mintybea
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/dcs/signals/signals_atom/signals_atom_x_act.dm
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,6 @@
/// 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)
/// from /obj/projectile/energy/fisher/on_hit() or /obj/item/gun/energy/recharge/fisher when striking a target
#define COMSIG_ATOM_SABOTEUR_ACT "hit_by_saboteur"
#define COMSIG_SABOTEUR_SUCCESS 1
6 changes: 6 additions & 0 deletions code/__DEFINES/tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@

/// Combination flag for any item interaction that blocks the rest of the attack chain
#define ITEM_INTERACT_ANY_BLOCKER (ITEM_INTERACT_SUCCESS | ITEM_INTERACT_BLOCKING)

/**
* A helper for checking if an item interaction should be skipped.
* This is only used explicitly because some interactions may not want to ever be skipped.
*/
#define SHOULD_SKIP_INTERACTION(target, item, user) (HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION) && user.combat_mode)
13 changes: 13 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,19 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
///Trait which allows mobs to parry mining mob projectiles
#define TRAIT_MINING_PARRYING "mining_parrying"

/**
*
* This trait is used in some interactions very high in the interaction chain to allow
* certain atoms to be skipped by said interactions if the user is in combat mode.
*
* Its primarily use case is for stuff like storage and tables, to allow things like emags to be bagged
* (because in some contexts you might want to be emagging a bag, and in others you might want to be storing it.)
*
* This is only checked by certain items explicitly so you can't just add the trait and expect it to work.
* (This may be changed later but I chose to do it this way to avoid messing up interactions which require combat mode)
*/
#define TRAIT_COMBAT_MODE_SKIP_INTERACTION "combat_mode_skip_interaction"

///A "fake" effect that should not be subject to normal effect removal methods (like the effect remover component)
#define TRAIT_ILLUSORY_EFFECT "illusory_effect"

Expand Down
10 changes: 6 additions & 4 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BLOCKING_EXPLOSIVES" = TRAIT_BLOCKING_EXPLOSIVES,
"TRAIT_BOULDER_BREAKER" = TRAIT_BOULDER_BREAKER,
"TRAIT_CASTABLE_LOC" = TRAIT_CASTABLE_LOC,
"TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER,
"TRAIT_COMBAT_MODE_SKIP_INTERACTION" = TRAIT_COMBAT_MODE_SKIP_INTERACTION,
"TRAIT_DEL_ON_SPACE_DUMP" = TRAIT_DEL_ON_SPACE_DUMP,
"TRAIT_FISH_CASE_COMPATIBILE" = TRAIT_FISH_CASE_COMPATIBILE,
"TRAIT_FROZEN" = TRAIT_FROZEN,
Expand All @@ -50,28 +52,28 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING,
"TRAIT_MOVE_GROUND" = TRAIT_MOVE_GROUND,
"TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING,
"TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING,
"TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN,
"TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING,
"TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE,
"TRAIT_NO_FLOATING_ANIM" = TRAIT_NO_FLOATING_ANIM,
"TRAIT_NO_MANIFEST_CONTENTS_ERROR" = TRAIT_NO_MANIFEST_CONTENTS_ERROR,
"TRAIT_NO_MISSING_ITEM_ERROR" = TRAIT_NO_MISSING_ITEM_ERROR,
"TRAIT_NO_THROW_HITPUSH" = TRAIT_NO_THROW_HITPUSH,
"TRAIT_NOT_ENGRAVABLE" = TRAIT_NOT_ENGRAVABLE,
"TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC,
"TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT" = TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT,
"TRAIT_ON_HIT_EFFECT" = TRAIT_ON_HIT_EFFECT,
"TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN,
"TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN,
"TRAIT_SECLUDED_LOCATION" = TRAIT_SECLUDED_LOCATION,
"TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE,
"TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC,
"TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED,
"TRAIT_UNDERFLOOR" = TRAIT_UNDERFLOOR,
"TRAIT_UNIQUE_IMMERSE" = TRAIT_UNIQUE_IMMERSE,
"TRAIT_VOIDSTORM_IMMUNE" = TRAIT_VOIDSTORM_IMMUNE,
"TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED,
"TRAIT_WADDLING" = TRAIT_WADDLING,
"TRAIT_WAS_RENAMED" = TRAIT_WAS_RENAMED,
"TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE,
"TRAIT_CHASM_STOPPER" = TRAIT_CHASM_STOPPER,
),
/datum/controller/subsystem/economy = list(
"TRAIT_MARKET_CRASHING" = TRAIT_MARKET_CRASHING,
Expand Down
3 changes: 3 additions & 0 deletions code/datums/components/cleaner.dm
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
/datum/component/cleaner/proc/on_interaction(datum/source, mob/living/user, atom/target, list/modifiers)
SIGNAL_HANDLER

if(isitem(source) && SHOULD_SKIP_INTERACTION(target, source, user))
return NONE

// By default, give XP
var/give_xp = TRUE
if(pre_clean_callback)
Expand Down
1 change: 0 additions & 1 deletion code/datums/components/lockable_storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
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,
Expand Down
33 changes: 5 additions & 28 deletions code/datums/storage/storage.dm
Original file line number Diff line number Diff line change
Expand Up @@ -189,20 +189,19 @@

/// Set the passed atom as the parent
/datum/storage/proc/set_parent(atom/new_parent)
PRIVATE_PROC(TRUE)
PROTECTED_PROC(TRUE)

ASSERT(isnull(parent))

parent = new_parent
ADD_TRAIT(parent, TRAIT_COMBAT_MODE_SKIP_INTERACTION, REF(src))
// a few of theses should probably be on the real_location rather than the parent
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_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))
Expand Down Expand Up @@ -834,19 +833,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)
attempt_insert(dropping, user)
return COMPONENT_CANCEL_MOUSEDROPPED_ONTO

/// Signal handler for whenever we're attacked by an object.
/datum/storage/proc/on_item_interact(datum/source, mob/user, obj/item/thing, params)
SIGNAL_HANDLER

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

/// Called directly from the attack chain if [insert_on_attack] is TRUE.
/// Handles inserting an item into the storage when clicked.
/datum/storage/proc/item_interact_insert(mob/living/user, obj/item/thing)
if(iscyborg(user))
return ITEM_INTERACT_BLOCKING

Expand Down Expand Up @@ -897,18 +886,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches)

return toreturn

/// Signal handler for when we get attacked with secondary click by an item.
/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)

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)
SIGNAL_HANDLER
Expand Down
38 changes: 13 additions & 25 deletions code/game/atom/atom_tool_acts.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@
if(tool_return)
return tool_return

var/is_right_clicking = LAZYACCESS(modifiers, RIGHT_CLICK)
var/is_right_clicking = text2num(LAZYACCESS(modifiers, RIGHT_CLICK))
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
* This puts priority on the atom's signals, then the tool's signals, then the user's signals,
* so we can avoid doing two interactions at once
*/
early_sig_return = SEND_SIGNAL(src, COMSIG_ATOM_ITEM_INTERACTION, user, tool, modifiers) \
|| SEND_SIGNAL(tool, COMSIG_ITEM_INTERACTING_WITH_ATOM, user, src, modifiers) \
Expand All @@ -50,6 +48,16 @@
if(interact_return)
return interact_return

// We have to manually handle storage in item_interaction because storage is blocking in 99% of interactions, which stifles a lot
// Yeah it sucks not being able to signalize this, but the other option is to have a second signal here just for storage which is also not great
if(atom_storage)
if(is_left_clicking)
if(atom_storage.insert_on_attack)
return atom_storage.item_interact_insert(user, tool)
else
if(atom_storage.open_storage(user) && atom_storage.display_contents)
return ITEM_INTERACT_SUCCESS

return NONE

/**
Expand Down Expand Up @@ -325,23 +333,3 @@
/// Called on an object when a tool with analyzer capabilities is used to right click an object
/atom/proc/analyzer_act_secondary(mob/living/user, obj/item/tool)
return

/**
* 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

/**
* 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
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@
/obj/machinery/vending/imported/yangyu = "Fudobenda", //DOPPLER ADDITION
/obj/machinery/vending/imported/mothic = "Nomad Fleet Ration Chit Exchange", //DOPPLER ADDITION
/obj/machinery/vending/imported/tiziran = "Tiziran Imported Delicacies", //DOPPLER ADDITION
/obj/machinery/vending/deforest_medvend = "DeForest Med-Vend", //DOPPLER ADDITION
)

/obj/item/circuitboard/machine/vendor/screwdriver_act(mob/living/user, obj/item/tool)
Expand Down
2 changes: 2 additions & 0 deletions code/game/objects/items/climbingrope.dm
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
. += span_notice("The rope looks like you could use it [uses] times before it falls apart.")

/obj/item/climbing_hook/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(HAS_TRAIT(interacting_with, TRAIT_COMBAT_MODE_SKIP_INTERACTION))
return NONE
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)
Expand Down
3 changes: 0 additions & 3 deletions code/game/objects/items/clown_items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,6 @@
return CLEAN_BLOCKED
return ..()

/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
*/
Expand Down
8 changes: 5 additions & 3 deletions code/game/objects/items/control_wand.dm
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
update_icon_state()
balloon_alert(user, "mode: [desc[mode]]")

/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)
if(!istype(interacting_with, /obj/machinery/door) && !isturf(interacting_with))
return NONE
return ranged_interact_with_atom(interacting_with, user, modifiers)

/obj/item/door_remote/ranged_interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
var/obj/machinery/door/door

if (istype(interacting_with, /obj/machinery/door))
Expand Down
12 changes: 8 additions & 4 deletions code/game/objects/items/crayons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,10 @@
/obj/item/toy/crayon/spraycan/can_use_on(atom/target, mob/user, list/modifiers)
if(iscarbon(target))
return TRUE
if(ismob(target) && (HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE)))
if(is_capped && HAS_TRAIT(target, TRAIT_COMBAT_MODE_SKIP_INTERACTION))
// specifically don't try to use a capped spraycan on stuff like bags and tables, just place it
return FALSE
if(ismob(target) && HAS_TRAIT(target, TRAIT_SPRAY_PAINTABLE))
return TRUE
if(isobj(target) && !(target.flags_1 & UNPAINTABLE_1))
return TRUE
Expand Down Expand Up @@ -967,6 +970,10 @@

/obj/item/toy/crayon/spraycan/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
if(is_capped)
if(!interacting_with.color)
// let's be generous and assume if they're trying to match something with no color, while capped,
// we shouldn't be blocking further interactions
return NONE
balloon_alert(user, "take the cap off first!")
return ITEM_INTERACT_BLOCKING
if(check_empty(user))
Expand Down Expand Up @@ -1003,9 +1010,6 @@
update_appearance()
return CLICK_ACTION_SUCCESS

/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()
icon_state = is_capped ? icon_capped : icon_uncapped
return ..()
Expand Down
16 changes: 7 additions & 9 deletions code/game/objects/items/devices/aicard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,15 @@
user.visible_message(span_suicide("[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!"))
return BRUTELOSS

/obj/item/aicard/pre_attack(atom/target, mob/living/user, params)
. = ..()
if(.)
return

/obj/item/aicard/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(AI)
if(upload_ai(target, user))
return TRUE
if(upload_ai(interacting_with, user))
return ITEM_INTERACT_SUCCESS
else
if(capture_ai(target, user))
return TRUE
if(capture_ai(interacting_with, user))
return ITEM_INTERACT_SUCCESS

return NONE

/// Tries to get an AI from the atom clicked
/obj/item/aicard/proc/capture_ai(atom/from_what, mob/living/user)
Expand Down
33 changes: 22 additions & 11 deletions code/game/objects/items/devices/chameleonproj.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,36 @@
else
to_chat(user, span_warning("You can't use [src] while inside something!"))

/obj/item/chameleon/interact_with_atom(atom/target, mob/living/user, list/modifiers)
/obj/item/chameleon/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
if(!can_copy(interacting_with) || SHOULD_SKIP_INTERACTION(interacting_with, src, user))
return NONE
make_copy(interacting_with, user)
return ITEM_INTERACT_SUCCESS

/obj/item/chameleon/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers)
if(!can_copy(interacting_with)) // RMB scan works on storage items, LMB scan does not
return NONE
make_copy(interacting_with, user)
return ITEM_INTERACT_SUCCESS

/obj/item/chameleon/proc/can_copy(atom/target)
if(!check_sprite(target))
return ITEM_INTERACT_BLOCKING
return FALSE
if(active_dummy)//I now present you the blackli(f)st
return ITEM_INTERACT_BLOCKING
return FALSE
if(isturf(target))
return ITEM_INTERACT_BLOCKING
return FALSE
if(ismob(target))
return ITEM_INTERACT_BLOCKING
return FALSE
if(istype(target, /obj/structure/falsewall))
return ITEM_INTERACT_BLOCKING
return FALSE
if(target.alpha != 255)
return ITEM_INTERACT_BLOCKING
return FALSE
if(target.invisibility != 0)
return ITEM_INTERACT_BLOCKING
return FALSE
if(iseffect(target) && !istype(target, /obj/effect/decal)) //be a footprint
return ITEM_INTERACT_BLOCKING
make_copy(target, user)
return ITEM_INTERACT_SUCCESS
return FALSE
return TRUE

/obj/item/chameleon/proc/make_copy(atom/target, mob/user)
playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, TRUE, -6)
Expand Down
6 changes: 3 additions & 3 deletions code/game/objects/items/devices/forcefieldprojector.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
/// Checks to make sure the projector isn't busy with making another forcefield.
var/force_proj_busy = FALSE

/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)
return ranged_interact_with_atom(interacting_with, user, modifiers)

/obj/item/forcefield_projector/ranged_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))
Expand Down
Loading

0 comments on commit 4baa3c7

Please sign in to comment.