mirror of
https://github.com/Skyrat-SS13/Skyrat-tg.git
synced 2026-08-28 15:27:44 +01:00
## About The Pull Request This PR mainly adds more fish and more fishing spots to the game, while refactoring a few aspects of the fishing minigame. Listing out with the new fish: - Arctic char: mainly filler content for the ice hole fishing spot - Sockeye Salmon: ditto but also provides better fillets that boost the quality of resulting food items when cooked or used in recipes - Soulfish: joke content, found by the cursed spring ruin - Skin Crab: also a joke found by the cursed spring - Bump-Fish: filler for the sand fishing spot - Burrower Crab: ditto, reusing a fish sprite I made last year - Sand Surfer: ditto - Three-Eyed Goldfish: It's a reference, doh - Stingray: A modestly weaponizable fish (whoops I've forgot to set the hit sounds), it possess a few traits that make it deliver bits of venom each time you hit someone with it - Swordfish: Huge-ass fish that may require two hands to wield (or not, if the RNG wants to make it smaller). Stats-wise, it's more or less the equivalent of the captain sabre, if not stronger (and more unwieldy due to size and weight). Becomes weaker when dead. Also gives better quality fillets. - Chainsawfish: A mutation of the goldfish with some size, weight and traits requirements, but can also be found on emagged fishing portals. Stronger than the swordfish, it behaves sort of like a chainsaw, with the similar tool behaviour and var values. Also becomes weaker when dead. As for the fishing spots, you can now fish on sand turfs, at the cursed springs or on ice. Rivers/jungle water now has its own fishing spot datum, and no longer uses the generic fishing portal one. To fish on ice, you first have to carve a hole with a pick or a shovel. I've also refactored the fish "AI" hardcoded stuff used in the fishing minigame into their own datums, which let me add a few fancier ways to how the fish moves during the minigame (i.e. the soulfish moving at 1 FPS or the chainsawfish getting faster and faster). As for the sword and chainsaw fish, their potential strength is balanced out by the need of keeping them alive, as well as the potential cumbersomeness, two-handed wielding and potential slowdown from the excessive weight of the fish (Thank you Big Slappy for the inspiration). Other minor changes include: Pufferfish giving better quality fillets (too bad they're poisonous, I'll go and make a skillchip to let cooks safely separate the poisonous liver from the fillets); McGill The lawyer's goldfish) having a 15% of being three-eyed; the aforementioned slowdown from fish weight and two-handed carry from fish size; a couple new fish icons (the ones that hint you on what you're trying to catch) for the fishing minigame; a few adjustments to prevent self-reproducing fish from ignoring the population cap and let fish with a stable population of 1 to crossbreed (also gotta make a different PR to let it happen rarely without the crossbreeding trait). This PR is still a WIP, gotta test it several times. ## Why It's Good For The Game Fishing is something I've been working on for about a year now, but there are still a few places where it's kinda lackluster, like there's not enough diverse fishing spots or useful fish (I'll be working on a separate PR to make the logistic of a carrying a fish around without letting it die a tad easier). Also, look at these sprites:  Can you guess which is which? ## Changelog For the sake of not dumping players with niche information 90% of the players won't understand, I'll keep the CL pretty generic 🆑 add: Added twelve new fish types to the game. Some are cool, other are not, some come with their own special traits and some are straight-up weapons. add: Added more fishing spots to the game. Sand, ice, rivers, the cursed spring... balance: A few fish like salmon, swordfish and pufferfish (poisonous btw) now give better quality fillets when butchered, which can improve the quality of food that uses them even further. balance: Excessive fish weight will make the fish slowier to carry, while excessive size may make it require two hands. balance: Adjusted size, weight and cooldowns of several fish, for the better. /🆑
215 lines
9.2 KiB
Plaintext
215 lines
9.2 KiB
Plaintext
/// Any lower than this, and the target position of the fish is considered null
|
|
#define FISH_TARGET_MIN_DISTANCE 6
|
|
/// The friction applied to fish jumps, so that it decelerates over time
|
|
#define FISH_FRICTION_MULT 0.9
|
|
/// Used to decide whether the fish can jump in a certain direction
|
|
#define FISH_SHORT_JUMP_MIN_DISTANCE 100
|
|
/// The maximum distance for a short jump
|
|
#define FISH_SHORT_JUMP_MAX_DISTANCE 200
|
|
|
|
///Fish movements are simple datums, generated by the fishing minigame, that represent how the fish moves suring the minigame.
|
|
/datum/fish_movement
|
|
/// The minigame that spawned us
|
|
var/datum/fishing_challenge/master
|
|
/// How many times move_fish() has been called
|
|
var/times_fired = 0
|
|
/// How likely the fish is to perform a standard jump, then multiplied by difficulty
|
|
var/short_jump_chance = 2.25
|
|
/// How likely the fish is to perform a long jump, then multiplied by difficulty
|
|
var/long_jump_chance = 0.0625
|
|
/// The speed limit for the short jump
|
|
var/short_jump_velocity_limit = 400
|
|
/// The speed limit for the long jump
|
|
var/long_jump_velocity_limit = 200
|
|
/// The current speed limit used
|
|
var/current_velocity_limit
|
|
/// The base velocity of the fish, which may affect jump distances and falling speed.
|
|
var/fish_idle_velocity = 0
|
|
/// A position on the slider the fish wants to get to
|
|
var/target_position
|
|
/// If true, the fish can jump while a target position is set, thus overriding it
|
|
var/can_interrupt_move = TRUE
|
|
/// The current speed the fish is moving at
|
|
var/fish_velocity = 0
|
|
|
|
/datum/fish_movement/New(datum/fishing_challenge/master)
|
|
src.master = master
|
|
|
|
/**
|
|
* Proc that adjusts movement values to the difficulty of the minigame.
|
|
* The operations can be a tad complex, but basically it ensures that jump
|
|
* chances with a probability higher than 1% increase in a smooth curve so that
|
|
* they still reach 100% prob when the difficulty peakes.
|
|
*/
|
|
/datum/fish_movement/proc/adjust_to_difficulty()
|
|
var/square_angle_rad = TORADIANS(90)
|
|
var/zero_one_difficulty = master.difficulty/100
|
|
if(short_jump_chance > 1)
|
|
short_jump_chance = (zero_one_difficulty**(square_angle_rad-TORADIANS(arctan(short_jump_chance * 1/square_angle_rad))))*100
|
|
else
|
|
short_jump_chance *= master.difficulty
|
|
if(long_jump_chance > 1)
|
|
long_jump_chance = (zero_one_difficulty**(square_angle_rad-TORADIANS(arctan(long_jump_chance * 1/square_angle_rad))))*100
|
|
else
|
|
long_jump_chance *= master.difficulty
|
|
|
|
///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++
|
|
/**
|
|
* The jump chances are meant to run every odd tick (each every decisecond)
|
|
* We cannot do it every tick because the fish would be jumpier than intended
|
|
* and we cannot cut the chances in half to fit on each tick, because the maximum probability
|
|
* would go from 100% to 75%.
|
|
*/
|
|
var/can_roll = times_fired % 2
|
|
|
|
var/long_chance = long_jump_chance * seconds_per_tick * (1/seconds_per_tick)
|
|
var/short_chance = short_jump_chance * seconds_per_tick * (1/seconds_per_tick)
|
|
|
|
// If we have the target but we're close enough, mark as target reached
|
|
if(abs(target_position - master.fish_position) < FISH_TARGET_MIN_DISTANCE)
|
|
target_position = null
|
|
|
|
// Switching to new long jump target can interrupt any other
|
|
if(can_roll && (can_interrupt_move || isnull(target_position)) && prob(long_chance))
|
|
/**
|
|
* Move at least 0.75 to full of the availible bar in given direction,
|
|
* and more likely to move in the direction where there's more space
|
|
*/
|
|
var/distance_from_top = FISHING_MINIGAME_AREA - master.fish_position - master.fish_height
|
|
var/distance_from_bottom = master.fish_position
|
|
var/top_chance
|
|
if(distance_from_top < FISH_SHORT_JUMP_MIN_DISTANCE)
|
|
top_chance = 0
|
|
else
|
|
top_chance = (distance_from_top/max(distance_from_bottom, 1)) * 100
|
|
var/new_target = master.fish_position
|
|
if(prob(top_chance))
|
|
new_target += distance_from_top * rand(75, 100)/100
|
|
else
|
|
new_target -= distance_from_bottom * rand(75, 100)/100
|
|
target_position = round(new_target)
|
|
current_velocity_limit = long_jump_velocity_limit
|
|
|
|
// Move towards target
|
|
if(!isnull(target_position))
|
|
var/distance = target_position - master.fish_position
|
|
// about 5 at diff 15 , 10 at diff 30, 30 at diff 100
|
|
var/acceleration_mult = get_acceleration(seconds_per_tick)
|
|
var/target_acceleration = distance * acceleration_mult * seconds_per_tick
|
|
|
|
fish_velocity = fish_velocity * FISH_FRICTION_MULT + target_acceleration
|
|
else if(can_roll && prob(short_chance))
|
|
var/distance_from_top = FISHING_MINIGAME_AREA - master.fish_position - master.fish_height
|
|
var/distance_from_bottom = master.fish_position
|
|
var/jump_length
|
|
if(distance_from_top >= FISH_SHORT_JUMP_MIN_DISTANCE)
|
|
jump_length = rand(FISH_SHORT_JUMP_MIN_DISTANCE, FISH_SHORT_JUMP_MAX_DISTANCE)
|
|
if(distance_from_bottom >= FISH_SHORT_JUMP_MIN_DISTANCE && (!jump_length || prob(50)))
|
|
jump_length = -rand(FISH_SHORT_JUMP_MIN_DISTANCE, FISH_SHORT_JUMP_MAX_DISTANCE)
|
|
target_position = clamp(master.fish_position + jump_length, 0, FISHING_MINIGAME_AREA - master.fish_height)
|
|
current_velocity_limit = short_jump_velocity_limit
|
|
|
|
fish_velocity = clamp(fish_velocity + fish_idle_velocity, -current_velocity_limit, current_velocity_limit)
|
|
set_fish_position(seconds_per_tick)
|
|
|
|
///Proc that returns the acceleration of the fish during the minigame.
|
|
/datum/fish_movement/proc/get_acceleration(seconds_per_tick)
|
|
return 0.3 * master.difficulty + 0.5
|
|
|
|
///Called at the end of move_fish(), for updating the position of the fish in the fishing minigame.
|
|
/datum/fish_movement/proc/set_fish_position(seconds_per_tick)
|
|
master.fish_position = clamp(master.fish_position + fish_velocity * seconds_per_tick, 0, FISHING_MINIGAME_AREA - master.fish_height)
|
|
|
|
///Generic fish movement datum that only performs slow, uninterrupted long jumps
|
|
/datum/fish_movement/slow
|
|
short_jump_chance = 0
|
|
long_jump_chance = 1.5
|
|
long_jump_velocity_limit = 150
|
|
can_interrupt_move = FALSE
|
|
|
|
///Generic fish movement datum with triple the short jump chance.
|
|
/datum/fish_movement/zippy
|
|
short_jump_chance = parent_type::short_jump_chance * 3
|
|
|
|
///fish movement datum that progressively gets faster until acceleration and velocity are double the starting ones.
|
|
/datum/fish_movement/accelerando
|
|
///The jump velocity to add each tick
|
|
var/short_jump_vel_add
|
|
///The long jump velocity to add each tick
|
|
var/long_jump_vel_add
|
|
///Time to reach full speed, in seconds.
|
|
var/accel_time_cap = 30
|
|
|
|
/datum/fish_movement/accelerando/move_fish(seconds_per_tick)
|
|
var/seconds_elapsed = (times_fired * seconds_per_tick)
|
|
if(seconds_elapsed >= accel_time_cap)
|
|
return ..()
|
|
if(!times_fired) //First tick, cache the initial jump velocities
|
|
short_jump_vel_add = short_jump_velocity_limit/accel_time_cap
|
|
long_jump_vel_add = long_jump_velocity_limit/accel_time_cap
|
|
return ..()
|
|
|
|
if(current_velocity_limit)
|
|
var/vel_add = current_velocity_limit == short_jump_velocity_limit ? short_jump_vel_add : long_jump_vel_add
|
|
current_velocity_limit += round(vel_add * seconds_per_tick, 0.01)
|
|
|
|
short_jump_velocity_limit += round(short_jump_vel_add * seconds_per_tick, 0.01)
|
|
long_jump_velocity_limit += round(long_jump_vel_add * seconds_per_tick, 0.01)
|
|
return ..()
|
|
|
|
/datum/fish_movement/accelerando/get_acceleration(seconds_per_tick)
|
|
var/acceleration = ..()
|
|
return acceleration + min(acceleration, acceleration * times_fired * seconds_per_tick / accel_time_cap)
|
|
|
|
/datum/fish_movement/accelerando/set_fish_position(seconds_per_tick)
|
|
fish_velocity = round(fish_velocity)
|
|
return ..()
|
|
|
|
///Fish movement datum that updates the fish position twice per second.
|
|
/datum/fish_movement/choppy
|
|
///We keep of the theorical fish position to eventually use
|
|
var/faux_position = 0
|
|
|
|
/datum/fish_movement/choppy/set_fish_position(seconds_per_tick)
|
|
faux_position = clamp(faux_position + fish_velocity * seconds_per_tick, 0, FISHING_MINIGAME_AREA - master.fish_height)
|
|
if(!((times_fired * SSfishing.wait) % (0.5 SECONDS)))
|
|
master.fish_position = faux_position
|
|
|
|
///Fish movement datum that weakly pushes the fish up and then down with greater force once it reaches the top of the minigame.
|
|
/datum/fish_movement/plunger
|
|
///Is the fish plunging to the bottom of the minigame area, or should it swim up?
|
|
var/is_plunging = TRUE
|
|
///The added idle velocity when plunging
|
|
var/plunging_speed = -22
|
|
|
|
/datum/fish_movement/plunger/adjust_to_difficulty()
|
|
. = ..()
|
|
//Adjust the fleeing velocity, up to five times the initial value.
|
|
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/move_fish(seconds_per_tick)
|
|
var/fish_area = FISHING_MINIGAME_AREA - master.fish_height
|
|
if(is_plunging)
|
|
if(target_position > master.fish_position) //nothing should stop us from plunging.
|
|
target_position = null
|
|
var/dist_bot_percent = master.fish_position/fish_area
|
|
if(dist_bot_percent <= 0.04)
|
|
fish_idle_velocity -= plunging_speed
|
|
is_plunging = FALSE
|
|
else
|
|
var/dist_top_percent = (fish_area - master.fish_position)/fish_area
|
|
if(dist_top_percent <= 0.04)
|
|
fish_idle_velocity += plunging_speed
|
|
is_plunging = TRUE
|
|
|
|
return ..()
|
|
|
|
|
|
#undef FISH_TARGET_MIN_DISTANCE
|
|
#undef FISH_FRICTION_MULT
|
|
#undef FISH_SHORT_JUMP_MIN_DISTANCE
|
|
#undef FISH_SHORT_JUMP_MAX_DISTANCE
|