mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-28 10:01:58 +00:00
* 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>
202 lines
8.3 KiB
Plaintext
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
|