mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 15:45:05 +01:00
249 lines
11 KiB
Plaintext
249 lines
11 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
|
|
|
|
/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++
|
|
/**
|
|
* 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
|
|
|
|
if(fish_idle_velocity)
|
|
var/idle_velocity = fish_idle_velocity
|
|
var/abs_idle_vel = abs(idle_velocity)
|
|
//Make sure idle velocity doesn't manage to halt fish to a grind and getting them unable to move.
|
|
//First, check if the directions of the two forces are oppositve
|
|
if((idle_velocity / abs_idle_vel) != (target_acceleration / abs(target_acceleration)))
|
|
//Then, calculate the ratio between absolute idle velocity and halved acceleration multiplier.
|
|
var/halved_ratio = (acceleration_mult * 0.5) / abs_idle_vel
|
|
/**
|
|
* If the idle velocity is more than half the acceleration,
|
|
* proceed to use powers, for diminishing loss of acceleration per additional unit of idle velocity.
|
|
* This way you never reach 0 acceleration while allowing more extreme values to keep lowering it.
|
|
*/
|
|
if(halved_ratio < 1)
|
|
var/power = min(halved_ratio + 0.5, 1)
|
|
target_acceleration *= 1 - (halved_ratio^power)
|
|
/**
|
|
* Otherwise we add the idle velocity (which we know is of opposite sign and
|
|
* has an absolute value between 0.ε and 0.5) to the target velocity
|
|
*/
|
|
else
|
|
target_acceleration += idle_velocity
|
|
|
|
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, -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/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)
|
|
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
|