diff --git a/code/__DEFINES/construction/material.dm b/code/__DEFINES/construction/material.dm
index 2764c0bbfaf..a8bef8cbec9 100644
--- a/code/__DEFINES/construction/material.dm
+++ b/code/__DEFINES/construction/material.dm
@@ -58,6 +58,8 @@
#define MATERIAL_AFFECT_STATISTICS (1<<3)
/// Applies the material greyscale color to the atom's greyscale color.
#define MATERIAL_GREYSCALE (1<<4)
+/// Materials like plasteel and alien alloy won't apply slowdowns.
+#define MATERIAL_NO_SLOWDOWN (1<<5)
//Special return values of [/datum/component/material_container/insert_item]
/// No material was found inside them item
diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm
index f7606b63a01..494d0541326 100644
--- a/code/__DEFINES/dcs/signals/signals_fish.dm
+++ b/code/__DEFINES/dcs/signals/signals_fish.dm
@@ -32,6 +32,8 @@
///From /obj/item/fish/interact_with_atom_secondary, sent to the target: (fish)
#define COMSIG_FISH_RELEASED_INTO "fish_released_into"
+///From /datum/fishing_challenge/New: (datum/fishing_challenge/challenge)
+#define COMSIG_ROD_BEGIN_FISHING "rod_begin_fishing"
///From /datum/fishing_challenge/New: (datum/fishing_challenge/challenge)
#define COMSIG_MOB_BEGIN_FISHING "mob_begin_fishing"
///From /datum/fishing_challenge/start_minigame_phase: (datum/fishing_challenge/challenge)
@@ -62,8 +64,11 @@
#define COMSIG_FISHING_ROD_CAUGHT_FISH "fishing_rod_caught_fish"
/// From /obj/item/fishing_rod/proc/hook_item(): (reward, user)
#define COMSIG_FISHING_ROD_HOOKED_ITEM "fishing_rod_hooked_item"
-/// From /datum/fish_source/proc/use_slot(), sent to the slotted item: (obj/item/fishing_rod/rod)
-#define COMSIG_FISHING_EQUIPMENT_SLOTTED "fishing_equipment_slotted"
+
+/// From /obj/item/fishing_rod/set_slot: (obj/item/fishing_rod/rod, slot)
+#define COMSIG_ITEM_FISHING_ROD_SLOTTED "item_fishing_rod_slotted"
+/// From /obj/item/fishing_rod/Exited: (obj/item/fishing_rod/rod, slot)
+#define COMSIG_ITEM_FISHING_ROD_UNSLOTTED "item_fishing_rod_unslotted"
/// Sent when the challenge is to be interrupted: (reason)
#define COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE "fishing_spot_interrupt_challenge"
diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm
index 43e0e8587f9..1eb3df686ed 100644
--- a/code/__DEFINES/fish.dm
+++ b/code/__DEFINES/fish.dm
@@ -33,30 +33,25 @@
// through the fishing rod, and not the hook itself. They could probably be
// handled differently, but for now that's how they work. It's grounds for
// a future refactor, however.
-/// Fishing hook trait that signifies that it's shiny. Useful for fishes
-/// that care about shiner hooks more.
-#define FISHING_HOOK_SHINY (1 << 0)
/// Fishing hook trait that lessens the bounce from hitting the edges of the minigame bar.
-#define FISHING_HOOK_WEIGHTED (1 << 1)
+#define FISHING_HOOK_WEIGHTED (1 << 0)
///See FISHING_MINIGAME_RULE_BIDIRECTIONAL
-#define FISHING_HOOK_BIDIRECTIONAL (1 << 2)
+#define FISHING_HOOK_BIDIRECTIONAL (1 << 1)
///Prevents the user from losing the game by letting the fish get away.
-#define FISHING_HOOK_NO_ESCAPE (1 << 3)
+#define FISHING_HOOK_NO_ESCAPE (1 << 2)
///Limits the completion loss of the minigame when the fsh is not on the bait area.
-#define FISHING_HOOK_ENSNARE (1 << 4)
+#define FISHING_HOOK_ENSNARE (1 << 3)
///Automatically kills the fish after a while, at the cost of killing it.
-#define FISHING_HOOK_KILL (1 << 5)
+#define FISHING_HOOK_KILL (1 << 4)
///Reduces the difficulty of the minigame
#define FISHING_LINE_CLOAKED (1 << 0)
-///Required to cast a line on lava.
-#define FISHING_LINE_REINFORCED (1 << 1)
/// Much like FISHING_HOOK_ENSNARE but for the fishing line.
-#define FISHING_LINE_BOUNCY (1 << 2)
+#define FISHING_LINE_BOUNCY (1 << 1)
/// The sorta opposite of FISHING_LINE_BOUNCY. It makes it slower to gain completion and faster to lose it.
-#define FISHING_LINE_STIFF (1 << 3)
+#define FISHING_LINE_STIFF (1 << 2)
///Skip the biting phase and go straight to the fishing phase.
-#define FISHING_LINE_AUTOREEL (1 << 4)
+#define FISHING_LINE_AUTOREEL (1 << 3)
///Keeps the bait from falling from gravity, instead allowing the player to move the bait down with right click.
#define FISHING_MINIGAME_RULE_BIDIRECTIONAL (1 << 0)
@@ -161,6 +156,9 @@
#define FISH_FLAG_PETTED (1<<2)
///This fish can be scanned to complete fish scanning experiments
#define FISH_FLAG_EXPERIMENT_SCANNABLE (1<<3)
+///It lets us know that fish/update_size_and_weight() is currently running.
+#define FISH_FLAG_UPDATING_SIZE_AND_WEIGHT (1<<3)
+
#define MIN_AQUARIUM_TEMP T0C
#define MAX_AQUARIUM_TEMP (T0C + 100)
@@ -226,6 +224,15 @@
///We multiply the weight of fish inside the loot table by this value if we are goofy enough to fish without a bait.
#define FISH_WEIGHT_MULT_WITHOUT_BAIT 0.15
+
+/**
+ * Flag for fish sources. It makes large explosions less efficient at spawning fish.
+ * Meant for lazy fishing spots that cover multiple turfs (rivers, oceans etc.)
+ */
+#define FISH_SOURCE_FLAG_EXPLOSIVE_MALUS (1<<0)
+/// The fish source is not elegible for random rewards from bluespace fishing rods
+#define FISH_SOURCE_FLAG_NO_BLUESPACE_ROD (1<<1)
+
/**
* A macro to ensure the wikimedia filenames of fish icons are unique, especially since there're a couple fish that have
* quite ambiguous names/icon_states like "checkered" or "pike"
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index 08e54d92eed..f4f5688819b 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -787,6 +787,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_UNCATCHABLE "uncatchable"
/// You won't catch duds while fishing with this rod.
#define TRAIT_ROD_REMOVE_FISHING_DUD "rod_remove_fishing_dud"
+/// This rod ignores environmental conditions for fishing (like low light for nocturnal fish)
+#define TRAIT_ROD_IGNORE_ENVIRONMENT "rod_ignore_environment"
+/// This rod attracts fish with the shiny lover fish trait
+#define TRAIT_ROD_ATTRACT_SHINY_LOVERS "rod_attract_shiny_lovers"
+/// This rod can be used to fish on lava
+#define TRAIT_ROD_LAVA_USABLE "rod_lava_usable"
/// Stuff that can go inside fish cases
#define TRAIT_FISH_CASE_COMPATIBILE "fish_case_compatibile"
/// If the item can be used as a bit.
@@ -801,8 +807,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_OMNI_BAIT "omni_bait"
/// The bait won't be consumed when used
#define TRAIT_BAIT_UNCONSUMABLE "bait_unconsumable"
-/// This bait ignores environmental conditions for fishing (like low light for nocturnal fish)
-#define TRAIT_BAIT_IGNORE_ENVIRONMENT "bait_ignore_environment"
/**
* This bait won't apply TRAIT_ROD_REMOVE_FISHING_DUD to the rod it's attached on,
* instead, it'll allow the fishing dud to be there unless there's at least one fish that likes the bait
@@ -1023,6 +1027,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_FISH_SHOULD_TWOHANDED "fish_should_twohanded"
///This fish won't be killed when cooked.
#define TRAIT_FISH_SURVIVE_COOKING "fish_survive_cooking"
+///This fish is healed by milk and hurt by bone hurting juice
+#define TRAIT_FISH_MADE_OF_BONE "fish_made_of_bone"
/**
* This fish has been fed teslium without the electrogenesis having trait.
* Gives the electrogenesis, but at halved output, and it hurts the fish over time.
diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm
index b0d5e835907..46a91854931 100644
--- a/code/_globalvars/traits/_traits.dm
+++ b/code/_globalvars/traits/_traits.dm
@@ -573,7 +573,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
/obj/item = list(
"TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING,
"TRAIT_BAIT_ALLOW_FISHING_DUD" = TRAIT_BAIT_ALLOW_FISHING_DUD,
- "TRAIT_BAIT_IGNORE_ENVIRONMENT" = TRAIT_BAIT_IGNORE_ENVIRONMENT,
"TRAIT_BAIT_UNCONSUMABLE" = TRAIT_BAIT_UNCONSUMABLE,
"TRAIT_BAKEABLE" = TRAIT_BAKEABLE,
"TRAIT_BASIC_QUALITY_BAIT" = TRAIT_BASIC_QUALITY_BAIT,
@@ -638,6 +637,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_FISH_FLOPPING" = TRAIT_FISH_FLOPPING,
"TRAIT_FISH_FROM_CASE" = TRAIT_FISH_FROM_CASE,
"TRAIT_FISH_INK_ON_COOLDOWN" = TRAIT_FISH_INK_ON_COOLDOWN,
+ "TRAIT_FISH_MADE_OF_BONE" = TRAIT_FISH_MADE_OF_BONE,
"TRAIT_FISH_MUTAGENIC" = TRAIT_FISH_MUTAGENIC,
"TRAIT_FISH_NO_HUNGER" = TRAIT_FISH_NO_HUNGER,
"TRAIT_FISH_NO_MATING" = TRAIT_FISH_NO_MATING,
@@ -655,6 +655,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_YUCKY_FISH" = TRAIT_YUCKY_FISH,
),
/obj/item/fishing_rod = list(
+ "TRAIT_ROD_ATTRACT_SHINY_LOVERS" = TRAIT_ROD_ATTRACT_SHINY_LOVERS,
+ "TRAIT_ROD_IGNORE_ENVIRONMENT" = TRAIT_ROD_IGNORE_ENVIRONMENT,
+ "TRAIT_ROD_LAVA_USABLE" = TRAIT_ROD_LAVA_USABLE,
"TRAIT_ROD_REMOVE_FISHING_DUD" = TRAIT_ROD_REMOVE_FISHING_DUD,
),
/obj/item/integrated_circuit = list(
diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm
index 31c88b492d6..9d1b47800b8 100644
--- a/code/_globalvars/traits/admin_tooling.dm
+++ b/code/_globalvars/traits/admin_tooling.dm
@@ -357,6 +357,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_FISH_FED_LUBE" = TRAIT_FISH_FED_LUBE,
"TRAIT_FISH_FROM_CASE" = TRAIT_FISH_FROM_CASE,
"TRAIT_FISH_INK_ON_COOLDOWN" = TRAIT_FISH_INK_ON_COOLDOWN,
+ "TRAIT_FISH_MADE_OF_BONE" = TRAIT_FISH_MADE_OF_BONE,
"TRAIT_FISH_MUTAGENIC" = TRAIT_FISH_MUTAGENIC,
"TRAIT_FISH_NO_HUNGER" = TRAIT_FISH_NO_HUNGER,
"TRAIT_FISH_NO_MATING" = TRAIT_FISH_NO_MATING,
@@ -373,6 +374,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_YUCKY_FISH" = TRAIT_YUCKY_FISH,
),
/obj/item/fishing_rod = list(
+ "TRAIT_ROD_ATTRACT_SHINY_LOVERS" = TRAIT_ROD_ATTRACT_SHINY_LOVERS,
+ "TRAIT_ROD_IGNORE_ENVIRONMENT" = TRAIT_ROD_IGNORE_ENVIRONMENT,
+ "TRAIT_ROD_LAVA_USABLE" = TRAIT_ROD_LAVA_USABLE,
"TRAIT_ROD_REMOVE_FISHING_DUD" = TRAIT_ROD_REMOVE_FISHING_DUD,
),
/obj/item/organ/liver = list(
diff --git a/code/datums/elements/shiny_bait.dm b/code/datums/elements/shiny_bait.dm
new file mode 100644
index 00000000000..72b34ec8808
--- /dev/null
+++ b/code/datums/elements/shiny_bait.dm
@@ -0,0 +1,34 @@
+///A component that gives fishing rod TRAIT_ROD_ATTRACT_SHINY_LOVERS when the attached item is used as bait.
+/datum/element/shiny_bait
+
+/datum/element/shiny_bait/Attach(obj/item/target)
+ . = ..()
+ if(!isitem(target))
+ return ELEMENT_INCOMPATIBLE
+ RegisterSignal(target, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(target, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
+ if(istype(target.loc, /obj/item/fishing_rod))
+ ADD_TRAIT(target.loc, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+ else if(istype(target, /obj/item/fishing_rod))
+ ADD_TRAIT(target, TRAIT_ROD_ATTRACT_SHINY_LOVERS, "[REF(src)]_rod")
+
+/datum/element/shiny_bait/Detach(obj/item/source)
+ UnregisterSignal(source, list(
+ COMSIG_ITEM_FISHING_ROD_SLOTTED,
+ COMSIG_ITEM_FISHING_ROD_UNSLOTTED,
+ ))
+ if(istype(source.loc, /obj/item/fishing_rod))
+ REMOVE_TRAIT(source.loc, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+ else if(istype(source, /obj/item/fishing_rod))
+ REMOVE_TRAIT(source, TRAIT_ROD_ATTRACT_SHINY_LOVERS, "[REF(src)]_rod")
+ return ..()
+
+/datum/element/shiny_bait/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ if(slot == ROD_SLOT_BAIT)
+ ADD_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(source))
+
+/datum/element/shiny_bait/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ if(slot == ROD_SLOT_BAIT)
+ REMOVE_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(source))
diff --git a/code/datums/elements/spooky.dm b/code/datums/elements/spooky.dm
index 89d53c4e997..62189371b61 100644
--- a/code/datums/elements/spooky.dm
+++ b/code/datums/elements/spooky.dm
@@ -1,13 +1,17 @@
/datum/element/spooky
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
- var/too_spooky = TRUE //will it spawn a new instrument?
+ ///will it spawn a new instrument
+ var/too_spooky = TRUE
+ ///Once used, the element is detached
+ var/single_use = FALSE
-/datum/element/spooky/Attach(datum/target, too_spooky = TRUE)
+/datum/element/spooky/Attach(datum/target, too_spooky = TRUE, single_use = FALSE)
. = ..()
if(!isitem(target))
return ELEMENT_INCOMPATIBLE
src.too_spooky = too_spooky
+ src.single_use = single_use
RegisterSignal(target, COMSIG_ITEM_ATTACK, PROC_REF(spectral_attack))
/datum/element/spooky/Detach(datum/source)
@@ -26,6 +30,9 @@
if(U.getStaminaLoss() > 95)
to_chat(U, "Your ears weren't meant for this spectral sound.")
INVOKE_ASYNC(src, PROC_REF(spectral_change), U)
+ if(single_use)
+ to_chat(user, span_warning("You feel like [source] has lost its spookiness..."))
+ Detach(source)
return
if(ishuman(C))
@@ -42,6 +49,9 @@
to_chat(C, "DOOT")
to_chat(C, span_robot("You're feeling more bony."))
INVOKE_ASYNC(src, PROC_REF(spectral_change), H)
+ if(single_use)
+ to_chat(user, span_warning("You feel like [source] has lost its spookiness..."))
+ Detach(source)
else //the sound will spook monkeys.
C.set_jitter_if_lower(30 SECONDS)
diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm
index cff0ea0e6d1..d179be2dc01 100644
--- a/code/datums/materials/_material.dm
+++ b/code/datums/materials/_material.dm
@@ -78,6 +78,26 @@ Simple datum which is instanced once per type and is used for every object of sa
/// The slowdown that is added to items.
var/added_slowdown = 0
+ /// Fish made of or infused with this material have their weight multiplied by this value.
+ var/fish_weight_modifier = 1
+
+ /// Additive bonus/malus to the fishing difficulty modifier of any rod made of this item. Negative is good, positive bad
+ var/fishing_difficulty_modifier = 0
+ /// Additive bonus/malus to the cast range of the fishing rod
+ var/fishing_cast_range = 0
+ /// The multiplier of how much experience is gained when using a fishing rod made of this material
+ var/fishing_experience_multiplier = 1
+ /// The multiplier to the completion gain of the fishing rod made of this material
+ var/fishing_completion_speed = 1
+ /// The multiplier of the bait/bobber speed of the fishing challenge for fishing rods made of this material
+ var/fishing_bait_speed_mult = 1
+ /// The multiplier of the deceleration/friction for fishing rods made of this material
+ var/fishing_deceleration_mult = 1
+ /// The multiplier of the bounciness of the bait/bobber upon hitting the edges of the minigame area
+ var/fishing_bounciness_mult = 1
+ /// The multiplier of negative velocity that pulls the bait/bobber of a fishing rod down when not holding the click
+ var/fishing_gravity_mult = 1
+
/** Handles initializing the material.
*
* Arguments:
@@ -100,7 +120,9 @@ Simple datum which is instanced once per type and is used for every object of sa
///This proc is called when the material becomes the one the object is composed of the most
/datum/material/proc/on_main_applied(atom/source, mat_amount, multiplier)
- return
+ SHOULD_CALL_PARENT(TRUE)
+ if(beauty_modifier >= 0.15 && HAS_TRAIT(source, TRAIT_FISHING_BAIT))
+ source.AddElement(/datum/element/shiny_bait)
/datum/material/proc/setup_glow(turf/on)
if(GET_TURF_PLANE_OFFSET(on) != GET_LOWEST_STACK_OFFSET(on.z)) // We ain't the bottom brother
@@ -126,7 +148,9 @@ Simple datum which is instanced once per type and is used for every object of sa
///This proc is called when the material is no longer the one the object is composed by the most
/datum/material/proc/on_main_removed(atom/source, mat_amount, multiplier)
- return
+ SHOULD_CALL_PARENT(TRUE)
+ if(beauty_modifier >= 0.15 && HAS_TRAIT(source, TRAIT_FISHING_BAIT))
+ source.RemoveElement(/datum/element/shiny_bait)
/**
* This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption.
diff --git a/code/datums/materials/alloys.dm b/code/datums/materials/alloys.dm
index d13a88c49c3..d8c107d21aa 100644
--- a/code/datums/materials/alloys.dm
+++ b/code/datums/materials/alloys.dm
@@ -42,6 +42,20 @@
composition = list(/datum/material/iron=1, /datum/material/plasma=1)
mat_rust_resistance = RUST_RESISTANCE_REINFORCED
added_slowdown = 0.05
+ fish_weight_modifier = 1.75
+ fishing_difficulty_modifier = 5
+ fishing_experience_multiplier = 1.1
+ fishing_gravity_mult = 1.6
+
+/datum/material/alloy/plasteel/on_applied(atom/target, mat_amount, multiplier)
+ . = ..()
+ if(istype(target, /obj/item/fishing_rod))
+ ADD_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
+
+/datum/material/alloy/plasteel/on_removed(atom/target, mat_amount, multiplier)
+ . = ..()
+ if(istype(target, /obj/item/fishing_rod))
+ REMOVE_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
/** Plastitanium
*
@@ -65,6 +79,20 @@
)
composition = list(/datum/material/titanium=1, /datum/material/plasma=1)
mat_rust_resistance = RUST_RESISTANCE_TITANIUM
+ fish_weight_modifier = 1.1
+ fishing_difficulty_modifier = -10
+ fishing_cast_range = 1
+ fishing_experience_multiplier = 0.95
+
+/datum/material/alloy/plastitanium/on_applied(atom/target, mat_amount, multiplier)
+ . = ..()
+ if(istype(target, /obj/item/fishing_rod))
+ ADD_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
+
+/datum/material/alloy/plastitanium/on_removed(atom/target, mat_amount, multiplier)
+ . = ..()
+ if(istype(target, /obj/item/fishing_rod))
+ REMOVE_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
/** Plasmaglass
*
@@ -90,6 +118,10 @@
MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE,
)
composition = list(/datum/material/glass=1, /datum/material/plasma=0.5)
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = 5
+ fishing_experience_multiplier = 1.3
+ fishing_gravity_mult = 0.9
/** Titaniumglass
*
@@ -114,6 +146,10 @@
MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE,
)
composition = list(/datum/material/glass=1, /datum/material/titanium=0.5)
+ fish_weight_modifier = 1.25
+ fishing_difficulty_modifier = -5
+ fishing_experience_multiplier = 1.25
+ fishing_gravity_mult = 0.95
/** Plastitanium Glass
*
@@ -139,6 +175,9 @@
MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE,
)
composition = list(/datum/material/glass=1, /datum/material/alloy/plastitanium=0.5)
+ fish_weight_modifier = 1.2
+ fishing_experience_multiplier = 1.5
+ fishing_gravity_mult = 0.9
/** Alien Alloy
*
@@ -164,13 +203,26 @@
)
composition = list(/datum/material/iron=2, /datum/material/plasma=2)
added_slowdown = 0.1
+ fish_weight_modifier = 2.4
+ fishing_difficulty_modifier = -25
+ fishing_cast_range = 2
+ fishing_experience_multiplier = 0.5
+ fishing_completion_speed = 2
+ fishing_bait_speed_mult = 1.25
+ fishing_deceleration_mult = 1.5
+ fishing_bounciness_mult = 0.5
+ fishing_gravity_mult = 2
/datum/material/alloy/alien/on_applied(atom/target, mat_amount, multiplier)
. = ..()
if(isobj(target))
target.AddElement(/datum/element/obj_regen, _rate=0.02) // 2% regen per tick.
+ if(istype(target, /obj/item/fishing_rod))
+ ADD_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
/datum/material/alloy/alien/on_removed(atom/target, mat_amount, multiplier)
. = ..()
if(isobj(target))
target.RemoveElement(/datum/element/obj_regen, _rate=0.02)
+ if(istype(target, /obj/item/fishing_rod))
+ REMOVE_TRAIT(target, TRAIT_ROD_LAVA_USABLE, REF(src))
diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm
index 76d44c1f164..f21759f42a7 100644
--- a/code/datums/materials/basemats.dm
+++ b/code/datums/materials/basemats.dm
@@ -19,6 +19,8 @@
minimum_value_override = 0
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_COMMON
+ fish_weight_modifier = 1.3
+ fishing_gravity_mult = 1.1
/datum/material/iron/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
@@ -51,6 +53,13 @@
mineral_rarity = MATERIAL_RARITY_COMMON
points_per_unit = 1 / SHEET_MATERIAL_AMOUNT
texture_layer_icon_state = "shine"
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = 5
+ fishing_experience_multiplier = 1.2
+ fishing_bait_speed_mult = 0.9
+ fishing_deceleration_mult = 1.2
+ fishing_bounciness_mult = 0.5
+ fishing_gravity_mult = 0.9
/datum/material/glass/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5, sharpness = TRUE) //cronch
@@ -92,6 +101,14 @@ Unless you know what you're doing, only use the first three numbers. They're in
mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS
points_per_unit = 16 / SHEET_MATERIAL_AMOUNT
texture_layer_icon_state = "shine"
+ fish_weight_modifier = 1.35
+ fishing_difficulty_modifier = -5
+ fishing_experience_multiplier = 0.85
+ fishing_completion_speed = 1.1
+ fishing_bait_speed_mult = 1.1
+ fishing_deceleration_mult = 1.1
+ fishing_bounciness_mult = 0.9
+ fishing_gravity_mult = 1.15
/datum/material/silver/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
@@ -120,6 +137,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
mineral_rarity = MATERIAL_RARITY_PRECIOUS
points_per_unit = 18 / SHEET_MATERIAL_AMOUNT
texture_layer_icon_state = "shine"
+ fish_weight_modifier = 1.5
+ fishing_difficulty_modifier = -10
+ fishing_cast_range = 1
+ fishing_experience_multiplier = 0.75
+ fishing_completion_speed = 1.2
+ fishing_bait_speed_mult = 1.3
+ fishing_deceleration_mult = 1.2
+ fishing_bounciness_mult = 0.8
+ fishing_gravity_mult = 1.25
/datum/material/gold/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(10, BRUTE, BODY_ZONE_HEAD, wound_bonus = 5)
@@ -142,12 +168,23 @@ Unless you know what you're doing, only use the first three numbers. They're in
alpha = 132
starlight_color = COLOR_BLUE_LIGHT
value_per_unit = 500 / SHEET_MATERIAL_AMOUNT
+ strength_modifier = 1.1
+ integrity_modifier = 1.25
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC
beauty_modifier = 0.3
armor_modifiers = list(MELEE = 1.3, BULLET = 1.3, LASER = 0.6, ENERGY = 1, BOMB = 1.2, BIO = 1, FIRE = 1, ACID = 1)
mineral_rarity = MATERIAL_RARITY_RARE
points_per_unit = 50 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 1.4
+ fishing_difficulty_modifier = -13
+ fishing_cast_range = -1
+ fishing_experience_multiplier = 0.7
+ fishing_completion_speed = 1.25
+ fishing_bait_speed_mult = 1.3
+ fishing_deceleration_mult = 1.25
+ fishing_bounciness_mult = 0.8
+ fishing_gravity_mult = 1.2
/datum/material/diamond/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
@@ -174,6 +211,12 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.5, BULLET = 1.4, LASER = 0.5, ENERGY = 0.5, FIRE = 1, ACID = 1)
mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS
points_per_unit = 30 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 2
+ fishing_completion_speed = 0.9
+ fishing_bait_speed_mult = 0.8
+ fishing_deceleration_mult = 1.4
+ fishing_bounciness_mult = 0.6
+ fishing_gravity_mult = 1.6
/datum/material/uranium/on_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -217,18 +260,25 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.4, BULLET = 0.7, ENERGY = 1.2, BIO = 1.2, ACID = 0.5)
mineral_rarity = MATERIAL_RARITY_PRECIOUS
points_per_unit = 15 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 1.3
+ fishing_deceleration_mult = 1.3
+ fishing_bounciness_mult = 0.6
/datum/material/plasma/on_applied(atom/source, mat_amount, multiplier)
. = ..()
if(ismovable(source))
source.AddElement(/datum/element/firestacker, 1 * multiplier)
source.AddComponent(/datum/component/combustible_flooder, "plasma", mat_amount * 0.05 * multiplier) //Empty temp arg, fully dependent on whatever ignited it.
+ if(istype(source, /obj/item/fishing_rod))
+ ADD_TRAIT(source, TRAIT_ROD_LAVA_USABLE, REF(src))
/datum/material/plasma/on_removed(atom/source, mat_amount, multiplier)
. = ..()
source.RemoveElement(/datum/element/firestacker, mat_amount = 1 * multiplier)
qdel(source.GetComponent(/datum/component/combustible_flooder))
qdel(source.GetComponent(/datum/component/explodable))
+ if(istype(source, /obj/item/fishing_rod))
+ ADD_TRAIT(source, TRAIT_ROD_LAVA_USABLE, REF(src))
/datum/material/plasma/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/toxin/plasma, rand(6, 8))
@@ -258,6 +308,35 @@ Unless you know what you're doing, only use the first three numbers. They're in
tradable = TRUE
tradable_base_quantity = MATERIAL_QUANTITY_EXOTIC
texture_layer_icon_state = "shine"
+ fish_weight_modifier = 1.3
+ fishing_difficulty_modifier = -5
+ fishing_cast_range = 5 //space-bending scifi magic
+ fishing_experience_multiplier = 0.85
+ fishing_completion_speed = 1.1
+ fishing_bait_speed_mult = 1.2
+ fishing_deceleration_mult = 0.9
+ fishing_bounciness_mult = 1.1
+
+/datum/material/bluespace/on_main_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ RegisterSignal(source, COMSIG_ROD_BEGIN_FISHING, PROC_REF(on_begin_fishing))
+
+/datum/material/bluespace/proc/on_begin_fishing(obj/item/fishing_rod/rod, datum/fishing_challenge/challenge)
+ SIGNAL_HANDLER
+ if(prob(67))
+ return
+ var/list/elegible_fish_sources = flatten_list(GLOB.preset_fish_sources)
+ for(var/datum/fish_source/source as anything in elegible_fish_sources)
+ if(source.fish_source_flags & FISH_SOURCE_FLAG_NO_BLUESPACE_ROD)
+ elegible_fish_sources -= source
+ var/datum/fish_source/new_source = pick(elegible_fish_sources)
+ challenge.register_reward_signals(new_source)
+
+/datum/material/bluespace/on_main_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ UnregisterSignal(source, COMSIG_ROD_BEGIN_FISHING)
/datum/material/bluespace/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/bluespace, rand(5, 8))
@@ -284,17 +363,50 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(BOMB = 100, FIRE = 10) //Clowns cant be blown away.
mineral_rarity = MATERIAL_RARITY_UNDISCOVERED
points_per_unit = 60 / SHEET_MATERIAL_AMOUNT
+ fishing_difficulty_modifier = 20 //can't get a good grip on slipperiness.
+ fishing_cast_range = 3 //long slide
+ fishing_experience_multiplier = 1.6
+ fishing_completion_speed = 1.3
+ fishing_bait_speed_mult = 1.5
+ fishing_deceleration_mult = 0.5
+ fishing_bounciness_mult = 2
/datum/material/bananium/on_applied(atom/source, mat_amount, multiplier)
. = ..()
source.LoadComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50 * multiplier, falloff_exponent = 20)
source.AddComponent(/datum/component/slippery, min(mat_amount / 10 * multiplier, 80 * multiplier))
+/datum/material/bananium/on_main_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ RegisterSignal(source, COMSIG_ROD_BEGIN_FISHING, PROC_REF(on_begin_fishing))
+
+/datum/material/bananium/proc/on_begin_fishing(obj/item/fishing_rod/rod, datum/fishing_challenge/challenge)
+ SIGNAL_HANDLER
+ if(prob(40))
+ RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, PROC_REF(roll_funny_fish))
+
+/datum/material/bananium/proc/roll_funny_fish(datum/source, obj/item/fishing_rod/rod, mob/fisherman, atom/location, list/rewards)
+ SIGNAL_HANDLER
+ var/static/list/funny_fish = list(
+ /obj/item/fish/clownfish = 5,
+ /obj/item/fish/clownfish/lube = 3,
+ /obj/item/fish/soul = 2,
+ /obj/item/fish/skin_crab = 2,
+ /obj/item/fish/donkfish = 2,
+ )
+ rewards += pick_weight(funny_fish)
+
/datum/material/bananium/on_removed(atom/source, mat_amount, multiplier)
. = ..()
qdel(source.GetComponent(/datum/component/slippery))
qdel(source.GetComponent(/datum/component/squeak))
+/datum/material/bananium/on_main_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ UnregisterSignal(source, COMSIG_ROD_BEGIN_FISHING)
+
/datum/material/bananium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/consumable/banana, rand(8, 12))
source_item?.reagents?.add_reagent(/datum/reagent/consumable/banana, source_item.reagents.total_volume*(2/5))
@@ -323,6 +435,14 @@ Unless you know what you're doing, only use the first three numbers. They're in
mat_rust_resistance = RUST_RESISTANCE_TITANIUM
mineral_rarity = MATERIAL_RARITY_SEMIPRECIOUS
texture_layer_icon_state = "shine"
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = -5
+ fishing_cast_range = 1
+ fishing_completion_speed = 1.15
+ fishing_bait_speed_mult = 1.15
+ fishing_deceleration_mult = 1.3
+ fishing_bounciness_mult = 0.75
+ fishing_gravity_mult = 1.1
/datum/material/titanium/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
@@ -345,6 +465,24 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.35, BULLET = 2, LASER = 0.5, ENERGY = 1.25, BOMB = 1.25, BIO = 1, FIRE = 1.4, ACID = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle.
mineral_rarity = MATERIAL_RARITY_UNDISCOVERED
points_per_unit = 100 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 1.5
+ fishing_difficulty_modifier = -18
+ fishing_cast_range = 1
+ fishing_experience_multiplier = 3.2 //grind all the way to level 100 in no time.
+ fishing_completion_speed = 1.3
+ fishing_bait_speed_mult = 0.9
+ fishing_deceleration_mult = 1.2
+ fishing_gravity_mult = 1.25
+
+/datum/material/runite/on_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ ADD_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //light-absorbing, environment-cancelling fishing rod.
+
+/datum/material/runite/on_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ REMOVE_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //light-absorbing, environment-cancelling fishing rod.
/datum/material/runite/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = 10)
@@ -370,6 +508,14 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.5, BULLET = 1.1, LASER = 0.3, ENERGY = 0.5, BOMB = 1, BIO = 1, FIRE = 1.1, ACID = 1)
mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Nobody's found oil on lavaland yet.
points_per_unit = 4 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 0.8
+ fishing_difficulty_modifier = -5
+ fishing_cast_range = 2
+ fishing_experience_multiplier = 1.2
+ fishing_bait_speed_mult = 1.3
+ fishing_deceleration_mult = 0.8
+ fishing_bounciness_mult = 1.3
+ fishing_gravity_mult = 0.85
/datum/material/plastic/on_accidental_mat_consumption(mob/living/carbon/eater, obj/item/food)
eater.reagents.add_reagent(/datum/reagent/plastic_polymers, rand(6, 8))
@@ -400,6 +546,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.1
armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 0.4, ENERGY = 0.4, BOMB = 1, BIO = 0.2, ACID = 0.3)
texture_layer_icon_state = "woodgrain"
+ fish_weight_modifier = 0.5
+ fishing_difficulty_modifier = 8
+ fishing_cast_range = -1
+ fishing_experience_multiplier = 1.3
+ fishing_completion_speed = 0.9
+ fishing_bait_speed_mult = 0.8
+ fishing_deceleration_mult = 1.3
+ fishing_bounciness_mult = 0.4
+ fishing_gravity_mult = 0.8
/datum/material/wood/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -438,6 +593,25 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.5, BULLET = 1.5, LASER = 1.3, ENERGY = 1.3, BOMB = 1, BIO = 1, FIRE = 2.5, ACID = 1)
mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Doesn't naturally spawn on lavaland.
points_per_unit = 100 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 1.6
+ fishing_difficulty_modifier = -23
+ fishing_cast_range = 1
+ fishing_experience_multiplier = 0.6
+ fishing_completion_speed = 1.3
+ fishing_bait_speed_mult = 1.3
+ fishing_deceleration_mult = 1.3
+ fishing_bounciness_mult = 0.7
+ fishing_gravity_mult = 1.4
+
+/datum/material/adamantine/on_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ ADD_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //light-absorbing, environment-cancelling fishing rod.
+
+/datum/material/adamantine/on_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ REMOVE_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //light-absorbing, environment-cancelling fishing rod.
/datum/material/adamantine/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = 10)
@@ -461,6 +635,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.5
mineral_rarity = MATERIAL_RARITY_UNDISCOVERED //Doesn't naturally spawn on lavaland.
points_per_unit = 100 / SHEET_MATERIAL_AMOUNT
+ fish_weight_modifier = 1.4
+ fishing_difficulty_modifier = -25
+ fishing_cast_range = 2
+ fishing_experience_multiplier = 0.5
+ fishing_completion_speed = 1.35
+ fishing_bait_speed_mult = 1.35
+ fishing_deceleration_mult = 1.35
+ fishing_bounciness_mult = 0.65
+ fishing_gravity_mult = 1.4
/datum/material/mythril/on_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -494,6 +677,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
sheet_type = /obj/item/stack/sheet/hot_ice
value_per_unit = 400 / SHEET_MATERIAL_AMOUNT
beauty_modifier = 0.2
+ fish_weight_modifier = 0.9
+ fishing_difficulty_modifier = -10
+ fishing_cast_range = 1
+ fishing_experience_multiplier = 0.9
+ fishing_completion_speed = 1.4
+ fishing_bait_speed_mult = 1.5
+ fishing_deceleration_mult = 0.5
+ fishing_bounciness_mult = 0.3
+ fishing_gravity_mult = 0.8
/datum/material/hot_ice/on_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -526,6 +718,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.35
strength_modifier = 1.2
armor_modifiers = list(MELEE = 1.35, BULLET = 1.3, LASER = 1.3, ENERGY = 1.25, BOMB = 0.7, BIO = 1, FIRE = 1.3, ACID = 1)
+ fish_weight_modifier = 0.6 //It may be metallic, but it's just "denser" hydrogen at the end of the day, no?
+ fishing_difficulty_modifier = -15
+ fishing_cast_range = 4
+ fishing_experience_multiplier = 0.8
+ fishing_completion_speed = 1.4
+ fishing_bait_speed_mult = 1.6
+ fishing_deceleration_mult = 0.8
+ fishing_bounciness_mult = 1.7
+ fishing_gravity_mult = 0.7
/datum/material/metalhydrogen/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(15, BRUTE, BODY_ZONE_HEAD, wound_bonus = 7)
@@ -549,6 +750,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.25
turf_sound_override = FOOTSTEP_SAND
texture_layer_icon_state = "sand"
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = 30 //Sand fishing rods? What the hell are you doing?
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.2
+ fishing_completion_speed = 0.8
+ fishing_bait_speed_mult = 0.8
+ fishing_deceleration_mult = 2.5
+ fishing_bounciness_mult = 0.3
+ fishing_gravity_mult = 0.9
/datum/material/sand/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.adjust_disgust(17)
@@ -571,6 +781,15 @@ Unless you know what you're doing, only use the first three numbers. They're in
beauty_modifier = 0.3
turf_sound_override = FOOTSTEP_WOOD
texture_layer_icon_state = "brick"
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = 25 //Sand fishing rods? What the hell are you doing?
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.3
+ fishing_completion_speed = 0.9
+ fishing_bait_speed_mult = 0.8
+ fishing_deceleration_mult = 2.5
+ fishing_bounciness_mult = 0.2
+ fishing_gravity_mult = 0.9
/datum/material/snow
name = "snow"
@@ -582,11 +801,22 @@ Unless you know what you're doing, only use the first three numbers. They're in
MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE,
)
sheet_type = /obj/item/stack/sheet/mineral/snow
+ strength_modifier = 0.4
+ integrity_modifier = 0.4
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
armor_modifiers = list(MELEE = 0.25, BULLET = 0.25, LASER = 0.25, ENERGY = 0.25, BOMB = 0.25, BIO = 0.25, FIRE = 0.25, ACID = 1.5)
beauty_modifier = 0.3
turf_sound_override = FOOTSTEP_SAND
texture_layer_icon_state = "sand"
+ fish_weight_modifier = 0.8
+ fishing_difficulty_modifier = 25
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.3
+ fishing_completion_speed = 0.9
+ fishing_bait_speed_mult = 0.75
+ fishing_deceleration_mult = 0.3
+ fishing_bounciness_mult = 0.2
+ fishing_gravity_mult = 0.7
/datum/material/snow/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/water, rand(5, 10))
@@ -607,6 +837,14 @@ Unless you know what you're doing, only use the first three numbers. They're in
armor_modifiers = list(MELEE = 1.2, BULLET = 1.2, LASER = 1, ENERGY = 1, BOMB = 1.2, BIO = 1.2, FIRE = 1.5, ACID = 1.5)
beauty_modifier = -0.15
texture_layer_icon_state = "runed"
+ fish_weight_modifier = 1.5
+ fishing_difficulty_modifier = -12
+ fishing_experience_multiplier = 0.9
+ fishing_completion_speed = 1.2
+ fishing_bait_speed_mult = 1.666
+ fishing_deceleration_mult = 1.666
+ fishing_bounciness_mult = 0.666
+ fishing_gravity_mult = 1.666
/datum/material/runedmetal/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.reagents.add_reagent(/datum/reagent/fuel/unholywater, rand(8, 12))
@@ -627,6 +865,11 @@ Unless you know what you're doing, only use the first three numbers. They're in
value_per_unit = 50 / SHEET_MATERIAL_AMOUNT
armor_modifiers = list(MELEE = 1, BULLET = 1, LASER = 1, ENERGY = 1, BOMB = 1, BIO = 1, FIRE = 1.5, ACID = 1.5)
beauty_modifier = 0.2
+ fish_weight_modifier = 1.4
+ fishing_bait_speed_mult = 1.1
+ fishing_deceleration_mult = 0.8
+ fishing_bounciness_mult = 1.2
+ fishing_gravity_mult = 1.05
/datum/material/paper
name = "paper"
@@ -640,23 +883,47 @@ Unless you know what you're doing, only use the first three numbers. They're in
)
sheet_type = /obj/item/stack/sheet/paperframes
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
+ strength_modifier = 0.3
armor_modifiers = list(MELEE = 0.1, BULLET = 0.1, LASER = 0.1, ENERGY = 0.1, BOMB = 0.1, BIO = 0.1, ACID = 1.5)
beauty_modifier = 0.3
turf_sound_override = FOOTSTEP_SAND
texture_layer_icon_state = "paper"
+ fish_weight_modifier = 0.4
+ fishing_difficulty_modifier = 40 //child's play
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.1
+ fishing_bait_speed_mult = 0.7
+ fishing_deceleration_mult = 1.5
+ fishing_bounciness_mult = 0.2
+ fishing_gravity_mult = 0.6
/datum/material/paper/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
- if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS)
- var/obj/paper = source
- paper.resistance_flags |= FLAMMABLE
- paper.obj_flags |= UNIQUE_RENAME
+ if(!isobj(source) || !(source.material_flags & MATERIAL_AFFECT_STATISTICS))
+ return
+ var/obj/paper = source
+ paper.resistance_flags |= FLAMMABLE
+ paper.obj_flags |= UNIQUE_RENAME
+ if(istype(paper, /obj/item/fishing_rod))
+ RegisterSignal(paper, COMSIG_ROD_BEGIN_FISHING, PROC_REF(on_begin_fishing))
+
+/datum/material/paper/proc/on_begin_fishing(obj/item/fishing_rod/rod, datum/fishing_challenge/challenge)
+ SIGNAL_HANDLER
+ if(prob(40)) //consider the default reward and it's 15%
+ RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, PROC_REF(roll_stickman))
+
+/datum/material/paper/proc/roll_stickman(datum/source, obj/item/fishing_rod/rod, mob/fisherman, atom/location, list/rewards)
+ SIGNAL_HANDLER
+ rewards += pick(/mob/living/basic/stickman, /mob/living/basic/stickman/dog, /mob/living/basic/stickman/ranged)
/datum/material/paper/on_main_removed(atom/source, mat_amount, multiplier)
- if(isobj(source) && source.material_flags & MATERIAL_AFFECT_STATISTICS)
- var/obj/paper = source
- paper.resistance_flags &= ~FLAMMABLE
- return ..()
+ . = ..()
+ if(!isobj(source) || !(source.material_flags & MATERIAL_AFFECT_STATISTICS))
+ return
+ var/obj/paper = source
+ paper.resistance_flags &= ~FLAMMABLE
+ if(istype(paper, /obj/item/fishing_rod))
+ UnregisterSignal(paper, COMSIG_ROD_BEGIN_FISHING)
/datum/material/cardboard
name = "cardboard"
@@ -670,8 +937,17 @@ Unless you know what you're doing, only use the first three numbers. They're in
)
sheet_type = /obj/item/stack/sheet/cardboard
value_per_unit = 6 / SHEET_MATERIAL_AMOUNT
+ strength_modifier = 0.3
armor_modifiers = list(MELEE = 0.25, BULLET = 0.25, LASER = 0.25, ENERGY = 0.25, BOMB = 0.25, BIO = 0.25, ACID = 1.5)
beauty_modifier = -0.1
+ fish_weight_modifier = 0.4
+ fishing_difficulty_modifier = 40 //child's play
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.1
+ fishing_bait_speed_mult = 0.7
+ fishing_deceleration_mult = 1.5
+ fishing_bounciness_mult = 0.2
+ fishing_gravity_mult = 0.6
/datum/material/cardboard/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -700,6 +976,48 @@ Unless you know what you're doing, only use the first three numbers. They're in
value_per_unit = 100 / SHEET_MATERIAL_AMOUNT
armor_modifiers = list(MELEE = 1.2, BULLET = 0.75, LASER = 0.75, ENERGY = 1.2, BOMB = 1, BIO = 1, FIRE = 1.5, ACID = 1.5)
beauty_modifier = -0.2
+ fish_weight_modifier = 1.05
+ fishing_difficulty_modifier = 15
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.85
+ fishing_completion_speed = 0.9
+ fishing_bait_speed_mult = 0.9
+ fishing_deceleration_mult = 0.9
+ fishing_bounciness_mult = 0.8
+ fishing_gravity_mult = 0.85
+
+/datum/material/bone/on_main_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ RegisterSignal(source, COMSIG_ROD_BEGIN_FISHING, PROC_REF(on_begin_fishing))
+ else if(istype(source, /obj/item/fish))
+ ADD_TRAIT(source, TRAIT_FISH_MADE_OF_BONE, REF(src))
+
+/datum/material/bone/proc/on_begin_fishing(obj/item/fishing_rod/rod, datum/fishing_challenge/challenge)
+ SIGNAL_HANDLER
+ if(prob(40))
+ RegisterSignal(challenge, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, PROC_REF(roll_bones))
+
+/datum/material/bone/proc/roll_bones(datum/source, obj/item/fishing_rod/rod, mob/fisherman, atom/location, list/rewards)
+ SIGNAL_HANDLER
+ var/static/list/bones = list(
+ /obj/item/fish/boned = 65,
+ /obj/item/fish/mastodon = 8,
+ /mob/living/basic/skeleton = 6,
+ /mob/living/basic/skeleton/ice = 6,
+ /mob/living/basic/skeleton/templar = 6,
+ /obj/item/instrument/trumpet/spectral/one_doot = 3,
+ /obj/item/instrument/saxophone/spectral/one_doot = 3,
+ /obj/item/instrument/trombone/spectral/one_doot = 3,
+ )
+ rewards += pick_weight(bones)
+
+/datum/material/bone/on_main_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ UnregisterSignal(source, COMSIG_ROD_BEGIN_FISHING)
+ else if(istype(source, /obj/item/fish))
+ REMOVE_TRAIT(source, TRAIT_FISH_MADE_OF_BONE, REF(src))
/datum/material/bamboo
name = "bamboo"
@@ -712,11 +1030,21 @@ Unless you know what you're doing, only use the first three numbers. They're in
MAT_CATEGORY_ITEM_MATERIAL_COMPLEMENTARY = TRUE,
)
sheet_type = /obj/item/stack/sheet/mineral/bamboo
+ strength_modifier = 0.5
value_per_unit = 5 / SHEET_MATERIAL_AMOUNT
armor_modifiers = list(MELEE = 0.5, BULLET = 0.5, LASER = 0.5, ENERGY = 0.5, BOMB = 0.5, BIO = 0.51, FIRE = 0.5, ACID = 1.5)
beauty_modifier = 0.2
turf_sound_override = FOOTSTEP_WOOD
texture_layer_icon_state = "bamboo"
+ fish_weight_modifier = 0.5
+ fishing_difficulty_modifier = -4
+ fishing_cast_range = -1
+ fishing_experience_multiplier = 1.3
+ fishing_completion_speed = 1.15
+ fishing_bait_speed_mult = 1.2
+ fishing_deceleration_mult = 0.8
+ fishing_bounciness_mult = 0.7
+ fishing_gravity_mult = 0.7
/datum/material/zaukerite
name = "zaukerite"
@@ -732,6 +1060,24 @@ Unless you know what you're doing, only use the first three numbers. They're in
value_per_unit = 900 / SHEET_MATERIAL_AMOUNT
armor_modifiers = list(MELEE = 0.9, BULLET = 0.9, LASER = 1.75, ENERGY = 1.75, BOMB = 0.5, BIO = 1, FIRE = 0.1, ACID = 1)
beauty_modifier = 0.001
+ fish_weight_modifier = 1.2
+ fishing_difficulty_modifier = -16
+ fishing_experience_multiplier = 0.9
+ fishing_completion_speed = 1.3
+ fishing_bait_speed_mult = 1.3
+ fishing_deceleration_mult = 1.3
+ fishing_bounciness_mult = 1.1
+ fishing_gravity_mult = 1.35
+
+/datum/material/zaukerite/on_applied(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ ADD_TRAIT(source, TRAIT_ROD_IGNORE_ENVIRONMENT, REF(src)) //light-absorbing, environment-cancelling fishing rod.
+
+/datum/material/zaukerite/on_removed(atom/source, mat_amount, multiplier)
+ . = ..()
+ if(istype(source, /obj/item/fishing_rod))
+ REMOVE_TRAIT(source, TRAIT_ROD_IGNORE_ENVIRONMENT, REF(src)) //light-absorbing, environment-cancelling fishing rod.
/datum/material/zaukerite/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item)
victim.apply_damage(30, BURN, BODY_ZONE_HEAD, wound_bonus = 5)
diff --git a/code/datums/materials/hauntium.dm b/code/datums/materials/hauntium.dm
index b8eee26a08f..995c566a4d6 100644
--- a/code/datums/materials/hauntium.dm
+++ b/code/datums/materials/hauntium.dm
@@ -17,6 +17,13 @@
//pretty good but only the undead can actually make use of these modifiers
strength_modifier = 1.2
armor_modifiers = list(MELEE = 1.1, BULLET = 1.1, LASER = 1.15, ENERGY = 1.15, BOMB = 1, BIO = 1, FIRE = 1, ACID = 0.7)
+ fish_weight_modifier = 1.4
+ fishing_difficulty_modifier = -30 //Only the undead and the coroner can game this.
+ fishing_cast_range = 2
+ fishing_experience_multiplier = 1.5
+ fishing_completion_speed = 1.1
+ fishing_bait_speed_mult = 0.85
+ fishing_gravity_mult = 0.8
/datum/material/hauntium/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
diff --git a/code/datums/materials/meat.dm b/code/datums/materials/meat.dm
index 008099a526e..512b97f81be 100644
--- a/code/datums/materials/meat.dm
+++ b/code/datums/materials/meat.dm
@@ -18,11 +18,19 @@
item_sound_override = 'sound/effects/meatslap.ogg'
turf_sound_override = FOOTSTEP_MEAT
texture_layer_icon_state = "meat"
+ fishing_difficulty_modifier = 13
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.8
+ fishing_bait_speed_mult = 0.9
+ fishing_deceleration_mult = 0.9
+ fishing_bounciness_mult = 0.9
+ fishing_gravity_mult = 0.85
/datum/material/meat/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
if(!IS_EDIBLE(source))
make_edible(source, mat_amount, multiplier)
+ ADD_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //The rod itself is the bait... sorta.
/datum/material/meat/on_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -64,6 +72,7 @@
/datum/material/meat/on_main_removed(atom/source, mat_amount, multiplier)
. = ..()
qdel(source.GetComponent(/datum/component/edible))
+ REMOVE_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src))
/datum/material/meat/mob_meat
init_flags = MATERIAL_INIT_BESPOKE
diff --git a/code/datums/materials/pizza.dm b/code/datums/materials/pizza.dm
index 1906e5786d2..1bbaaefa909 100644
--- a/code/datums/materials/pizza.dm
+++ b/code/datums/materials/pizza.dm
@@ -16,11 +16,20 @@
item_sound_override = 'sound/effects/meatslap.ogg'
turf_sound_override = FOOTSTEP_MEAT
texture_layer_icon_state = "pizza"
+ fish_weight_modifier = 0.9
+ fishing_difficulty_modifier = 13
+ fishing_cast_range = -2
+ fishing_experience_multiplier = 0.8
+ fishing_bait_speed_mult = 0.9
+ fishing_deceleration_mult = 0.9
+ fishing_bounciness_mult = 0.9
+ fishing_gravity_mult = 0.8
/datum/material/pizza/on_main_applied(atom/source, mat_amount, multiplier)
. = ..()
if(!IS_EDIBLE(source))
make_edible(source, mat_amount)
+ ADD_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src)) //the fishing rod itself is the bait... sorta.
/datum/material/pizza/on_applied(atom/source, mat_amount, multiplier)
. = ..()
@@ -39,3 +48,4 @@
/datum/material/pizza/on_main_removed(atom/source, mat_amount, multiplier)
. = ..()
qdel(source.GetComponent(/datum/component/edible))
+ REMOVE_TRAIT(source, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src))
diff --git a/code/game/atom/atom_materials.dm b/code/game/atom/atom_materials.dm
index cb88c83f3eb..a04d3aac566 100644
--- a/code/game/atom/atom_materials.dm
+++ b/code/game/atom/atom_materials.dm
@@ -10,11 +10,11 @@
/// Sets the custom materials for an atom. This is what you want to call, since most of the ones below are mainly internal.
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
SHOULD_NOT_OVERRIDE(TRUE)
+ var/replace_mats = length(materials)
if(length(custom_materials))
- remove_material_effects()
+ remove_material_effects(replace_mats)
- if(!length(materials))
- custom_materials = null
+ if(!replace_mats)
return
initialize_materials(materials, multiplier)
@@ -31,27 +31,30 @@
materials[current_material] *= multiplier
apply_material_effects(materials)
- custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials)
///proc responsible for applying material effects when setting materials.
/atom/proc/apply_material_effects(list/materials)
SHOULD_CALL_PARENT(TRUE)
- if(!materials || !(material_flags & MATERIAL_EFFECTS))
- return
- var/list/material_effects = get_material_effects_list(materials)
- finalize_material_effects(material_effects)
+ if(material_flags & MATERIAL_EFFECTS)
+ var/list/material_effects = get_material_effects_list(materials)
+ finalize_material_effects(material_effects)
+
+ custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials)
/// Proc responsible for removing material effects when setting materials.
-/atom/proc/remove_material_effects()
+/atom/proc/remove_material_effects(replace_mats = TRUE)
SHOULD_CALL_PARENT(TRUE)
//Only runs if custom materials existed at first and affected src.
- if(!custom_materials || !(material_flags & MATERIAL_EFFECTS))
- return
- var/list/material_effects = get_material_effects_list(custom_materials)
- finalize_remove_material_effects(material_effects)
+ if(material_flags & MATERIAL_EFFECTS)
+ var/list/material_effects = get_material_effects_list(custom_materials)
+ finalize_remove_material_effects(material_effects)
+
+ if(!replace_mats)
+ custom_materials = null
/atom/proc/get_material_effects_list(list/materials)
SHOULD_NOT_OVERRIDE(TRUE)
+ PRIVATE_PROC(TRUE)
var/list/material_effects = list()
var/index = 1
for(var/current_material in materials)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2522b8b9af3..28d52d32604 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -1806,13 +1806,13 @@
/obj/item/apply_single_mat_effect(datum/material/material, mat_amount, multiplier)
. = ..()
- if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || !slowdown)
+ if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || (material_flags & MATERIAL_NO_SLOWDOWN) || !material.added_slowdown)
return
slowdown += GET_MATERIAL_MODIFIER(material.added_slowdown * mat_amount, multiplier)
/obj/item/remove_single_mat_effect(datum/material/material, mat_amount, multiplier)
. = ..()
- if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || !slowdown)
+ if(!(material_flags & MATERIAL_AFFECT_STATISTICS) || (material_flags & MATERIAL_NO_SLOWDOWN) || !material.added_slowdown)
return
slowdown -= GET_MATERIAL_MODIFIER(material.added_slowdown * mat_amount, multiplier)
diff --git a/code/modules/fishing/bait.dm b/code/modules/fishing/bait.dm
index ec758be7042..aad7a8d3d1d 100644
--- a/code/modules/fishing/bait.dm
+++ b/code/modules/fishing/bait.dm
@@ -76,16 +76,15 @@
/obj/item/fishing_lure/Initialize(mapload)
. = ..()
add_traits(list(TRAIT_FISHING_BAIT, TRAIT_BAIT_ALLOW_FISHING_DUD, TRAIT_OMNI_BAIT, TRAIT_BAIT_UNCONSUMABLE), INNATE_TRAIT)
- RegisterSignal(src, COMSIG_FISHING_EQUIPMENT_SLOTTED, PROC_REF(lure_equipped))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
-/obj/item/fishing_lure/proc/lure_equipped(datum/source, obj/item/fishing_rod/rod)
+/obj/item/fishing_lure/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
rod.spin_frequency = spin_frequency
- RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_removed))
-/obj/item/fishing_lure/proc/on_removed(atom/movable/source, obj/item/fishing_rod/rod, dir, forced)
+/obj/item/fishing_lure/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
- UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
rod.spin_frequency = null
///Called for every fish subtype by the fishing subsystem when initializing, to populate the list of fish that can be catched with this lure.
@@ -203,13 +202,20 @@
/obj/item/fishing_lure/led/Initialize(mapload)
. = ..()
- ADD_TRAIT(src, TRAIT_BAIT_IGNORE_ENVIRONMENT, INNATE_TRAIT)
update_appearance(UPDATE_OVERLAYS)
/obj/item/fishing_lure/led/update_overlays()
. = ..()
. += emissive_appearance(icon, "led_emissive", src)
+/obj/item/fishing_lure/led/on_fishing_rod_slotted(obj/item/fishing_rod/rod, slot)
+ . = ..()
+ ADD_TRAIT(rod, TRAIT_ROD_IGNORE_ENVIRONMENT, type)
+
+/obj/item/fishing_lure/led/on_fishing_rod_unslotted(obj/item/fishing_rod/rod, slot)
+ . = ..()
+ REMOVE_TRAIT(rod, TRAIT_ROD_IGNORE_ENVIRONMENT, type)
+
/obj/item/fishing_lure/led/is_catchable_fish(obj/item/fish/fish_type, list/fish_properties)
var/list/fish_traits = fish_properties[FISH_PROPERTIES_TRAITS]
if(length(list(/datum/fish_trait/nocturnal, /datum/fish_trait/heavy) & fish_traits))
@@ -222,6 +228,14 @@
icon_state = "lucky_coin"
spin_frequency = list(1.5 SECONDS, 2.7 SECONDS)
+/obj/item/fishing_lure/lucky_coin/on_fishing_rod_slotted(obj/item/fishing_rod/rod, slot)
+ . = ..()
+ ADD_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+
+/obj/item/fishing_lure/lucky_coin/on_fishing_rod_unslotted(obj/item/fishing_rod/rod, slot)
+ . = ..()
+ REMOVE_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+
/obj/item/fishing_lure/lucky_coin/is_catchable_fish(obj/item/fish/fish_type, list/fish_properties)
var/list/fish_traits = fish_properties[FISH_PROPERTIES_TRAITS]
if(/datum/fish_trait/shiny_lover in fish_traits)
diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm
index 021f1be45d8..aa889057ecd 100644
--- a/code/modules/fishing/fish/_fish.dm
+++ b/code/modules/fishing/fish/_fish.dm
@@ -21,6 +21,8 @@
sound_vary = TRUE
obj_flags = UNIQUE_RENAME
item_flags = SLOWS_WHILE_IN_HAND
+ //we handle slowdowns internally, and the fish weight modifier from materials already contributes to it.
+ material_flags = MATERIAL_EFFECTS|MATERIAL_AFFECT_STATISTICS|MATERIAL_COLOR|MATERIAL_ADD_PREFIX|MATERIAL_NO_SLOWDOWN
/// Flags for fish variables that would otherwise be TRUE/FALSE
var/fish_flags = FISH_FLAG_SHOW_IN_CATALOG|FISH_DO_FLOP_ANIM|FISH_FLAG_EXPERIMENT_SCANNABLE
@@ -116,6 +118,8 @@
var/size
/// Average size for this fish type in centimeters. Will be used as gaussian distribution with 20% deviation for fishing, bought fish are always standard size
var/average_size = 50
+ /// Temporarily stores the new size of the fish from randomize_size_and_weight() to be used by update_size_weight() later, so that it can be deferred.
+ var/temp_size
/// The maximum size this fish can reach, calculated the first time update_size_and_weight() is called.
var/maximum_size
@@ -123,8 +127,12 @@
var/weight
/// Average weight for this fish type in grams
var/average_weight = 1000
+ /// Temporarily stores the new weight of the fish from randomize_size_and_weight() to be used by update_size_weight() later, so that it can be deferred.
+ var/temp_weight
/// The maximum weight this fish can reach, calculated the first time update_size_and_weight() is called.
var/maximum_weight
+ /// Stores the current total weight modifier from materials.
+ var/material_weight_mult = 1
///The general deviation from the average weight and size this fish has in the wild
var/weight_size_deviation = 0.2
@@ -439,25 +447,40 @@
if(bites_amount)
. += span_warning("It's been bitten by someone.")
-///Randomizes weight and size.
-/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = weight_size_deviation)
+/**
+ * This proc takes a base size, base weight and deviation arguments to generate new size and weight through a gaussian distribution (bell curve)
+ * Mainly used to determinate the size and weight of caught fish.
+ */
+/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = weight_size_deviation, update = TRUE)
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))
+ temp_size = round(clamp(gaussian(base_size, size_deviation), average_size * 1/MAX_FISH_DEVIATION_COEFF, average_size * MAX_FISH_DEVIATION_COEFF))
var/weight_deviation = 0.2 * base_weight
- var/new_weight = round(clamp(gaussian(base_weight, weight_deviation), average_weight * 1/MAX_FISH_DEVIATION_COEFF, average_weight * MAX_FISH_DEVIATION_COEFF))
+ temp_weight = round(clamp(gaussian(base_weight, weight_deviation), average_weight * 1/MAX_FISH_DEVIATION_COEFF, average_weight * MAX_FISH_DEVIATION_COEFF))
- update_size_and_weight(new_size, new_weight)
+ set_max_size_and_weight(temp_size, temp_weight)
+ if(update)
+ update_size_and_weight(temp_size, temp_weight)
+
+///Set the maximum size and weight a fish can reach from base size and weight args if they have't been set already.
+/obj/item/fish/proc/set_max_size_and_weight(base_size, base_weight)
+ if(!maximum_size)
+ maximum_size = min(base_size * 2, average_size * MAX_FISH_DEVIATION_COEFF)
+ if(!maximum_weight)
+ maximum_weight = min(base_weight * 2, average_size * MAX_FISH_DEVIATION_COEFF)
///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)
+/obj/item/fish/proc/update_size_and_weight(new_size = average_size, new_weight = average_weight, update_materials = TRUE)
+ fish_flags |= FISH_FLAG_UPDATING_SIZE_AND_WEIGHT
SEND_SIGNAL(src, COMSIG_FISH_UPDATE_SIZE_AND_WEIGHT, new_size, new_weight)
+
if(size)
remove_fillet_type()
if(size > FISH_SIZE_TWO_HANDS_REQUIRED)
qdel(GetComponent(/datum/component/two_handed))
else
- maximum_size = min(new_size * 2, average_size * MAX_FISH_DEVIATION_COEFF)
+ set_max_size_and_weight(new_size, new_weight)
+
size = new_size
var/init_icon_state = initial(inhand_icon_state)
@@ -512,8 +535,6 @@
else
reagents.multiply_reagents(new_weight_ratio)
adjust_reagents_capacity(volume_diff)
- else
- maximum_weight = min(new_weight * 2, new_weight * MAX_FISH_DEVIATION_COEFF)
weight = new_weight
@@ -533,8 +554,22 @@
for(var/reagent_type in grind_results)
grind_results[reagent_type] *= max(FLOOR(weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR, 0.1), 0.1)
+ var/mats_len = length(custom_materials)
+ if(update_materials && mats_len)
+ var/list/new_mats_list = custom_materials.Copy()
+ var/multiplier = 1 / mats_len
+ var/unmodified_weight = weight
+ for(var/mat_type in custom_materials)
+ var/datum/material/material = GET_MATERIAL_REF(mat_type)
+ unmodified_weight /= GET_MATERIAL_MODIFIER(material.fish_weight_modifier, multiplier)
+ multiplier = unmodified_weight / weight
+ for(var/mat_type in new_mats_list)
+ new_mats_list[mat_type] *= multiplier
+ set_custom_materials(new_mats_list) // apply_material_effects() will call update_fish_force for us
update_fish_force()
+ fish_flags &= ~FISH_FLAG_UPDATING_SIZE_AND_WEIGHT
+
/obj/item/fish/proc/remove_fillet_type()
if(!fillet_type)
return
@@ -586,17 +621,24 @@
if(bonus_malus)
calculate_fish_force_bonus(bonus_malus)
- throwforce = force
+ if(material_flags & MATERIAL_EFFECTS && length(custom_materials)) //struck by metal gen or something.
+ var/multiplier = 1 / length(custom_materials)
+ if(material_flags & MATERIAL_AFFECT_STATISTICS)
+ for(var/current_material in custom_materials)
+ var/datum/material/material = GET_MATERIAL_REF(current_material)
+ force *= GET_MATERIAL_MODIFIER(material.strength_modifier, multiplier)
+ var/datum/material/master = get_master_material()
+ if(master?.item_sound_override)
+ hitsound = master.item_sound_override
+ usesound = master.item_sound_override
+ mob_throw_hit_sound = master.item_sound_override
+ equip_sound = master.item_sound_override
+ pickup_sound = master.item_sound_override
+ drop_sound = master.item_sound_override
SEND_SIGNAL(src, COMSIG_FISH_FORCE_UPDATED, weight_rank, bonus_malus)
- if(material_flags & MATERIAL_EFFECTS) //struck by metal gen or something.
- for(var/current_material in custom_materials)
- var/datum/material/material = GET_MATERIAL_REF(current_material)
- force *= material.strength_modifier
- throwforce *= material.strength_modifier
- if(material.item_sound_override)
- hitsound = material.item_sound_override
+ throwforce = force
if(force >=15 && hitsound == SFX_DEFAULT_FISH_SLAP) // don't override special attack sounds
hitsound = SFX_ALT_FISH_SLAP // do more damage - do heavier slap sound
@@ -626,6 +668,29 @@
attack_speed += 0.4 SECONDS
demolition_mod += 0.4
+/obj/item/fish/apply_single_mat_effect(datum/material/custom_material, amount, multiplier)
+ . = ..()
+ //The materials are being increased/decreased along with the weight.
+ if(fish_flags & FISH_FLAG_UPDATING_SIZE_AND_WEIGHT)
+ return
+ material_weight_mult *= GET_MATERIAL_MODIFIER(custom_material.fish_weight_modifier, multiplier)
+
+/obj/item/fish/apply_material_effects()
+ . = ..()
+ //Either effects aren't applied of he materials are simply being increased/decreased along with the weight. Avoids recursion.
+ if(!(material_flags & MATERIAL_EFFECTS) || (fish_flags & FISH_FLAG_UPDATING_SIZE_AND_WEIGHT) || material_weight_mult == 1)
+ return
+ maximum_weight *= material_weight_mult
+ update_size_and_weight(size, (temp_weight || weight) * material_weight_mult, update_materials = FALSE)
+
+/obj/item/fish/remove_material_effects(replace_mats = TRUE)
+ . = ..()
+ if(replace_mats || !(material_flags & MATERIAL_EFFECTS) || material_weight_mult == 1)
+ return
+ maximum_weight /= material_weight_mult
+ update_size_and_weight(size, weight / material_weight_mult)
+ material_weight_mult = 1
+
/**
* 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;
@@ -720,6 +785,7 @@
///If one of the reagent with fish effects is also our food reagent this is set to TRUE
var/already_fed = FALSE
+ var/was_hungry = get_hunger()
for(var/datum/reagent/reagent as anything in fed_reagents.reagent_list)
if(!fed_reagents.has_reagent(reagent.type, 0.1) || !reagent.used_on_fish(src))
continue
@@ -727,6 +793,9 @@
if(reagent.type == food)
already_fed = TRUE
+ if(was_hungry && !get_hunger()) //one of the other reagents already sated its hunger.
+ return
+
if(already_fed)
sate_hunger()
return
@@ -1149,16 +1218,39 @@
//Try to pass down compatible traits based on inheritability
new_fish.inherit_traits(fish_traits, partner?.fish_traits, evolution?.new_traits, evolution?.removed_traits)
+ ///If set, the offspring will inherit materials from the parent.
+ var/obj/item/fish/chosen_material_giver
//We combine two methods for determining the size and weight of the offspring for less extreme results.
if(partner)
var/ratio_size = new_fish.average_size * (((size / average_size) + (partner.size / partner.average_size)) / 2)
var/mean_size = (size + partner.size)/2
var/ratio_weight = new_fish.average_size * (((weight / average_weight) + (partner.weight / partner.average_weight)) / 2)
var/mean_weight = (weight + partner.weight)/2
- new_fish.randomize_size_and_weight((mean_size + ratio_size) * 0.5, (mean_weight + ratio_weight) * 0.5, 0.3)
+ new_fish.randomize_size_and_weight((mean_size + ratio_size) * 0.5, (mean_weight + ratio_weight) * 0.5, 0.3, update = FALSE)
partner.breeding_wait = world.time + breeding_timeout
- else //Make a close of this fish.
- new_fish.update_size_and_weight(size, weight)
+
+ if(length(partner.custom_materials))
+ if(length(custom_materials))
+ chosen_material_giver = pick(src, partner)
+ else if(prob(50))
+ chosen_material_giver = partner
+ else if(length(custom_materials) && prob(50))
+ chosen_material_giver = src
+ else
+ new_fish.temp_size = size
+ new_fish.temp_weight = weight
+ if(length(custom_materials))
+ chosen_material_giver = src
+
+ if(chosen_material_giver)
+ //We need the original weight of the fish to set the correct amount (it scales with weight) of mats for the offspring
+ var/mats_multiplier = new_fish.temp_weight / (chosen_material_giver.weight / material_weight_mult)
+ var/list/new_mats = chosen_material_giver.custom_materials.Copy()
+ for(var/material in new_mats)
+ new_mats[material] *= mats_multiplier
+ new_fish.set_custom_materials(new_mats) // apply_material_effects() will call update_size_and_weight()
+ else
+ new_fish.update_size_and_weight(new_fish.temp_size, new_fish.temp_weight)
breeding_wait = world.time + breeding_timeout
diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm
index 2030c1b6158..75fa7b5f981 100644
--- a/code/modules/fishing/fish/fish_traits.dm
+++ b/code/modules/fishing/fish/fish_traits.dm
@@ -112,6 +112,8 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/wary/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman)
. = ..()
+ if(rod.alpha <= /datum/material/glass::alpha)
+ return
// Wary fish require transparent line or they're harder
if(!rod.line || !(rod.line.fishing_line_traits & FISHING_LINE_CLOAKED))
.[ADDITIVE_FISHING_MOD] += FISH_TRAIT_MINOR_DIFFICULTY_BOOST
@@ -123,13 +125,13 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/shiny_lover/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman)
. = ..()
// These fish are easier to catch with shiny hook
- if(rod.hook && rod.hook.fishing_hook_traits & FISHING_HOOK_SHINY)
+ if(HAS_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS))
.[ADDITIVE_FISHING_MOD] -= FISH_TRAIT_MINOR_DIFFICULTY_BOOST
/datum/fish_trait/shiny_lover/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman)
. = ..()
// These fish are harder to find without a shiny hook
- if(rod.hook && rod.hook.fishing_hook_traits & FISHING_HOOK_SHINY)
+ if(!HAS_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS))
.[MULTIPLICATIVE_FISHING_MOD] = 0.5
/datum/fish_trait/picky_eater
@@ -138,13 +140,18 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/picky_eater/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
. = ..()
+ var/list/fav_baits = SSfishing.fish_properties[fish_type][FISH_PROPERTIES_FAV_BAIT]
+ for(var/list/identifier in fav_baits)
+ if(identifier[FISH_BAIT_TYPE] != FISH_BAIT_FOODTYPE)
+ continue
+ if(is_matching_bait(rod, identifier)) //Bait or no bait, it's a yummy rod.
+ return
if(!rod.bait)
.[MULTIPLICATIVE_FISHING_MOD] = 0
return
if(HAS_TRAIT(rod.bait, TRAIT_OMNI_BAIT))
return
- var/list/fav_baits = SSfishing.fish_properties[fish_type][FISH_PROPERTIES_FAV_BAIT]
for(var/identifier in fav_baits)
if(is_matching_bait(rod.bait, identifier)) //we like this bait anyway
return
@@ -164,7 +171,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/nocturnal/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
. = ..()
- if(rod.bait && HAS_TRAIT(rod.bait, TRAIT_BAIT_IGNORE_ENVIRONMENT))
+ if(HAS_TRAIT(rod, TRAIT_ROD_IGNORE_ENVIRONMENT))
return
var/turf/turf = get_turf(location)
var/light_amount = turf?.get_lumcount()
@@ -207,6 +214,14 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
name = "Demersal"
catalog_description = "This fish tends to stay near the waterbed."
+/datum/fish_trait/heavy/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
+ . = ..()
+ var/datum/material/material = rod.get_master_material()
+ if(!material)
+ return
+ //the fish weight modifier of the material influences the chance of cathing this type of fish.
+ .[MULTIPLICATIVE_FISHING_MOD] = material.fish_weight_modifier
+
/datum/fish_trait/heavy/apply_to_mob(mob/living/basic/mob)
. = ..()
mob.add_movespeed_modifier(/datum/movespeed_modifier/heavy_fish)
@@ -226,18 +241,18 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/carnivore/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
. = ..()
+ if(istype(rod.get_master_material(), /datum/material/meat)) //who cares about the bait, that fishing rod is yummy!
+ return
if(!rod.bait)
.[MULTIPLICATIVE_FISHING_MOD] = 0
return
if(HAS_TRAIT(rod.bait, TRAIT_OMNI_BAIT))
return
- if(isfish(rod.bait))
- return
- if(!istype(rod.bait, /obj/item/food))
- .[MULTIPLICATIVE_FISHING_MOD] = 0
- return
- var/obj/item/food/food_bait = rod.bait
- if(!(food_bait.foodtypes & (MEAT|SEAFOOD|BUGS)))
+ var/list/bait_identifier = list(
+ FISH_BAIT_TYPE = FISH_BAIT_FOODTYPE,
+ FISH_BAIT_VALUE = MEAT|SEAFOOD|BUGS,
+ )
+ if(!is_matching_bait(rod.bait, bait_identifier))
.[MULTIPLICATIVE_FISHING_MOD] = 0
/datum/fish_trait/vegan
@@ -247,18 +262,24 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/vegan/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
. = ..()
+ if(istype(rod.get_master_material(), /datum/material/bamboo)) //bamboo is technically grass.
+ return
if(!rod.bait)
.[MULTIPLICATIVE_FISHING_MOD] = 0
return
if(HAS_TRAIT(rod.bait, TRAIT_OMNI_BAIT))
return
- if(!istype(rod.bait, /obj/item/food))
- .[MULTIPLICATIVE_FISHING_MOD] = 0
- return
if(istype(rod.bait, /obj/item/food/grown))
return
- var/obj/item/food/food_bait = rod.bait
- if(food_bait.foodtypes & (MEAT|SEAFOOD|GORE|BUGS|DAIRY) || !(food_bait.foodtypes & (VEGETABLES|FRUIT)))
+ var/list/bait_liked_identifier = list(
+ FISH_BAIT_TYPE = FISH_BAIT_FOODTYPE,
+ FISH_BAIT_VALUE = VEGETABLES|FRUIT,
+ )
+ var/list/bait_hated_identifier = list(
+ FISH_BAIT_TYPE = FISH_BAIT_FOODTYPE,
+ FISH_BAIT_VALUE = MEAT|SEAFOOD|GORE|BUGS|DAIRY,
+ )
+ if(!is_matching_bait(rod.bait, bait_liked_identifier) || is_matching_bait(rod.bait, bait_hated_identifier))
.[MULTIPLICATIVE_FISHING_MOD] = 0
/datum/fish_trait/emulsijack
@@ -530,6 +551,11 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
added_difficulty = 5
reagents_to_add = list(/datum/reagent/lube = 1.2)
+/datum/fish_trait/lubed/catch_weight_mod(obj/item/fishing_rod/rod, mob/fisherman, atom/location, obj/item/fish/fish_type)
+ . = ..()
+ if(istype(rod.get_master_material(), /datum/material/bananium)) //x5 chance of catching lubefish & co with a bananium rod.
+ .[MULTIPLICATIVE_FISHING_MOD] *= 5
+
/datum/fish_trait/lubed/apply_to_fish(obj/item/fish/fish)
. = ..()
fish.AddComponent(/datum/component/slippery, 8 SECONDS, SLIDE|GALOSHES_DONT_HELP)
diff --git a/code/modules/fishing/fish/types/air_space.dm b/code/modules/fishing/fish/types/air_space.dm
index 177ae9c6e0e..b0c8208fe81 100644
--- a/code/modules/fishing/fish/types/air_space.dm
+++ b/code/modules/fishing/fish/types/air_space.dm
@@ -154,7 +154,7 @@
. += eyes
///Determines the speed at which the carp grows based on how big it's
-/obj/item/fish/baby_carp/update_size_and_weight(new_size = average_size, new_weight = average_weight)
+/obj/item/fish/baby_carp/update_size_and_weight(new_size = average_size, new_weight = average_weight, update_materials = TRUE)
. = ..()
var/growth_rate = 4.5 MINUTES
growth_rate *= clamp(size/average_size, 0.5, 2)
diff --git a/code/modules/fishing/fish/types/mining.dm b/code/modules/fishing/fish/types/mining.dm
index 9e44e08ae31..f3f4137fae3 100644
--- a/code/modules/fishing/fish/types/mining.dm
+++ b/code/modules/fishing/fish/types/mining.dm
@@ -42,7 +42,7 @@
return list("cooked crab" = 2)
///A chasm crab growth speed is determined by its initial weight and size, ergo bigger crabs for faster lobstrosities
-/obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight)
+/obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight, update_materials = TRUE)
. = ..()
var/multiplier = 1
switch(size)
@@ -134,6 +134,10 @@
evolution_types = list(/datum/fish_evolution/mastodon)
beauty = FISH_BEAUTY_UGLY
+/obj/item/fish/boned/Initialize(mapload, apply_qualities = TRUE)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_FISH_MADE_OF_BONE, INNATE_TRAIT)
+
/obj/item/fish/boned/make_edible(weight_val)
return //it's all bones and no meat.
diff --git a/code/modules/fishing/fish/types/ruins.dm b/code/modules/fishing/fish/types/ruins.dm
index 153a5bc3b7b..ccf6560139c 100644
--- a/code/modules/fishing/fish/types/ruins.dm
+++ b/code/modules/fishing/fish/types/ruins.dm
@@ -26,6 +26,10 @@
fish_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/amphibious, /datum/fish_trait/revival, /datum/fish_trait/carnivore, /datum/fish_trait/predator, /datum/fish_trait/aggressive)
beauty = FISH_BEAUTY_BAD
+/obj/item/fish/mastodon/Initialize(mapload, apply_qualities = TRUE)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_FISH_MADE_OF_BONE, INNATE_TRAIT)
+
/obj/item/fish/mastodon/make_edible(weight_val)
return //it's all bones and gibs.
diff --git a/code/modules/fishing/fish/types/station.dm b/code/modules/fishing/fish/types/station.dm
index 96a7ca7e99f..c4c851dc97d 100644
--- a/code/modules/fishing/fish/types/station.dm
+++ b/code/modules/fishing/fish/types/station.dm
@@ -146,7 +146,7 @@
add_traits(list(TRAIT_FISHING_BAIT, TRAIT_GREAT_QUALITY_BAIT), INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_FISH_SURVIVE_COOKING, INNATE_TRAIT)
-/obj/item/fish/fryish/update_size_and_weight(new_size = average_size, new_weight = average_weight)
+/obj/item/fish/fryish/update_size_and_weight(new_size = average_size, new_weight = average_weight, update_materials = FALSE)
. = ..()
if(!next_type)
return
diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm
index cddabd90c06..79a43fc6052 100644
--- a/code/modules/fishing/fishing_equipment.dm
+++ b/code/modules/fishing/fishing_equipment.dm
@@ -23,10 +23,22 @@
name = "reinforced fishing line reel"
desc = "Essential for fishing in extreme environments."
icon_state = "reel_green"
- fishing_line_traits = FISHING_LINE_REINFORCED
line_color = "#2b9c2b"
wiki_desc = "Allows you to fish in lava and plasma rivers and lakes."
+/obj/item/fishing_line/reinforced/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
+
+/obj/item/fishing_line/reinforced/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ ADD_TRAIT(rod, TRAIT_ROD_LAVA_USABLE, REF(src))
+
+/obj/item/fishing_line/reinforced/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ REMOVE_TRAIT(rod, TRAIT_ROD_LAVA_USABLE, REF(src))
+
/obj/item/fishing_line/cloaked
name = "cloaked fishing line reel"
desc = "Even harder to notice than the common variety."
@@ -47,10 +59,23 @@
name = "fishing sinew"
desc = "An all-natural fishing line made of stretched out sinew. A bit stiff, but usable to fish in extreme enviroments."
icon_state = "reel_sinew"
- fishing_line_traits = FISHING_LINE_REINFORCED|FISHING_LINE_STIFF
+ fishing_line_traits = FISHING_LINE_STIFF
line_color = "#d1cca3"
wiki_desc = "Crafted from sinew. It allows you to fish in lava and plasma like the reinforced line, but it'll make the minigame harder."
+/obj/item/fishing_line/sinew/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
+
+/obj/item/fishing_line/sinew/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ ADD_TRAIT(rod, TRAIT_ROD_LAVA_USABLE, REF(src))
+
+/obj/item/fishing_line/sinew/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ REMOVE_TRAIT(rod, TRAIT_ROD_LAVA_USABLE, REF(src))
+
/**
* A special line reel that let you skip the biting phase of the minigame, netting you a completion bonus,
* and thrown hooked items at you, so you can rapidly catch them from afar.
@@ -68,17 +93,16 @@
/obj/item/fishing_line/auto_reel/Initialize(mapload)
. = ..()
- RegisterSignal(src, COMSIG_FISHING_EQUIPMENT_SLOTTED, PROC_REF(line_equipped))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
-/obj/item/fishing_line/auto_reel/proc/line_equipped(datum/source, obj/item/fishing_rod/rod)
+/obj/item/fishing_line/auto_reel/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
RegisterSignal(rod, COMSIG_FISHING_ROD_HOOKED_ITEM, PROC_REF(on_hooked_item))
- RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_removed))
-/obj/item/fishing_line/auto_reel/proc/on_removed(atom/movable/source, atom/old_loc, dir, forced)
+/obj/item/fishing_line/auto_reel/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
- UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
- UnregisterSignal(old_loc, COMSIG_FISHING_ROD_HOOKED_ITEM)
+ UnregisterSignal(rod, COMSIG_FISHING_ROD_HOOKED_ITEM)
/obj/item/fishing_line/auto_reel/proc/on_hooked_item(obj/item/fishing_rod/source, atom/target, mob/living/user)
SIGNAL_HANDLER
@@ -176,18 +200,16 @@
/obj/item/fishing_hook/magnet/Initialize(mapload)
. = ..()
- RegisterSignal(src, COMSIG_FISHING_EQUIPMENT_SLOTTED, PROC_REF(hook_equipped))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
-///We make sure that the fishng rod doesn't need a bait to reliably catch non-fish loot.
-/obj/item/fishing_hook/magnet/proc/hook_equipped(datum/source, obj/item/fishing_rod/rod)
+/obj/item/fishing_hook/magnet/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
- ADD_TRAIT(rod, TRAIT_ROD_REMOVE_FISHING_DUD, type)
- RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(on_removed))
+ ADD_TRAIT(rod, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src))
-/obj/item/fishing_hook/magnet/proc/on_removed(atom/movable/source, atom/old_loc, dir, forced)
+/obj/item/fishing_hook/magnet/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
SIGNAL_HANDLER
- REMOVE_TRAIT(old_loc, TRAIT_ROD_REMOVE_FISHING_DUD, type)
- UnregisterSignal(src, COMSIG_MOVABLE_MOVED)
+ REMOVE_TRAIT(rod, TRAIT_ROD_REMOVE_FISHING_DUD, REF(src))
/obj/item/fishing_hook/magnet/get_hook_bonus_multiplicative(fish_type, datum/fish_source/source)
if(fish_type == FISHING_DUD || ispath(fish_type, /obj/item/fish))
@@ -199,10 +221,24 @@
/obj/item/fishing_hook/shiny
name = "shiny lure hook"
icon_state = "gold_shiny"
- fishing_hook_traits = FISHING_HOOK_SHINY
rod_overlay_icon_state = "hook_shiny_overlay"
wiki_desc = "It's used to attract shiny-loving fish and make them easier to catch."
+/obj/item/fishing_hook/shiny/Initialize(mapload)
+ . = ..()
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_SLOTTED, PROC_REF(on_fishing_rod_slotted))
+ RegisterSignal(src, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, PROC_REF(on_fishing_rod_unslotted))
+
+/obj/item/fishing_hook/shiny/proc/on_fishing_rod_slotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ rod.material_fish_chance += 15 //Increases the chance of catching a shiny po... erh, material fish
+ ADD_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+
+/obj/item/fishing_hook/shiny/proc/on_fishing_rod_unslotted(datum/source, obj/item/fishing_rod/rod, slot)
+ SIGNAL_HANDLER
+ rod.material_fish_chance -= 15
+ REMOVE_TRAIT(rod, TRAIT_ROD_ATTRACT_SHINY_LOVERS, REF(src))
+
/obj/item/fishing_hook/weighted
name = "weighted hook"
icon_state = "weighted"
diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm
index 646b9816a6e..8d4b312c4f6 100644
--- a/code/modules/fishing/fishing_minigame.dm
+++ b/code/modules/fishing/fishing_minigame.dm
@@ -9,8 +9,6 @@
#define FISH_ON_BAIT_ACCELERATION_MULT 0.6
/// The minimum velocity required for the bait to bounce
#define BAIT_MIN_VELOCITY_BOUNCE 150
-/// The extra deceleration of velocity that happens when the bait switches direction
-#define BAIT_DECELERATION_MULT 1.8
/// Reduce initial completion rate depending on difficulty
#define MAX_FISH_COMPLETION_MALUS 15
@@ -107,10 +105,15 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
var/reeling_velocity = 1200
/// By how much the bait recoils back when hitting the bounds of the slider while idle
var/bait_bounce_mult = 0.6
+ /// The multiplier of deceleration of velocity that happens when the bait switches direction
+ var/deceleration_mult = 1.8
///The background as shown in the minigame, and the holder of the other visual overlays
var/atom/movable/screen/fishing_hud/fishing_hud
+ ///Keep track of the fish source from which we're pulling the reward
+ var/datum/fish_source/fish_source
+
/datum/fishing_challenge/New(datum/component/fishing_spot/comp, obj/item/fishing_rod/rod, mob/user)
src.user = user
used_rod = rod
@@ -119,12 +122,12 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
float.spin_frequency = rod.spin_frequency
RegisterSignal(location, COMSIG_QDELETING, PROC_REF(on_spot_gone))
RegisterSignal(comp, COMSIG_QDELETING, PROC_REF(on_spot_gone))
- RegisterSignal(comp.fish_source, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, PROC_REF(interrupt_challenge))
- comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, TYPE_PROC_REF(/datum/fish_source, roll_reward_minigame))
- comp.fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, TYPE_PROC_REF(/datum/fish_source, calculate_difficulty_minigame))
- comp.fish_source.RegisterSignal(user, COMSIG_MOB_COMPLETE_FISHING, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
+ register_reward_signals(comp.fish_source)
+ RegisterSignal(fish_source, COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE, PROC_REF(interrupt_challenge))
+ fish_source.RegisterSignal(user, COMSIG_MOB_COMPLETE_FISHING, TYPE_PROC_REF(/datum/fish_source, on_challenge_completed))
background = comp.fish_source.background
SEND_SIGNAL(user, COMSIG_MOB_BEGIN_FISHING, src)
+ SEND_SIGNAL(rod, COMSIG_ROD_BEGIN_FISHING, src)
GLOB.fishing_challenges_by_user[user] = src
/// Enable special parameters
@@ -153,6 +156,12 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
completion_loss += user.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)/5
completion_gain -= user.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)/7.5
+ reeling_velocity *= rod.bait_speed_mult
+ completion_gain *= rod.completion_speed_mult
+ bait_bounce_mult *= rod.bounciness_mult
+ deceleration_mult *= rod.deceleration_mult
+ gravity_velocity *= rod.gravity_mult
+
/datum/fishing_challenge/Destroy(force)
GLOB.fishing_challenges_by_user -= user
if(!completed)
@@ -169,6 +178,20 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
QDEL_NULL(mover)
return ..()
+/**
+ * Proc responsible for registering the signals for difficulty and possible reward.
+ * Call this if you want to override the fish source from which we roll rewards (preferably before the minigame phase).
+ */
+/datum/fishing_challenge/proc/register_reward_signals(datum/fish_source/fish_source)
+ if(fish_source)
+ fish_source.UnregisterSignal(src, list(
+ COMSIG_FISHING_CHALLENGE_ROLL_REWARD,
+ COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY,
+ ))
+ src.fish_source = fish_source
+ fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_ROLL_REWARD, TYPE_PROC_REF(/datum/fish_source, roll_reward_minigame))
+ fish_source.RegisterSignal(src, COMSIG_FISHING_CHALLENGE_GET_DIFFICULTY, TYPE_PROC_REF(/datum/fish_source, calculate_difficulty_minigame))
+
/datum/fishing_challenge/proc/send_alert(message)
location?.balloon_alert(user, message)
@@ -321,6 +344,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
var/extra_exp_malus = user.mind.get_skill_level(/datum/skill/fishing) - difficulty * 0.1
if(extra_exp_malus > 0)
experience_multiplier /= (1 + extra_exp_malus * EXPERIENCE_MALUS_MULT)
+ experience_multiplier *= used_rod.experience_multiplier
user.mind.adjust_experience(/datum/skill/fishing, round(seconds_spent * FISHING_SKILL_EXP_PER_SECOND * experience_multiplier))
if(user.mind.get_skill_level(/datum/skill/fishing) >= SKILL_LEVEL_LEGENDARY)
user.client?.give_award(/datum/award/achievement/skill/legendary_fisher, user)
@@ -663,9 +687,9 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
* have different directions, making the bait less slippery, thus easier to control
*/
if(bait_velocity > 0 && velocity_change < 0)
- bait_velocity += max(-bait_velocity, velocity_change * BAIT_DECELERATION_MULT)
+ bait_velocity += max(-bait_velocity, velocity_change * deceleration_mult)
else if(bait_velocity < 0 && velocity_change > 0)
- bait_velocity += min(-bait_velocity, velocity_change * BAIT_DECELERATION_MULT)
+ bait_velocity += min(-bait_velocity, velocity_change * deceleration_mult)
///bidirectional baits stay bouyant while idle
if(bidirectional && reeling_state == REELING_STATE_IDLE)
@@ -832,7 +856,6 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user)
#undef FISH_ON_BAIT_ACCELERATION_MULT
#undef BAIT_MIN_VELOCITY_BOUNCE
-#undef BAIT_DECELERATION_MULT
#undef MAX_FISH_COMPLETION_MALUS
#undef BITING_TIME_WINDOW
diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm
index bfa701d36eb..e876f4764f5 100644
--- a/code/modules/fishing/fishing_rod.dm
+++ b/code/modules/fishing/fishing_rod.dm
@@ -55,6 +55,21 @@
///Prevents spamming the line casting, without affecting the player's click cooldown.
COOLDOWN_DECLARE(casting_cd)
+ ///The chance of catching fish made of the same material of the fishing rod (if MATERIAL_EFFECTS is enabled)
+ var/material_fish_chance = 10
+ ///The multiplier of how much experience is gained when fishing with this rod.
+ var/experience_multiplier = 1
+ ///The multiplier of the completion gain during the minigame
+ var/completion_speed_mult = 1
+ ///The multiplier of the speed of the bobber/bait during the minigame
+ var/bait_speed_mult = 1
+ ///The multiplier of the decelaration during the minigame
+ var/deceleration_mult = 1
+ ///The multiplier of the bounciness of the bobber/bait upon hitting the edges of the minigame area
+ var/bounciness_mult = 1
+ /// The multiplier of negative velocity that pulls the bait/bobber down when not holding the click
+ var/gravity_mult = 1
+
/obj/item/fishing_rod/Initialize(mapload)
. = ..()
register_context()
@@ -105,6 +120,85 @@
. += span_notice("It has \a [english_list(equipped_stuff)] equipped.")
if(!bait)
. += span_warning("It doesn't have a bait attached to it. Fishing will be more tedious!")
+ if(HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISH))
+ . += "" //add a new line
+ . += span_notice("Thanks to your fishing skills, you can examine it again for more in-depth information.")
+ return
+
+/obj/item/fishing_rod/examine_more(mob/user)
+ . = ..()
+ if(!HAS_MIND_TRAIT(user, TRAIT_EXAMINE_FISH))
+ return
+
+ var/list/block = list()
+ var/get_percent = HAS_MIND_TRAIT(user, TRAIT_EXAMINE_DEEPER_FISH)
+ block += span_info("You think you can cast it up to [get_cast_range()] tiles away.")
+ block += get_stat_info(get_percent, difficulty_modifier, "Fishing will be", "easier", "harder", "with this fishing rod")
+ block += get_stat_info(get_percent, experience_multiplier, "You will gain experience", "faster", "slower")
+ block += get_stat_info(get_percent, completion_speed_mult, "You should complete the minigame", "faster", "slower")
+ block += get_stat_info(get_percent, bait_speed_mult, "Reeling is", "faster", "slower")
+ block += get_stat_info(get_percent, deceleration_mult, "Deceleration is", "faster", "slower", less_is_better = TRUE)
+ block += get_stat_info(get_percent, bounciness_mult, "This fishing rod is ", "bouncier", "less bouncy", "than a normal one", less_is_better = TRUE)
+ block += get_stat_info(get_percent, gravity_mult, "The lure will sink", "faster", "slower", span_info = TRUE)
+
+ . += examine_block(block.Join("\n"))
+
+ if(get_percent && (material_flags & MATERIAL_EFFECTS) && length(custom_materials))
+ block = list()
+ block += span_info("Right now, fish caught by this fishing rod have a [get_material_fish_chance(user)]% of being made of its same materials.")
+ var/datum/material/material = get_master_material()
+ if(material.fish_weight_modifier != 1)
+ var/heavier = material.fish_weight_modifier > 1 ? "heavier" : "lighter"
+ block += span_info("Fish made of the same material as this rod tend to be [abs(material.fish_weight_modifier - 1) * 100]% [heavier].")
+ . += examine_block(block.Join("\n"))
+
+ block = list()
+ if(HAS_TRAIT(src, TRAIT_ROD_ATTRACT_SHINY_LOVERS))
+ block += span_info("This fishing rod will attract shiny-loving fish.")
+ if(HAS_TRAIT(src, TRAIT_ROD_IGNORE_ENVIRONMENT))
+ block += span_info("Environment and light shouldn't be an issue with this rod.")
+ if(HAS_TRAIT_NOT_FROM(src, TRAIT_ROD_REMOVE_FISHING_DUD, INNATE_TRAIT)) // Duds are innately removed by baits, we all know that.
+ block += span_info("You won't catch duds with this rod.")
+ if(HAS_TRAIT(src, TRAIT_ROD_LAVA_USABLE))
+ block += span_info("This fishing rod can be used to fish on lava.")
+ if(length(block))
+ . += examine_block(block.Join("\n"))
+
+///Used in examine_more to reduce all the copypasta when getting more information about the various stats of the fishing rod.
+/obj/item/fishing_rod/proc/get_stat_info(get_percent, value, prefix, easier, harder, suffix = "with this fishing rod", span_info = FALSE, less_is_better = FALSE)
+ if(value == 1)
+ return
+ var/percent = get_percent ? "[abs(value)]% " : ""
+ var/harder_easier = value > 1 ? easier : harder
+ . = "[prefix] [percent][harder_easier] [suffix]."
+ if(span_info)
+ return span_info(.)
+ if(less_is_better ? value < 1 : value > 1)
+ return span_nicegreen(.)
+ return span_danger(.)
+
+/obj/item/fishing_rod/apply_single_mat_effect(datum/material/custom_material, amount, multiplier)
+ . = ..()
+ difficulty_modifier += custom_material.fishing_difficulty_modifier * multiplier
+ cast_range += custom_material.fishing_cast_range * multiplier
+ experience_multiplier *= GET_MATERIAL_MODIFIER(custom_material.fishing_experience_multiplier, multiplier)
+ completion_speed_mult *= GET_MATERIAL_MODIFIER(custom_material.fishing_completion_speed, multiplier)
+ bait_speed_mult *= GET_MATERIAL_MODIFIER(custom_material.fishing_bait_speed_mult, multiplier)
+ deceleration_mult *= GET_MATERIAL_MODIFIER(custom_material.fishing_deceleration_mult, multiplier)
+ bounciness_mult *= GET_MATERIAL_MODIFIER(custom_material.fishing_bounciness_mult, multiplier)
+ gravity_mult *= GET_MATERIAL_MODIFIER(custom_material.fishing_gravity_mult, multiplier)
+
+
+/obj/item/fishing_rod/remove_single_mat_effect(datum/material/custom_material, amount, multiplier)
+ . = ..()
+ difficulty_modifier -= custom_material.fishing_difficulty_modifier * multiplier
+ cast_range -= custom_material.fishing_cast_range * multiplier
+ experience_multiplier /= GET_MATERIAL_MODIFIER(custom_material.fishing_experience_multiplier, multiplier)
+ completion_speed_mult /= GET_MATERIAL_MODIFIER(custom_material.fishing_completion_speed, multiplier)
+ bait_speed_mult /= GET_MATERIAL_MODIFIER(custom_material.fishing_bait_speed_mult, multiplier)
+ deceleration_mult /= GET_MATERIAL_MODIFIER(custom_material.fishing_deceleration_mult, multiplier)
+ bounciness_mult /= GET_MATERIAL_MODIFIER(custom_material.fishing_bounciness_mult, multiplier)
+ gravity_mult /= GET_MATERIAL_MODIFIER(custom_material.fishing_gravity_mult, multiplier)
/**
* Is there a reason why this fishing rod couldn't fish in target_fish_source?
@@ -116,16 +210,25 @@
/obj/item/fishing_rod/proc/reason_we_cant_fish(datum/fish_source/target_fish_source)
return hook?.reason_we_cant_fish(target_fish_source)
-/obj/item/fishing_rod/proc/consume_bait(atom/movable/reward)
+///Called at the end of on_challenge_completed() once the reward has been spawned
+/obj/item/fishing_rod/proc/on_reward_caught(atom/movable/reward, mob/user)
+ if(isnull(reward))
+ return
+ var/isfish = isfish(reward)
+ if((material_flags & MATERIAL_EFFECTS) && isfish && length(custom_materials))
+ if(prob(get_material_fish_chance(user)))
+ var/obj/item/fish/fish = reward
+ var/datum/material/material = get_master_material()
+ fish.set_custom_materials(list(material.type = fish.weight))
// catching things that aren't fish or alive mobs doesn't consume baits.
- if(isnull(reward) || isnull(bait) || HAS_TRAIT(bait, TRAIT_BAIT_UNCONSUMABLE))
+ if(isnull(bait) || HAS_TRAIT(bait, TRAIT_BAIT_UNCONSUMABLE))
return
if(isliving(reward))
var/mob/living/caught_mob = reward
if(caught_mob.stat == DEAD)
return
else
- if(!isfish(reward))
+ if(!isfish)
return
var/obj/item/fish/fish = reward
if(HAS_TRAIT(bait, TRAIT_POISONOUS_BAIT) && !HAS_TRAIT(fish, TRAIT_FISH_TOXIN_IMMUNE))
@@ -140,6 +243,18 @@
QDEL_NULL(bait)
update_icon()
+///Returns the probability that a fish caught by this (custom material) rod will be of the same material.
+/obj/item/fishing_rod/proc/get_material_fish_chance(mob/user)
+ var/material_chance = material_fish_chance
+ if(bait)
+ if(HAS_TRAIT(bait, TRAIT_GREAT_QUALITY_BAIT))
+ material_chance += 16
+ else if(HAS_TRAIT(bait, TRAIT_GOOD_QUALITY_BAIT))
+ material_chance += 8
+ else if(HAS_TRAIT(bait, TRAIT_BASIC_QUALITY_BAIT))
+ material_chance += 4
+ material_chance += user.mind?.get_skill_level(/datum/skill/fishing) * 1.5
+
///Fishing rodss should only bane fish DNA-infused spessman
/obj/item/fishing_rod/proc/attempt_bane(datum/source, mob/living/fish)
SIGNAL_HANDLER
@@ -162,7 +277,7 @@
return
playsound(src, SFX_REEL, 50, vary = FALSE)
- var/time = (0.8 - round(user.mind?.get_skill_level(/datum/skill/fishing) * 0.04, 0.1)) SECONDS
+ var/time = (0.8 - round(user.mind?.get_skill_level(/datum/skill/fishing) * 0.04, 0.1)) SECONDS * bait_speed_mult
if(!do_after(user, time, currently_hooked, timed_action_flags = IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE, extra_checks = CALLBACK(src, PROC_REF(fishing_line_check))))
return
@@ -171,7 +286,7 @@
return
//About thirty minutes of non-stop reeling to get from zero to master... not worth it but hey, you do what you do.
- user.mind?.adjust_experience(/datum/skill/fishing, time * 0.13)
+ user.mind?.adjust_experience(/datum/skill/fishing, time * 0.13 * experience_multiplier)
//Try to move it 'till it's under the user's feet, then try to pick it up
if(isitem(currently_hooked))
@@ -221,13 +336,14 @@
currently_hooked = null
/obj/item/fishing_rod/proc/get_cast_range(mob/living/user)
- . = cast_range
+ . = max(cast_range, 1)
if(!user && !isliving(loc))
return
user = loc
if(!user.is_holding(src) || !user.mind)
return
. += round(user.mind.get_skill_level(/datum/skill/fishing) * 0.3)
+ return max(., 1)
/obj/item/fishing_rod/dropped(mob/user, silent)
. = ..()
@@ -336,12 +452,14 @@
/// Line part by the rod.
if(reel_overlay)
var/mutable_appearance/reel_appearance = mutable_appearance(icon, reel_overlay)
+ reel_appearance.appearance_flags = RESET_COLOR
reel_appearance.color = line_color
. += reel_appearance
// Line & hook is also visible when only bait is equipped but it uses default appearances then
if(hook || bait)
var/mutable_appearance/line_overlay = mutable_appearance(icon, "line_overlay")
+ line_overlay.appearance_flags = RESET_COLOR
line_overlay.color = line_color
. += line_overlay
. += hook?.rod_overlay_icon_state || "hook_overlay"
@@ -501,20 +619,27 @@
else
CRASH("set_slot called with an undefined slot: [slot]")
- SEND_SIGNAL(equipment, COMSIG_FISHING_EQUIPMENT_SLOTTED, src)
+ SEND_SIGNAL(equipment, COMSIG_ITEM_FISHING_ROD_SLOTTED, src, slot)
/obj/item/fishing_rod/Exited(atom/movable/gone, direction)
. = ..()
+ var/slot
if(gone == bait)
+ slot = ROD_SLOT_BAIT
bait = null
REMOVE_TRAIT(src, TRAIT_ROD_REMOVE_FISHING_DUD, INNATE_TRAIT)
if(gone == line)
+ slot = ROD_SLOT_LINE
cast_range -= FISHING_ROD_REEL_CAST_RANGE
line = null
if(gone == hook)
+ slot = ROD_SLOT_HOOK
QDEL_NULL(fishing_line)
hook = null
+ if(slot)
+ SEND_SIGNAL(gone, COMSIG_ITEM_FISHING_ROD_UNSLOTTED, src, slot)
+
///Found in the fishing toolbox (the hook and line are separate items)
/obj/item/fishing_rod/unslotted
hook = null
@@ -547,6 +672,11 @@
ui_description = "A collapsible fishing rod that can fit within a backpack."
wiki_description = "It has to be bought from Cargo."
reel_overlay = "reel_telescopic"
+ completion_speed_mult = 1.1
+ bait_speed_mult = 1.1
+ deceleration_mult = 1.1
+ bounciness_mult = 0.9
+ gravity_mult = 0.9
///The force of the item when extended.
var/active_force = 8
@@ -615,6 +745,12 @@
cast_range = 5
line = /obj/item/fishing_line/bouncy
hook = /obj/item/fishing_hook/weighted
+ completion_speed_mult = 1.55
+ bait_speed_mult = 1.2
+ deceleration_mult = 1.55
+ bounciness_mult = 0.3
+ gravity_mult = 1.2
+ material_fish_chance = 33 //if somehow you metalgen it.
/obj/item/fishing_rod/tech
name = "advanced fishing rod"
@@ -624,6 +760,10 @@
icon_state = "fishing_rod_science"
reel_overlay = "reel_science"
bait = /obj/item/food/bait/doughball/synthetic/unconsumable
+ completion_speed_mult = 1.1
+ bait_speed_mult = 1.1
+ deceleration_mult = 1.1
+ gravity_mult = 1.2
/obj/item/fishing_rod/tech/Initialize(mapload)
. = ..()
@@ -650,6 +790,23 @@
return
return ..()
+/obj/item/fishing_rod/material
+ name = "material fishing rod" //name shown on the autowiki.
+ desc = "A custom fishing rod from your local autolathe."
+ icon_state = "fishing_rod_material"
+ reel_overlay = "reel_material"
+ ui_description = "An autolathe-printable fishing rod made of some material."
+ wiki_description = "Different materials can have different effects. They also catch fish made of the same material used to print the rod."
+ material_flags = MATERIAL_EFFECTS|MATERIAL_AFFECT_STATISTICS|MATERIAL_COLOR|MATERIAL_ADD_PREFIX
+
+/obj/item/fishing_rod/material/Initialize(mapload)
+ . = ..()
+ name = "fishing_rod"
+
+/obj/item/fishing_rod/material/finalize_remove_material_effects(list/materials)
+ . = ..()
+ name = "fishing_rod" //so it doesn't reset to "material fishing rod"
+
#undef ROD_SLOT_BAIT
#undef ROD_SLOT_LINE
#undef ROD_SLOT_HOOK
diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm
index 0e80ee423ca..2ad6a2bc5bb 100644
--- a/code/modules/fishing/sources/_fish_source.dm
+++ b/code/modules/fishing/sources/_fish_source.dm
@@ -16,6 +16,8 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/mob/living/basic/frog = FISH_ICON_CRITTER,
/mob/living/basic/carp = FISH_ICON_DEF,
/mob/living/basic/mining = FISH_ICON_HOSTILE,
+ /mob/living/basic/skeleton = FISH_ICON_BONE,
+ /mob/living/basic/stickman = FISH_ICON_HOSTILE,
/obj/effect/decal/remains = FISH_ICON_BONE,
/obj/effect/mob_spawn/corpse = FISH_ICON_BONE,
/obj/effect/spawner/message_in_a_bottle = FISH_ICON_BOTTLE,
@@ -41,6 +43,9 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/obj/item/fish/stingray = FISH_ICON_WEAPON,
/obj/item/fish/swordfish = FISH_ICON_WEAPON,
/obj/item/fish/zipzap = FISH_ICON_ELECTRIC,
+ /obj/item/instrument/trumpet/spectral = FISH_ICON_BONE,
+ /obj/item/instrument/saxophone/spectral = FISH_ICON_BONE,
+ /obj/item/instrument/trombone/spectral = FISH_ICON_BONE,
/obj/item/knife/carp = FISH_ICON_WEAPON,
/obj/item/seeds/grass = FISH_ICON_SEED,
/obj/item/seeds/random = FISH_ICON_SEED,
@@ -79,14 +84,14 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
var/catalog_description
/// Background image name from /datum/asset/simple/fishing_minigame
var/background = "background_default"
- /// It true, repeated and large explosions won't be as efficient. This is usually for fish sources that cover multiple turfs (i.e. rivers, oceans).
- var/explosive_malus = FALSE
- /// If explosive_malus is true, this will be used to keep track of the turfs where an explosion happened for when we'll spawn the loot.
+ var/fish_source_flags = NONE
+ /// If FISH_SOURCE_FLAG_EXPLOSIVE_MALUS is set, this will be used to keep track of the turfs where an explosion happened for when we'll spawn the loot.
var/list/exploded_turfs
///When linked to a fishing portal, this will be the icon_state of this option in the radial menu
var/radial_state = "default"
///When selected by the fishing portal, this will be the icon_state of the overlay shown on the machine.
var/overlay_state = "portal_aquarium"
+
/// Mindless mobs that can fish will never pull up items on this list
var/static/list/profound_fisher_blacklist = typecacheof(list(
/mob/living/basic/mining/lobstrosity,
@@ -241,7 +246,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
if(reward)
user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = reward.name)
SEND_SIGNAL(challenge.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user)
- challenge.used_rod.consume_bait(reward)
+ challenge.used_rod.on_reward_caught(reward, user)
/// Gives out the reward if possible
/datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, turf/fishing_spot)
@@ -461,7 +466,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
examine_text += span_info("[info]: [english_list(known_fishes)].")
/datum/fish_source/proc/spawn_reward_from_explosion(atom/location, severity)
- if(!explosive_malus)
+ if(!(fish_source_flags & FISH_SOURCE_FLAG_EXPLOSIVE_MALUS))
explosive_spawn(location, severity)
return
if(isnull(exploded_turfs))
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index 382ffeb3867..4663a7f2f10 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -31,7 +31,7 @@
/obj/item/fish/swordfish = 5 MINUTES,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
- explosive_malus = TRUE
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/ocean/beach
catalog_description = "Beach shore water"
@@ -76,7 +76,7 @@
/obj/item/fish/pike = 4 MINUTES,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
- explosive_malus = TRUE
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/sand
catalog_description = "Sand"
@@ -89,7 +89,7 @@
/obj/item/coin/gold = 3,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
- explosive_malus = TRUE
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/cursed_spring
catalog_description = null //it's a secret (sorta, I know you're reading this)
@@ -104,7 +104,7 @@
/obj/item/fishing_rod/telescopic/master = 1,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 25
- explosive_malus = TRUE
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/portal
fish_table = list(
@@ -240,8 +240,9 @@
catalog_description = null // it'd make a bad entry in the catalog.
radial_name = "Randomizer"
overlay_state = "portal_randomizer"
- var/static/list/all_portal_fish_sources_at_once
radial_state = "misaligned_question_mark"
+ fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD
+ var/static/list/all_portal_fish_sources_at_once
///Generate the fish table if we don't have one already.
/datum/fish_source/portal/random/on_fishing_spot_init(datum/component/fishing_spot/spot)
@@ -350,12 +351,12 @@
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10
- explosive_malus = TRUE
+ fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/lavaland/reason_we_cant_fish(obj/item/fishing_rod/rod, mob/fisherman, atom/parent)
. = ..()
- if(!rod.line || !(rod.line.fishing_line_traits & FISHING_LINE_REINFORCED))
- return "You'll need reinforced fishing line to fish in there"
+ if(!HAS_TRAIT(rod, TRAIT_ROD_LAVA_USABLE))
+ return "You'll need reinforced fishing line to fish in there."
/datum/fish_source/lavaland/icemoon
catalog_description = "Liquid plasma vents"
@@ -416,6 +417,7 @@
/obj/item/fish/holo/halffish = 5,
)
fishing_difficulty = FISHING_EASY_DIFFICULTY
+ fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD
/datum/fish_source/holographic/on_fishing_spot_init(datum/component/fishing_spot/spot)
ADD_TRAIT(spot.parent, TRAIT_UNLINKABLE_FISHING_SPOT, REF(src)) //You would have to be inside the holodeck anyway...
diff --git a/code/modules/instruments/items.dm b/code/modules/instruments/items.dm
index 4cf7df5a671..d9225b8e905 100644
--- a/code/modules/instruments/items.dm
+++ b/code/modules/instruments/items.dm
@@ -112,15 +112,19 @@
force = 0
attack_verb_continuous = list("plays", "jazzes", "trumpets", "mourns", "doots", "spooks")
attack_verb_simple = list("play", "jazz", "trumpet", "mourn", "doot", "spook")
+ var/single_use = FALSE
/obj/item/instrument/trumpet/spectral/Initialize(mapload)
. = ..()
- AddElement(/datum/element/spooky)
+ AddElement(/datum/element/spooky, too_spooky = !single_use, single_use = single_use)
/obj/item/instrument/trumpet/spectral/attack(mob/living/target_mob, mob/living/user, params)
playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1)
return ..()
+/obj/item/instrument/trumpet/spectral/one_doot
+ single_use = TRUE
+
/obj/item/instrument/saxophone
name = "saxophone"
desc = "This soothing sound will be sure to leave your audience in tears."
@@ -136,15 +140,19 @@
force = 0
attack_verb_continuous = list("plays", "jazzes", "saxxes", "mourns", "doots", "spooks")
attack_verb_simple = list("play", "jazz", "sax", "mourn", "doot", "spook")
+ var/single_use = FALSE
/obj/item/instrument/saxophone/spectral/Initialize(mapload)
. = ..()
- AddElement(/datum/element/spooky)
+ AddElement(/datum/element/spooky, too_spooky = !single_use, single_use = single_use)
/obj/item/instrument/saxophone/spectral/attack(mob/living/target_mob, mob/living/user, params)
playsound(src, 'sound/runtime/instruments/trombone/En4.mid', 1000, 1, -1)
return ..()
+/obj/item/instrument/saxophone/spectral/one_doot
+ single_use = TRUE
+
/obj/item/instrument/trombone
name = "trombone"
desc = "How can any pool table ever hope to compete?"
@@ -160,10 +168,14 @@
force = 0
attack_verb_continuous = list("plays", "jazzes", "trombones", "mourns", "doots", "spooks")
attack_verb_simple = list("play", "jazz", "trombone", "mourn", "doot", "spook")
+ var/single_use = FALSE
/obj/item/instrument/trombone/spectral/Initialize(mapload)
. = ..()
- AddElement(/datum/element/spooky)
+ AddElement(/datum/element/spooky, too_spooky = !single_use, single_use = single_use)
+
+/obj/item/instrument/trombone/spectral/one_doot
+ single_use = TRUE
/obj/item/instrument/trombone/spectral/attack(mob/living/target_mob, mob/living/user, params)
playsound(src, 'sound/runtime/instruments/trombone/Cn4.mid', 1000, 1, -1)
diff --git a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm
index f70ffb329d2..09da70baa16 100644
--- a/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drinks/drink_reagents.dm
@@ -226,6 +226,12 @@
holder.remove_reagent(/datum/reagent/consumable/capsaicin, seconds_per_tick)
return ..() || .
+/datum/reagent/milk/used_on_fish(obj/item/fish/fish)
+ if(HAS_TRAIT(fish, TRAIT_FISH_MADE_OF_BONE))
+ fish.adjust_health(fish.health + initial(fish.health) * max(fish.get_hunger() * 0.5, 0.12))
+ fish.sate_hunger()
+ return TRUE
+
/datum/reagent/consumable/soymilk
name = "Soy Milk"
description = "An opaque white liquid made from soybeans."
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 1c340cbc657..a5d8fdaae18 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -1230,6 +1230,11 @@
to_chat(affected_mob, span_warning("A phantom limb hurts!"))
affected_mob.say("Why are we still here, just to suffer?", forced = /datum/reagent/toxin/bonehurtingjuice)
+/datum/reagent/toxin/bonehurtingjuice/used_on_fish(obj/item/fish/fish)
+ if(HAS_TRAIT(fish, TRAIT_FISH_MADE_OF_BONE))
+ fish.adjust_health(fish.health - 30)
+ return TRUE
+
/datum/reagent/toxin/bungotoxin
name = "Bungotoxin"
description = "A horrible cardiotoxin that protects the humble bungo pit."
diff --git a/code/modules/research/designs/autolathe/service_designs.dm b/code/modules/research/designs/autolathe/service_designs.dm
index 29523bf5820..21fda49fc1b 100644
--- a/code/modules/research/designs/autolathe/service_designs.dm
+++ b/code/modules/research/designs/autolathe/service_designs.dm
@@ -531,7 +531,7 @@
name = "Fishing Rod"
id = "fishing_rod"
build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE
- materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT * 2, /datum/material/glass =SMALL_MATERIAL_AMOUNT * 2)
+ materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT * 2, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2)
build_path = /obj/item/fishing_rod
category = list(
RND_CATEGORY_INITIAL,
@@ -539,6 +539,17 @@
)
departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE
+/datum/design/fishing_rod_material
+ name = "Material Fishing Rod"
+ id = "fishing_rod_material"
+ build_type = AUTOLATHE
+ materials = list(MAT_CATEGORY_ITEM_MATERIAL = SMALL_MATERIAL_AMOUNT * 4)
+ build_path = /obj/item/fishing_rod/material
+ category = list(
+ RND_CATEGORY_INITIAL,
+ RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_SERVICE,
+ )
+
/datum/design/fish_case
name = "Stasis Fish Case"
id = "fish_case"
diff --git a/icons/obj/fishing.dmi b/icons/obj/fishing.dmi
index 36344d15e01..d97384f1f79 100644
Binary files a/icons/obj/fishing.dmi and b/icons/obj/fishing.dmi differ
diff --git a/strings/fishing_tips.txt b/strings/fishing_tips.txt
index f7143c87966..af67d15e27e 100644
--- a/strings/fishing_tips.txt
+++ b/strings/fishing_tips.txt
@@ -44,10 +44,13 @@ The legendary fishing hat isn't just cosmetic. Space carps (as well as young lob
Have you ever heard a lobster or crab talk? Well, neither have I, but they say they're quite the fishy punsters.
You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) to research.
Fish is, of course, edible. Is it safe to eat raw? Well, if you've strong stomach, otherwise your best option is to cook it for a at least half a spessman minute if you don't want to catch nasty diseases.
-After researching the Advanced Fishing Technology Node, you can print special fishing gloves that let you fish without having to carry around a fishing rod. There's one pair that even trains athletics on top of fishing. You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) for research.
+After researching the Advanced Fishing Technology Node, you can print special fishing gloves that let you fish without having to carry around a fishing rod. There's one pair that even trains athletics on top of fishing.
+You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) for research.
If you have enough credits, you can buy a set of fishing lures from cargo (or the library vending machine). Each lure allows you to catch different species of fish and won't get consumed, however they need to be spun at intervals to work.
Various clothing and handheld items, as well as chairs you sit on, can make fishing easier (or sometimes harder). A trained fisherman can tell what can help and what won't, so keep an eye out.
This may sound silly, but (live) squids and their ink sacs can be used as weapons to temporarily blind foes.
Got a bioelectricity generator aquarium but no electrogenic fish? Worry not, you can always feed your fish some teslium or liquid electricity to temporarily grant them (slightly less powerful) eletrogenesis. It'll also gradually hurt them however.
Fish can grow in size and weight if you fed them somewhat frequently. Giving them growth serum (from fly amanita) will also boost the rate at which they grow.
-Feeding a fish mutagen can triple the probability of generating evolved offsprings, provided it has an evolution.
\ No newline at end of file
+Feeding a fish mutagen can triple the probability of generating evolved offsprings, provided it has an evolution.
+You can print fishing rods of different materials from an autolathe, which can inrease or decrease fishing difficulty, casting range, experience gained and can have other, special effects.
+Albeit scarcely, it's possible to catch fish made of the same materials of a custom material fishing rod. Equipping a shiny fishing hook and the quality of the bait can improve your odds.
diff --git a/tgstation.dme b/tgstation.dme
index 659e1f33096..fc9625c6c0b 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1556,6 +1556,7 @@
#include "code\datums\elements\rust.dm"
#include "code\datums\elements\selfknockback.dm"
#include "code\datums\elements\series.dm"
+#include "code\datums\elements\shiny_bait.dm"
#include "code\datums\elements\sideway_movement.dm"
#include "code\datums\elements\simple_flying.dm"
#include "code\datums\elements\skill_reward.dm"