mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-04-05 03:41:50 +01:00
Adds the capability of fishing in chasms. Chasms contain Chasm Chrabs, which are cute little crustaceans you can eat or put in an aquarium. More importantly, chasms contain everything which has ever fallen into a chasm. Falling into a chasm is no longer instant permanent round removal... as long as someone is willing to do some fishing, which means your chances of return haven't necessarily increased that much. Potential rescuers (or people lamenting about how they dropped their necropolis chest into a hole) should also beware, chasm crabs are actually young Lobstrosities and there's a rare but not insubstantial chance that you'll fish one of them up instead, which won't make it very happy. If you somehow come back to life inside a chasm (generally only likely by being a changeling or some admin interference, but perhaps you have some kind of implant which does it) you'll climb back out again, so holes are no longer a way of disposing of a changeling for good. You think The Thing would be defeated if you threw it down a hole? Ethereals can't manage this because falling into a chasm causes too much damage and they simply smash on the way down. add: You can now fish in chasms, and might manage to catch things that careless miners have dropped in there. add: If your pole is long enough to reach into a deep hole, you might catch crabs. balance: Changelings can climb out of chasms if you throw them into one. imageadd: An icon of a nice little crab, who will grow up into something less nice. add: You can craft fishing equipment from various lavaland materials, so that Ashwalkers can fish up dead miners before you. add: You can sometimes find worms while digging up tiles, if appropriate for that material.
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
|