diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index dceb37dbe51..eee89e7d3ca 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -1119,6 +1119,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Currently fishing
#define TRAIT_GONE_FISHING "fishing"
+/// Currently fishing, and it's the active minigame phase
+#define TRAIT_ACTIVELY_FISHING "actively_fishing"
/// Makes a character be better/worse at tackling depending on their wing's status
#define TRAIT_TACKLING_WINGED_ATTACKER "tacking_winged_attacker"
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index f872dde9b34..2cf71438e82 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -125,6 +125,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_ABDUCTOR_TRAINING" = TRAIT_ABDUCTOR_TRAINING,
"TRAIT_ACT_AS_CULTIST" = TRAIT_ACT_AS_CULTIST,
"TRAIT_ACT_AS_HERETIC" = TRAIT_ACT_AS_HERETIC,
+ "TRAIT_ACTIVELY_FISHING" = TRAIT_ACTIVELY_FISHING,
"TRAIT_ADAMANTINE_EXTRACT_ARMOR" = TRAIT_ADAMANTINE_EXTRACT_ARMOR,
"TRAIT_ADVANCEDTOOLUSER" = TRAIT_ADVANCEDTOOLUSER,
"TRAIT_AGENDER" = TRAIT_AGENDER,
diff --git a/code/datums/components/profound_fisher.dm b/code/datums/components/profound_fisher.dm
index 4485115db06..947e9d26f51 100644
--- a/code/datums/components/profound_fisher.dm
+++ b/code/datums/components/profound_fisher.dm
@@ -1,39 +1,107 @@
-///component that allows player mobs to play the fishing minigame, non-player mobs will "pretend" fish
+///component that allows player mobs to play the fishing minigame without a rod equipped, non-player mobs will "pretend" fish
/datum/component/profound_fisher
///the fishing rod this mob will use
var/obj/item/fishing_rod/mob_fisher/our_rod
-/datum/component/profound_fisher/Initialize(list/npc_fishing_preset = list())
- if(!isliving(parent))
- return
- our_rod = new(parent)
- ADD_TRAIT(parent, TRAIT_PROFOUND_FISHER, REF(src))
+/datum/component/profound_fisher/Initialize(our_rod)
+ var/isgloves = istype(parent, /obj/item/clothing/gloves)
+ if(!isliving(parent) && !isgloves)
+ return COMPONENT_INCOMPATIBLE
+ src.our_rod = our_rod || new(parent)
+ src.our_rod.internal = TRUE
+ RegisterSignal(src.our_rod, COMSIG_QDELETING, PROC_REF(on_rod_qdel))
-/datum/component/profound_fisher/RegisterWithParent()
- RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack))
+ if(!isgloves)
+ RegisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(pre_attack))
+ else
+ var/obj/item/clothing/gloves = parent
+ RegisterSignal(gloves, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
+ RegisterSignal(gloves, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
+ RegisterSignal(gloves, COMSIG_ATOM_ATTACK_HAND_SECONDARY, PROC_REF(open_rod_menu))
+ RegisterSignal(gloves, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+ gloves.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1
+ RegisterSignal(gloves, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
+ var/mob/living/wearer = gloves.loc
+ if(istype(wearer) && wearer.get_item_by_slot(ITEM_SLOT_GLOVES) == gloves)
+ RegisterSignal(wearer, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack))
-/datum/component/profound_fisher/UnregisterFromParent()
- UnregisterSignal(parent, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)
- REMOVE_TRAIT(parent, TRAIT_PROFOUND_FISHER, REF(src))
+/datum/component/profound_fisher/proc/on_requesting_context_from_item(datum/source, list/context, obj/item/held_item, mob/living/user)
+ SIGNAL_HANDLER
+ if(isnull(held_item) && user.contains(parent))
+ context[SCREENTIP_CONTEXT_RMB] = "Open rod UI"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/datum/component/profound_fisher/proc/on_examine(datum/source, mob/user, list/examine_list)
+ SIGNAL_HANDLER
+ examine_list += span_info("When [EXAMINE_HINT("held")] or [EXAMINE_HINT("equipped")], [EXAMINE_HINT("right-click")] with a empty hand to open the integrated fishing rod interface.")
+ examine_list += span_tinynoticeital("To fish, you need to turn combat mode off.")
+
+/datum/component/profound_fisher/proc/on_rod_qdel(datum/source)
+ SIGNAL_HANDLER
+ qdel(src)
/datum/component/profound_fisher/Destroy()
- QDEL_NULL(our_rod)
+ our_rod.internal = FALSE
+ UnregisterSignal(our_rod, COMSIG_QDELETING)
+ our_rod = null
return ..()
-/datum/component/profound_fisher/proc/pre_attack(datum/source, atom/target)
+/datum/component/profound_fisher/proc/on_equip(obj/item/source, atom/equipper, slot)
+ SIGNAL_HANDLER
+ if(slot != ITEM_SLOT_GLOVES)
+ return
+ RegisterSignal(equipper, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_unarmed_attack))
+
+/datum/component/profound_fisher/proc/open_rod_menu(datum/source, mob/user, list/modifiers)
+ SIGNAL_HANDLER
+ INVOKE_ASYNC(our_rod, TYPE_PROC_REF(/datum, ui_interact), user)
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/datum/component/profound_fisher/proc/on_drop(datum/source, atom/dropper)
+ SIGNAL_HANDLER
+ UnregisterSignal(dropper, COMSIG_LIVING_UNARMED_ATTACK)
+ REMOVE_TRAIT(dropper, TRAIT_PROFOUND_FISHER, TRAIT_GENERIC) //this will cancel the current minigame if the fishing rod was internal.
+
+/datum/component/profound_fisher/proc/on_unarmed_attack(mob/living/source, atom/attack_target, proximity_flag, list/modifiers)
+ SIGNAL_HANDLER
+ if(!source.client || !should_fish_on(source, attack_target))
+ return
+ INVOKE_ASYNC(src, PROC_REF(begin_fishing), source, attack_target)
+ return COMPONENT_CANCEL_ATTACK_CHAIN
+
+/datum/component/profound_fisher/proc/pre_attack(mob/living/source, atom/target)
SIGNAL_HANDLER
- if(!HAS_TRAIT(target, TRAIT_FISHING_SPOT))
- return NONE
- var/mob/living/living_parent = parent
- if(living_parent.combat_mode || !living_parent.CanReach(target))
- return NONE
- if(living_parent.client)
- INVOKE_ASYNC(our_rod, TYPE_PROC_REF(/obj/item, melee_attack_chain), parent, target)
+ if(!should_fish_on(source, target))
+ return
+ if(source.client)
+ INVOKE_ASYNC(src, PROC_REF(begin_fishing), source, target)
else
INVOKE_ASYNC(src, PROC_REF(pretend_fish), target)
return COMPONENT_HOSTILE_NO_ATTACK
+/datum/component/profound_fisher/proc/should_fish_on(mob/living/user, atom/target)
+ if(!HAS_TRAIT(target, TRAIT_FISHING_SPOT) || HAS_TRAIT(user, TRAIT_GONE_FISHING))
+ return FALSE
+ if(user.combat_mode || !user.CanReach(target))
+ return FALSE
+ return TRUE
+
+/datum/component/profound_fisher/proc/begin_fishing(mob/living/user, atom/target)
+ RegisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_GONE_FISHING), PROC_REF(actually_fishing_with_internal_rod))
+ our_rod.melee_attack_chain(user, target)
+ UnregisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_GONE_FISHING))
+
+/datum/component/profound_fisher/proc/actually_fishing_with_internal_rod(datum/source)
+ SIGNAL_HANDLER
+ ADD_TRAIT(source, TRAIT_PROFOUND_FISHER, REF(parent))
+ RegisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING), PROC_REF(remove_profound_fisher))
+
+/datum/component/profound_fisher/proc/remove_profound_fisher(datum/source)
+ SIGNAL_HANDLER
+ REMOVE_TRAIT(source, TRAIT_PROFOUND_FISHER, TRAIT_GENERIC)
+ UnregisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING))
+
/datum/component/profound_fisher/proc/pretend_fish(atom/target)
var/mob/living/living_parent = parent
if(DOING_INTERACTION_WITH_TARGET(living_parent, target))
@@ -56,8 +124,6 @@
qdel(lure)
/obj/item/fishing_rod/mob_fisher
- display_fishing_line = FALSE
line = /obj/item/fishing_line/reinforced
bait = /obj/item/food/bait/doughball/synthetic/unconsumable
-
-
+ resistance_flags = INDESTRUCTIBLE
diff --git a/code/game/machinery/newscaster/newscaster_machine.dm b/code/game/machinery/newscaster/newscaster_machine.dm
index 45c9d9db001..19c7a8416e7 100644
--- a/code/game/machinery/newscaster/newscaster_machine.dm
+++ b/code/game/machinery/newscaster/newscaster_machine.dm
@@ -64,7 +64,7 @@
acid = 30
/obj/machinery/newscaster/pai/ui_state(mob/user)
- return GLOB.reverse_contained_state
+ return GLOB.deep_inventory_state
WALL_MOUNT_DIRECTIONAL_HELPERS(/obj/machinery/newscaster)
diff --git a/code/modules/clothing/gloves/special.dm b/code/modules/clothing/gloves/special.dm
index d7fb34ae7c7..1366a29ac4a 100644
--- a/code/modules/clothing/gloves/special.dm
+++ b/code/modules/clothing/gloves/special.dm
@@ -155,3 +155,95 @@
siemens_coefficient = 0.3
clothing_traits = list(TRAIT_QUICKER_CARRY, TRAIT_CHUNKYFINGERS)
clothing_flags = THICKMATERIAL
+
+///A pair of gloves that both allow the user to fish without the need of a held fishing rod and provides athletics experience.
+/obj/item/clothing/gloves/fishing
+ name = "athletic fishing gloves"
+ desc = "A pair of gloves to fish without a fishing rod but your raw athletics strength. It doubles as a good workout device. WARNING: May cause injuries when catching bigger fish."
+ icon_state = "fishing_gloves"
+
+/obj/item/clothing/gloves/fishing/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/profound_fisher, new /obj/item/fishing_rod/mob_fisher/athletic(src))
+
+/obj/item/clothing/gloves/fishing/equipped(mob/user, slot)
+ . = ..()
+ if(slot == ITEM_SLOT_GLOVES)
+ RegisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_ACTIVELY_FISHING), PROC_REF(begin_workout))
+
+/obj/item/clothing/gloves/fishing/dropped(mob/user)
+ UnregisterSignal(user, list(SIGNAL_ADDTRAIT(TRAIT_ACTIVELY_FISHING), SIGNAL_REMOVETRAIT(TRAIT_ACTIVELY_FISHING)))
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
+/obj/item/clothing/gloves/fishing/proc/begin_workout(datum/source)
+ SIGNAL_HANDLER
+ RegisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_ACTIVELY_FISHING), PROC_REF(stop_workout))
+ if(HAS_TRAIT(source, TRAIT_PROFOUND_FISHER)) //Only begin working out if we're fishing with these gloves and not some other fishing rod..
+ START_PROCESSING(SSprocessing, src)
+
+/obj/item/clothing/gloves/fishing/proc/stop_workout(datum/source)
+ SIGNAL_HANDLER
+ UnregisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_ACTIVELY_FISHING))
+ STOP_PROCESSING(SSprocessing, src)
+
+/obj/item/clothing/gloves/fishing/process(seconds_per_tick)
+ var/mob/living/wearer = loc
+ var/list/trait_source = GET_TRAIT_SOURCES(wearer, TRAIT_ACTIVELY_FISHING)
+ var/datum/fishing_challenge/challenge = trait_source[1]
+ var/stamina_exhaustion = 2.5 + challenge.difficulty * 0.025
+ var/is_heavy_gravity = wearer.has_gravity() > STANDARD_GRAVITY
+ var/obj/item/organ/internal/cyberimp/chest/spine/potential_spine = wearer.get_organ_slot(ORGAN_SLOT_SPINE)
+ if(istype(potential_spine))
+ stamina_exhaustion *= potential_spine.athletics_boost_multiplier
+ if(HAS_TRAIT(wearer, TRAIT_STRENGTH))
+ stamina_exhaustion *= 0.5
+
+ var/experience = 0.3 + challenge.difficulty * 0.003
+ if(is_heavy_gravity)
+ stamina_exhaustion *= 1.5
+ experience *= 2
+
+ wearer.adjustStaminaLoss(stamina_exhaustion)
+ wearer.mind?.adjust_experience(/datum/skill/athletics, experience)
+ wearer.apply_status_effect(/datum/status_effect/exercised)
+
+///The internal fishing rod of the athletic fishing gloves. The more athletic you're, the easier the minigame will be.
+/obj/item/fishing_rod/mob_fisher/athletic
+ icon = /obj/item/clothing/gloves/fishing::icon
+ icon_state = /obj/item/clothing/gloves/fishing::icon_state
+ line = null
+ bait = null
+ ui_description = "The integrated fishing rod of a pair of athletic fishing gloves"
+
+/obj/item/fishing_rod/mob_fisher/athletic/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_FISHING_ROD_CAUGHT_FISH, PROC_REF(noodling_is_dangerous))
+
+/obj/item/fishing_rod/mob_fisher/athletic/get_fishing_overlays()
+ return list()
+
+/obj/item/fishing_rod/mob_fisher/athletic/hook_hit(atom/atom_hit_by_hook_projectile, mob/user)
+ difficulty_modifier = -3 * user.mind?.get_skill_level(/datum/skill/athletics)
+ return ..()
+
+/obj/item/fishing_rod/mob_fisher/athletic/proc/noodling_is_dangerous(datum/source, atom/movable/reward, mob/living/user)
+ SIGNAL_HANDLER
+ if(!isfish(reward))
+ return
+ var/damage = 0
+ var/obj/item/fish/fishe = reward
+ switch(fishe.w_class)
+ if(WEIGHT_CLASS_BULKY)
+ damage = 10
+ if(WEIGHT_CLASS_HUGE)
+ damage = 14
+ if(WEIGHT_CLASS_GIGANTIC)
+ damage = 18
+ if(!damage && fishe.weight >= 2000)
+ damage = 5
+ damage = round(damage * fishe.weight * 0.0005)
+ if(damage)
+ var/body_zone = pick(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM)
+ user.apply_damage(damage, BRUTE, body_zone, user.run_armor_check(body_zone, MELEE))
+ playsound(src,'sound/weapons/bite.ogg', damage * 2, TRUE)
diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm
index db01410d0e2..93a86ff82a9 100644
--- a/code/modules/fishing/fishing_minigame.dm
+++ b/code/modules/fishing/fishing_minigame.dm
@@ -196,21 +196,25 @@
interrupt()
/datum/fishing_challenge/proc/interrupt_challenge(datum/source, reason)
+ SIGNAL_HANDLER
if(reason)
send_alert(reason)
interrupt()
/datum/fishing_challenge/proc/start(mob/living/user)
/// Create fishing line visuals
- if(used_rod.display_fishing_line)
- fishing_line = used_rod.create_fishing_line(lure, target_py = 5)
+ if(!used_rod.internal)
+ fishing_line = used_rod.create_fishing_line(lure, user, target_py = 5)
RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(on_line_deleted))
else //if the rod doesnt have a fishing line, then it ends when they move away
- RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_user_move))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_lure_or_user_move))
+ RegisterSignal(lure, COMSIG_MOVABLE_MOVED, PROC_REF(on_lure_or_user_move))
+ RegisterSignal(user, SIGNAL_ADDTRAIT(TRAIT_HANDS_BLOCKED), PROC_REF(on_hands_blocked))
+ RegisterSignal(user, SIGNAL_REMOVETRAIT(TRAIT_PROFOUND_FISHER), PROC_REF(no_longer_fishing))
active_effects = bitfield_to_list(special_effects & FISHING_MINIGAME_ACTIVE_EFFECTS)
// If fishing line breaks los / rod gets dropped / deleted
RegisterSignal(used_rod, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self))
- ADD_TRAIT(user, TRAIT_GONE_FISHING, REF(src))
+ ADD_TRAIT(user, TRAIT_GONE_FISHING, WEAKREF(src))
user.add_mood_event("fishing", /datum/mood_event/fishing)
RegisterSignal(user, COMSIG_MOB_CLICKON, PROC_REF(handle_click))
start_baiting_phase()
@@ -224,17 +228,33 @@
user.balloon_alert(user, user.is_holding(used_rod) ? "line snapped" : "rod dropped")
interrupt()
-/datum/fishing_challenge/proc/on_user_move(datum/source)
+/datum/fishing_challenge/proc/on_lure_or_user_move(datum/source)
SIGNAL_HANDLER
- user.balloon_alert(user, "too far!")
+ if(!user.CanReach(lure))
+ user.balloon_alert(user, "too far!")
+ interrupt()
+
+/datum/fishing_challenge/proc/on_hands_blocked(datum/source)
+ SIGNAL_HANDLER
+ if(completed) //the rod was dropped and therefore challenge already completed.
+ return
+ user.balloon_alert(user, "hands blocked!")
+ interrupt()
+
+/datum/fishing_challenge/proc/no_longer_fishing(datum/source)
+ SIGNAL_HANDLER
+ user.balloon_alert(user, "interrupted!")
interrupt()
/datum/fishing_challenge/proc/handle_click(mob/source, atom/target, modifiers)
SIGNAL_HANDLER
- //You need to be holding the rod to use it.
+ if(HAS_TRAIT(source, TRAIT_HANDS_BLOCKED)) //blocked, can't do stuff
+ return
+ //Doing other stuff
if(LAZYACCESS(modifiers, SHIFT_CLICK) || LAZYACCESS(modifiers, CTRL_CLICK) || LAZYACCESS(modifiers, ALT_CLICK))
return
+ //You need to be actively holding on the fishing rod to use it, unless you've the profound_fisher trait.
if(!HAS_TRAIT(source, TRAIT_PROFOUND_FISHER) && source.get_active_held_item() != used_rod)
return
if(phase == WAIT_PHASE)
@@ -267,8 +287,9 @@
completed = TRUE
if(phase == MINIGAME_PHASE)
remove_minigame_hud()
- if(user)
- REMOVE_TRAIT(user, TRAIT_GONE_FISHING, REF(src))
+ if(!QDELETED(user))
+ UnregisterSignal(user, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING))
+ user.remove_traits(list(TRAIT_GONE_FISHING, TRAIT_ACTIVELY_FISHING), WEAKREF(src))
if(start_time)
var/seconds_spent = (world.time - start_time) * 0.1
if(!(special_effects & FISHING_MINIGAME_RULE_NO_EXP))
@@ -381,6 +402,7 @@
bait_position = clamp(round(fish_position + rand(-diff_dist, diff_dist) - bait_height * 0.5), 0, FISHING_MINIGAME_AREA - bait_height)
if(!prepare_minigame_hud())
return
+ ADD_TRAIT(user, TRAIT_ACTIVELY_FISHING, WEAKREF(src))
phase = MINIGAME_PHASE
deltimer(next_phase_timer)
if((FISHING_MINIGAME_RULE_KILL in special_effects) && ispath(reward_path,/obj/item/fish))
diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm
index ece2f9d84af..68ac1cf2371 100644
--- a/code/modules/fishing/fishing_rod.dm
+++ b/code/modules/fishing/fishing_rod.dm
@@ -36,8 +36,8 @@
/// The default color for the reel overlay if no line is equipped.
var/default_line_color = "gray"
- ///should there be a fishing line?
- var/display_fishing_line = TRUE
+ ///Is this currently being used by the profound fisher component?
+ var/internal = FALSE
///The name of the icon state of the reel overlay
var/reel_overlay = "reel_overlay"
@@ -158,21 +158,18 @@
ui_interact(user)
/// 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)
- return null
- var/mob/user = loc
- if(!istype(user))
+/obj/item/fishing_rod/proc/create_fishing_line(atom/movable/target, mob/living/firer, target_py = null)
+ if(internal)
return null
if(fishing_line)
QDEL_NULL(fishing_line)
var/beam_color = line?.line_color || default_line_color
- fishing_line = new(user, target, icon_state = "fishing_line", beam_color = beam_color, emissive = FALSE, override_target_pixel_y = target_py)
- fishing_line.lefthand = user.get_held_index_of_item(src) % 2 == 1
+ fishing_line = new(firer, target, icon_state = "fishing_line", beam_color = beam_color, emissive = FALSE, override_target_pixel_y = target_py)
+ fishing_line.lefthand = firer.get_held_index_of_item(src) % 2 == 1
RegisterSignal(fishing_line, COMSIG_BEAM_BEFORE_DRAW, PROC_REF(check_los))
RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(clear_line))
INVOKE_ASYNC(fishing_line, TYPE_PROC_REF(/datum/beam/, Start))
- user.update_held_items()
+ firer.update_held_items()
return fishing_line
/obj/item/fishing_rod/proc/clear_line(datum/source)
@@ -194,7 +191,7 @@
if(!hook.can_be_hooked(target_atom))
return
currently_hooked = target_atom
- create_fishing_line(target_atom)
+ create_fishing_line(target_atom, user)
hook.hook_attached(target_atom, src)
SEND_SIGNAL(src, COMSIG_FISHING_ROD_HOOKED_ITEM, target_atom, user)
@@ -208,6 +205,9 @@
return BEAM_CANCEL_DRAW
/obj/item/fishing_rod/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
+ //this prevent trying to use telekinesis to fish (which would be broken anyway)
+ if(!user.contains(src))
+ return ..()
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)
@@ -256,9 +256,8 @@
COOLDOWN_START(src, casting_cd, 1 SECONDS)
/// Called by hook projectile when hitting things
-/obj/item/fishing_rod/proc/hook_hit(atom/atom_hit_by_hook_projectile)
- var/mob/user = loc
- if(!hook || !istype(user))
+/obj/item/fishing_rod/proc/hook_hit(atom/atom_hit_by_hook_projectile, mob/user)
+ if(!hook)
return
if(SEND_SIGNAL(atom_hit_by_hook_projectile, COMSIG_FISHING_ROD_CAST, src, user) & FISHING_ROD_CAST_HANDLED)
return
@@ -272,6 +271,12 @@
ui.set_autoupdate(FALSE)
ui.open()
+/obj/item/fishing_rod/ui_state()
+ if(internal)
+ return GLOB.deep_inventory_state
+ else
+ return GLOB.default_state
+
/obj/item/fishing_rod/update_overlays()
. = ..()
. += get_fishing_overlays()
@@ -390,6 +395,8 @@
/// Ideally this will be replaced with generic slotted storage datum + display
/obj/item/fishing_rod/proc/use_slot(slot, mob/user, obj/item/new_item)
+ if(fishing_line || HAS_TRAIT(user, TRAIT_GONE_FISHING))
+ return
var/obj/item/current_item
switch(slot)
if(ROD_SLOT_BAIT)
@@ -596,13 +603,13 @@
transform = transform.Scale(1, -1)
. = ..()
if(!QDELETED(src))
- our_line = owner.create_fishing_line(src)
+ our_line = owner.create_fishing_line(src, firer)
/obj/projectile/fishing_cast/on_hit(atom/target, blocked = 0, pierce_hit)
. = ..()
if(blocked < 100)
QDEL_NULL(our_line) //we need to delete the old beam datum, otherwise it won't let you fish.
- owner.hook_hit(target)
+ owner.hook_hit(target, firer)
/obj/projectile/fishing_cast/Destroy()
QDEL_NULL(our_line)
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index 2ab0b0a1fd2..f1b14b0f900 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -953,6 +953,76 @@
balloon_alert(mod.wearer, "ammo box dispensed.")
playsound(src, 'sound/machines/microwave/microwave-end.ogg', 50, TRUE)
+/obj/item/mod/module/fishing_glove
+ name = "MOD fishing glove module"
+ desc = "A MOD module that takes in an external fishing rod to enable the user to fish without having to hold one."
+ icon_state = "fishing_glove"
+ complexity = 1
+ overlay_state_inactive = "fishing_glove"
+ incompatible_modules = (/obj/item/mod/module/fishing_glove)
+ required_slots = list(ITEM_SLOT_GLOVES)
+ var/obj/item/fishing_rod/equipped
+
+/obj/item/mod/module/fishing_glove/Initialize(mapload)
+ . = ..()
+ register_context()
+
+/obj/item/mod/module/fishing_glove/add_context(atom/source, list/context, obj/item/held_item, mob/user)
+ if(!held_item && equipped)
+ context[SCREENTIP_CONTEXT_RMB] = "Remove rod"
+ return CONTEXTUAL_SCREENTIP_SET
+ if(istype(held_item, /obj/item/fishing_rod))
+ context[SCREENTIP_CONTEXT_LMB] = "Insert rod"
+ return CONTEXTUAL_SCREENTIP_SET
+
+/obj/item/mod/module/fishing_glove/examine(mob/user)
+ . = ..()
+ . += span_info("You can [EXAMINE_HINT("right-click")] the modsuit gloves to open the fishing rod interface once attached and activated.")
+ if(equipped)
+ . += span_info("it has a [icon2html(equipped, user)] installed. [EXAMINE_HINT("Right-Click")] to remove it.")
+
+/obj/item/mod/module/fishing_glove/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
+ if(!istype(tool, /obj/item/fishing_rod))
+ return ..()
+ if(equipped)
+ balloon_alert(user, "remove current rod first!")
+ if(!user.transferItemToLoc(tool, src))
+ user.balloon_alert(user, "it's stuck!")
+ equipped = tool
+ balloon_alert(user, "rod inserted")
+ playsound(src, 'sound/items/click.ogg', 50, TRUE)
+ return ITEM_INTERACT_SUCCESS
+
+/obj/item/mod/module/fishing_glove/attack_hand_secondary(mob/user, list/modifiers)
+ . = ..()
+ if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN)
+ return
+ if(!equipped)
+ return
+ user.put_in_hands(equipped)
+ balloon_alert(user, "rod removed")
+ playsound(src, 'sound/items/click.ogg', 50, TRUE)
+ return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
+
+/obj/item/mod/module/fishing_glove/Exited(atom/movable/gone)
+ if(gone == equipped)
+ equipped = null
+ var/obj/item/gloves = mod?.get_part_from_slot(ITEM_SLOT_GLOVES)
+ if(gloves && !QDELETED(mod))
+ qdel(gloves.GetComponent(/datum/component/profound_fisher))
+
+/obj/item/mod/module/fishing_glove/on_suit_activation()
+ if(!equipped)
+ return
+ var/obj/item/gloves = mod.get_part_from_slot(ITEM_SLOT_GLOVES)
+ if(gloves)
+ gloves.AddComponent(/datum/component/profound_fisher, equipped)
+
+/obj/item/mod/module/fishing_glove/on_suit_deactivation(deleting = FALSE)
+ var/obj/item/gloves = mod.get_part_from_slot(ITEM_SLOT_GLOVES)
+ if(gloves && !deleting)
+ qdel(gloves.GetComponent(/datum/component/profound_fisher))
+
/obj/item/mod/module/shock_absorber
name = "MOD shock absorption module"
desc = "A module that makes the user resistant to the knockdown inflicted by Stun Batons."
diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm
index b40ae45f27f..d2c48fb5b8d 100644
--- a/code/modules/modular_computers/computers/item/pda.dm
+++ b/code/modules/modular_computers/computers/item/pda.dm
@@ -419,7 +419,7 @@
return TRUE
/obj/item/modular_computer/pda/silicon/ui_state(mob/user)
- return GLOB.reverse_contained_state
+ return GLOB.deep_inventory_state
/obj/item/modular_computer/pda/silicon/cyborg/syndicate
icon_state = "tablet-silicon-syndicate"
diff --git a/code/modules/modular_computers/file_system/programs/messenger/messenger_program.dm b/code/modules/modular_computers/file_system/programs/messenger/messenger_program.dm
index 4ad633aa94d..6436e6be2b8 100644
--- a/code/modules/modular_computers/file_system/programs/messenger/messenger_program.dm
+++ b/code/modules/modular_computers/file_system/programs/messenger/messenger_program.dm
@@ -157,7 +157,7 @@
/datum/computer_file/program/messenger/ui_state(mob/user)
if(issilicon(user))
- return GLOB.reverse_contained_state
+ return GLOB.deep_inventory_state
return GLOB.default_state
/datum/computer_file/program/messenger/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm
index 9a5e6495c53..fb15c40b32f 100644
--- a/code/modules/research/designs/mechfabricator_designs.dm
+++ b/code/modules/research/designs/mechfabricator_designs.dm
@@ -2741,6 +2741,17 @@
RND_CATEGORY_MODSUIT_MODULES + RND_SUBCATEGORY_MODSUIT_MODULES_ENGINEERING
)
+/datum/design/module/fishing_glove
+ name = "MOD Fishing Glove Module"
+ id = "mod_fishing"
+ materials = list(
+ /datum/material/titanium = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT,
+ /datum/material/plastic = HALF_SHEET_MATERIAL_AMOUNT,
+ )
+ build_path = /obj/item/mod/module/fishing_glove
+
/datum/design/posisphere
name = "Positronic Sphere"
desc = "The latest in Artificial Pesterance."
diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm
index 4d80a09987a..22306cffe71 100644
--- a/code/modules/research/designs/misc_designs.dm
+++ b/code/modules/research/designs/misc_designs.dm
@@ -986,6 +986,18 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE
+/datum/design/fishing_gloves
+ name = "Athletic Fishing Gloves"
+ desc = "A pair of gloves to fish without a fishing rod and train your athletics with."
+ id = "fishing_gloves"
+ build_type = PROTOLATHE | AWAY_LATHE
+ materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT, /datum/material/plastic = SHEET_MATERIAL_AMOUNT)
+ build_path = /obj/item/clothing/gloves/fishing
+ category = list(
+ RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SERVICE
+ )
+ departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE
+
/datum/design/stabilized_hook
name = "Gyro-Stabilized Hook"
desc = "An advanced fishing hook that gives the user a tighter control on the fish when reeling in."
diff --git a/code/modules/research/techweb/nodes/service_nodes.dm b/code/modules/research/techweb/nodes/service_nodes.dm
index 9c0d68b6b2b..3735dc41b3b 100644
--- a/code/modules/research/techweb/nodes/service_nodes.dm
+++ b/code/modules/research/techweb/nodes/service_nodes.dm
@@ -165,6 +165,8 @@
prereq_ids = list(TECHWEB_NODE_FISHING_EQUIP)
design_ids = list(
"fishing_rod_tech",
+ "fishing_gloves",
+ "mod_fishing",
"stabilized_hook",
"auto_reel",
"fish_analyzer",
diff --git a/code/modules/tgui/states/reverse_contained.dm b/code/modules/tgui/states/reverse_contained.dm
deleted file mode 100644
index a6d1034a789..00000000000
--- a/code/modules/tgui/states/reverse_contained.dm
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * Not copyrighted, but magatsuchi made it.
- *
- */
-
-/**
- * tgui state: reverse_contained_state
- *
- *
- * Checks if src_object is inside of user.
- */
-
-GLOBAL_DATUM_INIT(reverse_contained_state, /datum/ui_state/reverse_contained_state, new)
-
-/datum/ui_state/reverse_contained_state/can_use_topic(atom/src_object, mob/user)
- if(!user.contains(src_object))
- return UI_CLOSE
- return user.shared_ui_interaction(src_object)
diff --git a/icons/mob/clothing/hands.dmi b/icons/mob/clothing/hands.dmi
index 449be68d4e5..78a07c08e6e 100644
Binary files a/icons/mob/clothing/hands.dmi and b/icons/mob/clothing/hands.dmi differ
diff --git a/icons/mob/clothing/modsuit/mod_modules.dmi b/icons/mob/clothing/modsuit/mod_modules.dmi
index 4f2dc9740d1..5c433defa07 100644
Binary files a/icons/mob/clothing/modsuit/mod_modules.dmi and b/icons/mob/clothing/modsuit/mod_modules.dmi differ
diff --git a/icons/mob/inhands/clothing/gloves_lefthand.dmi b/icons/mob/inhands/clothing/gloves_lefthand.dmi
index 4d191e42939..13b91d3108f 100644
Binary files a/icons/mob/inhands/clothing/gloves_lefthand.dmi and b/icons/mob/inhands/clothing/gloves_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing/gloves_righthand.dmi b/icons/mob/inhands/clothing/gloves_righthand.dmi
index f8ce306cc98..f7325d02e7a 100644
Binary files a/icons/mob/inhands/clothing/gloves_righthand.dmi and b/icons/mob/inhands/clothing/gloves_righthand.dmi differ
diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi
index a4549f9e74b..b2b3d333bb4 100644
Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ
diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi
index 36d95aa61fd..5cab83c56d5 100644
Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index f6c90844e0c..204142715ac 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -6086,7 +6086,6 @@
#include "code\modules\tgui\states\notcontained.dm"
#include "code\modules\tgui\states\observer.dm"
#include "code\modules\tgui\states\physical.dm"
-#include "code\modules\tgui\states\reverse_contained.dm"
#include "code\modules\tgui\states\self.dm"
#include "code\modules\tgui\states\zlevel.dm"
#include "code\modules\tgui_input\alert.dm"