mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +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:
@@ -194,6 +194,8 @@
|
||||
#define COMSIG_TOOL_IN_USE "tool_in_use"
|
||||
///from base of [/obj/item/proc/tool_start_check]: (mob/living/user)
|
||||
#define COMSIG_TOOL_START_USE "tool_start_use"
|
||||
/// From /obj/item/multitool/remove_buffer(): (buffer)
|
||||
#define COMSIG_MULTITOOL_REMOVE_BUFFER "multitool_remove_buffer"
|
||||
///from [/obj/item/proc/disableEmbedding]:
|
||||
#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed"
|
||||
///from [/obj/effect/mine/proc/triggermine]:
|
||||
|
||||
@@ -239,6 +239,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_EXAMINE_DEEPER_FISH "examine_deeper_fish"
|
||||
///Trait given to turfs or objects that can be fished from
|
||||
#define TRAIT_FISHING_SPOT "fishing_spot"
|
||||
///This trait prevents the fishing spot from being linked to the fish-porter when a multitool is being used.
|
||||
#define TRAIT_UNLINKABLE_FISHING_SPOT "unlinkable_fishing_spot"
|
||||
///Trait given to mobs that can fish without a rod
|
||||
#define TRAIT_PROFOUND_FISHER "profound_fisher"
|
||||
/// If an atom has this trait, then you can toss a bottle with a message in it.
|
||||
|
||||
@@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_DO_NOT_SPLASH" = TRAIT_DO_NOT_SPLASH,
|
||||
"TRAIT_DRIED" = TRAIT_DRIED,
|
||||
"TRAIT_DRYABLE" = TRAIT_DRYABLE,
|
||||
"TRAIT_FISHING_SPOT" = TRAIT_FISHING_SPOT,
|
||||
"TRAIT_FOOD_CHEF_MADE" = TRAIT_FOOD_CHEF_MADE,
|
||||
"TRAIT_FOOD_FRIED" = TRAIT_FOOD_FRIED,
|
||||
"TRAIT_QUALITY_FOOD_INGREDIENT" = TRAIT_QUALITY_FOOD_INGREDIENT,
|
||||
@@ -30,6 +31,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_SPINNING" = TRAIT_SPINNING,
|
||||
"TRAIT_STICKERED" = TRAIT_STICKERED,
|
||||
"TRAIT_UNHITTABLE_BY_PROJECTILES" = TRAIT_UNHITTABLE_BY_PROJECTILES,
|
||||
"TRAIT_UNLINKABLE_FISHING_SPOT" = TRAIT_UNLINKABLE_FISHING_SPOT,
|
||||
),
|
||||
/atom/movable = list(
|
||||
"TRAIT_ACTIVE_STORAGE" = TRAIT_ACTIVE_STORAGE,
|
||||
@@ -676,7 +678,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_CONTAINMENT_FIELD" = TRAIT_CONTAINMENT_FIELD,
|
||||
"TRAIT_ELEVATED_TURF" = TRAIT_ELEVATED_TURF,
|
||||
"TRAIT_FIREDOOR_STOP" = TRAIT_FIREDOOR_STOP,
|
||||
"TRAIT_FISHING_SPOT" = TRAIT_FISHING_SPOT,
|
||||
"TRAIT_HYPERSPACE_STOPPED" = TRAIT_HYPERSPACE_STOPPED,
|
||||
"TRAIT_IMMERSE_STOPPED" = TRAIT_IMMERSE_STOPPED,
|
||||
"TRAIT_LAVA_STOPPED" = TRAIT_LAVA_STOPPED,
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
RegisterSignal(parent, COMSIG_NPC_FISHING, PROC_REF(return_fishing_spot))
|
||||
RegisterSignal(parent, COMSIG_ATOM_EX_ACT, PROC_REF(explosive_fishing))
|
||||
RegisterSignal(parent, COMSIG_FISH_RELEASED_INTO, PROC_REF(fish_released))
|
||||
RegisterSignal(parent, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(link_to_fish_porter))
|
||||
ADD_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src))
|
||||
|
||||
/datum/component/fishing_spot/Destroy()
|
||||
REMOVE_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src))
|
||||
fish_source.on_fishing_spot_del(src)
|
||||
fish_source = null
|
||||
REMOVE_TRAIT(parent, TRAIT_FISHING_SPOT, REF(src))
|
||||
@@ -84,6 +86,12 @@
|
||||
SIGNAL_HANDLER
|
||||
fish_source.spawn_reward_from_explosion(location, severity)
|
||||
|
||||
/datum/component/fishing_spot/proc/link_to_fish_porter(atom/source, mob/user, obj/item/multitool/tool)
|
||||
SIGNAL_HANDLER
|
||||
if(istype(tool.buffer, /obj/machinery/fishing_portal_generator))
|
||||
var/obj/machinery/fishing_portal_generator/portal = tool.buffer
|
||||
return portal.link_fishing_spot(fish_source, source, user)
|
||||
|
||||
/datum/component/fishing_spot/proc/fish_released(datum/source, obj/item/fish/fish, mob/living/releaser)
|
||||
SIGNAL_HANDLER
|
||||
fish_source.readd_fish(fish, releaser)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
RegisterSignal(target, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_examined_more))
|
||||
RegisterSignal(target, COMSIG_ATOM_EX_ACT, PROC_REF(explosive_fishing))
|
||||
RegisterSignal(target, COMSIG_FISH_RELEASED_INTO, PROC_REF(fish_released))
|
||||
RegisterSignal(target, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(link_to_fish_porter))
|
||||
|
||||
/datum/element/lazy_fishing_spot/Detach(datum/target)
|
||||
UnregisterSignal(target, list(
|
||||
@@ -30,6 +31,7 @@
|
||||
COMSIG_ATOM_EXAMINE,
|
||||
COMSIG_ATOM_EXAMINE_MORE,
|
||||
COMSIG_ATOM_EX_ACT,
|
||||
COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL),
|
||||
))
|
||||
REMOVE_TRAIT(target, TRAIT_FISHING_SPOT, REF(src))
|
||||
return ..()
|
||||
@@ -69,6 +71,14 @@
|
||||
/datum/element/lazy_fishing_spot/proc/return_glob_fishing_spot(datum/source, list/fish_spot_container)
|
||||
fish_spot_container[NPC_FISHING_SPOT] = GLOB.preset_fish_sources[configuration]
|
||||
|
||||
/datum/element/lazy_fishing_spot/proc/link_to_fish_porter(atom/source, mob/user, obj/item/multitool/tool)
|
||||
SIGNAL_HANDLER
|
||||
if(!istype(tool.buffer, /obj/machinery/fishing_portal_generator))
|
||||
return
|
||||
var/datum/fish_source/fish_source = GLOB.preset_fish_sources[configuration]
|
||||
var/obj/machinery/fishing_portal_generator/portal = tool.buffer
|
||||
return portal.link_fishing_spot(fish_source, source, user)
|
||||
|
||||
/datum/element/lazy_fishing_spot/proc/fish_released(datum/source, obj/item/fish/fish, mob/living/releaser)
|
||||
SIGNAL_HANDLER
|
||||
var/datum/fish_source/fish_source = GLOB.preset_fish_sources[configuration]
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
var/apc_scanner = TRUE
|
||||
COOLDOWN_DECLARE(next_apc_scan)
|
||||
|
||||
/obj/item/multitool/Destroy()
|
||||
if(buffer)
|
||||
remove_buffer(buffer)
|
||||
return ..()
|
||||
|
||||
/obj/item/multitool/examine(mob/user)
|
||||
. = ..()
|
||||
. += span_notice("Its buffer [buffer ? "contains [buffer]." : "is empty."]")
|
||||
@@ -70,9 +75,10 @@
|
||||
/obj/item/multitool/proc/set_buffer(datum/buffer)
|
||||
if(src.buffer)
|
||||
UnregisterSignal(src.buffer, COMSIG_QDELETING)
|
||||
remove_buffer(src.buffer)
|
||||
src.buffer = buffer
|
||||
if(!QDELETED(buffer))
|
||||
RegisterSignal(buffer, COMSIG_QDELETING, PROC_REF(on_buffer_del))
|
||||
RegisterSignal(buffer, COMSIG_QDELETING, PROC_REF(remove_buffer))
|
||||
|
||||
/**
|
||||
* Called when the buffer's stored object is deleted
|
||||
@@ -80,8 +86,9 @@
|
||||
* This proc does not clear the buffer of the multitool, it is here to
|
||||
* handle the deletion of the object the buffer references
|
||||
*/
|
||||
/obj/item/multitool/proc/on_buffer_del(datum/source)
|
||||
/obj/item/multitool/proc/remove_buffer(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
SEND_SIGNAL(src, COMSIG_MULTITOOL_REMOVE_BUFFER, source)
|
||||
buffer = null
|
||||
|
||||
// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -190,6 +190,54 @@
|
||||
. = ..()
|
||||
probability = 0 //works around the global list initialization skipping abstract/impossible evolutions.
|
||||
|
||||
///A test that checks that fishing portals can be linked and function as expected
|
||||
/datum/unit_test/fish_portal_gen_linking
|
||||
|
||||
/datum/unit_test/fish_portal_gen_linking/Run()
|
||||
var/mob/living/carbon/human/consistent/user = allocate(/mob/living/carbon/human/consistent)
|
||||
var/obj/machinery/fishing_portal_generator/portal = allocate(/obj/machinery/fishing_portal_generator/no_power)
|
||||
var/obj/structure/toilet/unit_test/fishing_spot = new(get_turf(user)) //This is deleted during the test
|
||||
var/obj/structure/moisture_trap/extra_spot = allocate(/obj/structure/moisture_trap)
|
||||
var/obj/machinery/hydroponics/constructable/inaccessible = allocate(/obj/machinery/hydroponics/constructable)
|
||||
ADD_TRAIT(inaccessible, TRAIT_UNLINKABLE_FISHING_SPOT, INNATE_TRAIT)
|
||||
var/obj/item/multitool/tool = allocate(/obj/item/multitool)
|
||||
var/datum/fish_source/toilet/fish_source = GLOB.preset_fish_sources[/datum/fish_source/toilet]
|
||||
|
||||
portal.max_fishing_spots = 1 //We've no scrying orb to know if it'll be buffed or nerfed this in the future. We only have space for one here.
|
||||
portal.activate(fish_source, user)
|
||||
TEST_ASSERT(!portal.active, "[portal] was activated with a fish source from an unlinked fishing spot")
|
||||
portal.multitool_act(user, tool)
|
||||
TEST_ASSERT_EQUAL(tool.buffer, portal, "[portal] wasn't set as buffer for [tool]")
|
||||
tool.melee_attack_chain(user, fishing_spot)
|
||||
TEST_ASSERT_EQUAL(LAZYACCESS(portal.linked_fishing_spots, fishing_spot), fish_source, "We tried linking [portal] to the fishing spot but didn't succeed.")
|
||||
portal.activate(fish_source, user)
|
||||
TEST_ASSERT(portal.active?.fish_source == fish_source, "[portal] can't acces a fish source from a linked fishing spot")
|
||||
//Let's move the fishing spot away. This is fine as long as the portal moves to another z level, away from the toilet
|
||||
var/turf/other_z_turf = pick(GLOB.newplayer_start)
|
||||
portal.forceMove(other_z_turf)
|
||||
TEST_ASSERT(!portal.active, "[portal] (not upgraded) is still active though the fishing spot is on another z-level.[portal.z == fishing_spot.z ? " Actually they're still on the same level!" : ""]")
|
||||
portal.long_range_link = TRUE
|
||||
portal.activate(fish_source, user)
|
||||
TEST_ASSERT(portal.active?.fish_source == fish_source, "[portal] can't acces a fish source from a linked fishing spot on a different z-level despite being upgraded")
|
||||
fishing_spot.forceMove(other_z_turf)
|
||||
portal.forceMove(get_turf(user))
|
||||
TEST_ASSERT(portal.active?.fish_source == fish_source, "[portal] (upgraded) deactivated while changing z-level")
|
||||
tool.melee_attack_chain(user, extra_spot)
|
||||
TEST_ASSERT_EQUAL(length(portal.linked_fishing_spots), 1, "We managed to link to another fishing spot when there's only space for one")
|
||||
TEST_ASSERT_EQUAL(LAZYACCESS(portal.linked_fishing_spots, fishing_spot), fish_source, "linking to another fishing spot fouled up the other linked spots")
|
||||
QDEL_NULL(fishing_spot)
|
||||
TEST_ASSERT(!portal.active, "[portal] is still linked to the fish source of the deleted fishing spot it's associated to")
|
||||
tool.melee_attack_chain(user, inaccessible)
|
||||
TEST_ASSERT(!length(portal.linked_fishing_spots), "We managed to link to an unlinkable fishing spot")
|
||||
|
||||
/obj/machinery/fishing_portal_generator/no_power
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
/obj/structure/toilet/unit_test/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!HAS_TRAIT(src, TRAIT_FISHING_SPOT)) //Ensure this toilet has a fishing spot because only maploaded ones have it.
|
||||
AddElement(/datum/element/lazy_fishing_spot, /datum/fish_source/toilet)
|
||||
|
||||
// we want no default spawns in this unit test
|
||||
/datum/chasm_detritus/restricted/bodies/no_defaults
|
||||
default_contents_chance = 0
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -15,6 +15,8 @@ You may find worms by digging through sand, ash and snow.
|
||||
You can revive fish by using a Lazarus Injector on them. However, using Strange Reagent would be a smarter option here.
|
||||
You can feed fish outside of an aquarium by tapping them with a can of fish feed.
|
||||
More fishing rods and fish cases can be printed at the autolathe.
|
||||
You can link the fish portal generator to other fishing spots with a multitool. The maximum amount of fishing spots that can be linked and whether or not the link works on different z-levels depends on the quality of the machinery components.
|
||||
The actual name of the fishing portal generator is 'fish-porter 3000'. They're totally the same thing however.
|
||||
Seeking alternative ways to catch fish without bothering to do it yourself? Explosives can be thrown at fishing spots to get several (dead) fishes in a pinch.
|
||||
You can raise lobstrosities from chasm chrabs. However, lobstrosities can only be tamed with spare limbs or lavaloop fish while still young.
|
||||
Lavaloop fish make for dangerous yet somewhat effective throwing weapons against big fauna.
|
||||
|
||||
Reference in New Issue
Block a user