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"