mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-31 00:58:26 +01:00
Aquariums are now potential fishing spots. (#88243)
## About The Pull Request You can now fish from aquariums if you wish to. This includes some backend changes to make it possible for the fish table from get_fish_table() to contain instances, and all that it entails up to spawn_reward(), which is a requirement for the gimmick to respect the various traits and other variables of the already instantiated fish rather than read from cached properties. ## Why It's Good For The Game The fish progress score/index had only little nasty flaw that has been nagging me since day one: Not all fish species can be caught. Skipping McGill, which is a peculiar case that for cheevo purposes should be considered a standard goldfish, there is the one, unsignificant yet rare purple sludgefish which can only be gotten as a rare evolution of the generic sludgefish. Talk about petty, but this may be a long-term nit I prefer to handle right now. Also why not? The 'unmarine mastodon' is near impossible to get unless you somehow find a oil well which is locked behind a specific ruin. ## Changelog 🆑 fix: Aquariums are now potential fishing spots. /🆑
This commit is contained in:
@@ -180,16 +180,20 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
// Difficulty modifier added by the rod
|
||||
. += rod.difficulty_modifier
|
||||
|
||||
if(!ispath(result,/obj/item/fish))
|
||||
var/is_fish_instance = isfish(result)
|
||||
if(!ispath(result,/obj/item/fish) && !is_fish_instance)
|
||||
// In the future non-fish rewards can have variable difficulty calculated here
|
||||
return
|
||||
|
||||
var/obj/item/fish/caught_fish = result
|
||||
var/list/fish_properties = SSfishing.fish_properties[caught_fish]
|
||||
|
||||
//Just to clarify when we should use the path instead of the fish, which can be both a path and an instance.
|
||||
var/result_path = is_fish_instance ? caught_fish.type : result
|
||||
|
||||
// Baseline fish difficulty
|
||||
. += initial(caught_fish.fishing_difficulty_modifier)
|
||||
|
||||
|
||||
var/list/fish_properties = SSfishing.fish_properties[result_path]
|
||||
if(rod.bait)
|
||||
var/obj/item/bait = rod.bait
|
||||
//Fav bait makes it easier
|
||||
@@ -204,7 +208,11 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
. += DISLIKED_BAIT_DIFFICULTY_MOD
|
||||
|
||||
// Matching/not matching fish traits and equipment
|
||||
var/list/fish_traits = fish_properties[FISH_PROPERTIES_TRAITS]
|
||||
var/list/fish_traits
|
||||
if(is_fish_instance)
|
||||
fish_traits = caught_fish.fish_traits
|
||||
else
|
||||
fish_traits = fish_properties[FISH_PROPERTIES_TRAITS]
|
||||
|
||||
var/additive_mod = 0
|
||||
var/multiplicative_mod = 1
|
||||
@@ -217,6 +225,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
. += additive_mod
|
||||
. *= multiplicative_mod
|
||||
|
||||
|
||||
///Comsig proc from the fishing minigame for 'roll_reward'
|
||||
/datum/fish_source/proc/roll_reward_minigame(datum/source, obj/item/fishing_rod/rod, mob/fisherman, atom/location, list/rewards)
|
||||
SIGNAL_HANDLER
|
||||
@@ -265,8 +274,6 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
else if(istype(reward, /obj/effect/spawner)) // Do not attempt to forceMove() a spawner. It will break things, and the spawned item should already be at the mob's turf by now.
|
||||
fisherman.balloon_alert(fisherman, "caught something!")
|
||||
return
|
||||
else // for fishing things like corpses, move them to the turf of the fisherman
|
||||
INVOKE_ASYNC(reward, TYPE_PROC_REF(/atom/movable, forceMove), get_turf(fisherman))
|
||||
fisherman.balloon_alert(fisherman, "caught [reward]!")
|
||||
|
||||
return reward
|
||||
@@ -306,6 +313,10 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
/datum/fish_source/proc/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
|
||||
if(reward_path == FISHING_DUD)
|
||||
return
|
||||
if(ismovable(reward_path))
|
||||
var/atom/movable/reward = reward_path
|
||||
reward.forceMove(spawn_location)
|
||||
return reward
|
||||
if(ispath(reward_path, /datum/chasm_detritus))
|
||||
return GLOB.chasm_detritus_types[reward_path].dispense_detritus(spawn_location, fishing_spot)
|
||||
if(!ispath(reward_path, /atom/movable))
|
||||
@@ -317,7 +328,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
return reward
|
||||
|
||||
/// Returns the fish table, with with the unavailable items from fish_counts removed.
|
||||
/datum/fish_source/proc/get_fish_table(from_explosion = FALSE)
|
||||
/datum/fish_source/proc/get_fish_table(atom/location, from_explosion = FALSE)
|
||||
var/list/table = fish_table.Copy()
|
||||
//message bottles cannot spawn from explosions. They're meant to be one-time messages (rarely) and photos from past rounds
|
||||
//and it would suck if the pool of bottle messages were constantly being emptied by explosive fishing.
|
||||
@@ -336,8 +347,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
///Multiplier used to make fishes more common compared to everything else.
|
||||
var/result_multiplier = 1
|
||||
|
||||
|
||||
var/list/final_table = get_fish_table()
|
||||
var/list/final_table = get_fish_table(location)
|
||||
|
||||
if(bait)
|
||||
for(var/trait in weight_result_multiplier)
|
||||
@@ -357,7 +367,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
final_table[result] *= rod.hook.get_hook_bonus_multiplicative(result)
|
||||
final_table[result] += rod.hook.get_hook_bonus_additive(result)//Decide on order here so it can be multiplicative
|
||||
|
||||
if(ispath(result, /obj/item/fish))
|
||||
if(ispath(result, /obj/item/fish) || isfish(result))
|
||||
if(bait)
|
||||
final_table[result] = round(final_table[result] * result_multiplier, 1)
|
||||
var/mult = bait.check_bait(result)
|
||||
@@ -384,7 +394,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
var/highest_fish_weight
|
||||
var/list/collected_fish_weights = list()
|
||||
for(var/fishable in table)
|
||||
if(ispath(fishable, /obj/item/fish))
|
||||
if(ispath(fishable, /obj/item/fish) || isfish(fishable))
|
||||
var/fish_weight = table[fishable]
|
||||
collected_fish_weights[fishable] = fish_weight
|
||||
if(fish_weight > highest_fish_weight)
|
||||
@@ -397,30 +407,38 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
table[fish] += round(difference**exponent, 1)
|
||||
|
||||
/datum/fish_source/proc/get_fish_trait_catch_mods(weight, obj/item/fish/fish, obj/item/fishing_rod/rod, mob/user, atom/location)
|
||||
if(!ispath(fish, /obj/item/fish))
|
||||
var/is_fish_instance = isfish(fish)
|
||||
if(!ispath(fish, /obj/item/fish) && !is_fish_instance)
|
||||
return weight
|
||||
var/multiplier = 1
|
||||
for(var/fish_trait in SSfishing.fish_properties[fish][FISH_PROPERTIES_TRAITS])
|
||||
var/list/fish_traits
|
||||
if(is_fish_instance)
|
||||
fish_traits = fish.fish_traits
|
||||
else
|
||||
fish_traits = SSfishing.fish_properties[fish][FISH_PROPERTIES_TRAITS]
|
||||
for(var/fish_trait in fish_traits)
|
||||
var/datum/fish_trait/trait = GLOB.fish_traits[fish_trait]
|
||||
var/list/mod = trait.catch_weight_mod(rod, user, location, fish)
|
||||
var/list/mod = trait.catch_weight_mod(rod, user, location, is_fish_instance ? fish.type : fish)
|
||||
weight += mod[ADDITIVE_FISHING_MOD]
|
||||
multiplier *= mod[MULTIPLICATIVE_FISHING_MOD]
|
||||
|
||||
return round(weight * multiplier, 1)
|
||||
|
||||
///returns true if this fishing spot has fish that are shown in the catalog.
|
||||
/datum/fish_source/proc/has_known_fishes()
|
||||
for(var/reward in fish_table)
|
||||
if(!ispath(reward, /obj/item/fish))
|
||||
/datum/fish_source/proc/has_known_fishes(atom/location)
|
||||
var/show_anyway = fish_source_flags & FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG
|
||||
for(var/reward in get_fish_table(location))
|
||||
if(!ispath(reward, /obj/item/fish) && !isfish(reward))
|
||||
continue
|
||||
var/obj/item/fish/prototype = reward
|
||||
if(initial(prototype.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG)
|
||||
if(!show_anyway && initial(prototype.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
///Add a string with the names of catchable fishes to the examine text.
|
||||
/datum/fish_source/proc/get_catchable_fish_names(mob/user, atom/location, list/examine_text)
|
||||
var/list/known_fishes = list()
|
||||
var/show_anyway = fish_source_flags & FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG
|
||||
|
||||
var/obj/item/fishing_rod/rod = user.get_active_held_item()
|
||||
var/list/final_table
|
||||
@@ -433,17 +451,18 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
var/list/rodless_weights = list()
|
||||
var/total_rod_weight = 0
|
||||
var/list/rod_weights = list()
|
||||
for(var/reward in fish_table)
|
||||
var/weight = fish_table[reward]
|
||||
var/list/table = get_fish_table(location)
|
||||
for(var/reward in table)
|
||||
var/weight = table[reward]
|
||||
var/final_weight
|
||||
if(rod)
|
||||
total_weight += weight
|
||||
final_weight = final_table[reward]
|
||||
total_rod_weight += final_weight
|
||||
if(!ispath(reward, /obj/item/fish))
|
||||
if(!ispath(reward, /obj/item/fish) && !isfish(reward))
|
||||
continue
|
||||
var/obj/item/fish/prototype = reward
|
||||
if(!(initial(prototype.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG))
|
||||
if(!show_anyway && !(initial(prototype.fish_flags) & FISH_FLAG_SHOW_IN_CATALOG))
|
||||
continue
|
||||
if(rod)
|
||||
rodless_weights[reward] = weight
|
||||
@@ -472,7 +491,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
var/info = "You can catch the following fish here"
|
||||
|
||||
if(rod)
|
||||
info = span_tooltip("boldened are the fish you're more likely to catch with your current setup. The opposite is true for smaller names", info)
|
||||
info = span_tooltip("In bold are fish you're more likely to catch with the current setup. The opposite is true for the smaller font", info)
|
||||
examine_text += span_info("[info]: [english_list(known_fishes)].")
|
||||
|
||||
///How much the explosive_fishing_score impacts explosive fishing. The higher the value, the stronger the malus for repeated calls
|
||||
@@ -493,7 +512,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
for(var/i in 1 to (severity + 2))
|
||||
if(!prob((100 + 100 * severity)/i * multiplier))
|
||||
continue
|
||||
var/reward_loot = pick_weight(get_fish_table(from_explosion = TRUE))
|
||||
var/reward_loot = pick_weight(get_fish_table(location, from_explosion = TRUE))
|
||||
var/atom/spawn_location = isturf(location) ? location : location.drop_location()
|
||||
var/atom/movable/reward = simple_dispense_reward(reward_loot, spawn_location, location)
|
||||
if(isnull(reward))
|
||||
|
||||
@@ -698,6 +698,46 @@
|
||||
|
||||
return data
|
||||
|
||||
#define RANDOM_AQUARIUM_FISH "random_aquarium_fish"
|
||||
|
||||
/datum/fish_source/aquarium
|
||||
radial_state = "fish_tank"
|
||||
fish_table = list(
|
||||
FISHING_DUD = 10,
|
||||
)
|
||||
fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD|FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG
|
||||
fishing_difficulty = FISHING_EASY_DIFFICULTY - 5
|
||||
|
||||
#undef RANDOM_AQUARIUM_FISH
|
||||
|
||||
/datum/fish_source/aquarium/get_fish_table(atom/location, from_explosion = FALSE)
|
||||
if(istype(location, /obj/machinery/fishing_portal_generator))
|
||||
var/obj/machinery/fishing_portal_generator/portal = location
|
||||
location = portal.current_linked_atom
|
||||
var/list/table = list()
|
||||
for(var/obj/item/fish/fish in location)
|
||||
if(fish.status == FISH_DEAD) //dead fish cannot be caught
|
||||
continue
|
||||
table[fish] = 10
|
||||
if(!length(table))
|
||||
return fish_table
|
||||
return table
|
||||
|
||||
/datum/fish_source/aquarium/spawn_reward_from_explosion(atom/location, severity)
|
||||
return //If the aquarium breaks, all fish are released anyway.
|
||||
|
||||
/datum/fish_source/aquarium/generate_wiki_contents(datum/autowiki/fish_sources/wiki)
|
||||
var/list/data = list()
|
||||
|
||||
data += LIST_VALUE_WRAP_LISTS(list(
|
||||
FISH_SOURCE_AUTOWIKI_NAME = "Fish",
|
||||
FISH_SOURCE_AUTOWIKI_DUD = "",
|
||||
FISH_SOURCE_AUTOWIKI_WEIGHT = 100,
|
||||
FISH_SOURCE_AUTOWIKI_NOTES = "Any fish currently inside the aquarium, be they alive or dead.",
|
||||
))
|
||||
|
||||
return data
|
||||
|
||||
/datum/fish_source/hot_spring
|
||||
catalog_description = "Hot Springs"
|
||||
radial_state = "onsen"
|
||||
|
||||
Reference in New Issue
Block a user