What you wear and on what chair you sit on can now influence fishing difficulty (#86646)

## About The Pull Request
A foreword, I had to refactor a few bits of shitcode my past self added
first. For context, the "gone fishing" and "actively fishing" traits
only had one source, which is the fishing challenge itself, ad there was
no way to access the challenge from outside its code, except for a few
weakrefs which were being used as sources for the aforementioned traits
(the shitcode in a nutshell). There were also a few signals that I
didn't like because they were being sent to the harder-to-access
challenge datum rather than the user. So I scrapped the traits for a
couple signals to send to the user, then added a global list as a mean
to easily access the challenge datum, and lastly changed the code to
accomodate the titled feature (and allow the challenge to recalculate
its difficulty DURING the minigame phase)

Moving on to the actual feature: I've added a component that can be
added to objects on which mobs can be buckled to or items. When equipped
in the right slots or buckled to, the object will adjust the difficulty
of current and future fishing challenges by a certain amount (more often
than not positive, but there're many exceptions) as long as the object
isn't equipped or the user is unbuckled.

I've been having some fun adding component to a ton of clothes in the
game as well as chairs. Way too many objects to enumerate, so I'll give
you the general idea:
- each carp-themed article provides a slight positive modifier (easier)
- some (not all) doctor-related garbs provide a marginal positive
modifier each (fish doctor jokes)
- floortile camo clothes have positive modifiers
- Tuxedo, laceups, gowns provide negative modifier (more difficult)
- utility garbs such as bio/bomb/rad hoods and suits are quite bad. Riot
armor too.
- boxing gloves are very, very bad. Insulated gloves and haul gauntlets
are also very bad, to a lesser degree.
- **tackle** gloves are good. (pun intended)
- wizard garbs are good, because wizards are good at casting. (also a
pun)
- magboots slightly bad. Space suits bad.
- Blindfolds and welding protection are also bad. Gas masks marginally
bad.
- Pirate attire is nice to have. (I just vibed a little on this one)
- plastic chairs are quite versatile because they can be carried around,
but the mime chair is the best, followed by ratvarian chairs.
- Fishing toolboxes, analyzers and the fish catalog are a plus, because
they can be held.
- And the fishing hat, obviously (not as great as you'd think)

Some of these may be subject to change depending on what people say.

## Why It's Good For The Game
A hundred lines of fishing challenge code made ever-so-slightly less
awful, and a way to modify fishing diffculty beside skills and bait.

## Changelog

🆑
add: Your current clothes and what chair you sit on can now influence
the difficulty of fishing minigames. Having a bare minimum of fishing
skill will let you distinguish which objects can help and which won't,
so keep an eye out. Holding fishing toolboxes, fish analyzers or fish
catalogs can also help.
/🆑
This commit is contained in:
Ghom
2024-09-17 22:33:04 +00:00
committed by GitHub
parent f6fa3ae4a2
commit ba4fa8fe07
72 changed files with 702 additions and 83 deletions
@@ -41,7 +41,7 @@
register_item_context()
update_appearance()
AddComponent(/datum/component/adjust_fishing_difficulty, -3, ITEM_SLOT_HANDS)
/obj/item/fish_analyzer/examine(mob/user)
. = ..()
+4
View File
@@ -6,6 +6,10 @@
custom_price = PAYCHECK_CREW * 2
starting_content = "Lot of fish stuff" //book wrappers could use cleaning so this is not necessary
/obj/item/book/manual/fish_catalog/Initialize(mapload)
. = ..()
AddComponent(/datum/component/adjust_fishing_difficulty, -4, ITEM_SLOT_HANDS)
/obj/item/book/manual/fish_catalog/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
+10
View File
@@ -53,6 +53,10 @@
else
long_jump_chance *= master.difficulty
/datum/fish_movement/proc/reset_difficulty_values()
short_jump_chance = initial(short_jump_chance)
long_jump_chance = initial(long_jump_chance)
///The main proc, called by minigame every SSfishing tick while it's in the 'active' phase.
/datum/fish_movement/proc/move_fish(seconds_per_tick)
times_fired++
@@ -190,6 +194,12 @@
plunging_speed += round(plunging_speed * master.difficulty * 0.03)
fish_idle_velocity += plunging_speed //so it can be safely subtracted if the fish starts at the bottom.
/datum/fish_movement/plunger/reset_difficulty_values()
. = ..()
if(is_plunging)
fish_idle_velocity -= plunging_speed
plunging_speed = initial(plunging_speed)
/datum/fish_movement/plunger/move_fish(seconds_per_tick)
var/fish_area = FISHING_MINIGAME_AREA - master.fish_height
if(is_plunging)
@@ -288,6 +288,8 @@
inhand_icon_state = "artistic_toolbox"
material_flags = NONE
custom_price = PAYCHECK_CREW * 3
///How much holding this affects fishing difficulty
var/fishing_modifier = -2
/obj/item/storage/toolbox/fishing/Initialize(mapload)
. = ..()
@@ -296,6 +298,7 @@
/obj/item/fishing_rod,
))
atom_storage.exception_hold = exception_cache
AddComponent(/datum/component/adjust_fishing_difficulty, -2, ITEM_SLOT_HANDS)
/obj/item/storage/toolbox/fishing/PopulateContents()
new /obj/item/bait_can/worm(src)
@@ -326,6 +329,7 @@
desc = "Contains EVERYTHING (almost) you need for your fishing trip."
icon_state = "gold"
inhand_icon_state = "toolbox_gold"
fishing_modifier = -7
/obj/item/storage/toolbox/fishing/master/PopulateContents()
new /obj/item/fishing_rod/telescopic/master(src)
+52 -22
View File
@@ -32,6 +32,8 @@
///The standard pixel height of the fish (minus a pixel on each direction for the sake of a better looking sprite)
#define MINIGAME_FISH_HEIGHT 4
GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
/datum/fishing_challenge
/// When the ui minigame phase started
var/start_time
@@ -120,8 +122,10 @@
RegisterSignal(comp.fish_source, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, PROC_REF(interrupt_challenge))
comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, TYPE_PROC_REF(/datum/fish_source, roll_reward_minigame))
comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, TYPE_PROC_REF(/datum/fish_source, calculate_difficulty_minigame))
comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_COMPLETED, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
comp.fish_source.RegisterSignal(user, COMSIG_MOB_COMPLETE_FISHING, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
background = comp.fish_source.background
SEND_SIGNAL(user, COMSIG_MOB_BEGIN_FISHING, src)
GLOB.fishing_challenges_by_user[user] = src
/// Enable special parameters
if(rod.line)
@@ -148,6 +152,7 @@
completion_loss += user.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)/5
/datum/fishing_challenge/Destroy(force)
GLOB.fishing_challenges_by_user -= user
if(!completed)
complete(win = FALSE)
if(fishing_line)
@@ -192,7 +197,6 @@
active_effects = bitfield_to_list(special_effects & FISHING_MINIGAME_ACTIVE_EFFECTS)
// If fishing line breaks los / rod gets dropped / deleted
RegisterSignal(used_rod, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self))
ADD_TRAIT(user, TRAIT_GONE_FISHING, WEAKREF(src))
user.add_mood_event("fishing", /datum/mood_event/fishing)
RegisterSignal(user, COMSIG_MOB_CLICKON, PROC_REF(handle_click))
start_baiting_phase()
@@ -308,8 +312,6 @@
if(phase == MINIGAME_PHASE)
remove_minigame_hud()
if(!QDELETED(user))
UnregisterSignal(user, SIGNAL_REMOVETRAIT(TRAIT_GONE_FISHING))
user.remove_traits(list(TRAIT_GONE_FISHING, TRAIT_ACTIVELY_FISHING), WEAKREF(src))
if(start_time)
var/seconds_spent = (world.time - start_time) * 0.1
if(!(special_effects & FISHING_MINIGAME_RULE_NO_EXP))
@@ -319,7 +321,7 @@
if(win)
if(reward_path != FISHING_DUD)
playsound(location, 'sound/effects/bigsplash.ogg', 100)
SEND_SIGNAL(src, COMSIG_FISHING_CHALLENGE_COMPLETED, user, win)
SEND_SIGNAL(user, COMSIG_MOB_COMPLETE_FISHING, src, win)
if(!QDELETED(src))
qdel(src)
@@ -419,16 +421,41 @@
var/damage = CEILING((world.time - start_time)/10 * FISH_DAMAGE_PER_SECOND, 1)
reward.adjust_health(reward.health - damage)
///Get the difficulty and other variables, than start the minigame
/datum/fishing_challenge/proc/start_minigame_phase(auto_reel = FALSE)
/datum/fishing_challenge/proc/get_difficulty()
var/list/difficulty_holder = list(0)
SEND_SIGNAL(src, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, reward_path, used_rod, user, difficulty_holder)
difficulty = difficulty_holder[1]
//If you manage to be so well-equipped and skilled to completely crush the difficulty, just skip to the reward.
if(difficulty <= 0)
complete(TRUE)
return
return FALSE
difficulty = clamp(round(difficulty), FISHING_MINIMUM_DIFFICULTY, 100)
return TRUE
/datum/fishing_challenge/proc/update_difficulty()
if(phase != MINIGAME_PHASE)
return
var/old_difficulty = difficulty
//early return if the difficulty is the same or we crush the minigame all the way to 0 difficulty
if(!get_difficulty() || difficulty == old_difficulty)
return
bait_height = initial(bait_height)
experience_multiplier -= difficulty * FISHING_SKILL_DIFFIULTY_EXP_MULT
mover.reset_difficulty_values()
adjust_to_difficulty()
/datum/fishing_challenge/proc/adjust_to_difficulty()
mover.adjust_to_difficulty()
bait_height -= round(difficulty * BAIT_HEIGHT_DIFFICULTY_MALUS)
bait_pixel_height = round(MINIGAME_BAIT_HEIGHT * (bait_height/initial(bait_height)), 1)
experience_multiplier += difficulty * FISHING_SKILL_DIFFIULTY_EXP_MULT
fishing_hud.hud_bait.adjust_to_difficulty(src)
///Get the difficulty and other variables, than start the minigame
/datum/fishing_challenge/proc/start_minigame_phase(auto_reel = FALSE)
SEND_SIGNAL(user, COMSIG_MOB_BEGIN_FISHING_MINIGAME, src)
if(!get_difficulty()) //we totalized 0 or less difficulty, instant win.
return
if(difficulty > FISHING_DEFAULT_DIFFICULTY)
completion -= MAX_FISH_COMPLETION_MALUS * (difficulty * 0.01)
@@ -449,11 +476,6 @@
else
mover = new /datum/fish_movement(src)
mover.adjust_to_difficulty()
bait_height -= round(difficulty * BAIT_HEIGHT_DIFFICULTY_MALUS)
bait_pixel_height = round(MINIGAME_BAIT_HEIGHT * (bait_height/initial(bait_height)), 1)
if(auto_reel)
completion *= 1.3
else
@@ -471,11 +493,14 @@
fish_position = rand(0, (FISHING_MINIGAME_AREA - fish_height) * 0.8)
var/diff_dist = 100 + difficulty
bait_position = clamp(round(fish_position + rand(-diff_dist, diff_dist) - bait_height * 0.5), 0, FISHING_MINIGAME_AREA - bait_height)
if(!prepare_minigame_hud())
get_stack_trace("couldn't prepare minigame hud for a fishing challenge.") //just to be sure. This shouldn't happen.
qdel(src)
return
ADD_TRAIT(user, TRAIT_ACTIVELY_FISHING, WEAKREF(src))
adjust_to_difficulty()
phase = MINIGAME_PHASE
deltimer(next_phase_timer)
if((FISHING_MINIGAME_RULE_KILL in special_effects) && ispath(reward_path,/obj/item/fish))
@@ -483,7 +508,6 @@
var/wait_time = (initial(fish.health) / FISH_DAMAGE_PER_SECOND) SECONDS
addtimer(CALLBACK(src, PROC_REF(win_anyway)), wait_time, TIMER_DELETE_ME)
start_time = world.time
experience_multiplier += difficulty * FISHING_SKILL_DIFFIULTY_EXP_MULT
///Throws a stack with prefixed text.
/datum/fishing_challenge/proc/get_stack_trace(init_text)
@@ -709,18 +733,24 @@
icon = 'icons/hud/fishing_hud.dmi'
icon_state = "bait"
vis_flags = VIS_INHERIT_ID
///The stored value we used to squish the bar based on the difficulty
var/current_vertical_transform
/atom/movable/screen/hud_bait/Initialize(mapload, datum/hud/hud_owner, datum/fishing_challenge/challenge)
. = ..()
if(!challenge || challenge.bait_pixel_height == MINIGAME_BAIT_HEIGHT)
return
var/static/icon_height
if(!icon_height)
var/list/icon_dimensions = get_icon_dimensions(icon)
icon_height = icon_dimensions["height"]
var/height_percent_diff = challenge.bait_pixel_height/MINIGAME_BAIT_HEIGHT
transform = transform.Scale(1, height_percent_diff)
pixel_z = -icon_height * (1 - height_percent_diff) * 0.5
adjust_to_difficulty(challenge)
/atom/movable/screen/hud_bait/proc/adjust_to_difficulty(datum/fishing_challenge/challenge)
if(current_vertical_transform)
transform = transform.Scale(1, 1/current_vertical_transform)
pixel_z = 0
var/list/icon_dimensions = get_icon_dimensions(icon)
var/icon_height = icon_dimensions["height"]
current_vertical_transform = challenge.bait_pixel_height/MINIGAME_BAIT_HEIGHT
transform = transform.Scale(1, current_vertical_transform)
pixel_z = -icon_height * (1 - current_vertical_transform) * 0.5
/atom/movable/screen/hud_fish
icon = 'icons/hud/fishing_hud.dmi'
+3 -3
View File
@@ -79,7 +79,7 @@
/obj/item/fishing_rod/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
. = ..()
var/gone_fishing = HAS_TRAIT(user, TRAIT_GONE_FISHING)
var/gone_fishing = GLOB.fishing_challenges_by_user[user]
if(currently_hooked || gone_fishing)
context[SCREENTIP_CONTEXT_LMB] = (gone_fishing && spin_frequency) ? "Spin" : "Reel in"
if(!gone_fishing)
@@ -411,7 +411,7 @@
/// Ideally this will be replaced with generic slotted storage datum + display
/obj/item/fishing_rod/proc/use_slot(slot, mob/user, obj/item/new_item)
if(fishing_line || HAS_TRAIT(user, TRAIT_GONE_FISHING))
if(fishing_line || GLOB.fishing_challenges_by_user[user])
return
var/obj/item/current_item
switch(slot)
@@ -545,7 +545,7 @@
if(HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE))
return
//the fishing minigame uses the attack_self signal to let the user end it early without having to drop the rod.
if(HAS_TRAIT(user, TRAIT_GONE_FISHING))
if(GLOB.fishing_challenges_by_user[user])
return COMPONENT_BLOCK_TRANSFORM
///Gives feedback to the user, makes it show up inhand, toggles whether it can be used for fishing.
+9 -9
View File
@@ -222,21 +222,21 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
SEND_SIGNAL(src, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, reason)
/**
* Proc called when the COMSIG_FISHING_CHALLENGE_COMPLETED signal is sent.
* Proc called when the COMSIG_MOB_COMPLETE_FISHING signal is sent.
* Check if we've succeeded. If so, write into memory and dispense the reward.
*/
/datum/fish_source/proc/on_challenge_completed(datum/fishing_challenge/source, mob/user, success)
/datum/fish_source/proc/on_challenge_completed(mob/user, datum/fishing_challenge/challenge, success)
SIGNAL_HANDLER
SHOULD_CALL_PARENT(TRUE)
UnregisterSignal(user, COMSIG_MOB_COMPLETE_FISHING)
if(!success)
return
var/obj/item/fish/caught = source.reward_path
user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = initial(caught.name))
var/turf/fishing_spot = get_turf(source.float)
var/atom/movable/reward = dispense_reward(source.reward_path, user, fishing_spot)
if(source.used_rod)
SEND_SIGNAL(source.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user)
source.used_rod.consume_bait(reward)
var/turf/fishing_spot = get_turf(challenge.float)
var/atom/movable/reward = dispense_reward(challenge.reward_path, user, fishing_spot)
if(reward)
user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = reward.name)
SEND_SIGNAL(challenge.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user)
challenge.used_rod.consume_bait(reward)
/// Gives out the reward if possible
/datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, turf/fishing_spot)