Files
Bubberstation/code/modules/fishing/sources/_fish_source.dm
SkyratBot 3b088ec9e9 [MIRROR] Chasm Fishing [MDB IGNORE] (#15855)
* Chasm Fishing

* Update code/datums/components/chasm.dm

Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
2022-09-04 03:31:49 +01:00

202 lines
8.3 KiB
Plaintext

/// Keyed list of preset sources to configuration instance
GLOBAL_LIST_INIT(preset_fish_sources,init_fishing_configurations())
/// These are shared between their spots
/proc/init_fishing_configurations()
. = list()
var/datum/fish_source/ocean/beach/beach_preset = new
.[FISHING_SPOT_PRESET_BEACH] = beach_preset
var/datum/fish_source/lavaland/lava_preset = new
.[FISHING_SPOT_PRESET_LAVALAND_LAVA] = lava_preset
var/datum/fish_source/chasm/chasm_preset = new
.[FISHING_SPOT_PRESET_CHASM] = chasm_preset
/// Where the fish actually come from - every fishing spot has one assigned but multiple fishing holes can share single source, ie single shared one for ocean/lavaland river
/datum/fish_source
/// Fish catch weight table - these are relative weights
var/list/fish_table = list()
/// If a key from fish_table is present here, that fish is availible in limited quantity and is reduced by one on successful fishing
var/list/fish_counts = list()
/// Text shown as baloon alert when you roll a dud in the table
var/duds = list("it was nothing", "the hook is empty")
/// Baseline difficulty for fishing in this spot
var/fishing_difficulty = FISHING_DEFAULT_DIFFICULTY
/// How the spot type is described in fish catalog section about fish sources, will be skipped if null
var/catalog_description
/// Background image name from /datum/asset/simple/fishing_minigame
var/background = "fishing_background_default"
/// Can we fish in this spot at all. Returns DENIAL_REASON or null if we're good to go
/datum/fish_source/proc/can_fish(obj/item/fishing_rod/rod, mob/fisherman)
return
/// DIFFICULTY = (SPOT_BASE_VALUE + FISH_MODIFIER + ROD_MODIFIER + FAV/DISLIKED_BAIT_MODIFIER + TRAITS_ADDITIVE) * TRAITS_MULTIPLICATIVE , For non-fish it's just SPOT_BASE_VALUE
/datum/fish_source/proc/calculate_difficulty(result, obj/item/fishing_rod/rod, mob/fisherman)
. = fishing_difficulty
if(!ispath(result,/obj/item/fish))
// In the future non-fish rewards can have variable difficulty calculated here
return
var/list/fish_list_properties = collect_fish_properties()
var/obj/item/fish/caught_fish = result
// Baseline fish difficulty
. += initial(caught_fish.fishing_difficulty_modifier)
. += rod.difficulty_modifier
if(rod.bait)
var/obj/item/bait = rod.bait
//Fav bait makes it easier
var/list/fav_bait = fish_list_properties[caught_fish][NAMEOF(caught_fish, favorite_bait)]
for(var/bait_identifer in fav_bait)
if(is_matching_bait(bait, bait_identifer))
. += FAV_BAIT_DIFFICULTY_MOD
break
//Disliked bait makes it harder
var/list/disliked_bait = fish_list_properties[caught_fish][NAMEOF(caught_fish, disliked_bait)]
for(var/bait_identifer in disliked_bait)
if(is_matching_bait(bait, bait_identifer))
. += DISLIKED_BAIT_DIFFICULTY_MOD
break
// Matching/not matching fish traits and equipment
var/list/fish_traits = fish_list_properties[caught_fish][NAMEOF(caught_fish, fishing_traits)]
var/additive_mod = 0
var/multiplicative_mod = 1
for(var/fish_trait in fish_traits)
var/datum/fishing_trait/trait = new fish_trait
var/list/mod = trait.difficulty_mod(rod, fisherman)
additive_mod += mod[ADDITIVE_FISHING_MOD]
multiplicative_mod *= mod[MULTIPLICATIVE_FISHING_MOD]
. += additive_mod
. *= multiplicative_mod
/// In case you want more complex rules for specific spots
/datum/fish_source/proc/roll_reward(obj/item/fishing_rod/rod, mob/fisherman)
return pick_weight(get_modified_fish_table(rod,fisherman))
/// Gives out the reward if possible
/datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman)
if((reward_path in fish_counts)) // This is limited count result
if(fish_counts[reward_path] > 0)
fish_counts[reward_path] -= 1
else
reward_path = FISHING_DUD //Ran out of these since rolling (multiple fishermen on same source most likely)
if(ispath(reward_path))
if(ispath(reward_path,/obj/item))
var/obj/item/reward = new reward_path(get_turf(fisherman))
if(ispath(reward_path,/obj/item/fish))
var/obj/item/fish/caught_fish = reward
caught_fish.randomize_weight_and_size()
//fish caught signal if needed goes here and/or fishing achievements
//Try to put it in hand
fisherman.put_in_hands(reward)
fisherman.balloon_alert(fisherman, "caught [reward]!")
else //If someone adds fishing out carp/chests/singularities or whatever just plop it down on the fisher's turf
fisherman.balloon_alert(fisherman, "caught something!")
new reward_path(get_turf(fisherman))
else if (reward_path == FISHING_DUD)
//baloon alert instead
fisherman.balloon_alert(fisherman,pick(duds))
/// Cached fish list properties so we don't have to initalize fish every time, init deffered
GLOBAL_LIST(fishing_property_cache)
/// Awful workaround around initial(x.list_variable) not being a thing while trying to keep some semblance of being structured
/proc/collect_fish_properties()
if(GLOB.fishing_property_cache == null)
var/list/fish_property_table = list()
for(var/fish_type in subtypesof(/obj/item/fish))
var/obj/item/fish/fish = new fish_type(null)
fish_property_table[fish_type] = list()
fish_property_table[fish_type][NAMEOF(fish, favorite_bait)] = fish.favorite_bait.Copy()
fish_property_table[fish_type][NAMEOF(fish, disliked_bait)] = fish.disliked_bait.Copy()
fish_property_table[fish_type][NAMEOF(fish, fishing_traits)] = fish.fishing_traits.Copy()
QDEL_NULL(fish)
GLOB.fishing_property_cache = fish_property_table
return GLOB.fishing_property_cache
/// Checks if bait matches identifier from fav/disliked bait list
/datum/fish_source/proc/is_matching_bait(obj/item/bait, identifier)
if(ispath(identifier)) //Just a path
return istype(bait, identifier)
if(islist(identifier))
var/list/special_identifier = identifier
switch(special_identifier["Type"])
if("Foodtype")
var/obj/item/food/food_bait = bait
return istype(food_bait) && food_bait.foodtypes & special_identifier["Value"]
else
CRASH("Unknown bait identifier in fish favourite/disliked list")
else
return HAS_TRAIT(bait, identifier)
/// Builds a fish weights table modified by bait/rod/user properties
/datum/fish_source/proc/get_modified_fish_table(obj/item/fishing_rod/rod, mob/fisherman)
var/obj/item/bait = rod.bait
var/list/fish_list_properties = collect_fish_properties()
var/list/final_table = fish_table.Copy()
for(var/result in final_table)
if((result in fish_counts) && fish_counts[result] <= 0) //ran out of these, ignore
final_table -= result
continue
final_table[result] += rod.fish_bonus(result) //Decide on order here so it can be multiplicative
if(result == FISHING_DUD)
//Modify dud result
//Bait quality reduces dud chance heavily.
if(bait)
if(HAS_TRAIT(bait, GREAT_QUALITY_BAIT_TRAIT))
final_table[result] *= 0.1
else if(HAS_TRAIT(bait, GOOD_QUALITY_BAIT_TRAIT))
final_table[result] *= 0.3
else if(HAS_TRAIT(bait, BASIC_QUALITY_BAIT_TRAIT))
final_table[result] *= 0.5
else
final_table[result] *= 10 //Fishing without bait is not going to be easy
else if(ispath(result, /obj/item/fish))
//Modify fish roll chance
var/obj/item/fish/caught_fish = result
if(bait)
//Bait matching likes doubles the chance
var/list/fav_bait = fish_list_properties[result][NAMEOF(caught_fish, favorite_bait)]
for(var/bait_identifer in fav_bait)
if(is_matching_bait(bait, bait_identifer))
final_table[result] *= 2
break // could compound possibly
//Bait matching dislikes
var/list/disliked_bait = fish_list_properties[result][NAMEOF(caught_fish, disliked_bait)]
for(var/bait_identifer in disliked_bait)
if(is_matching_bait(bait, bait_identifer))
final_table[result] *= 0.5
break // same question as above
// Apply fishing trait modifiers
var/list/fish_traits = fish_list_properties[caught_fish][NAMEOF(caught_fish, fishing_traits)]
var/additive_mod = 0
var/multiplicative_mod = 1
for(var/fish_trait in fish_traits)
var/datum/fishing_trait/trait = new fish_trait
var/list/mod = trait.catch_weight_mod(rod, fisherman)
additive_mod += mod[ADDITIVE_FISHING_MOD]
multiplicative_mod *= mod[MULTIPLICATIVE_FISHING_MOD]
final_table[result] += additive_mod
final_table[result] *= multiplicative_mod
else
//Modify other paths chance
if(rod.hook && rod.hook.fishing_hook_traits & FISHING_HOOK_MAGNETIC)
final_table[result] *= 5
if(final_table[result] <= 0)
final_table -= result
return final_table