mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
You can now link fishing portal generators to other fishing spots. (#86291)
## About The Pull Request You can now interact with the fishing portal generator with a multitool to load it in the buffer and subsequently link fishing spots to it by tapping them with the same multitool. The maximum number of fishing spots that can be linked at once depends on the tier of the matter bins of the machinery. Normally, while you can link fishing spots from other z-levels, they can only be activated if they're on the same z-level as the machinery (or if both are on station for multi-z stations). This limitation can be bypassed by upgrading the machinery with a tier 3 or higher capacitator. While it's possible, I'm not spriting new fishing portal overlays and icons for the radial menu for every fish source out there (yet). The code is enough work for now. This also comes with a unit test, because there is no such thing as too many unit tests for fishing. ## Why It's Good For The Game Fish portal generators are designed to let players fish a different bunch of things while being able to be moved wherever you like, unlike a lake or an ocean, with all the comfort of being able to able to catch fish from distant locations. Allowing players to link other fishing spots to it fits its design. It also means that you can go out and explore, find more fishing spots and then return to the station without having to detach yourself from the ongoing round for several more minutes. ## Changelog 🆑 add: You can now link fishing portal generators to other fishing spots with a multitool. The number of fishing spots that can be linked at once and whether the link can be activated from different z levels depends on the tier of the stock parts it's built with. /🆑 --------- Co-authored-by: Emmett Gaines <ninjanomnom@gmail.com>
This commit is contained in:
@@ -11,6 +11,46 @@
|
||||
|
||||
///The current fishing spot loaded in
|
||||
var/datum/component/fishing_spot/active
|
||||
///A list of fishing spot it's linked to with a multitool.
|
||||
var/list/linked_fishing_spots
|
||||
///The maximum number of fishing spots it can be linked to
|
||||
var/max_fishing_spots = 1
|
||||
///If true, the fishing portal can stay connected to a linked fishing spot even on different z-levels
|
||||
var/long_range_link = FALSE
|
||||
|
||||
/obj/machinery/fishing_portal_generator/Initialize(mapload)
|
||||
. = ..()
|
||||
var/static/list/tool_screentips = list(
|
||||
TOOL_MULTITOOL = list(
|
||||
SCREENTIP_CONTEXT_LMB = "Link",
|
||||
SCREENTIP_CONTEXT_RMB = "Unlink fishing spots"
|
||||
),
|
||||
)
|
||||
AddElement(/datum/element/contextual_screentip_tools, tool_screentips)
|
||||
ADD_TRAIT(src, TRAIT_UNLINKABLE_FISHING_SPOT, INNATE_TRAIT)
|
||||
|
||||
/obj/machinery/fishing_portal_generator/Destroy()
|
||||
deactivate()
|
||||
linked_fishing_spots = null
|
||||
return ..()
|
||||
|
||||
///Higher tier parts let you link to more fishing spots at once and eventually let you connect through different zlevels.
|
||||
/obj/machinery/fishing_portal_generator/RefreshParts()
|
||||
. = ..()
|
||||
max_fishing_spots = 0
|
||||
long_range_link = FALSE
|
||||
for(var/datum/stock_part/matter_bin/matter_bin in component_parts)
|
||||
max_fishing_spots += matter_bin.tier * 0.5
|
||||
max_fishing_spots = ROUND_UP(max_fishing_spots)
|
||||
for(var/datum/stock_part/capacitor/capacitor in component_parts)
|
||||
if(capacitor.tier >= 3)
|
||||
long_range_link = TRUE
|
||||
if(!long_range_link)
|
||||
check_fishing_spot_z()
|
||||
if(length(linked_fishing_spots) > max_fishing_spots)
|
||||
if(active)
|
||||
deactivate()
|
||||
linked_fishing_spots.len = max_fishing_spots
|
||||
|
||||
/obj/machinery/fishing_portal_generator/on_set_panel_open()
|
||||
update_appearance()
|
||||
@@ -21,9 +61,94 @@
|
||||
default_unfasten_wrench(user, tool)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/fishing_portal_generator/multitool_act(mob/living/user, obj/item/multitool/tool)
|
||||
if(machine_stat & NOPOWER)
|
||||
balloon_alert(user, "no power!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/unlink = tool.buffer == src
|
||||
tool.set_buffer(unlink ? null : src)
|
||||
balloon_alert(user, "fish-porter [unlink ? "un" : ""]linked")
|
||||
if(!unlink)
|
||||
tool.item_flags |= ITEM_HAS_CONTEXTUAL_SCREENTIPS
|
||||
RegisterSignal(tool, COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, PROC_REF(multitool_context))
|
||||
RegisterSignal(tool, COMSIG_MULTITOOL_REMOVE_BUFFER, PROC_REF(multitool_unbuffered))
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/fishing_portal_generator/multitool_act_secondary(mob/living/user, obj/item/tool)
|
||||
if(machine_stat & NOPOWER)
|
||||
balloon_alert(user, "no power!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!length(linked_fishing_spots))
|
||||
balloon_alert(user, "nothing to unlink!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
var/list/fishing_list = list()
|
||||
var/id = 1
|
||||
for(var/atom/spot as anything in linked_fishing_spots)
|
||||
var/choice_name = "[spot.name] ([id])"
|
||||
fishing_list[choice_name] = spot
|
||||
id++
|
||||
var/list/choices = list()
|
||||
for(var/radial_name in fishing_list)
|
||||
var/datum/fish_source/source = fishing_list[radial_name]
|
||||
var/mutable_appearance/appearance = mutable_appearance('icons/hud/radial_fishing.dmi', source.radial_state)
|
||||
appearance.add_overlay('icons/hud/radial_fishing.dmi', "minus_sign")
|
||||
choices[radial_name] = appearance
|
||||
|
||||
var/choice = show_radial_menu(user, src, choices, radius = 38, custom_check = CALLBACK(src, TYPE_PROC_REF(/atom, can_interact), user), tooltips = TRUE)
|
||||
if(!choice)
|
||||
return
|
||||
var/atom/spot = fishing_list[choice]
|
||||
if(QDELETED(spot) || !(spot in linked_fishing_spots) || !can_interact(user))
|
||||
return
|
||||
unlink_fishing_spot(spot)
|
||||
balloon_alert(user, "fishing spot unlinked")
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/multitool_context(obj/item/source, list/context, atom/target, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
if(HAS_TRAIT(target, TRAIT_FISHING_SPOT) && !HAS_TRAIT(target, TRAIT_UNLINKABLE_FISHING_SPOT))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Link to fish-porter"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
return NONE
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/multitool_unbuffered(datum/source, datum/buffer)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(source, list(COMSIG_ITEM_REQUESTING_CONTEXT_FOR_TARGET, COMSIG_MULTITOOL_REMOVE_BUFFER))
|
||||
|
||||
///Called when using a multitool on any other fishing source.
|
||||
/obj/machinery/fishing_portal_generator/proc/link_fishing_spot(datum/fish_source/source, atom/spot, mob/living/user)
|
||||
if(istype(spot, /obj/machinery/fishing_portal_generator)) //Don't link it to itself or other fishing portals.
|
||||
return
|
||||
if(length(linked_fishing_spots) >= max_fishing_spots)
|
||||
spot.balloon_alert(user, "cannot link more!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
for(var/other_spot in linked_fishing_spots)
|
||||
var/datum/fish_source/stored = linked_fishing_spots[other_spot]
|
||||
if(stored == source)
|
||||
spot.balloon_alert(user, "already linked!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 15, FALSE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(HAS_TRAIT(spot, TRAIT_UNLINKABLE_FISHING_SPOT))
|
||||
spot.balloon_alert(user, "unlinkable fishing spot!")
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 15, FALSE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
LAZYSET(linked_fishing_spots, spot, source)
|
||||
RegisterSignal(spot, SIGNAL_REMOVETRAIT(TRAIT_FISHING_SPOT), PROC_REF(unlink_fishing_spot))
|
||||
spot.balloon_alert(user, "fishing spot linked")
|
||||
playsound(spot, 'sound/machines/ping.ogg', 15, TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/unlink_fishing_spot(atom/spot)
|
||||
SIGNAL_HANDLER
|
||||
var/datum/fish_source/source = linked_fishing_spots[spot]
|
||||
if(active?.fish_source == source)
|
||||
deactivate()
|
||||
LAZYREMOVE(linked_fishing_spots, spot)
|
||||
UnregisterSignal(spot, SIGNAL_REMOVETRAIT(TRAIT_FISHING_SPOT))
|
||||
|
||||
/obj/machinery/fishing_portal_generator/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("You can unlock further portal settings by completing fish scanning experiments.")
|
||||
. += span_notice("You can unlock further portal settings by completing fish scanning experiments, \
|
||||
or by connecting it to other fishing spots with a multitool.")
|
||||
|
||||
/obj/machinery/fishing_portal_generator/emag_act(mob/user, obj/item/card/emag/emag_card)
|
||||
if(obj_flags & EMAGGED)
|
||||
@@ -47,21 +172,78 @@
|
||||
if(!active)
|
||||
return
|
||||
. += "portal_on"
|
||||
var/datum/fish_source/portal/portal = active.fish_source
|
||||
var/datum/fish_source/portal = active.fish_source
|
||||
. += portal.overlay_state
|
||||
. += emissive_appearance(icon, "portal_emissive", src)
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/activate(datum/fish_source/selected_source)
|
||||
/obj/machinery/fishing_portal_generator/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents)
|
||||
. = ..()
|
||||
check_fishing_spot_z()
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/check_fishing_spot_z()
|
||||
if(!active || long_range_link || istype(active.fish_source, /datum/fish_source/portal))
|
||||
return
|
||||
var/turf/new_turf = get_turf(src)
|
||||
if(!new_turf)
|
||||
deactivate()
|
||||
return
|
||||
for(var/atom/spot as anything in linked_fishing_spots)
|
||||
if(linked_fishing_spots[spot] != active.fish_source)
|
||||
continue
|
||||
var/turf/turf = get_turf(spot)
|
||||
if(turf.z != new_turf.z && !(is_station_level(turf.z) && is_station_level(new_turf.z)))
|
||||
deactivate()
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/activate(datum/fish_source/selected_source, mob/user)
|
||||
if(QDELETED(selected_source))
|
||||
return
|
||||
if(machine_stat & NOPOWER)
|
||||
balloon_alert(user, "no power!")
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
if(!istype(selected_source, /datum/fish_source/portal)) //likely from a linked fishing spot
|
||||
var/abort = TRUE
|
||||
for(var/atom/spot as anything in linked_fishing_spots)
|
||||
if(linked_fishing_spots[spot] != selected_source)
|
||||
continue
|
||||
if(long_range_link)
|
||||
abort = FALSE
|
||||
var/turf/spot_turf = get_turf(spot)
|
||||
var/turf/turf = get_turf(src)
|
||||
if(turf.z == spot_turf.z || (is_station_level(turf.z) && is_station_level(spot_turf.z)))
|
||||
abort = FALSE
|
||||
if(!abort)
|
||||
RegisterSignal(spot, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_fishing_spot_z_level_changed))
|
||||
break
|
||||
if(abort)
|
||||
balloon_alert(user, "cannot reach linked!")
|
||||
return
|
||||
|
||||
active = AddComponent(/datum/component/fishing_spot, selected_source)
|
||||
ADD_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
if(use_power != NO_POWER_USE)
|
||||
use_power = ACTIVE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/deactivate()
|
||||
if(!active)
|
||||
return
|
||||
if(!istype(active.fish_source, /datum/fish_source/portal))
|
||||
for(var/atom/spot as anything in linked_fishing_spots)
|
||||
if(linked_fishing_spots[spot] == active.fish_source)
|
||||
UnregisterSignal(spot, COMSIG_MOVABLE_Z_CHANGED)
|
||||
QDEL_NULL(active)
|
||||
use_power = IDLE_POWER_USE
|
||||
|
||||
REMOVE_TRAIT(src, TRAIT_CATCH_AND_RELEASE, INNATE_TRAIT)
|
||||
update_icon()
|
||||
if(!QDELETED(src))
|
||||
if(use_power != NO_POWER_USE)
|
||||
use_power = IDLE_POWER_USE
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/fishing_portal_generator/proc/on_fishing_spot_z_level_changed(atom/spot, turf/old_turf, turf/new_turf, same_z_layer)
|
||||
SIGNAL_HANDLER
|
||||
var/turf/turf = get_turf(src)
|
||||
if(turf.z != new_turf.z && !(is_station_level(turf.z) && is_station_level(new_turf.z)))
|
||||
deactivate()
|
||||
|
||||
/obj/machinery/fishing_portal_generator/on_set_is_operational(old_value)
|
||||
if(old_value)
|
||||
@@ -90,18 +272,24 @@
|
||||
var/datum/fish_source/portal/reward = GLOB.preset_fish_sources[experiment.fish_source_reward]
|
||||
available_fish_sources[reward.radial_name] = reward
|
||||
|
||||
var/id = 1
|
||||
for(var/atom/spot as anything in linked_fishing_spots)
|
||||
var/choice_name = "[spot.name] ([id])"
|
||||
available_fish_sources[choice_name] = linked_fishing_spots[spot]
|
||||
id++
|
||||
|
||||
if(length(available_fish_sources) == 1)
|
||||
activate(default)
|
||||
activate(default, user)
|
||||
return
|
||||
var/list/choices = list()
|
||||
for(var/radial_name in available_fish_sources)
|
||||
var/datum/fish_source/portal/source = available_fish_sources[radial_name]
|
||||
var/datum/fish_source/source = available_fish_sources[radial_name]
|
||||
choices[radial_name] = image(icon = 'icons/hud/radial_fishing.dmi', icon_state = source.radial_state)
|
||||
|
||||
var/choice = show_radial_menu(user, src, choices, radius = 38, custom_check = CALLBACK(src, TYPE_PROC_REF(/atom, can_interact), user), tooltips = TRUE)
|
||||
if(!choice || !can_interact(user))
|
||||
return
|
||||
activate(available_fish_sources[choice])
|
||||
activate(available_fish_sources[choice], user)
|
||||
|
||||
/obj/machinery/fishing_portal_generator/emagged
|
||||
obj_flags = parent_type::obj_flags | EMAGGED
|
||||
|
||||
@@ -82,6 +82,10 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
var/explosive_malus = FALSE
|
||||
/// If explosive_malus is true, this will be used to keep track of the turfs where an explosion happened for when we'll spawn the loot.
|
||||
var/list/exploded_turfs
|
||||
///When linked to a fishing portal, this will be the icon_state of this option in the radial menu
|
||||
var/radial_state = "default"
|
||||
///When selected by the fishing portal, this will be the icon_state of the overlay shown on the machine.
|
||||
var/overlay_state = "portal_aquarium"
|
||||
/// Mindless mobs that can fish will never pull up items on this list
|
||||
var/static/list/profound_fisher_blacklist = typecacheof(list(
|
||||
/mob/living/basic/mining/lobstrosity,
|
||||
|
||||
@@ -106,12 +106,9 @@
|
||||
/obj/item/fish/goldfish/three_eyes = 3,
|
||||
)
|
||||
catalog_description = "Aquarium dimension (Fishing portal generator)"
|
||||
radial_state = "fish_tank"
|
||||
///The name of this option shown in the radial menu on the fishing portal generator
|
||||
var/radial_name = "Aquarium"
|
||||
///The icon state shown for this option in the radial menu
|
||||
var/radial_state = "fish_tank"
|
||||
///The icon state of the overlay shown on the machine when active.
|
||||
var/overlay_state = "portal_aquarium"
|
||||
|
||||
/datum/fish_source/portal/beach
|
||||
fish_table = list(
|
||||
@@ -404,6 +401,12 @@
|
||||
)
|
||||
fishing_difficulty = FISHING_EASY_DIFFICULTY
|
||||
|
||||
/datum/fish_source/holographic/on_fishing_spot_init(datum/component/fishing_spot/spot)
|
||||
ADD_TRAIT(spot.parent, TRAIT_UNLINKABLE_FISHING_SPOT, REF(src)) //You would have to be inside the holodeck anyway...
|
||||
|
||||
/datum/fish_source/holographic/on_fishing_spot_del(datum/component/fishing_spot/spot)
|
||||
REMOVE_TRAIT(spot.parent, TRAIT_UNLINKABLE_FISHING_SPOT, REF(src))
|
||||
|
||||
/datum/fish_source/holographic/generate_wiki_contents(datum/autowiki/fish_sources/wiki)
|
||||
var/obj/item/fish/prototype = /obj/item/fish/holo/checkered
|
||||
return LIST_VALUE_WRAP_LISTS(list(
|
||||
|
||||
Reference in New Issue
Block a user