mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-25 06:00:16 +01:00
Fishing expansion 2: one-year later boogaloo (#85252)
## 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. /🆑
This commit is contained in:
@@ -399,9 +399,13 @@
|
||||
new /obj/item/aquarium_prop/sand(src)
|
||||
new /obj/item/aquarium_prop/seaweed(src)
|
||||
|
||||
new /obj/item/fish/goldfish/gill(src)
|
||||
if(prob(85))
|
||||
new /obj/item/fish/goldfish/gill(src)
|
||||
reagents.add_reagent(/datum/reagent/consumable/nutriment, 2)
|
||||
else
|
||||
new /obj/item/fish/three_eyes/gill(src)
|
||||
reagents.add_reagent(/datum/reagent/toxin/mutagen, 2) //three eyes goldfish feed on mutagen.
|
||||
|
||||
reagents.add_reagent(/datum/reagent/consumable/nutriment, 2)
|
||||
|
||||
/obj/structure/aquarium/prefilled
|
||||
anchored = TRUE
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
name = "ominous fish case"
|
||||
|
||||
/obj/item/storage/fish_case/syndicate/get_fish_type()
|
||||
return pick(/obj/item/fish/donkfish, /obj/item/fish/emulsijack, /obj/item/fish/jumpercable)
|
||||
return pick(/obj/item/fish/donkfish, /obj/item/fish/emulsijack, /obj/item/fish/jumpercable, /obj/item/fish/chainsawfish)
|
||||
|
||||
/obj/item/storage/fish_case/tiziran
|
||||
name = "imported fish case"
|
||||
|
||||
@@ -61,3 +61,21 @@
|
||||
bait_type = /obj/item/food/bait/doughball/synthetic/super
|
||||
uses_left = 12
|
||||
|
||||
|
||||
/// Helper proc that checks if a bait matches identifier from fav/disliked bait list
|
||||
/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"]
|
||||
if("Reagent")
|
||||
return bait.reagents?.has_reagent(special_identifier["Value"], special_identifier["Amount"], check_subtypes = TRUE)
|
||||
else
|
||||
CRASH("Unknown bait identifier in fish favourite/disliked list")
|
||||
else
|
||||
return HAS_TRAIT(bait, identifier)
|
||||
|
||||
|
||||
@@ -6,17 +6,19 @@
|
||||
icon_state = "bugfish"
|
||||
lefthand_file = 'icons/mob/inhands/fish_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/fish_righthand.dmi'
|
||||
inhand_icon_state = "fish_normal"
|
||||
force = 6
|
||||
throwforce = 6
|
||||
throw_range = 8
|
||||
attack_verb_continuous = list("slaps", "whacks")
|
||||
attack_verb_simple = list("slap", "whack")
|
||||
hitsound = 'sound/weapons/slap.ogg'
|
||||
///The grind results of the fish. They scale with the weight of the fish.
|
||||
grind_results = list(/datum/reagent/blood = 5, /datum/reagent/consumable/liquidgibs = 5)
|
||||
obj_flags = UNIQUE_RENAME
|
||||
item_flags = IMMUTABLE_SLOW|SLOWS_WHILE_IN_HAND
|
||||
|
||||
/// Resulting width of aquarium visual icon - default size of "fish_greyscale" state
|
||||
var/sprite_width = 3
|
||||
var/sprite_width = 5
|
||||
/// Resulting height of aquarium visual icon - default size of "fish_greyscale" state
|
||||
var/sprite_height = 3
|
||||
|
||||
@@ -93,8 +95,8 @@
|
||||
*/
|
||||
var/list/fish_traits = list()
|
||||
|
||||
/// Fishing behaviour
|
||||
var/fish_ai_type = FISH_AI_DUMB
|
||||
/// path to datums that dictate how the fish moves during the fishing minigame
|
||||
var/fish_movement_type = /datum/fish_movement
|
||||
|
||||
/// Base additive modifier to fishing difficulty
|
||||
var/fishing_difficulty_modifier = 0
|
||||
@@ -121,6 +123,9 @@
|
||||
/// Average weight for this fish type in grams
|
||||
var/average_weight = 1000
|
||||
|
||||
///The general deviation from the average weight and size this fish has in the wild
|
||||
var/weight_size_deviation = 0.2
|
||||
|
||||
/// When outside of an aquarium, these gases that are checked (as well as pressure and temp) to assert if the environment is safe or not.
|
||||
var/list/safe_air_limits = list(
|
||||
/datum/gas/oxygen = list(12, 100),
|
||||
@@ -203,7 +208,7 @@
|
||||
. += span_notice("It weighs [weight] g.")
|
||||
|
||||
///Randomizes weight and size.
|
||||
/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = 0.2)
|
||||
/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = weight_size_deviation)
|
||||
var/size_deviation = 0.2 * base_size
|
||||
var/new_size = round(clamp(gaussian(base_size, size_deviation), average_size * 1/MAX_FISH_DEVIATION_COEFF, average_size * MAX_FISH_DEVIATION_COEFF))
|
||||
|
||||
@@ -214,38 +219,125 @@
|
||||
|
||||
///Updates weight and size, along with weight class, number of fillets you can get and grind results.
|
||||
/obj/item/fish/proc/update_size_and_weight(new_size = average_size, new_weight = average_weight)
|
||||
if(size && fillet_type)
|
||||
RemoveElement(/datum/element/processable, TOOL_KNIFE, fillet_type, num_fillets, 0.5 SECONDS, screentip_verb = "Cut")
|
||||
SEND_SIGNAL(src, COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT, new_size, new_weight)
|
||||
if(size)
|
||||
if(fillet_type)
|
||||
RemoveElement(/datum/element/processable, TOOL_KNIFE, fillet_type, num_fillets, 0.5 SECONDS * num_fillets, screentip_verb = "Cut")
|
||||
if(size > FISH_SIZE_TWO_HANDS_REQUIRED)
|
||||
qdel(GetComponent(/datum/component/two_handed))
|
||||
size = new_size
|
||||
var/init_icon_state = initial(inhand_icon_state)
|
||||
switch(size)
|
||||
if(0 to FISH_SIZE_TINY_MAX)
|
||||
update_weight_class(WEIGHT_CLASS_TINY)
|
||||
inhand_icon_state = "fish_small"
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_small"
|
||||
if(FISH_SIZE_TINY_MAX to FISH_SIZE_SMALL_MAX)
|
||||
inhand_icon_state = "fish_small"
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_small"
|
||||
update_weight_class(WEIGHT_CLASS_SMALL)
|
||||
if(FISH_SIZE_SMALL_MAX to FISH_SIZE_NORMAL_MAX)
|
||||
inhand_icon_state = "fish_normal"
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_normal"
|
||||
update_weight_class(WEIGHT_CLASS_NORMAL)
|
||||
if(FISH_SIZE_NORMAL_MAX to FISH_SIZE_BULKY_MAX)
|
||||
inhand_icon_state = "fish_bulky"
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_bulky"
|
||||
update_weight_class(WEIGHT_CLASS_BULKY)
|
||||
if(FISH_SIZE_BULKY_MAX to INFINITY)
|
||||
inhand_icon_state = "fish_huge"
|
||||
if(FISH_SIZE_BULKY_MAX to FISH_SIZE_HUGE_MAX)
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_huge"
|
||||
update_weight_class(WEIGHT_CLASS_HUGE)
|
||||
if(FISH_SIZE_HUGE_MAX to INFINITY)
|
||||
if(!init_icon_state)
|
||||
inhand_icon_state = "fish_huge"
|
||||
update_weight_class(WEIGHT_CLASS_GIGANTIC)
|
||||
|
||||
if(size > FISH_SIZE_TWO_HANDS_REQUIRED)
|
||||
inhand_icon_state = "[inhand_icon_state]_wielded"
|
||||
AddComponent(/datum/component/two_handed, require_twohands = TRUE)
|
||||
|
||||
if(fillet_type)
|
||||
var/init_fillets = initial(num_fillets)
|
||||
var/amount = max(round(init_fillets * size / FISH_FILLET_NUMBER_SIZE_DIVISOR, 1), 1)
|
||||
num_fillets = amount
|
||||
AddElement(/datum/element/processable, TOOL_KNIFE, fillet_type, num_fillets, 0.5 SECONDS, screentip_verb = "Cut")
|
||||
AddElement(/datum/element/processable, TOOL_KNIFE, fillet_type, num_fillets, 0.5 SECONDS * num_fillets, screentip_verb = "Cut")
|
||||
|
||||
if(weight)
|
||||
for(var/reagent_type in grind_results)
|
||||
grind_results[reagent_type] /= FLOOR(weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR, 0.1)
|
||||
weight = new_weight
|
||||
|
||||
if(weight >= FISH_WEIGHT_SLOWDOWN)
|
||||
slowdown = round(((weight/FISH_WEIGHT_SLOWDOWN_DIVISOR)**FISH_WEIGHT_SLOWDOWN_EXPONENT)-1.3, 0.1)
|
||||
drag_slowdown = round(slowdown * 0.5, 1)
|
||||
else
|
||||
slowdown = 0
|
||||
drag_slowdown = 0
|
||||
if(ismob(loc))
|
||||
var/mob/mob = loc
|
||||
mob.update_equipment_speed_mods()
|
||||
|
||||
for(var/reagent_type in grind_results)
|
||||
grind_results[reagent_type] *= FLOOR(weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR, 0.1)
|
||||
|
||||
update_fish_force()
|
||||
|
||||
///Reset weapon-related variables of this items and recalculates those values based on the fish weight and size.
|
||||
/obj/item/fish/proc/update_fish_force()
|
||||
force = initial(force)
|
||||
throwforce = initial(throwforce)
|
||||
throw_range = initial(throw_range)
|
||||
demolition_mod = initial(demolition_mod)
|
||||
attack_verb_continuous = initial(attack_verb_continuous)
|
||||
attack_verb_simple = initial(attack_verb_simple)
|
||||
hitsound = initial(hitsound)
|
||||
damtype = initial(damtype)
|
||||
attack_speed = initial(attack_speed)
|
||||
block_chance = initial(block_chance)
|
||||
armour_penetration = initial(armour_penetration)
|
||||
wound_bonus = initial(wound_bonus)
|
||||
bare_wound_bonus = initial(bare_wound_bonus)
|
||||
toolspeed = initial(toolspeed)
|
||||
|
||||
var/weight_rank = max(round(1 + log(2, weight/FISH_WEIGHT_FORCE_DIVISOR), 1), 1)
|
||||
|
||||
throw_range -= weight_rank
|
||||
get_force_rank()
|
||||
|
||||
var/bonus_malus = weight_rank - w_class
|
||||
if(bonus_malus)
|
||||
calculate_fish_force_bonus(bonus_malus)
|
||||
|
||||
throwforce = force
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_FISH_FORCE_UPDATED, weight_rank, bonus_malus)
|
||||
|
||||
///A proc that makes the fish slightly stronger or weaker if there's a noticeable discrepancy between size and weight.
|
||||
/obj/item/fish/proc/calculate_fish_force_bonus(bonus_malus)
|
||||
demolition_mod += bonus_malus * 0.1
|
||||
attack_speed += bonus_malus * 0.1
|
||||
force = round(force * (1 + bonus_malus * 0.1), 0.1)
|
||||
|
||||
/obj/item/fish/proc/get_force_rank()
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY)
|
||||
force -= 3
|
||||
attack_speed -= 0.1 SECONDS
|
||||
if(WEIGHT_CLASS_NORMAL)
|
||||
force += 2
|
||||
if(WEIGHT_CLASS_BULKY)
|
||||
force += 5
|
||||
attack_speed += 0.1 SECONDS
|
||||
if(WEIGHT_CLASS_HUGE)
|
||||
force += 9
|
||||
attack_speed += 0.2 SECONDS
|
||||
demolition_mod += 0.2
|
||||
if(WEIGHT_CLASS_GIGANTIC)
|
||||
force += 13
|
||||
attack_speed += 0.4 SECONDS
|
||||
demolition_mod += 0.4
|
||||
|
||||
/**
|
||||
* This proc has fish_traits list populated with fish_traits paths from three different lists:
|
||||
* traits from x_traits and y_traits are compared, and inserted if conditions are met;
|
||||
@@ -370,7 +462,7 @@
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_FISH_LIFE, seconds_per_tick)
|
||||
|
||||
/obj/item/fish/proc/set_status(new_status)
|
||||
/obj/item/fish/proc/set_status(new_status, silent = FALSE)
|
||||
if(status == new_status)
|
||||
return
|
||||
switch(new_status)
|
||||
@@ -384,12 +476,14 @@
|
||||
status = FISH_DEAD
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
stop_flopping()
|
||||
var/message = span_notice(replacetext(death_text, "%SRC", "[src]"))
|
||||
if(isaquarium(loc))
|
||||
loc.visible_message(message)
|
||||
else
|
||||
visible_message(message)
|
||||
if(!silent)
|
||||
var/message = span_notice(replacetext(death_text, "%SRC", "[src]"))
|
||||
if(isaquarium(loc))
|
||||
loc.visible_message(message)
|
||||
else
|
||||
visible_message(message)
|
||||
update_appearance()
|
||||
update_fish_force()
|
||||
SEND_SIGNAL(src, COMSIG_FISH_STATUS_CHANGED)
|
||||
|
||||
/obj/item/fish/expose_reagents(list/reagents, datum/reagents/source, methods = TOUCH, volume_modifier = 1, show_message = TRUE)
|
||||
@@ -476,7 +570,7 @@
|
||||
return FALSE
|
||||
if(!being_targeted && length(aquarium.get_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION)
|
||||
return FALSE
|
||||
return aquarium.allow_breeding && health >= initial(health) * 0.8 && stable_population > 1 && world.time >= breeding_wait
|
||||
return aquarium.allow_breeding && health >= initial(health) * 0.8 && stable_population >= 1 && world.time >= breeding_wait
|
||||
|
||||
/obj/item/fish/proc/try_to_reproduce()
|
||||
var/obj/structure/aquarium/aquarium = loc
|
||||
@@ -511,36 +605,48 @@
|
||||
second_fish = other_fish
|
||||
break
|
||||
|
||||
if(!second_fish && !HAS_TRAIT(src, TRAIT_FISH_SELF_REPRODUCE))
|
||||
return FALSE
|
||||
if(!second_fish)
|
||||
if(!HAS_TRAIT(src, TRAIT_FISH_SELF_REPRODUCE))
|
||||
return FALSE
|
||||
if(length(aquarium.tracked_fish_by_type[type]) >= stable_population)
|
||||
return FALSE
|
||||
|
||||
if(PERFORM_ALL_TESTS(fish_breeding) && second_fish && !length(evolution_types))
|
||||
return create_offspring(second_fish.type, second_fish)
|
||||
|
||||
var/chosen_type
|
||||
var/datum/fish_evolution/chosen_evolution
|
||||
if(PERFORM_ALL_TESTS(fish_breeding) && second_fish && !length(evolution_types))
|
||||
chosen_type = second_fish.type
|
||||
else
|
||||
var/list/possible_evolutions = list()
|
||||
for(var/evolution_type in evolution_types)
|
||||
var/list/possible_evolutions = list()
|
||||
for(var/evolution_type in evolution_types)
|
||||
var/datum/fish_evolution/evolution = GLOB.fish_evolutions[evolution_type]
|
||||
if(evolution.check_conditions(src, second_fish, aquarium))
|
||||
possible_evolutions += evolution
|
||||
if(second_fish?.evolution_types)
|
||||
var/secondary_evolutions = (second_fish.evolution_types - evolution_types)
|
||||
for(var/evolution_type in secondary_evolutions)
|
||||
var/datum/fish_evolution/evolution = GLOB.fish_evolutions[evolution_type]
|
||||
if(evolution.check_conditions(src, second_fish, aquarium))
|
||||
if(evolution.check_conditions(second_fish, src, aquarium))
|
||||
possible_evolutions += evolution
|
||||
if(second_fish?.evolution_types)
|
||||
var/secondary_evolutions = (second_fish.evolution_types - evolution_types)
|
||||
for(var/evolution_type in secondary_evolutions)
|
||||
var/datum/fish_evolution/evolution = GLOB.fish_evolutions[evolution_type]
|
||||
if(evolution.check_conditions(second_fish, src, aquarium))
|
||||
possible_evolutions += evolution
|
||||
|
||||
if(length(possible_evolutions))
|
||||
chosen_evolution = pick(possible_evolutions)
|
||||
chosen_type = chosen_evolution.new_fish_type
|
||||
else if(second_fish)
|
||||
if(length(aquarium.tracked_fish_by_type[type]) >= stable_population)
|
||||
if(length(possible_evolutions))
|
||||
chosen_evolution = pick(possible_evolutions)
|
||||
chosen_type = chosen_evolution.new_fish_type
|
||||
else if(second_fish)
|
||||
var/recessive = HAS_TRAIT(src, TRAIT_FISH_RECESSIVE)
|
||||
var/recessive_partner = HAS_TRAIT(second_fish, TRAIT_FISH_RECESSIVE)
|
||||
if(length(aquarium.tracked_fish_by_type[type]) >= stable_population)
|
||||
if(recessive_partner && !recessive)
|
||||
return FALSE
|
||||
chosen_type = second_fish.type
|
||||
else
|
||||
if(recessive && !recessive_partner)
|
||||
chosen_type = second_fish.type
|
||||
else if(recessive_partner && !recessive)
|
||||
chosen_type = type
|
||||
else
|
||||
chosen_type = pick(second_fish.type, type)
|
||||
else
|
||||
chosen_type = type
|
||||
else
|
||||
chosen_type = type
|
||||
|
||||
return create_offspring(chosen_type, second_fish, chosen_evolution)
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ GLOBAL_LIST_INIT(fish_evolutions, init_subtypes_w_path_keys(/datum/fish_evolutio
|
||||
/datum/fish_evolution/purple_sludgefish
|
||||
probability = 5
|
||||
new_fish_type = /obj/item/fish/sludgefish/purple
|
||||
new_traits = list(/datum/fish_trait/recessive)
|
||||
removed_traits = list(/datum/fish_trait/no_mating)
|
||||
|
||||
/datum/fish_evolution/mastodon
|
||||
@@ -85,7 +86,7 @@ GLOBAL_LIST_INIT(fish_evolutions, init_subtypes_w_path_keys(/datum/fish_evolutio
|
||||
probability = 40
|
||||
new_fish_type = /obj/item/fish/mastodon
|
||||
new_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/amphibious, /datum/fish_trait/predator, /datum/fish_trait/aggressive)
|
||||
conditions_note = "The fish (and its mate) need to be unusually big both in size and weight."
|
||||
conditions_note = "The fish (and its mate) needs to be unusually big both in size and weight."
|
||||
|
||||
/datum/fish_evolution/mastodon/check_conditions(obj/item/fish/source, obj/item/fish/mate, obj/structure/aquarium/aquarium)
|
||||
if((source.size < 120 || source.weight < 3000) || (mate && (mate.size < 120 || mate.weight < 3000)))
|
||||
@@ -103,3 +104,21 @@ GLOBAL_LIST_INIT(fish_evolutions, init_subtypes_w_path_keys(/datum/fish_evolutio
|
||||
new_fish_type = /obj/item/fish/chasm_crab/ice
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+9
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+10
|
||||
|
||||
/datum/fish_evolution/three_eyes
|
||||
name = "Three-eyed Goldfish"
|
||||
probability = 3
|
||||
new_fish_type = /obj/item/fish/three_eyes
|
||||
new_traits = list(/datum/fish_trait/recessive)
|
||||
|
||||
/datum/fish_evolution/chainsawfish
|
||||
name = "Chainsawfish"
|
||||
probability = 30
|
||||
new_fish_type = /obj/item/fish/chainsawfish
|
||||
new_traits = list(/datum/fish_trait/predator, /datum/fish_trait/aggressive)
|
||||
conditions_note = "The fish needs to be unusually big and aggressive"
|
||||
|
||||
/datum/fish_evolution/chainsawfish/check_conditions(obj/item/fish/source, obj/item/fish/mate, obj/structure/aquarium/aquarium)
|
||||
if(source.size >= 60 && source.size >= 1000 && (/datum/fish_trait/aggressive in source.fish_traits))
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
@@ -37,6 +37,8 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
var/list/fish_whitelist
|
||||
/// Depending on the value, fish with trait will be reported as more or less difficult in the catalog.
|
||||
var/added_difficulty = 0
|
||||
/// Reagents added to the fish when gained
|
||||
var/list/reagents_to_add
|
||||
|
||||
/// Difficulty modifier from this mod, needs to return a list with two values
|
||||
/datum/fish_trait/proc/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman)
|
||||
@@ -54,7 +56,11 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
|
||||
/// Applies some special qualities to the fish that has been spawned
|
||||
/datum/fish_trait/proc/apply_to_fish(obj/item/fish/fish)
|
||||
return
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(reagents_to_add)
|
||||
for(var/reagent in reagents_to_add)
|
||||
add_to_reagents(fish, reagent, reagents_to_add[reagent])
|
||||
RegisterSignal(fish, COMSIG_ATOM_PROCESSED, PROC_REF(process_reagents))
|
||||
|
||||
/// Applies some special qualities to basic mobs generated by fish (i.e. chasm chrab --> young lobstrosity --> lobstrosity).
|
||||
/datum/fish_trait/proc/apply_to_mob(mob/living/basic/mob)
|
||||
@@ -79,6 +85,37 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
fish.grind_results.Insert(1, reagent_type)
|
||||
fish.grind_results[reagent_type] = amount
|
||||
|
||||
/// Proc that handles adding reagents from the trait to the fillets from butchered fish.
|
||||
/datum/fish_trait/proc/process_reagents(obj/item/fish/source, mob/living/user, obj/item/process_item, list/results)
|
||||
SIGNAL_HANDLER
|
||||
var/results_with_reagents = 0
|
||||
for(var/atom/result as anything in results)
|
||||
if(result.reagents)
|
||||
results_with_reagents++
|
||||
if(!results_with_reagents)
|
||||
return
|
||||
for(var/reagent in reagents_to_add)
|
||||
var/amount = round(source.grind_results[reagent] / results_with_reagents, 0.1)
|
||||
for(var/atom/result as anything in results)
|
||||
result.reagents?.add_reagent(reagent, amount)
|
||||
|
||||
/// Proc that adds or changes the venomous when the fish size and/or weight are updated
|
||||
/datum/fish_trait/proc/add_venom(obj/item/fish/source, venom_path, new_weight, mult = 0.25)
|
||||
if(source.size)
|
||||
var/old_amount = max(round((source.weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR) * mult, 0.1), mult)
|
||||
source.RemoveElement(/datum/element/venomous, venom_path, old_amount)
|
||||
|
||||
var/new_amount = max(round((new_weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR) * mult, 0.1), mult)
|
||||
source.AddElement(/datum/element/venomous, venom_path, new_amount)
|
||||
|
||||
/// Proc that changes the venomous element based on if the fish is alive or dead (basically dead fish are weaker).
|
||||
/datum/fish_trait/proc/change_venom_on_death(obj/item/fish/source, venom_path, live_mult, dead_mult)
|
||||
var/live_amount = max(round((source.weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR) * live_mult, 0.1), live_mult)
|
||||
var/dead_amount = max(round((source.weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR) * dead_mult, 0.1), dead_mult)
|
||||
var/is_dead = source.status == FISH_DEAD
|
||||
source.RemoveElement(/datum/element/venomous, venom_path, is_dead ? live_amount : dead_amount)
|
||||
source.AddElement(/datum/element/venomous, venom_path, is_dead ? dead_amount : live_amount)
|
||||
|
||||
/datum/fish_trait/wary
|
||||
name = "Wary"
|
||||
catalog_description = "This fish will avoid visible fish lines, cloaked line recommended."
|
||||
@@ -110,7 +147,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
return
|
||||
if(HAS_TRAIT(rod.bait, TRAIT_OMNI_BAIT))
|
||||
return
|
||||
if(HAS_TRAIT(rod.bait, TRAIT_GOOD_QUALITY_BAIT) || HAS_TRAIT(rod.bait, TRAIT_GREAT_QUALITY_BAIT))
|
||||
if(!HAS_TRAIT(rod.bait, TRAIT_GOOD_QUALITY_BAIT) && !HAS_TRAIT(rod.bait, TRAIT_GREAT_QUALITY_BAIT))
|
||||
.[MULTIPLICATIVE_FISHING_MOD] = 0
|
||||
|
||||
|
||||
@@ -126,6 +163,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
.[MULTIPLICATIVE_FISHING_MOD] = 0
|
||||
|
||||
/datum/fish_trait/nocturnal/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(check_light))
|
||||
|
||||
/datum/fish_trait/nocturnal/proc/check_light(obj/item/fish/source, seconds_per_tick)
|
||||
@@ -170,7 +208,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
mob.obj_damage *= 1.3
|
||||
|
||||
/datum/fish_trait/heavy/minigame_mod(obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/minigame)
|
||||
minigame.fish_idle_velocity -= 10
|
||||
minigame.mover.fish_idle_velocity -= 10
|
||||
|
||||
/datum/fish_trait/carnivore
|
||||
name = "Carnivore"
|
||||
@@ -211,6 +249,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish emits an invisible toxin that emulsifies other fish for it to feed on."
|
||||
|
||||
/datum/fish_trait/emulsijack/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(emulsify))
|
||||
ADD_TRAIT(fish, TRAIT_RESIST_EMULSIFY, FISH_TRAIT_DATUM)
|
||||
|
||||
@@ -250,6 +289,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
incompatible_traits = list(/datum/fish_trait/vegan)
|
||||
|
||||
/datum/fish_trait/necrophage/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(eat_dead_fishes))
|
||||
|
||||
/datum/fish_trait/necrophage/proc/eat_dead_fishes(obj/item/fish/source, seconds_per_tick)
|
||||
@@ -269,6 +309,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
diff_traits_inheritability = 25
|
||||
|
||||
/datum/fish_trait/parthenogenesis/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_SELF_REPRODUCE, FISH_TRAIT_DATUM)
|
||||
|
||||
/**
|
||||
@@ -282,8 +323,19 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
incompatible_traits = list(/datum/fish_trait/crossbreeder)
|
||||
|
||||
/datum/fish_trait/no_mating/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_NO_MATING, FISH_TRAIT_DATUM)
|
||||
|
||||
///Prevent offsprings of fish with this trait from being of the same type (unless self-mating or the partner also has the trait)
|
||||
/datum/fish_trait/recessive
|
||||
name = "Recessive"
|
||||
catalog_description = "If crossbred, offsprings will always be of the mate species, unless it also possess the trait."
|
||||
diff_traits_inheritability = 0
|
||||
|
||||
/datum/fish_trait/no_mating/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_RECESSIVE, FISH_TRAIT_DATUM)
|
||||
|
||||
/datum/fish_trait/revival
|
||||
diff_traits_inheritability = 15
|
||||
name = "Self-Revival"
|
||||
@@ -291,6 +343,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
spontaneous_manifest_types = list(/obj/item/fish/boned = 100, /obj/item/fish/mastodon = 100)
|
||||
|
||||
/datum/fish_trait/revival/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_STATUS_CHANGED, PROC_REF(check_status))
|
||||
|
||||
/datum/fish_trait/revival/proc/check_status(obj/item/fish/source)
|
||||
@@ -319,6 +372,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
incompatible_traits = list(/datum/fish_trait/vegan)
|
||||
|
||||
/datum/fish_trait/predator/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(eat_fishes))
|
||||
|
||||
/datum/fish_trait/predator/proc/eat_fishes(obj/item/fish/source, seconds_per_tick)
|
||||
@@ -327,7 +381,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
return
|
||||
var/obj/structure/aquarium/aquarium = source.loc
|
||||
for(var/obj/item/fish/victim in aquarium.get_fishes(TRUE, source))
|
||||
if(victim.size < source.size * 0.75) // It's a big fish eat small fish world
|
||||
if(victim.size < source.size * 0.7) // It's a big fish eat small fish world
|
||||
continue
|
||||
if(victim.status != FISH_ALIVE || victim == source || HAS_TRAIT(victim, TRAIT_YUCKY_FISH) || SPT_PROB(80, seconds_per_tick))
|
||||
continue
|
||||
@@ -337,31 +391,35 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
/datum/fish_trait/yucky
|
||||
name = "Yucky"
|
||||
catalog_description = "This fish tastes so repulsive, other fishes won't try to eat it."
|
||||
reagents_to_add = list(/datum/reagent/yuck = 3)
|
||||
|
||||
/datum/fish_trait/yucky/apply_to_fish(obj/item/fish/fish)
|
||||
RegisterSignal(fish, COMSIG_ATOM_PROCESSED, PROC_REF(add_yuck))
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_YUCKY_FISH, FISH_TRAIT_DATUM)
|
||||
add_to_reagents(fish, /datum/reagent/yuck, 3)
|
||||
|
||||
/datum/fish_trait/yucky/proc/add_yuck(obj/item/fish/source, mob/living/user, obj/item/process_item, list/results)
|
||||
var/amount = source.grind_results[/datum/reagent/yuck] / length(results)
|
||||
for(var/atom/result as anything in results)
|
||||
result.reagents?.add_reagent(/datum/reagent/yuck, amount)
|
||||
|
||||
/datum/fish_trait/toxic
|
||||
name = "Toxic"
|
||||
catalog_description = "This fish contains toxins in its liver. Feeding it to predatory fishes or people is not reccomended."
|
||||
catalog_description = "This fish contains toxins. Feeding it to predatory fishes or people is not reccomended."
|
||||
diff_traits_inheritability = 25
|
||||
reagents_to_add = list(/datum/reagent/toxin/tetrodotoxin = 2.5)
|
||||
|
||||
/datum/fish_trait/toxic/apply_to_fish(obj/item/fish/fish)
|
||||
RegisterSignal(fish, COMSIG_ATOM_PROCESSED, PROC_REF(add_toxin))
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT, PROC_REF(make_venomous))
|
||||
RegisterSignal(fish, COMSIG_FISH_STATUS_CHANGED, PROC_REF(on_status_change))
|
||||
RegisterSignal(fish, COMSIG_FISH_EATEN_BY_OTHER_FISH, PROC_REF(on_eaten))
|
||||
add_to_reagents(fish, /datum/reagent/toxin/tetrodotoxin, 2.5)
|
||||
|
||||
/datum/fish_trait/toxic/proc/add_toxin(obj/item/fish/source, mob/living/user, obj/item/process_item, list/results)
|
||||
var/amount = source.grind_results[ /datum/reagent/toxin/tetrodotoxin] / length(results)
|
||||
for(var/atom/result as anything in results)
|
||||
result.reagents?.add_reagent(/datum/reagent/toxin/tetrodotoxin, amount)
|
||||
/datum/fish_trait/toxic/proc/make_venomous(obj/item/fish/source, new_size, new_weight)
|
||||
SIGNAL_HANDLER
|
||||
if(!HAS_TRAIT(source, TRAIT_FISH_STINGER))
|
||||
return
|
||||
add_venom(source, /datum/reagent/toxin/tetrodotoxin, new_weight, mult = source.status == FISH_DEAD ? 0.1 : 0.25)
|
||||
|
||||
/datum/fish_trait/toxic/proc/on_status_change(obj/item/fish/source)
|
||||
SIGNAL_HANDLER
|
||||
if(!HAS_TRAIT(source, TRAIT_FISH_STINGER))
|
||||
return
|
||||
change_venom_on_death(source, /datum/reagent/toxin/tetrodotoxin, 0.25, 0.1)
|
||||
|
||||
/datum/fish_trait/toxic/proc/on_eaten(obj/item/fish/source, obj/item/fish/predator)
|
||||
if(HAS_TRAIT(predator, TRAIT_FISH_TOXIN_IMMUNE))
|
||||
@@ -388,6 +446,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
diff_traits_inheritability = 40
|
||||
|
||||
/datum/fish_trait/toxin_immunity/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_TOXIN_IMMUNE, FISH_TRAIT_DATUM)
|
||||
|
||||
/datum/fish_trait/crossbreeder
|
||||
@@ -398,6 +457,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
incompatible_traits = list(/datum/fish_trait/no_mating)
|
||||
|
||||
/datum/fish_trait/crossbreeder/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_CROSSBREEDER, FISH_TRAIT_DATUM)
|
||||
|
||||
/datum/fish_trait/aggressive
|
||||
@@ -407,6 +467,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish is aggressively territorial, and may attack fish that come close to it."
|
||||
|
||||
/datum/fish_trait/aggressive/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(try_attack_fish))
|
||||
|
||||
/datum/fish_trait/aggressive/proc/try_attack_fish(obj/item/fish/source, seconds_per_tick)
|
||||
@@ -431,6 +492,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
added_difficulty = 5
|
||||
|
||||
/datum/fish_trait/lubed/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
fish.AddComponent(/datum/component/slippery, 8 SECONDS, SLIDE|GALOSHES_DONT_HELP)
|
||||
|
||||
/datum/fish_trait/lubed/apply_to_mob(mob/living/basic/mob)
|
||||
@@ -448,6 +510,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish has developed a primitive adaptation to life on both land and water."
|
||||
|
||||
/datum/fish_trait/amphibious/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_AMPHIBIOUS, FISH_TRAIT_DATUM)
|
||||
if(fish.required_fluid_type == AQUARIUM_FLUID_AIR)
|
||||
fish.required_fluid_type = AQUARIUM_FLUID_FRESHWATER
|
||||
@@ -460,6 +523,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
incompatible_traits = list(/datum/fish_trait/predator, /datum/fish_trait/necrophage)
|
||||
|
||||
/datum/fish_trait/mixotroph/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_NO_HUNGER, FISH_TRAIT_DATUM)
|
||||
|
||||
/datum/fish_trait/antigrav
|
||||
@@ -467,12 +531,13 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
inheritability = 75
|
||||
diff_traits_inheritability = 25
|
||||
catalog_description = "This fish will invert the gravity of the bait at random. May fall upward outside after being caught."
|
||||
added_difficulty = 15
|
||||
added_difficulty = 20
|
||||
|
||||
/datum/fish_trait/antigrav/minigame_mod(obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/minigame)
|
||||
minigame.special_effects |= FISHING_MINIGAME_RULE_ANTIGRAV
|
||||
|
||||
/datum/fish_trait/antigrav/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
fish.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY)
|
||||
|
||||
/datum/fish_trait/antigrav/apply_to_mob(mob/living/basic/mob)
|
||||
@@ -489,6 +554,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish tends to die of stress when forced to be around too many other fish."
|
||||
|
||||
/datum/fish_trait/anxiety/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(on_fish_life))
|
||||
|
||||
///signal sent when the anxiety fish is fed, killing it if sharing contents with too many fish.
|
||||
@@ -511,24 +577,18 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish is electroreceptive, and will generate electric fields. Can be harnessed inside a bioelectric generator."
|
||||
|
||||
/datum/fish_trait/electrogenesis/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_ELECTROGENESIS, FISH_TRAIT_DATUM)
|
||||
RegisterSignal(fish, COMSIG_ITEM_ATTACK, PROC_REF(on_item_attack))
|
||||
RegisterSignal(fish, COMSIG_FISH_FORCE_UPDATED, PROC_REF(on_force_updated))
|
||||
|
||||
/datum/fish_trait/electrogenesis/proc/on_item_attack(obj/item/fish/fish, mob/living/target, mob/living/user)
|
||||
/datum/fish_trait/electrogenesis/proc/on_force_updated(obj/item/fish/fish, weight_rank, bonus_or_malus)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(fish.status == FISH_ALIVE)
|
||||
fish.force = 16
|
||||
fish.force += 10 - fish.w_class
|
||||
fish.damtype = BURN
|
||||
fish.attack_verb_continuous = list("shocks", "zaps")
|
||||
fish.attack_verb_simple = list("shock", "zap")
|
||||
fish.hitsound = 'sound/effects/sparks4.ogg'
|
||||
else
|
||||
fish.force = fish::force
|
||||
fish.damtype = fish::damtype
|
||||
fish.attack_verb_continuous = fish::attack_verb_continuous
|
||||
fish.attack_verb_simple = fish::attack_verb_simple
|
||||
fish.hitsound = fish::hitsound
|
||||
|
||||
/datum/fish_trait/electrogenesis/apply_to_mob(mob/living/basic/mob)
|
||||
. = ..()
|
||||
@@ -546,3 +606,44 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
/datum/fish_trait/stunted/apply_to_mob(mob/living/basic/mob)
|
||||
. = ..()
|
||||
qdel(mob.GetComponent(/datum/component/growth_and_differentiation))
|
||||
|
||||
/datum/fish_trait/stinger
|
||||
name = "Stinger"
|
||||
inheritability = 80
|
||||
diff_traits_inheritability = 35
|
||||
catalog_description = "This fish is equipped with a sharp stringer or bill capable of delivering damage and toxins."
|
||||
spontaneous_manifest_types = list(/obj/item/fish/stingray = 100, /obj/item/fish/swordfish = 100, /obj/item/fish/chainsawfish = 100)
|
||||
|
||||
/datum/fish_trait/stinger/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_STINGER, FISH_TRAIT_DATUM)
|
||||
RegisterSignal(fish, COMSIG_FISH_FORCE_UPDATED, PROC_REF(on_force_updated))
|
||||
|
||||
/datum/fish_trait/stinger/proc/on_force_updated(obj/item/fish/fish, weight_rank, bonus_or_malus)
|
||||
SIGNAL_HANDLER
|
||||
fish.force += 1 + fish.w_class + bonus_or_malus
|
||||
|
||||
/datum/fish_trait/toxic_barbs
|
||||
name = "Toxic Barbs"
|
||||
catalog_description = "This fish' stinger, bill or otherwise, is coated with simple, yet effetive venom."
|
||||
spontaneous_manifest_types = list(/obj/item/fish/stingray = 35)
|
||||
|
||||
/datum/fish_trait/toxic_barbs/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
RegisterSignal(fish, COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT, PROC_REF(make_venomous))
|
||||
RegisterSignal(fish, COMSIG_FISH_STATUS_CHANGED, PROC_REF(on_status_change))
|
||||
|
||||
/datum/fish_trait/toxic_barbs/proc/make_venomous(obj/item/fish/source, new_size, new_weight)
|
||||
SIGNAL_HANDLER
|
||||
if(!HAS_TRAIT(source, TRAIT_FISH_STINGER))
|
||||
///Remove the trait from the fish so it doesn't show on the analyzer as it doesn't do anything on stingerless ones.
|
||||
source.fish_traits -= type
|
||||
UnregisterSignal(source, list(COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT, COMSIG_FISH_STATUS_CHANGED))
|
||||
return
|
||||
add_venom(source, /datum/reagent/toxin/venom, new_weight, mult = source.status == FISH_DEAD ? 0.3 : 0.7)
|
||||
|
||||
/datum/fish_trait/toxic_barbs/proc/on_status_change(obj/item/fish/source)
|
||||
SIGNAL_HANDLER
|
||||
if(!HAS_TRAIT(source, TRAIT_FISH_STINGER))
|
||||
return
|
||||
change_venom_on_death(source, /datum/reagent/toxin/venom, 0.7, 0.3)
|
||||
|
||||
@@ -10,9 +10,12 @@
|
||||
stable_population = 3
|
||||
average_size = 30
|
||||
average_weight = 500
|
||||
weight_size_deviation = 0.35
|
||||
favorite_bait = list(/obj/item/food/bait/worm)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+18
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+26
|
||||
evolution_types = list(/datum/fish_evolution/three_eyes, /datum/fish_evolution/chainsawfish)
|
||||
compatible_types = list(/obj/item/fish/goldfish/gill, /obj/item/fish/three_eyes, /obj/item/fish/three_eyes/gill)
|
||||
|
||||
/obj/item/fish/goldfish/gill
|
||||
name = "McGill"
|
||||
@@ -21,6 +24,8 @@
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
show_in_catalog = FALSE
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
compatible_types = list(/obj/item/fish/goldfish, /obj/item/fish/three_eyes)
|
||||
fish_traits = list(/datum/fish_trait/recessive)
|
||||
|
||||
/obj/item/fish/angelfish
|
||||
name = "angelfish"
|
||||
@@ -63,13 +68,14 @@
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+28
|
||||
|
||||
/obj/item/fish/catfish
|
||||
name = "cory catfish"
|
||||
name = "catfish"
|
||||
desc = "A catfish has about 100,000 taste buds, and their bodies are covered with them to help detect chemicals present in the water and also to respond to touch."
|
||||
icon_state = "catfish"
|
||||
dedicated_in_aquarium_icon_state = "fish_greyscale"
|
||||
aquarium_vc_color = "#907420"
|
||||
average_size = 100
|
||||
average_weight = 2000
|
||||
average_size = 80
|
||||
average_weight = 1600
|
||||
weight_size_deviation = 0.35
|
||||
stable_population = 3
|
||||
favorite_bait = list(
|
||||
list(
|
||||
@@ -107,7 +113,7 @@
|
||||
RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks))
|
||||
RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth))
|
||||
|
||||
/obj/item/fish/tadpole/set_status(new_status)
|
||||
/obj/item/fish/tadpole/set_status(new_status, silent = FALSE)
|
||||
. = ..()
|
||||
if(status == FISH_DEAD)
|
||||
del_timerid = QDEL_IN_STOPPABLE(src, 12 SECONDS)
|
||||
@@ -159,6 +165,7 @@
|
||||
evolution_types = null
|
||||
compatible_types = list(/obj/item/fish/clownfish)
|
||||
food = /datum/reagent/lube
|
||||
fishing_difficulty_modifier = 5
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
|
||||
/obj/item/fish/cardinal
|
||||
@@ -200,7 +207,7 @@
|
||||
average_weight = 500
|
||||
stable_population = 3
|
||||
disliked_bait = list(/obj/item/food/bait/worm, /obj/item/food/bait/doughball)
|
||||
fish_ai_type = FISH_AI_ZIPPY
|
||||
fish_movement_type = /datum/fish_movement/zippy
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+23
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+28
|
||||
|
||||
@@ -216,10 +223,10 @@
|
||||
stable_population = 3
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+23
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+28
|
||||
fillet_type = /obj/item/food/fishmeat/quality //Too bad they're poisonous
|
||||
fish_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/toxic)
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
|
||||
/obj/item/fish/lanternfish
|
||||
name = "lanternfish"
|
||||
desc = "Typically found in areas below 6600 feet below the surface of the ocean, they live in complete darkness."
|
||||
@@ -230,8 +237,8 @@
|
||||
source_height = 21
|
||||
sprite_width = 8
|
||||
sprite_height = 8
|
||||
average_size = 100
|
||||
average_weight = 1500
|
||||
average_size = 50
|
||||
average_weight = 1000
|
||||
stable_population = 3
|
||||
fish_traits = list(/datum/fish_trait/nocturnal)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+2 //My source is that the water at a depth 6600 feet is pretty darn cold.
|
||||
@@ -246,8 +253,8 @@
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
stable_population = 2
|
||||
fillet_type = /obj/item/food/fishmeat/moonfish
|
||||
average_size = 100
|
||||
average_weight = 2000
|
||||
average_size = 60
|
||||
average_weight = 1000
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+20
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+30
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
@@ -271,6 +278,7 @@
|
||||
sprite_width = 7
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
stable_population = 12
|
||||
breeding_timeout = 1 MINUTES
|
||||
fillet_type = null
|
||||
average_size = 20
|
||||
average_weight = 300
|
||||
@@ -285,10 +293,13 @@
|
||||
dedicated_in_aquarium_icon_state = "armorfish_small"
|
||||
sprite_height = 5
|
||||
sprite_width = 6
|
||||
average_size = 25
|
||||
average_weight = 350
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
stable_population = 10
|
||||
breeding_timeout = 1.25 MINUTES
|
||||
fillet_type = /obj/item/food/fishmeat/armorfish
|
||||
fish_ai_type = FISH_AI_SLOW
|
||||
fish_movement_type = /datum/fish_movement/slow
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+10
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+32
|
||||
|
||||
@@ -456,7 +467,7 @@
|
||||
fish_traits = list(/datum/fish_trait/necrophage)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+15
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+35
|
||||
fish_ai_type = FISH_AI_ZIPPY
|
||||
fish_movement_type = /datum/fish_movement/zippy
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
@@ -534,7 +545,7 @@
|
||||
dedicated_in_aquarium_icon_state = "bonemass_small"
|
||||
sprite_width = 10
|
||||
sprite_height = 7
|
||||
fish_ai_type = FISH_AI_ZIPPY
|
||||
fish_movement_type = /datum/fish_movement/zippy
|
||||
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
|
||||
required_fluid_type = AQUARIUM_FLUID_ANY_WATER
|
||||
min_pressure = HAZARD_LOW_PRESSURE
|
||||
@@ -563,16 +574,16 @@
|
||||
sprite_height = 7
|
||||
show_in_catalog = FALSE
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
fishing_difficulty_modifier = 5
|
||||
fishing_difficulty_modifier = 30
|
||||
required_fluid_type = AQUARIUM_FLUID_ANY_WATER
|
||||
min_pressure = HAZARD_LOW_PRESSURE
|
||||
health = 300
|
||||
stable_population = 2 //This means they can only crossbreed.
|
||||
stable_population = 1 //This means they can only crossbreed.
|
||||
grind_results = list(/datum/reagent/bone_dust = 5, /datum/reagent/consumable/liquidgibs = 5)
|
||||
fillet_type = /obj/item/stack/sheet/bone
|
||||
num_fillets = 2
|
||||
feeding_frequency = 2 MINUTES
|
||||
breeding_timeout = 10 MINUTES
|
||||
breeding_timeout = 5 MINUTES
|
||||
average_size = 180
|
||||
average_weight = 5000
|
||||
death_text = "%SRC stops moving."
|
||||
@@ -605,7 +616,7 @@
|
||||
return
|
||||
holo_area.linked.add_to_spawned(src)
|
||||
|
||||
/obj/item/fish/holo/set_status(new_status)
|
||||
/obj/item/fish/holo/set_status(new_status, silent = FALSE)
|
||||
. = ..()
|
||||
if(status == FISH_DEAD)
|
||||
animate(src, alpha = 0, 3 SECONDS, easing = SINE_EASING)
|
||||
@@ -709,7 +720,7 @@
|
||||
average_weight = 500
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
required_fluid_type = AQUARIUM_FLUID_ANY_WATER //if we can survive hot lava and freezing plasrivers, we can survive anything
|
||||
fish_ai_type = FISH_AI_ZIPPY
|
||||
fish_movement_type = /datum/fish_movement/zippy
|
||||
min_pressure = HAZARD_LOW_PRESSURE
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+30
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+35
|
||||
@@ -795,3 +806,404 @@
|
||||
//anxiety naturally limits the amount of zipzaps per tank, so they are stronger alone
|
||||
electrogenesis_power = 20 MEGA JOULES
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/sockeye_salmon
|
||||
name = "sockeye salmon"
|
||||
desc = "A fairly common and iconic salmon endemic of the Pacific Ocean. At some point imported into outer space, where we're now."
|
||||
icon_state = "sockeye"
|
||||
dedicated_in_aquarium_icon_state = "sockeye_small"
|
||||
sprite_width = 6
|
||||
sprite_height = 4
|
||||
stable_population = 6
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+3
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+19
|
||||
required_fluid_type = AQUARIUM_FLUID_ANADROMOUS
|
||||
fillet_type = /obj/item/food/fishmeat/salmon
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/arctic_char
|
||||
name = "arctic char"
|
||||
desc = "A cold-water anadromous fish widespread around the Northern Hemisphere of Earth, yet it has somehow found a way here."
|
||||
icon_state = "arctic_char"
|
||||
dedicated_in_aquarium_icon_state = "arctic_char"
|
||||
sprite_width = 7
|
||||
sprite_height = 4
|
||||
stable_population = 6
|
||||
average_size = 60
|
||||
average_weight = 1200
|
||||
weight_size_deviation = 0.5 // known for their size dismophism
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+3
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+19
|
||||
required_fluid_type = AQUARIUM_FLUID_ANADROMOUS
|
||||
|
||||
/obj/item/fish/stingray
|
||||
name = "stingray"
|
||||
desc = "A type of ray, most known for its venomous stinger. Despite that, They're normally docile, if not a bit easily frightened."
|
||||
icon_state = "stingray"
|
||||
dedicated_in_aquarium_icon_state = "stingray_small"
|
||||
stable_population = 4
|
||||
sprite_height = 7
|
||||
sprite_width = 8
|
||||
average_size = 60
|
||||
average_weight = 700
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
random_case_rarity = FISH_RARITY_RARE
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER //Someone ought to add river rays later I guess.
|
||||
fish_traits = list(/datum/fish_trait/stinger, /datum/fish_trait/toxic_barbs, /datum/fish_trait/wary, /datum/fish_trait/carnivore, /datum/fish_trait/predator)
|
||||
|
||||
/obj/item/fish/sand_surfer
|
||||
name = "sand surfer"
|
||||
desc = "A bronze alien \"fish\" living and swimming underneath faraway sandy places."
|
||||
icon_state = "sand_surfer"
|
||||
dedicated_in_aquarium_icon_state = "sand_surfer_small"
|
||||
sprite_height = 6
|
||||
sprite_width = 6
|
||||
stable_population = 5
|
||||
average_size = 65
|
||||
average_weight = 1100
|
||||
weight_size_deviation = 0.35
|
||||
random_case_rarity = FISH_RARITY_RARE
|
||||
required_fluid_type = AQUARIUM_FLUID_AIR
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+25
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+60
|
||||
fish_movement_type = /datum/fish_movement/plunger
|
||||
fishing_difficulty_modifier = 5
|
||||
fish_traits = list(/datum/fish_trait/shiny_lover)
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/sand_crab
|
||||
name = "burrower crab"
|
||||
desc = "A sand-dwelling crustacean. It looks like a crab and tastes like a crab, but waddles like a fish."
|
||||
icon_state = "crab"
|
||||
dedicated_in_aquarium_icon_state = "crab_small"
|
||||
sprite_height = 6
|
||||
sprite_width = 10
|
||||
average_size = 60
|
||||
average_weight = 1000
|
||||
weight_size_deviation = 0.1
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+20
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+40
|
||||
fillet_type = /obj/item/food/meat/slab/rawcrab
|
||||
fish_traits = list(/datum/fish_trait/amphibious, /datum/fish_trait/shiny_lover, /datum/fish_trait/carnivore)
|
||||
fish_movement_type = /datum/fish_movement/slow
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = SEAFOOD,
|
||||
),
|
||||
)
|
||||
|
||||
/obj/item/fish/bumpy
|
||||
name = "bump-fish"
|
||||
desc = "An misshapen fish-thing all covered in stubby little tendrils"
|
||||
icon_state = "bumpy"
|
||||
dedicated_in_aquarium_icon_state = "bumpy_small"
|
||||
sprite_height = 4
|
||||
sprite_width = 5
|
||||
stable_population = 4
|
||||
required_fluid_type = AQUARIUM_FLUID_ANY_WATER
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+15
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+40
|
||||
beauty = FISH_BEAUTY_BAD
|
||||
fish_traits = list(/datum/fish_trait/amphibious, /datum/fish_trait/vegan)
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = VEGETABLES,
|
||||
),
|
||||
)
|
||||
|
||||
/obj/item/fish/three_eyes
|
||||
name = "three-eyed goldfish"
|
||||
desc = "A goldfish with an extra half a pair of eyes. You wonder what it's been feeding on lately..."
|
||||
icon_state = "three_eyes"
|
||||
sprite_width = 8
|
||||
sprite_height = 8
|
||||
average_size = 30
|
||||
average_weight = 500
|
||||
stable_population = 4
|
||||
fish_traits = list(/datum/fish_trait/recessive, /datum/fish_trait/shiny_lover)
|
||||
compatible_types = list(/obj/item/fish/goldfish, /obj/item/fish/goldfish/gill, /obj/item/fish/three_eyes/gill)
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
fishing_difficulty_modifier = 10
|
||||
random_case_rarity = FISH_RARITY_VERY_RARE
|
||||
food = /datum/reagent/toxin/mutagen
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Reagent",
|
||||
"Value" = /datum/reagent/toxin/mutagen,
|
||||
"Amount" = 3,
|
||||
),
|
||||
)
|
||||
|
||||
/obj/item/fish/three_eyes/gill
|
||||
name = "McGill"
|
||||
desc = "A great rubber duck tool for Lawyers who can't get a grasp over their case. It looks kinda different today..."
|
||||
compatible_types = list(/obj/item/fish/goldfish, /obj/item/fish/three_eyes)
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
show_in_catalog = FALSE
|
||||
stable_population = 1
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
/obj/item/fish/swordfish
|
||||
name = "swordfish"
|
||||
desc = "A large billfish, most famous for its elongated bill, while also fairly popular for cooking, and as a fearsome weapon in the hands of a veteran spess-fisherman."
|
||||
icon = 'icons/obj/structures/aquarium/wide.dmi'
|
||||
icon_state = "swordfish"
|
||||
inhand_icon_state = "swordfish"
|
||||
dedicated_in_aquarium_icon = 'icons/obj/structures/aquarium/fish.dmi'
|
||||
dedicated_in_aquarium_icon_state = "swordfish_small"
|
||||
force = 18
|
||||
sharpness = SHARP_EDGED
|
||||
attack_verb_continuous = list("slashes", "cuts", "pierces")
|
||||
attack_verb_simple = list("slash", "cut", "pierce")
|
||||
block_sound = 'sound/weapons/parry.ogg'
|
||||
hitsound = 'sound/weapons/rapierhit.ogg'
|
||||
demolition_mod = 0.75
|
||||
attack_speed = 1 SECONDS
|
||||
block_chance = 50
|
||||
wound_bonus = 10
|
||||
bare_wound_bonus = 20
|
||||
armour_penetration = 75
|
||||
base_pixel_x = -18
|
||||
pixel_x = -18
|
||||
sprite_width = 13
|
||||
sprite_height = 6
|
||||
stable_population = 3
|
||||
average_size = 140
|
||||
average_weight = 4000
|
||||
breeding_timeout = 4.5 MINUTES
|
||||
feeding_frequency = 4 MINUTES
|
||||
health = 180
|
||||
beauty = FISH_BEAUTY_EXCELLENT
|
||||
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
fish_movement_type = /datum/fish_movement/plunger
|
||||
fishing_difficulty_modifier = 25
|
||||
fillet_type = /obj/item/food/fishmeat/quality
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = SEAFOOD,
|
||||
),
|
||||
)
|
||||
fish_traits = list(/datum/fish_trait/carnivore, /datum/fish_trait/predator, /datum/fish_trait/stinger)
|
||||
|
||||
/obj/item/fish/swordfish/get_force_rank()
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY)
|
||||
force -= 11
|
||||
attack_speed -= 0.4 SECONDS
|
||||
block_chance -= 45
|
||||
armour_penetration -= 20
|
||||
wound_bonus -= 15
|
||||
bare_wound_bonus -= 20
|
||||
if(WEIGHT_CLASS_SMALL)
|
||||
force -= 8
|
||||
attack_speed -= 0.3 SECONDS
|
||||
block_chance -= 30
|
||||
armour_penetration -= 15
|
||||
wound_bonus -= 10
|
||||
bare_wound_bonus -= 20
|
||||
if(WEIGHT_CLASS_NORMAL)
|
||||
force -= 5
|
||||
attack_speed -= 0.2 SECONDS
|
||||
block_chance -= 20
|
||||
armour_penetration -= 10
|
||||
wound_bonus -= 10
|
||||
bare_wound_bonus -= 15
|
||||
if(WEIGHT_CLASS_BULKY)
|
||||
force -= 3
|
||||
attack_speed -= 0.1 SECONDS
|
||||
block_chance -= 10
|
||||
armour_penetration -= 5
|
||||
wound_bonus -= 5
|
||||
bare_wound_bonus -= 10
|
||||
if(WEIGHT_CLASS_GIGANTIC)
|
||||
force += 5
|
||||
attack_speed += 0.2 SECONDS
|
||||
demolition_mod += 0.15
|
||||
block_chance += 10
|
||||
armour_penetration += 5
|
||||
wound_bonus += 5
|
||||
bare_wound_bonus += 10
|
||||
|
||||
if(status == FISH_DEAD)
|
||||
force -= 4 + w_class
|
||||
block_chance -= 25
|
||||
armour_penetration -= 30
|
||||
wound_bonus -= 10
|
||||
bare_wound_bonus -= 10
|
||||
|
||||
/obj/item/fish/swordfish/calculate_fish_force_bonus(bonus_malus)
|
||||
. = ..()
|
||||
armour_penetration += bonus_malus * 5
|
||||
wound_bonus += bonus_malus * 3
|
||||
bare_wound_bonus += bonus_malus * 5
|
||||
block_chance += bonus_malus * 7
|
||||
|
||||
/obj/item/fish/chainsawfish
|
||||
name = "chainsawfish"
|
||||
desc = "A very, very angry bioweapon, whose sole purpose is to rip and tear."
|
||||
icon = 'icons/obj/structures/aquarium/wide.dmi'
|
||||
icon_state = "chainsawfish"
|
||||
inhand_icon_state = "chainsawfish"
|
||||
icon_state_dead = "chainsawfish_dead"
|
||||
dedicated_in_aquarium_icon = 'icons/obj/structures/aquarium/fish.dmi'
|
||||
dedicated_in_aquarium_icon_state = "chainsaw_small"
|
||||
force = 22
|
||||
demolition_mod = 1.5
|
||||
block_chance = 15
|
||||
attack_verb_continuous = list("saws", "tears", "lacerates", "cuts", "chops", "dices")
|
||||
attack_verb_simple = list("saw", "tear", "lacerate", "cut", "chop", "dice")
|
||||
hitsound = 'sound/weapons/chainsawhit.ogg'
|
||||
sharpness = SHARP_EDGED
|
||||
tool_behaviour = TOOL_SAW
|
||||
toolspeed = 0.5
|
||||
base_pixel_x = -16
|
||||
pixel_x = -16
|
||||
sprite_width = 8
|
||||
sprite_height = 5
|
||||
stable_population = 3
|
||||
average_size = 85
|
||||
average_weight = 2500
|
||||
breeding_timeout = 4.25 MINUTES
|
||||
feeding_frequency = 3 MINUTES
|
||||
health = 180
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
|
||||
required_fluid_type = AQUARIUM_FLUID_FRESHWATER
|
||||
fish_movement_type = /datum/fish_movement/accelerando
|
||||
fishing_difficulty_modifier = 30
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = GORE
|
||||
),
|
||||
)
|
||||
fish_traits = list(/datum/fish_trait/aggressive, /datum/fish_trait/carnivore, /datum/fish_trait/predator, /datum/fish_trait/stinger)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+18
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+26
|
||||
|
||||
/obj/item/fish/chainsawfish/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
|
||||
/obj/item/fish/chainsawfish/update_icon_state()
|
||||
if(status == FISH_DEAD)
|
||||
inhand_icon_state = "chainsawfish_dead"
|
||||
else
|
||||
inhand_icon_state = "chainsawfish"
|
||||
if(HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
inhand_icon_state = "[inhand_icon_state]_wielded"
|
||||
return ..()
|
||||
|
||||
/obj/item/fish/chainsawfish/get_force_rank()
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY)
|
||||
force -= 10
|
||||
attack_speed -= 0.2 SECONDS
|
||||
demolition_mod -= 0.4
|
||||
block_chance -= 15
|
||||
armour_penetration -= 10
|
||||
wound_bonus -= 10
|
||||
bare_wound_bonus -= 10
|
||||
toolspeed += 0.6
|
||||
if(WEIGHT_CLASS_SMALL)
|
||||
force -= 8
|
||||
attack_speed -= 0.1 SECONDS
|
||||
demolition_mod -= 0.3
|
||||
block_chance -= 10
|
||||
armour_penetration -= 10
|
||||
wound_bonus -= 10
|
||||
bare_wound_bonus -= 10
|
||||
toolspeed += 0.4
|
||||
if(WEIGHT_CLASS_NORMAL)
|
||||
force -= 5
|
||||
demolition_mod -= 0.15
|
||||
block_chance -= 5
|
||||
armour_penetration -= 5
|
||||
wound_bonus -= 5
|
||||
bare_wound_bonus -= 5
|
||||
toolspeed += 0.2
|
||||
if(WEIGHT_CLASS_HUGE)
|
||||
force += 2
|
||||
attack_speed += 0.2 SECONDS
|
||||
demolition_mod += 0.15
|
||||
armour_penetration += 10
|
||||
block_chance += 10
|
||||
wound_bonus += 10
|
||||
bare_wound_bonus += 5
|
||||
if(WEIGHT_CLASS_GIGANTIC)
|
||||
force += 4
|
||||
attack_speed += 0.4 SECONDS
|
||||
demolition_mod += 0.3
|
||||
block_chance += 20
|
||||
armour_penetration += 20
|
||||
wound_bonus += 15
|
||||
bare_wound_bonus += 10
|
||||
toolspeed -= 0.1
|
||||
|
||||
if(status == FISH_DEAD)
|
||||
force -= 8 + w_class
|
||||
hitsound = SFX_SWING_HIT
|
||||
block_chance -= 25
|
||||
demolition_mod -= 0.3
|
||||
armour_penetration -= 15
|
||||
wound_bonus -= 5
|
||||
bare_wound_bonus -= 5
|
||||
toolspeed += 1
|
||||
|
||||
/obj/item/fish/chainsawfish/calculate_fish_force_bonus(bonus_malus)
|
||||
. = ..()
|
||||
armour_penetration += bonus_malus * 3
|
||||
wound_bonus += bonus_malus * 2
|
||||
bare_wound_bonus += bonus_malus * 3
|
||||
block_chance += bonus_malus * 2
|
||||
toolspeed -= bonus_malus * 0.1
|
||||
|
||||
/obj/item/fish/soul
|
||||
name = "soulfish"
|
||||
desc = "A distant yet vaguely close critter, like a long lost relative. You feel your soul rejuvenated just from looking at it... Also, what the fuck is this shit?!"
|
||||
icon_state = "soulfish"
|
||||
dedicated_in_aquarium_icon_state = "soul_small"
|
||||
sprite_width = 7
|
||||
sprite_height = 6
|
||||
average_size = 60
|
||||
average_weight = 1200
|
||||
stable_population = 4
|
||||
show_in_catalog = FALSE
|
||||
beauty = FISH_BEAUTY_EXCELLENT
|
||||
fish_movement_type = /datum/fish_movement/choppy //Glideless legacy movement? in my fishing minigame?
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = FRIED
|
||||
),
|
||||
)
|
||||
fillet_type = /obj/item/food/meat/cutlet/plain/human
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+3
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+38
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
/obj/item/fish/skin_crab
|
||||
name = "skin crab"
|
||||
desc = "<i>\"And on the eighth day, a demential mockery of both humanity and crabity was made.\"<i> Fascinating."
|
||||
icon_state = "skin_crab"
|
||||
dedicated_in_aquarium_icon_state = "skin_crab_small"
|
||||
sprite_width = 7
|
||||
sprite_height = 6
|
||||
average_size = 40
|
||||
average_weight = 750
|
||||
stable_population = 5
|
||||
show_in_catalog = FALSE
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
favorite_bait = list(
|
||||
list(
|
||||
"Type" = "Foodtype",
|
||||
"Value" = FRIED
|
||||
),
|
||||
)
|
||||
fillet_type = /obj/item/food/meat/slab/rawcrab
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/// 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
|
||||
@@ -5,16 +5,6 @@
|
||||
// UI minigame phase
|
||||
#define MINIGAME_PHASE 3
|
||||
|
||||
/// The height of the minigame slider. Not in pixels, but minigame units.
|
||||
#define FISHING_MINIGAME_AREA 1000
|
||||
/// 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
|
||||
// Acceleration mod when bait is over fish
|
||||
#define FISH_ON_BAIT_ACCELERATION_MULT 0.6
|
||||
/// The minimum velocity required for the bait to bounce
|
||||
@@ -47,8 +37,6 @@
|
||||
var/start_time
|
||||
/// Is it finished (either by win/lose or window closing)
|
||||
var/completed = FALSE
|
||||
/// Fish AI type to use
|
||||
var/fish_ai = FISH_AI_DUMB
|
||||
/// Rule modifiers (eg weighted bait)
|
||||
var/special_effects = NONE
|
||||
/// A list of possible active minigame effects. If not empty, one will be picked from time to time.
|
||||
@@ -93,8 +81,6 @@
|
||||
var/fish_position = 0
|
||||
/// The position of the bait on the minigame slider
|
||||
var/bait_position = 0
|
||||
/// The current speed the fish is moving at
|
||||
var/fish_velocity = 0
|
||||
/// The current speed the bait is moving at
|
||||
var/bait_velocity = 0
|
||||
|
||||
@@ -105,22 +91,7 @@
|
||||
/// How much completion is gained per second when the bait area is intersecting with the fish's
|
||||
var/completion_gain = 5
|
||||
|
||||
/// 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 = 200
|
||||
/// 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
|
||||
var/datum/fish_movement/mover
|
||||
|
||||
/// Whether the bait is idle or reeling up or down (left and right click)
|
||||
var/reeling_state = REELING_STATE_IDLE
|
||||
@@ -144,24 +115,21 @@
|
||||
RegisterSignal(comp.fish_source, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, PROC_REF(interrupt_challenge))
|
||||
comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_COMPLETED, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
|
||||
background = comp.fish_source.background
|
||||
|
||||
/// Fish minigame properties
|
||||
if(ispath(reward_path,/obj/item/fish))
|
||||
var/obj/item/fish/fish = reward_path
|
||||
fish_ai = initial(fish.fish_ai_type)
|
||||
switch(fish_ai)
|
||||
if(FISH_AI_ZIPPY) // Keeps on jumping
|
||||
short_jump_chance *= 3
|
||||
if(FISH_AI_SLOW) // Only does long jump, and doesn't change direction until it gets there
|
||||
short_jump_chance = 0
|
||||
long_jump_chance = 1.5
|
||||
long_jump_velocity_limit = 150
|
||||
long_jump_velocity_limit = FALSE
|
||||
var/movement_path = initial(fish.fish_movement_type)
|
||||
mover = new movement_path(src)
|
||||
// Apply fish trait modifiers
|
||||
var/list/fish_list_properties = collect_fish_properties()
|
||||
var/list/fish_traits = fish_list_properties[fish][NAMEOF(fish, fish_traits)]
|
||||
for(var/fish_trait in fish_traits)
|
||||
var/datum/fish_trait/trait = GLOB.fish_traits[fish_trait]
|
||||
trait.minigame_mod(rod, user, src)
|
||||
else
|
||||
mover = new /datum/fish_movement(src)
|
||||
|
||||
/// Enable special parameters
|
||||
if(rod.line)
|
||||
completion_gain += 1 // Any fishing line will provide a small boost by default
|
||||
@@ -198,22 +166,7 @@
|
||||
if(HAS_MIND_TRAIT(user, TRAIT_REVEAL_FISH))
|
||||
fish_icon = GLOB.specific_fish_icons[reward_path] || "fish"
|
||||
|
||||
/**
|
||||
* If the chances are higher than 1% (100% at maximum difficulty), they'll scale
|
||||
* less than proportionally (exponent less than 1) instead.
|
||||
* This way we ensure fish with high jump chances won't get TOO jumpy until
|
||||
* they near the maximum difficulty, at which they hit 100%
|
||||
*/
|
||||
var/square_angle_rad = TORADIANS(90)
|
||||
var/zero_one_difficulty = 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 *= 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 *= 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)
|
||||
@@ -230,6 +183,7 @@
|
||||
SStgui.close_uis(src)
|
||||
user = null
|
||||
used_rod = null
|
||||
QDEL_NULL(mover)
|
||||
return ..()
|
||||
|
||||
/datum/fishing_challenge/proc/send_alert(message)
|
||||
@@ -369,6 +323,14 @@
|
||||
send_alert("crustacean!!!")
|
||||
if(FISH_ICON_BONE)
|
||||
send_alert("bones!!!")
|
||||
if(FISH_ICON_ELECTRIC)
|
||||
send_alert("zappy!!!")
|
||||
if(FISH_ICON_WEAPON)
|
||||
send_alert("weapon!!!")
|
||||
if(FISH_ICON_CRITTER)
|
||||
send_alert("critter!!!")
|
||||
if(FISH_ICON_SEED)
|
||||
send_alert("seed!!!")
|
||||
else
|
||||
send_alert("!!!")
|
||||
animate(lure, pixel_y = 3, time = 5, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
@@ -413,6 +375,10 @@
|
||||
completion *= 1.2
|
||||
if(BITING_TIME_WINDOW - 0.5 SECONDS to BITING_TIME_WINDOW)
|
||||
completion *= 1.4
|
||||
//randomize the position of the fish a little
|
||||
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())
|
||||
return
|
||||
phase = MINIGAME_PHASE
|
||||
@@ -465,7 +431,7 @@
|
||||
/datum/fishing_challenge/process(seconds_per_tick)
|
||||
if(length(active_effects) && COOLDOWN_FINISHED(src, active_effect_cd))
|
||||
select_active_effect()
|
||||
move_fish(seconds_per_tick)
|
||||
mover.move_fish(seconds_per_tick)
|
||||
move_bait(seconds_per_tick)
|
||||
if(!QDELETED(fishing_hud))
|
||||
update_visuals()
|
||||
@@ -501,58 +467,6 @@
|
||||
fishing_hud.icon_state = background
|
||||
current_active_effect = null
|
||||
|
||||
///The proc that moves the fish around, just like in the old TGUI, mostly.
|
||||
/datum/fishing_challenge/proc/move_fish(seconds_per_tick)
|
||||
var/long_chance = long_jump_chance * seconds_per_tick * 10
|
||||
var/short_chance = short_jump_chance * seconds_per_tick * 10
|
||||
|
||||
// If we have the target but we're close enough, mark as target reached
|
||||
if(abs(target_position - fish_position) < FISH_TARGET_MIN_DISTANCE)
|
||||
target_position = null
|
||||
|
||||
// Switching to new long jump target can interrupt any other
|
||||
if((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 - fish_position - fish_height
|
||||
var/distance_from_bottom = 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 = 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 - fish_position
|
||||
// about 5 at diff 15 , 10 at diff 30, 30 at diff 100
|
||||
var/acceleration_mult = 0.3 * difficulty + 0.5
|
||||
var/target_acceleration = distance * acceleration_mult * seconds_per_tick
|
||||
|
||||
fish_velocity = fish_velocity * FISH_FRICTION_MULT + target_acceleration
|
||||
else if(prob(short_chance))
|
||||
var/distance_from_top = FISHING_MINIGAME_AREA - fish_position - fish_height
|
||||
var/distance_from_bottom = 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(fish_position + jump_length, 0, FISHING_MINIGAME_AREA - fish_height)
|
||||
current_velocity_limit = short_jump_velocity_limit
|
||||
|
||||
fish_velocity = clamp(fish_velocity + fish_idle_velocity, -current_velocity_limit, current_velocity_limit)
|
||||
fish_position = clamp(fish_position + fish_velocity * seconds_per_tick, 0, FISHING_MINIGAME_AREA - fish_height)
|
||||
|
||||
///The proc that moves the bait around, just like in the old TGUI, mostly.
|
||||
/datum/fishing_challenge/proc/move_bait(seconds_per_tick)
|
||||
var/should_bounce = abs(bait_velocity) > BAIT_MIN_VELOCITY_BOUNCE
|
||||
@@ -613,9 +527,7 @@
|
||||
bait_velocity += velocity_change
|
||||
|
||||
//check that the fish area is still intersecting the bait now that it has moved
|
||||
fish_on_bait = (fish_position + fish_height >= bait_position) && (bait_position + bait_height >= fish_position)
|
||||
|
||||
if(fish_on_bait)
|
||||
if(is_fish_on_bait())
|
||||
completion += completion_gain * seconds_per_tick
|
||||
if(completion >= 100)
|
||||
complete(TRUE)
|
||||
@@ -627,6 +539,10 @@
|
||||
|
||||
completion = clamp(completion, 0, 100)
|
||||
|
||||
///Returns TRUE if the fish and the bait are intersecting
|
||||
/datum/fishing_challenge/proc/is_fish_on_bait()
|
||||
return (fish_position + fish_height >= bait_position) && (bait_position + bait_height >= fish_position)
|
||||
|
||||
///update the vertical pixel position of both fish and bait, and the icon state of the completion bar
|
||||
/datum/fishing_challenge/proc/update_visuals()
|
||||
var/bait_offset_mult = bait_position/FISHING_MINIGAME_AREA
|
||||
@@ -726,15 +642,6 @@
|
||||
#undef BITING_PHASE
|
||||
#undef MINIGAME_PHASE
|
||||
|
||||
#undef FISHING_MINIGAME_AREA
|
||||
#undef FISH_TARGET_MIN_DISTANCE
|
||||
#undef FISH_FRICTION_MULT
|
||||
#undef FISH_SHORT_JUMP_MIN_DISTANCE
|
||||
#undef FISH_SHORT_JUMP_MAX_DISTANCE
|
||||
#undef FISH_ON_BAIT_ACCELERATION_MULT
|
||||
#undef BAIT_MIN_VELOCITY_BOUNCE
|
||||
#undef BAIT_DECELERATION_MULT
|
||||
|
||||
#undef MINIGAME_SLIDER_HEIGHT
|
||||
#undef MINIGAME_BAIT_HEIGHT
|
||||
#undef MINIGAME_FISH_HEIGHT
|
||||
@@ -745,5 +652,9 @@
|
||||
#undef REELING_STATE_UP
|
||||
#undef REELING_STATE_DOWN
|
||||
|
||||
#undef FISH_ON_BAIT_ACCELERATION_MULT
|
||||
#undef BAIT_MIN_VELOCITY_BOUNCE
|
||||
#undef BAIT_DECELERATION_MULT
|
||||
|
||||
#undef MAX_FISH_COMPLETION_MALUS
|
||||
#undef BITING_TIME_WINDOW
|
||||
|
||||
@@ -107,8 +107,19 @@
|
||||
var/mob/living/caught_mob = reward
|
||||
if(caught_mob.stat == DEAD)
|
||||
return
|
||||
else if(!isfish(reward))
|
||||
return
|
||||
else
|
||||
if(!isfish(reward))
|
||||
return
|
||||
var/obj/item/fish/fish = reward
|
||||
if(HAS_TRAIT(bait, TRAIT_POISONOUS_BAIT) && !HAS_TRAIT(fish, TRAIT_FISH_TOXIN_IMMUNE))
|
||||
var/kill_fish = TRUE
|
||||
for(var/bait_identifer in fish.favorite_bait)
|
||||
if(is_matching_bait(bait, bait_identifer))
|
||||
kill_fish = FALSE
|
||||
break
|
||||
if(kill_fish)
|
||||
fish.set_status(FISH_DEAD, silent = TRUE)
|
||||
|
||||
QDEL_NULL(bait)
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -8,30 +8,48 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour
|
||||
* A lot of the icons here may be a tad inaccurate, but since we're limited to the free font awesome icons we
|
||||
* have access to, we got to make do.
|
||||
*/
|
||||
GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list(
|
||||
/mob/living/basic/carp = FISH_ICON_DEF,
|
||||
/mob/living/basic/mining = FISH_ICON_HOSTILE,
|
||||
/obj/effect/decal/remains = FISH_ICON_BONE,
|
||||
/obj/effect/mob_spawn/corpse = FISH_ICON_BONE,
|
||||
/obj/item/coin = FISH_ICON_COIN,
|
||||
/obj/item/fish = FISH_ICON_DEF,
|
||||
/obj/item/fish/armorfish = FISH_ICON_CRAB,
|
||||
/obj/item/fish/boned = FISH_ICON_BONE,
|
||||
/obj/item/fish/chasm_crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/gunner_jellyfish = FISH_ICON_JELLYFISH,
|
||||
/obj/item/fish/holo/crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/holo/puffer = FISH_ICON_CHUNKY,
|
||||
/obj/item/fish/mastodon = FISH_ICON_BONE,
|
||||
/obj/item/fish/pufferfish = FISH_ICON_CHUNKY,
|
||||
/obj/item/fish/slimefish = FISH_ICON_SLIME,
|
||||
/obj/item/fish/sludgefish = FISH_ICON_SLIME,
|
||||
/obj/item/fish/starfish = FISH_ICON_STAR,
|
||||
/obj/item/storage/wallet = FISH_ICON_COIN,
|
||||
/obj/item/stack/sheet/bone = FISH_ICON_BONE,
|
||||
/obj/item/stack/sheet/mineral = FISH_ICON_GEM,
|
||||
/obj/item/stack/ore = FISH_ICON_GEM,
|
||||
/obj/structure/closet/crate = FISH_ICON_COIN,
|
||||
)))
|
||||
GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
|
||||
|
||||
/proc/generate_specific_fish_icons()
|
||||
var/list/return_list = zebra_typecacheof(list(
|
||||
/mob/living/basic/axolotl = FISH_ICON_CRITTER,
|
||||
/mob/living/basic/frog = FISH_ICON_CRITTER,
|
||||
/mob/living/basic/carp = FISH_ICON_DEF,
|
||||
/mob/living/basic/mining = FISH_ICON_HOSTILE,
|
||||
/obj/effect/decal/remains = FISH_ICON_BONE,
|
||||
/obj/effect/mob_spawn/corpse = FISH_ICON_BONE,
|
||||
/obj/item/coin = FISH_ICON_COIN,
|
||||
/obj/item/fish = FISH_ICON_DEF,
|
||||
/obj/item/fish/armorfish = FISH_ICON_CRAB,
|
||||
/obj/item/fish/boned = FISH_ICON_BONE,
|
||||
/obj/item/fish/chainsawfish = FISH_ICON_WEAPON,
|
||||
/obj/item/fish/chasm_crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/gunner_jellyfish = FISH_ICON_JELLYFISH,
|
||||
/obj/item/fish/holo/crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/holo/puffer = FISH_ICON_CHUNKY,
|
||||
/obj/item/fish/jumpercable = FISH_ICON_ELECTRIC,
|
||||
/obj/item/fish/lavaloop = FISH_ICON_WEAPON,
|
||||
/obj/item/fish/mastodon = FISH_ICON_BONE,
|
||||
/obj/item/fish/pufferfish = FISH_ICON_CHUNKY,
|
||||
/obj/item/fish/sand_crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/skin_crab = FISH_ICON_CRAB,
|
||||
/obj/item/fish/slimefish = FISH_ICON_SLIME,
|
||||
/obj/item/fish/sludgefish = FISH_ICON_SLIME,
|
||||
/obj/item/fish/starfish = FISH_ICON_STAR,
|
||||
/obj/item/fish/stingray = FISH_ICON_WEAPON,
|
||||
/obj/item/fish/swordfish = FISH_ICON_WEAPON,
|
||||
/obj/item/fish/zipzap = FISH_ICON_ELECTRIC,
|
||||
/obj/item/seeds/grass = FISH_ICON_SEED,
|
||||
/obj/item/seeds/random = FISH_ICON_SEED,
|
||||
/obj/item/storage/wallet = FISH_ICON_COIN,
|
||||
/obj/item/stack/sheet/bone = FISH_ICON_BONE,
|
||||
/obj/item/stack/sheet/mineral = FISH_ICON_GEM,
|
||||
/obj/item/stack/ore = FISH_ICON_GEM,
|
||||
/obj/structure/closet/crate = FISH_ICON_COIN,
|
||||
))
|
||||
|
||||
return_list[FISHING_RANDOM_SEED] = FISH_ICON_SEED
|
||||
return return_list
|
||||
|
||||
/**
|
||||
* Where the fish actually come from - every fishing spot has one assigned but multiple fishing holes
|
||||
@@ -45,6 +63,10 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list(
|
||||
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()
|
||||
/// Any limited quantity stuff in this list will be readded to the counts after a while
|
||||
var/list/fish_count_regen
|
||||
/// A list of stuff that's currently waiting to be readded to fish_counts
|
||||
var/list/currently_on_regen
|
||||
/// 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
|
||||
@@ -198,16 +220,26 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list(
|
||||
/datum/fish_source/proc/simple_dispense_reward(reward_path, atom/spawn_location, turf/fishing_spot)
|
||||
if(isnull(reward_path))
|
||||
return null
|
||||
if((reward_path in fish_counts)) // This is limited count result
|
||||
if(reward_path in fish_counts) // This is limited count result
|
||||
fish_counts[reward_path] -= 1
|
||||
if(!fish_counts[reward_path])
|
||||
fish_counts -= reward_path //Ran out of these since rolling (multiple fishermen on same source most likely)
|
||||
fish_table -= reward_path
|
||||
var/regen_time = fish_count_regen?[reward_path]
|
||||
if(regen_time)
|
||||
LAZYADDASSOC(currently_on_regen, reward_path, 1)
|
||||
if(currently_on_regen[reward_path] == 1)
|
||||
addtimer(CALLBACK(src, PROC_REF(regen_count), reward_path), regen_time)
|
||||
|
||||
var/atom/movable/reward = spawn_reward(reward_path, spawn_location, fishing_spot)
|
||||
SEND_SIGNAL(src, COMSIG_FISH_SOURCE_REWARD_DISPENSED, reward)
|
||||
return reward
|
||||
|
||||
/datum/fish_source/proc/regen_count(reward_path, regen_time)
|
||||
fish_counts[reward_path] += 1
|
||||
currently_on_regen[reward_path] -= 1
|
||||
if(!currently_on_regen[reward_path])
|
||||
LAZYREMOVE(currently_on_regen, reward_path)
|
||||
else
|
||||
addtimer(CALLBACK(src, PROC_REF(regen_count), reward_path), regen_time)
|
||||
|
||||
/// Spawns a reward from a atom path right where the fisherman is. Part of the dispense_reward() logic.
|
||||
/datum/fish_source/proc/spawn_reward(reward_path, atom/spawn_location, turf/fishing_spot)
|
||||
if(reward_path == FISHING_DUD)
|
||||
@@ -239,22 +271,13 @@ GLOBAL_LIST(fishing_property_cache)
|
||||
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"]
|
||||
if("Reagent")
|
||||
return bait.reagents?.has_reagent(special_identifier["Value"], special_identifier["Amount"], check_subtypes = TRUE)
|
||||
else
|
||||
CRASH("Unknown bait identifier in fish favourite/disliked list")
|
||||
else
|
||||
return HAS_TRAIT(bait, identifier)
|
||||
/// Returns the fish table, with with the unavailable items from fish_counts removed.
|
||||
/datum/fish_source/proc/get_fish_table()
|
||||
var/list/table = fish_table.Copy()
|
||||
for(var/result in table)
|
||||
if(fish_counts[result] == 0)
|
||||
table -= result
|
||||
return table
|
||||
|
||||
/// 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)
|
||||
@@ -364,13 +387,13 @@ GLOBAL_LIST(fishing_property_cache)
|
||||
for(var/i in 1 to (severity + 2))
|
||||
if(!prob((100 + 100 * severity)/i * multiplier))
|
||||
continue
|
||||
var/reward_loot = pick_weight(fish_table)
|
||||
var/reward_loot = pick_weight(get_fish_table())
|
||||
var/atom/movable/reward = simple_dispense_reward(reward_loot, location, location)
|
||||
if(isnull(reward))
|
||||
continue
|
||||
if(isfish(reward))
|
||||
var/obj/item/fish/fish = reward
|
||||
fish.set_status(FISH_DEAD)
|
||||
fish.set_status(FISH_DEAD, silent = TRUE)
|
||||
if(isitem(reward))
|
||||
reward.pixel_x = rand(-9, 9)
|
||||
reward.pixel_y = rand(-9, 9)
|
||||
|
||||
@@ -1,32 +1,90 @@
|
||||
/datum/fish_source/ocean
|
||||
fish_table = list(
|
||||
FISHING_DUD = 15,
|
||||
/obj/item/coin/gold = 5,
|
||||
/obj/item/coin/gold = 7,
|
||||
/obj/item/fish/clownfish = 15,
|
||||
/obj/item/fish/pufferfish = 15,
|
||||
/obj/item/fish/cardinal = 15,
|
||||
/obj/item/fish/greenchromis = 15,
|
||||
/obj/item/fish/lanternfish = 5,
|
||||
/obj/item/fish/zipzap = 5,
|
||||
/obj/item/fish/clownfish/lube = 3,
|
||||
/obj/item/fish/stingray = 10,
|
||||
/obj/item/fish/lanternfish = 7,
|
||||
/obj/item/fish/zipzap = 7,
|
||||
/obj/item/fish/clownfish/lube = 5,
|
||||
/obj/item/fish/swordfish = 5,
|
||||
/obj/structure/mystery_box/fishing = 1,
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/fish/clownfish/lube = 2,
|
||||
/obj/item/fish/swordfish = 2,
|
||||
/obj/structure/mystery_box/fishing = 1,
|
||||
)
|
||||
fish_count_regen = list(
|
||||
/obj/item/fish/clownfish/lube = 3 MINUTES,
|
||||
/obj/item/fish/swordfish = 5 MINUTES,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
|
||||
explosive_malus = TRUE
|
||||
|
||||
/datum/fish_source/ocean/beach
|
||||
catalog_description = "Beach shore water"
|
||||
|
||||
/datum/fish_source/ice_fishing
|
||||
catalog_description = "Ice-covered water"
|
||||
fish_table = list(
|
||||
FISHING_DUD = 4,
|
||||
/obj/item/fish/arctic_char = 5,
|
||||
/obj/item/fish/sockeye_salmon = 5,
|
||||
/obj/item/fish/chasm_crab/ice = 2,
|
||||
/obj/item/fish/boned = 1,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
|
||||
|
||||
/datum/fish_source/river
|
||||
catalog_description = "River water"
|
||||
fish_table = list(
|
||||
FISHING_DUD = 4,
|
||||
/obj/item/fish/goldfish = 5,
|
||||
/obj/item/fish/guppy = 5,
|
||||
/obj/item/fish/angelfish = 4,
|
||||
/obj/item/fish/catfish = 4,
|
||||
/obj/item/fish/slimefish = 2,
|
||||
/obj/item/fish/sockeye_salmon = 1,
|
||||
/obj/item/fish/arctic_char = 1,
|
||||
/obj/item/fish/three_eyes = 1,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
|
||||
|
||||
/datum/fish_source/sand
|
||||
catalog_description = "Sand"
|
||||
fish_table = list(
|
||||
FISHING_DUD = 8,
|
||||
/obj/item/fish/sand_crab = 10,
|
||||
/obj/item/fish/sand_surfer = 10,
|
||||
/obj/item/fish/bumpy = 10,
|
||||
/obj/item/coin/gold = 3,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
|
||||
|
||||
/datum/fish_source/cursed_spring
|
||||
catalog_description = null //it's a secret (sorta, I know you're reading this)
|
||||
fish_table = list(
|
||||
FISHING_DUD = 2,
|
||||
/obj/item/fish/soul = 3,
|
||||
/obj/item/fish/skin_crab = 3,
|
||||
/obj/item/fishing_rod/telescopic/master = 1,
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/fishing_rod/telescopic/master = 1,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 25
|
||||
|
||||
/datum/fish_source/portal
|
||||
fish_table = list(
|
||||
FISHING_DUD = 7,
|
||||
/obj/item/fish/goldfish = 10,
|
||||
/obj/item/fish/guppy = 10,
|
||||
/obj/item/fish/angelfish = 10,
|
||||
/obj/item/fish/three_eyes = 3,
|
||||
)
|
||||
catalog_description = "Aquarium dimension (Fishing portal generator)"
|
||||
///The name of this option shown in the radial menu on the fishing portal generator
|
||||
@@ -73,6 +131,14 @@
|
||||
/obj/item/fish/needlefish = 5,
|
||||
/obj/item/fish/armorfish = 5,
|
||||
/obj/item/fish/zipzap = 5,
|
||||
/obj/item/fish/stingray = 4,
|
||||
/obj/item/fish/swordfish = 3,
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/fish/swordfish = 2,
|
||||
)
|
||||
fish_count_regen = list(
|
||||
/obj/item/fish/swordfish = 5 MINUTES,
|
||||
)
|
||||
catalog_description = "Ocean dimension (Fishing portal generator)"
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
|
||||
@@ -104,6 +170,13 @@
|
||||
/obj/item/fish/donkfish = 5,
|
||||
/obj/item/fish/emulsijack = 5,
|
||||
/obj/item/fish/jumpercable = 5,
|
||||
/obj/item/fish/chainsawfish = 3,
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/fish/chainsawfish = 1,
|
||||
)
|
||||
fish_count_regen = list(
|
||||
/obj/item/fish/chainsawfish = 7 MINUTES,
|
||||
)
|
||||
catalog_description = "Syndicate dimension (Fishing portal generator)"
|
||||
radial_name = "Syndicate"
|
||||
@@ -130,6 +203,7 @@
|
||||
|
||||
///rewards not found in other fishing portals
|
||||
fish_table = list(
|
||||
/obj/item/fish/three_eyes = 3,
|
||||
/obj/item/fish/holo/checkered = 1,
|
||||
)
|
||||
|
||||
@@ -155,8 +229,8 @@
|
||||
challenge.bait_bounce_mult = clamp(challenge.bait_bounce_mult + (rand(-3, 3) * 0.1), 0.1, 1)
|
||||
challenge.completion_loss = max(challenge.completion_loss + rand(-2, 2), 0)
|
||||
challenge.completion_gain = max(challenge.completion_gain + rand(-1, 1), 2)
|
||||
challenge.short_jump_velocity_limit += rand(-100, 100)
|
||||
challenge.long_jump_velocity_limit += rand(-100, 100)
|
||||
challenge.mover.short_jump_velocity_limit += rand(-100, 100)
|
||||
challenge.mover.long_jump_velocity_limit += rand(-100, 100)
|
||||
var/static/list/active_effects = bitfield_to_list(FISHING_MINIGAME_ACTIVE_EFFECTS)
|
||||
for(var/effect in active_effects)
|
||||
if(prob(30))
|
||||
@@ -319,16 +393,19 @@
|
||||
/obj/item/clothing/gloves/bracer = 2,
|
||||
/obj/effect/decal/remains/human = 2,
|
||||
/obj/item/fish/mastodon = 1,
|
||||
/obj/item/fishing_rod/telescopic/master = 1,
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/clothing/gloves/bracer = 1,
|
||||
/obj/effect/decal/remains/human = 1,
|
||||
/obj/item/fish/mastodon = 1,
|
||||
/obj/item/fishing_rod/telescopic/master = 1,
|
||||
)
|
||||
fish_count_regen = list(
|
||||
/obj/item/fish/mastodon = 8 MINUTES,
|
||||
)
|
||||
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15
|
||||
|
||||
#define RANDOM_SEED "Random seed"
|
||||
|
||||
/datum/fish_source/hydro_tray
|
||||
catalog_description = "Hydroponics trays"
|
||||
fish_table = list(
|
||||
@@ -372,7 +449,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/fish_source/hydro_tray/spawn_reward(reward_path, mob/fisherman, turf/fishing_spot)
|
||||
if(reward_path != RANDOM_SEED)
|
||||
if(reward_path != FISHING_RANDOM_SEED)
|
||||
var/mob/living/created_reward = ..()
|
||||
if(istype(created_reward))
|
||||
created_reward.name = "small [created_reward.name]"
|
||||
@@ -393,5 +470,3 @@
|
||||
|
||||
var/picked_path = pick(seeds_to_draw_from)
|
||||
return new picked_path(get_turf(fishing_spot))
|
||||
|
||||
#undef RANDOM_SEED
|
||||
|
||||
Reference in New Issue
Block a user