Files
Bubberstation/code/modules/fishing/bait.dm
Ghom 093bf3d978 Fishing lures box peeve (#90741)
## About The Pull Request
This fixes a small excerpt from #90678: 
>"[...] double-examining it to see what extra items it can hold
(normally all lures) only reports the Artificial Minnow as fitting."

By making it use subtypesof instead of typesof for purpose of spawning
lures and making the minnow its own subtype.

## Why It's Good For The Game
Fixing a mild botherance.

## Changelog

🆑
fix: Examining a fishing lures box twice no longer says it can hold just
artificial minnows.
/🆑
2025-04-28 15:44:14 +01:00

313 lines
12 KiB
Plaintext

/obj/item/bait_can
name = "can o bait"
desc = "there's a lot of them in there, getting them out takes a while though."
icon = 'icons/obj/fishing.dmi'
icon_state = "bait_can"
base_icon_state = "bait_can"
w_class = WEIGHT_CLASS_SMALL
/// Tracking until we can take out another bait item
COOLDOWN_DECLARE(bait_removal_cooldown)
/// What bait item it produces
var/obj/item/bait_type = /obj/item/food/bait
/// Time between bait retrievals
var/cooldown_time = 5 SECONDS
/// How many uses does it have left.
var/uses_left = 20
/obj/item/bait_can/attack_self(mob/user, modifiers)
. = ..()
var/fresh_bait = retrieve_bait(user)
if(fresh_bait)
user.put_in_hands(fresh_bait)
/obj/item/bait_can/examine(mob/user)
. = ..()
. += span_info("It[uses_left ? " has got [uses_left] [bait_type::name] left" : "'s empty"].")
/obj/item/bait_can/update_icon_state()
. = ..()
icon_state = base_icon_state
if(uses_left <= initial(uses_left))
if(!uses_left)
icon_state = "[icon_state]_empty"
else
icon_state = "[icon_state]_open"
/obj/item/bait_can/proc/retrieve_bait(mob/user)
if(!uses_left)
user.balloon_alert(user, "empty")
return
if(!COOLDOWN_FINISHED(src, bait_removal_cooldown))
user.balloon_alert(user, "wait a bit")
return
COOLDOWN_START(src, bait_removal_cooldown, cooldown_time)
update_appearance()
uses_left--
return new bait_type(src)
/obj/item/bait_can/worm
name = "can o' worm"
desc = "This can got worms."
bait_type = /obj/item/food/bait/worm
/obj/item/bait_can/worm/premium
name = "can o' worm deluxe"
desc = "This can got fancy worms."
bait_type = /obj/item/food/bait/worm/premium
/obj/item/bait_can/super_baits
name = "can o' super-baits"
desc = "This can got the nectar of god."
bait_type = /obj/item/food/bait/doughball/synthetic/super
uses_left = 12
/obj/item/fishing_lure
name = "fishing lure"
desc = "It's just that, a plastic piece of fishing equipment, yet fish yearn with every last molecule of their bodies to take a bite of it."
icon = 'icons/obj/fishing.dmi'
icon_state = "minnow"
w_class = WEIGHT_CLASS_SMALL
/**
* A list with two keys delimiting the spinning interval in which a mouse click has to be pressed while fishing.
* This is passed down to the fishing rod, and then to the lure during the minigame.
*/
var/spin_frequency = list(2 SECONDS, 3 SECONDS)
/obj/item/fishing_lure/Initialize(mapload)
. = ..()
add_traits(list(TRAIT_FISHING_BAIT, TRAIT_BAIT_ALLOW_FISHING_DUD, TRAIT_OMNI_BAIT, TRAIT_BAIT_UNCONSUMABLE), INNATE_TRAIT)
RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
/obj/item/fishing_lure/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
rod.spin_frequency = spin_frequency
/obj/item/fishing_lure/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
rod.spin_frequency = null
///Called for every fish subtype by the fishing subsystem when initializing, to populate the list of fish that can be catched with this lure.
/obj/item/fishing_lure/proc/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
return TRUE
/obj/item/fishing_lure/examine(mob/user)
. = ..()
. += span_info("It has to be spun with a frequency of [spin_frequency[1] * 0.1] to [spin_frequency[2] * 0.1] seconds while fishing.")
if(HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISHING_SPOT))
. += span_tinynotice("Thanks to your experience, you can examine it again to get a list of fish you can catch with it.")
/obj/item/fishing_lure/examine_more(mob/user)
. = ..()
if(!HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISHING_SPOT))
return
var/list/known_fishes = list()
for(var/obj/item/fish/fish_type as anything in SSfishing.lure_catchables[type])
if(initial(fish_type.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG)
known_fishes += initial(fish_type.name)
if(!length(known_fishes))
return
. += span_info("You can catch the following fish with this lure: [english_list(known_fishes)].")
///Check if the fish is in the list of catchable fish for this fishing lure. Return value is a multiplier.
/obj/item/fishing_lure/check_bait(obj/item/fish/fish)
var/multiplier = 0
var/is_instance = istype(fish)
var/list/fish_properties = SSfishing.fish_properties[is_instance ? fish.type : fish]
if(is_type_in_list(/obj/item/fishing_lure, fish_properties[FISH_PROPERTIES_FAV_BAIT]))
multiplier += 2
if(is_instance)
if(is_catchable_fish(fish, fish_properties))
multiplier += 10
else if(fish in SSfishing.lure_catchables[type])
multiplier += 10
return multiplier
/obj/item/fishing_lure/minnow
name = "artificial minnow"
desc = "A fishing lure that may attract small fish. Too tiny, too large, or too picky prey won't be interested in it, though."
icon_state = "minnow"
/obj/item/fishing_lure/minnow/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
var/intermediate_size = FISH_SIZE_SMALL_MAX + (FISH_SIZE_NORMAL_MAX - FISH_SIZE_SMALL_MAX)
if(!ISINRANGE(fish.size, FISH_SIZE_TINY_MAX * 0.5, intermediate_size))
return FALSE
if(length(list(/datum/fish_trait/vegan, /datum/fish_trait/picky_eater, /datum/fish_trait/nocturnal, /datum/fish_trait/heavy) & fish.fish_traits))
return FALSE
return TRUE
/obj/item/fishing_lure/plug
name = "artificial plug lure"
desc = "A bigger fishing lure that may attract larger fish. Tiny or picky prey will remain uninterested."
icon_state = "plug"
/obj/item/fishing_lure/plug/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(fish.size <= FISH_SIZE_SMALL_MAX)
return FALSE
if(length(list(/datum/fish_trait/vegan, /datum/fish_trait/picky_eater, /datum/fish_trait/nocturnal, /datum/fish_trait/heavy) & fish.fish_traits))
return FALSE
return TRUE
/obj/item/fishing_lure/dropping
name = "plastic dropping"
desc = "A fishing lure to catch all sort of slimy, ratty, disgusting and/or junk-loving fish."
icon_state = "dropping"
spin_frequency = list(1.5 SECONDS, 2.8 SECONDS)
/obj/item/fishing_lure/dropping/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
var/list/sources = list(/datum/fish_source/toilet, /datum/fish_source/moisture_trap)
for(var/datum/fish_source/source as anything in sources)
var/datum/fish_source/instance = GLOB.preset_fish_sources[/datum/fish_source/toilet]
if(fish.type in instance.fish_table)
return TRUE
var/list/fav_baits = fish_properties[FISH_PROPERTIES_FAV_BAIT]
for(var/list/identifier in fav_baits)
if(identifier[FISH_BAIT_TYPE] == FISH_BAIT_FOODTYPE && (identifier[FISH_BAIT_VALUE] & (JUNKFOOD|GROSS|TOXIC)))
return TRUE
if(fish.beauty <= FISH_BEAUTY_DISGUSTING)
return TRUE
return FALSE
/obj/item/fishing_lure/spoon
name = "\improper Indy spoon lure"
desc = "A lustrous piece of metal mimicking the scales of a fish. It specializes in catching small-to-medium-sized fish that live in freshwater."
icon_state = "spoon"
spin_frequency = list(1.25 SECONDS, 2.25 SECONDS)
/obj/item/fishing_lure/spoon/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(!ISINRANGE(fish.size, FISH_SIZE_TINY_MAX + 1, FISH_SIZE_NORMAL_MAX))
return FALSE
if(length(list(/datum/fish_trait/vegan, /datum/fish_trait/picky_eater, /datum/fish_trait/nocturnal, /datum/fish_trait/heavy) & fish.fish_traits))
return FALSE
var/fluid_type = fish.required_fluid_type
if(fluid_type == AQUARIUM_FLUID_FRESHWATER || fluid_type == AQUARIUM_FLUID_ANADROMOUS || fluid_type == AQUARIUM_FLUID_ANY_WATER)
return TRUE
if((/datum/fish_trait/amphibious in fish.fish_traits) && fluid_type == AQUARIUM_FLUID_AIR)
return TRUE
return FALSE
/obj/item/fishing_lure/artificial_fly
name = "\improper Silkbuzz artificial fly"
desc = "A fishing lure resembling a large wooly fly. Unlike most other lures, it's fancy enough to catch the interest of picky fish, but only those."
icon_state = "artificial_fly"
spin_frequency = list(1.1 SECONDS, 2 SECONDS)
/obj/item/fishing_lure/artificial_fly/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(/datum/fish_trait/picky_eater in fish.fish_traits)
return TRUE
return FALSE
/obj/item/fishing_lure/led
name = "\improper LED fishing lure"
desc = "A heavy, waterproof and fish-looking LED stick, specialized to catch only nocturnal and deep-dwelling fish."
icon_state = "led"
spin_frequency = list(3 SECONDS, 3.8 SECONDS)
/obj/item/fishing_lure/led/Initialize(mapload)
. = ..()
update_appearance(UPDATE_OVERLAYS)
/obj/item/fishing_lure/led/update_overlays()
. = ..()
. += emissive_appearance(icon, "led_emissive", src)
/obj/item/fishing_lure/led/on_fishing_rod_slotted(obj/item/fishing_rod/rod, slot)
. = ..()
ADD_TRAIT(rod, TRAIT_ROD_IGNORE_ENVIRONMENT, type)
/obj/item/fishing_lure/led/on_fishing_rod_unslotted(obj/item/fishing_rod/rod, slot)
. = ..()
REMOVE_TRAIT(rod, TRAIT_ROD_IGNORE_ENVIRONMENT, type)
/obj/item/fishing_lure/led/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(length(list(/datum/fish_trait/nocturnal, /datum/fish_trait/heavy) & fish.fish_traits))
return TRUE
return FALSE
/obj/item/fishing_lure/lucky_coin
name = "\improper Maneki-Coin lure"
desc = "A faux-gold lure. Catches the attention of fishies that love shinies. Not nearly tasty-looking enough for anything else."
icon_state = "lucky_coin"
spin_frequency = list(1.5 SECONDS, 2.7 SECONDS)
/obj/item/fishing_lure/lucky_coin/on_fishing_rod_slotted(obj/item/fishing_rod/rod, slot)
. = ..()
ADD_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
/obj/item/fishing_lure/lucky_coin/on_fishing_rod_unslotted(obj/item/fishing_rod/rod, slot)
. = ..()
REMOVE_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
/obj/item/fishing_lure/lucky_coin/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(/datum/fish_trait/shiny_lover in fish.fish_traits)
return TRUE
return FALSE
/obj/item/fishing_lure/algae
name = "plastic algae lure"
desc = "A soft clump of fake algae. Herbivores love it. Nothing else does, not even omnivores."
icon_state = "algae"
spin_frequency = list(3 SECONDS, 5 SECONDS)
/obj/item/fishing_lure/algae/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(/datum/fish_trait/vegan in fish.fish_traits)
return TRUE
return FALSE
/obj/item/fishing_lure/grub
name = "\improper Twister Worm lure"
desc = "A soft plastic lure with the body of a grub and a twisting tail. Specialized for catching small fish, as long as they aren't herbivores, picky, or picky herbivores."
icon_state = "grub"
spin_frequency = list(1 SECONDS, 2.7 SECONDS)
/obj/item/fishing_lure/grub/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(fish.size >= FISH_SIZE_SMALL_MAX)
return FALSE
if(length(list(/datum/fish_trait/vegan, /datum/fish_trait/picky_eater) & fish.fish_traits))
return FALSE
return TRUE
/obj/item/fishing_lure/buzzbait
name = "\improper Electric-Buzz lure"
desc = "A metallic, colored clanker attached to a series of cables that somehow attract shock-worthy fish."
icon_state = "buzzbait"
spin_frequency = list(0.8 SECONDS, 1.7 SECONDS)
/obj/item/fishing_lure/buzzbait/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(HAS_TRAIT(fish, TRAIT_FISH_ELECTROGENESIS))
return TRUE
return FALSE
/obj/item/fishing_lure/spinnerbait
name = "spinnerbait lure"
desc = "A spinny, vulnerable lure, great for attracting freshwater predators, though omnivores won't be interested in it."
icon_state = "spinnerbait"
spin_frequency = list(2 SECONDS, 4 SECONDS)
/obj/item/fishing_lure/spinnerbait/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(!(/datum/fish_trait/predator in fish.fish_traits))
return FALSE
var/init_fluid_type = fish.required_fluid_type
if(init_fluid_type == AQUARIUM_FLUID_FRESHWATER || init_fluid_type == AQUARIUM_FLUID_ANADROMOUS || init_fluid_type == AQUARIUM_FLUID_ANY_WATER)
return TRUE
if((/datum/fish_trait/amphibious in fish.fish_traits) && init_fluid_type == AQUARIUM_FLUID_AIR) //fluid type is changed to freshwater on init
return TRUE
return FALSE
/obj/item/fishing_lure/daisy_chain
name = "daisy chain lure"
desc = "A lure resembling a small school of fish. Saltwater predators love it, but not much else will."
icon_state = "daisy_chain"
spin_frequency = list(2 SECONDS, 4 SECONDS)
/obj/item/fishing_lure/daisy_chain/is_catchable_fish(obj/item/fish/fish, list/fish_properties)
if(!(/datum/fish_trait/predator in fish.fish_traits))
return FALSE
var/init_fluid_type = fish.required_fluid_type
if(init_fluid_type == AQUARIUM_FLUID_SALTWATER || init_fluid_type == AQUARIUM_FLUID_ANADROMOUS || init_fluid_type == AQUARIUM_FLUID_ANY_WATER)
return TRUE
return FALSE