From db8eca7bf3366a97163c0abd6574bee82bd38fd3 Mon Sep 17 00:00:00 2001 From: Ghom <42542238+Ghommie@users.noreply.github.com> Date: Sun, 1 Oct 2023 05:11:55 +0200 Subject: [PATCH] The fishing portal generator expansion (plus skill-chip) (#78203) ## About The Pull Request This is a PR I worked on last month, but had to put on hold while dealing with some pressing issues with fishing feature, minigame and other stuff, and because I had to atomize out some of the stuff previously present here. I've expanded on the fishing portal generator to do something other than dispense guppies and goldfishes. It now has multiple settings, unlockable by performing scanning experiments for fish types, available from the get go, which also reward a meager amount of techweb points upon completion. The generator can now be built too. No longer it has to be ordered from cargo. It can also be emagged for the syndicate setting, tho right now it only dispenses donkfish and emulsijack, both otherwise impossible to get outside of... exodrone adventures. The advanced fishing rod now comes with an experiment handler component, specific to the fish scanning experiment, that automatically scans fished content. The node to get it now requires 2000 points and the first fish scanning exp to be unock. A new skillchip has been added, which adds a trait that changes the icon of the fish shown in the minigame UI, giving some clues on what the reward will be. The same trait is also gained by reaching the master (penultimate) level of the fishing skill. A new fish type has been added, with its own quirks. One of these quirks included temporarily switching movement direction of the bait. Currently, it can only be fished in the hyperspace and randomizer setting of the fishing portal. Screenshots: ![fuck yea](https://github.com/tgstation/tgstation/assets/42542238/b4c75951-fa07-44ae-99ee-f602adf8a5a4) ![radial](https://github.com/tgstation/tgstation/assets/42542238/68ff21d8-69fd-4ba5-aa58-9976b6e3282f) ## Why It's Good For The Game The fishing portal generator is but a stale and underdeveloped prototype of the fishing feature right now, so much I was thinking of removing it at first. However, we also have a lot of fishes which are pretty much unfishable, so I came up with the idea of adding new portal settings that allow people to actually get them. As for the skillchip and trait, it's but an extra to both the vending machine in the library and the fishing skill itself, which has an overall humble impact on the minigame. ## Changelog :cl: add: Expanded the fishing portal generator. It now comes with several portal options that can be unlocked by performing fish scanning experiments, which also award a modest amount of techweb points. balance: The fishing portal generator is now buildable and no longer orderable. The board can be printed from cargo, service and science lathes. balance: Advanced fishing tech is no longer a BEPIS design. It now requires the base fish scanning experiment and 2000 points to be unlocked. add: The advanced fishing rod now comes with an incorporated experiscanner specific for fish scanning. add: Added a new skillchip that may change the icon of the "fish" shown in the minigame UI to less generic ones. Reaching master level in fishing also does that. qol: The experiment handler UI no longer shows unselectable experiments. /:cl: --- code/__DEFINES/aquarium.dm | 44 ----- code/__DEFINES/dcs/signals/signals_fish.dm | 5 + code/__DEFINES/experisci.dm | 6 + code/__DEFINES/fish.dm | 136 +++++++++++++++ code/__DEFINES/fishing.dm | 62 ------- code/__DEFINES/traits.dm | 4 + code/_globalvars/traits.dm | 1 + code/datums/components/fishing_spot.dm | 1 + code/datums/mind/skills.dm | 6 +- code/datums/skills/_skill.dm | 12 +- code/datums/skills/fishing.dm | 14 ++ .../machinery/computer/operating_computer.dm | 6 +- .../machines/machine_circuitboards.dm | 9 + code/modules/cargo/packs/general.dm | 7 - code/modules/experisci/destructive_scanner.dm | 9 +- .../experisci/experiment/experiments.dm | 2 +- .../experiment/handlers/experiment_handler.dm | 71 ++++---- .../experisci/experiment/types/experiment.dm | 15 +- .../experisci/experiment/types/exploration.dm | 2 +- .../experiment/types/random_scanning.dm | 2 +- .../experisci/experiment/types/scanning.dm | 20 ++- .../experiment/types/scanning_fish.dm | 116 ++++++++++++ .../experiment/types/scanning_material.dm | 2 +- .../experiment/types/scanning_plants.dm | 2 +- code/modules/experisci/handheld_scanner.dm | 10 +- .../modules/fishing/aquarium/fish_analyzer.dm | 21 +-- code/modules/fishing/fish/_fish.dm | 34 ++-- code/modules/fishing/fish/fish_traits.dm | 32 +++- code/modules/fishing/fish/fish_types.dm | 41 ++++- code/modules/fishing/fish_catalog.dm | 18 +- code/modules/fishing/fishing_equipment.dm | 8 +- code/modules/fishing/fishing_minigame.dm | 87 ++++++++- .../modules/fishing/fishing_portal_machine.dm | 82 +++++++-- code/modules/fishing/fishing_rod.dm | 23 ++- code/modules/fishing/sources/_fish_source.dm | 50 +++++- code/modules/fishing/sources/source_types.dm | 165 +++++++++++++++++- .../library/skill_learning/skillchip.dm | 9 + .../research/designs/machine_designs.dm | 10 ++ code/modules/research/techweb/_techweb.dm | 18 +- code/modules/research/techweb/all_nodes.dm | 28 +-- code/modules/unit_tests/fish_unit_tests.dm | 19 +- code/modules/vending/games.dm | 1 + icons/hud/fishing_hud.dmi | Bin 2956 -> 4421 bytes icons/hud/radial_fishing.dmi | Bin 0 -> 1242 bytes icons/obj/aquarium.dmi | Bin 26713 -> 30068 bytes icons/obj/fishing.dmi | Bin 4692 -> 16887 bytes sound/attributions.txt | 6 + sound/effects/arcade_jump.ogg | Bin 0 -> 10761 bytes sound/effects/boing.ogg | Bin 0 -> 28224 bytes tgstation.dme | 4 +- .../tgui/interfaces/ExperimentConfigure.js | 38 +--- 51 files changed, 960 insertions(+), 298 deletions(-) delete mode 100644 code/__DEFINES/aquarium.dm create mode 100644 code/__DEFINES/fish.dm delete mode 100644 code/__DEFINES/fishing.dm create mode 100644 code/modules/experisci/experiment/types/scanning_fish.dm create mode 100644 icons/hud/radial_fishing.dmi create mode 100644 sound/effects/arcade_jump.ogg create mode 100644 sound/effects/boing.ogg diff --git a/code/__DEFINES/aquarium.dm b/code/__DEFINES/aquarium.dm deleted file mode 100644 index 6e0a39f5040..00000000000 --- a/code/__DEFINES/aquarium.dm +++ /dev/null @@ -1,44 +0,0 @@ -#define AQUARIUM_ANIMATION_FISH_SWIM "fish" -#define AQUARIUM_ANIMATION_FISH_DEAD "dead" - -#define AQUARIUM_PROPERTIES_PX_MIN "px_min" -#define AQUARIUM_PROPERTIES_PX_MAX "px_max" -#define AQUARIUM_PROPERTIES_PY_MIN "py_min" -#define AQUARIUM_PROPERTIES_PY_MAX "py_max" - -#define AQUARIUM_LAYER_MODE_BOTTOM "bottom" -#define AQUARIUM_LAYER_MODE_TOP "top" -#define AQUARIUM_LAYER_MODE_AUTO "auto" - -#define FISH_ALIVE "alive" -#define FISH_DEAD "dead" - -#define FISH_SIZE_TINY_MAX 30 -#define FISH_SIZE_SMALL_MAX 50 -#define FISH_SIZE_NORMAL_MAX 90 -#define FISH_SIZE_BULKY_MAX 130 - -#define FISH_GRIND_RESULTS_WEIGHT_DIVISOR 500 -#define FISH_FILLET_NUMBER_SIZE_DIVISOR 30 - -#define NEW_FISH_BREEDING_TIMEOUT_MULT 2 -#define NEW_FISH_LAST_FEEDING_MULT 0.5 - -#define MIN_AQUARIUM_TEMP T0C -#define MAX_AQUARIUM_TEMP (T0C + 100) -#define DEFAULT_AQUARIUM_TEMP (T0C + 24) - -#define FISH_RARITY_BASIC 1000 -#define FISH_RARITY_RARE 400 -#define FISH_RARITY_VERY_RARE 200 -#define FISH_RARITY_GOOD_LUCK_FINDING_THIS 1 -#define FISH_RARITY_NOPE 0 - -#define AQUARIUM_FLUID_FRESHWATER "Freshwater" -#define AQUARIUM_FLUID_SALTWATER "Saltwater" -#define AQUARIUM_FLUID_SULPHWATEVER "Sulfuric Water" -#define AQUARIUM_FLUID_AIR "Air" -#define AQUARIUM_FLUID_ANADROMOUS "Adaptive to both Freshwater and Saltwater" -#define AQUARIUM_FLUID_ANY_WATER "Adaptive to all kind of water" - -#define AQUARIUM_COMPANY "Aquatech Ltd." diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index f65b8c99805..90e580e9166 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -24,5 +24,10 @@ #define COMSIG_FISHING_ROD_CAST "fishing_rod_cast" #define FISHING_ROD_CAST_HANDLED (1 << 0) +/// From /datum/fish_source/proc/dispense_reward(), not set if the reward is a dud: (reward, user) +#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" + /// Sent when the challenge is to be interrupted: (reason) #define COMSIG_FISHING_SOURCE_INTERRUPT_CHALLENGE "fishing_spot_interrupt_challenge" diff --git a/code/__DEFINES/experisci.dm b/code/__DEFINES/experisci.dm index 9130e0ae565..c74290ff5f7 100644 --- a/code/__DEFINES/experisci.dm +++ b/code/__DEFINES/experisci.dm @@ -26,6 +26,8 @@ /// Destructive experiments which will destroy the sample #define EXPERIMENT_TRAIT_DESTRUCTIVE (1 << 0) +/// Used by scanning experiments: instead of storing refs or be a number, the list for scanned atoms is used as typecache +#define EXPERIMENT_TRAIT_TYPECACHE (1 << 1) /// Will always attempt to action every experiment eligible with a single input, /// no experiment selection required @@ -33,3 +35,7 @@ /// Experiment handlers with this flag will not automatically connect to the first techweb they find /// on initialization #define EXPERIMENT_CONFIG_NO_AUTOCONNECT (1 << 1) +/// Experiment handlers with this flag won't pester the user of objects not pertinent to the test or if no experiment is selected +#define EXPERIMENT_CONFIG_SILENT_FAIL (1 << 2) +/// Experiment handlers with this flag will bypass any delay when trying to scan something +#define EXPERIMENT_CONFIG_IMMEDIATE_ACTION (1 << 3) diff --git a/code/__DEFINES/fish.dm b/code/__DEFINES/fish.dm new file mode 100644 index 00000000000..89b7963d91d --- /dev/null +++ b/code/__DEFINES/fish.dm @@ -0,0 +1,136 @@ +/// Use in fish tables to denote miss chance. +#define FISHING_DUD "dud" + +// Baseline fishing difficulty levels +#define FISHING_DEFAULT_DIFFICULTY 15 + +/// Difficulty modifier when bait is fish's favorite +#define FAV_BAIT_DIFFICULTY_MOD -5 +/// Difficulty modifier when bait is fish's disliked +#define DISLIKED_BAIT_DIFFICULTY_MOD 15 +/// Difficulty modifier when our fisherman has the trait TRAIT_SETTLER +#define SETTLER_DIFFICULTY_MOD -5 + +#define FISH_TRAIT_MINOR_DIFFICULTY_BOOST 5 + +// These define how the fish will behave in the minigame +#define FISH_AI_DUMB "dumb" +#define FISH_AI_ZIPPY "zippy" +#define FISH_AI_SLOW "slow" + +#define ADDITIVE_FISHING_MOD "additive" +#define MULTIPLICATIVE_FISHING_MOD "multiplicative" + +// These defines are intended for use to interact with fishing hooks when going +// 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) +///See FISHING_MINIGAME_RULE_BIDIRECTIONAL +#define FISHING_HOOK_BIDIRECTIONAL (1 << 2) +///Prevents the user from losing the game by letting the fish get away. +#define FISHING_HOOK_NO_ESCAPE (1 << 3) +///Limits the completion loss of the minigame when the fsh is not on the bait area. +#define FISHING_HOOK_ENSNARE (1 << 4) +///Automatically kills the fish after a while, at the cost of killing it. +#define FISHING_HOOK_KILL (1 << 5) + +///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) + +///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 << 2) +///Prevents the player from losing the minigame when the completion reaches 0 +#define FISHING_MINIGAME_RULE_NO_ESCAPE (1 << 3) +///Automatically kills the fish after a while, at the cost of killing it +#define FISHING_MINIGAME_RULE_KILL (1 << 4) +///Prevents the fishing skill from having an effect on the minigame and experience from being awarded +#define FISHING_MINIGAME_RULE_NO_EXP (1 << 5) +///If enabled, the minigame will occasionally screw around and invert the velocity of the bait +#define FISHING_MINIGAME_RULE_ANTIGRAV (1 << 6) +///Will filp the minigame hud for the duration of the effect +#define FISHING_MINIGAME_RULE_FLIP (1 << 7) + +///all the effects that are active and will last for a few seconds before triggering a cooldown +#define FISHING_MINIGAME_ACTIVE_EFFECTS (FISHING_MINIGAME_RULE_ANTIGRAV|FISHING_MINIGAME_RULE_FLIP) + +/// The default additive value for fishing hook catch weight modifiers. +#define FISHING_DEFAULT_HOOK_BONUS_ADDITIVE 0 +/// The default multiplicative value for fishing hook catch weight modifiers. +#define FISHING_DEFAULT_HOOK_BONUS_MULTIPLICATIVE 1 + +//Fish icon defines, used by fishing minigame +#define FISH_ICON_DEF "fish" +#define FISH_ICON_HOSTILE "hostile" +#define FISH_ICON_STAR "star" +#define FISH_ICON_CHUNKY "chunky" +#define FISH_ICON_SLIME "slime" +#define FISH_ICON_COIN "coin" +#define FISH_ICON_GEM "gem" +#define FISH_ICON_CRAB "crab" +#define FISH_ICON_JELLYFISH "jellyfish" +#define FISH_ICON_BONE "bone" + +#define AQUARIUM_ANIMATION_FISH_SWIM "fish" +#define AQUARIUM_ANIMATION_FISH_DEAD "dead" + +#define AQUARIUM_PROPERTIES_PX_MIN "px_min" +#define AQUARIUM_PROPERTIES_PX_MAX "px_max" +#define AQUARIUM_PROPERTIES_PY_MIN "py_min" +#define AQUARIUM_PROPERTIES_PY_MAX "py_max" + +#define AQUARIUM_LAYER_MODE_BOTTOM "bottom" +#define AQUARIUM_LAYER_MODE_TOP "top" +#define AQUARIUM_LAYER_MODE_AUTO "auto" + +#define FISH_ALIVE "alive" +#define FISH_DEAD "dead" + +///Fish size thresholds for w_class. +#define FISH_SIZE_TINY_MAX 30 +#define FISH_SIZE_SMALL_MAX 50 +#define FISH_SIZE_NORMAL_MAX 90 +#define FISH_SIZE_BULKY_MAX 130 + +///The coefficient for maximum weight/size divergence relative to the averages. +#define MAX_FISH_DEVIATION_COEFF 2.5 + +///The volume of the grind results is multiplied by the fish' weight and divided by this. +#define FISH_GRIND_RESULTS_WEIGHT_DIVISOR 500 +///The number of fillets is multiplied by the fish' size and divided by this. +#define FISH_FILLET_NUMBER_SIZE_DIVISOR 30 + +///The breeding timeout for newly instantiated fish is multiplied by this. +#define NEW_FISH_BREEDING_TIMEOUT_MULT 2 +///The last feeding timestamp of newly instantiated fish is multiplied by this: ergo, they spawn 50% hungry. +#define NEW_FISH_LAST_FEEDING_MULT 0.5 + +#define MIN_AQUARIUM_TEMP T0C +#define MAX_AQUARIUM_TEMP (T0C + 100) +#define DEFAULT_AQUARIUM_TEMP (T0C + 24) + +///How likely one's to find a given fish from random fish cases. +#define FISH_RARITY_BASIC 1000 +#define FISH_RARITY_RARE 400 +#define FISH_RARITY_VERY_RARE 200 +#define FISH_RARITY_GOOD_LUCK_FINDING_THIS 5 +#define FISH_RARITY_NOPE 0 + +///Aquarium fluid variables. The fish' required fluid has to match this, or it'll slowly die. +#define AQUARIUM_FLUID_FRESHWATER "Freshwater" +#define AQUARIUM_FLUID_SALTWATER "Saltwater" +#define AQUARIUM_FLUID_SULPHWATEVER "Sulfuric Water" +#define AQUARIUM_FLUID_AIR "Air" +#define AQUARIUM_FLUID_ANADROMOUS "Adaptive to both Freshwater and Saltwater" +#define AQUARIUM_FLUID_ANY_WATER "Adaptive to all kind of water" + +///Fluff. The name of the aquarium company shown in the fish catalog +#define AQUARIUM_COMPANY "Aquatech Ltd." diff --git a/code/__DEFINES/fishing.dm b/code/__DEFINES/fishing.dm deleted file mode 100644 index dc73623f27c..00000000000 --- a/code/__DEFINES/fishing.dm +++ /dev/null @@ -1,62 +0,0 @@ -/// Use in fish tables to denote miss chance. -#define FISHING_DUD "dud" - -// Baseline fishing difficulty levels -#define FISHING_DEFAULT_DIFFICULTY 15 - -/// Difficulty modifier when bait is fish's favorite -#define FAV_BAIT_DIFFICULTY_MOD -5 -/// Difficulty modifier when bait is fish's disliked -#define DISLIKED_BAIT_DIFFICULTY_MOD 15 -/// Difficulty modifier when our fisherman has the trait TRAIT_SETTLER -#define SETTLER_DIFFICULTY_MOD -5 - - -#define FISH_TRAIT_MINOR_DIFFICULTY_BOOST 5 - -// These define how the fish will behave in the minigame -#define FISH_AI_DUMB "dumb" -#define FISH_AI_ZIPPY "zippy" -#define FISH_AI_SLOW "slow" - -#define ADDITIVE_FISHING_MOD "additive" -#define MULTIPLICATIVE_FISHING_MOD "multiplicative" - -// These defines are intended for use to interact with fishing hooks when going -// 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's used to make the bait more weighted, for the -/// fishing minigame itself. -#define FISHING_HOOK_WEIGHTED (1 << 1) -/** - * During the fishing minigame, it stops the bait from being pulled down by gravity, - * while also allowing the player to move it down with right-click. - */ -#define FISHING_HOOK_BIDIRECTIONAL (1 << 2) -///Prevents the user from losing the game by letting the fish get away. -#define FISHING_HOOK_NO_ESCAPE (1 << 3) -///Limits the completion loss of the minigame when the fsh is not on the bait area. -#define FISHING_HOOK_ENSNARE (1 << 4) -///Slowly damages the fish, until it dies, then it's victory. -#define FISHING_HOOK_KILL (1 << 5) - -///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 reel. -#define FISHING_LINE_BOUNCY (1 << 2) - -#define FISHING_MINIGAME_RULE_BIDIRECTIONAL (1 << 2) -#define FISHING_MINIGAME_RULE_NO_ESCAPE (1 << 3) -#define FISHING_MINIGAME_RULE_KILL (1 << 4) -#define FISHING_MINIGAME_RULE_NO_EXP (1 << 5) - -/// The default additive value for fishing hook catch weight modifiers. -#define FISHING_DEFAULT_HOOK_BONUS_ADDITIVE 0 -/// The default multiplicative value for fishing hook catch weight modifiers. -#define FISHING_DEFAULT_HOOK_BONUS_MULTIPLICATIVE 1 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index cd110f2464d..73fbe6723e6 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -319,6 +319,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_BLOOD_DEFICIENCY "blood_deficiency" #define TRAIT_JOLLY "jolly" #define TRAIT_NOCRITDAMAGE "no_crit" +///Added to mob or mind, changes the icons of the fish shown in the minigame UI depending on the possible reward. +#define TRAIT_REVEAL_FISH "reveal_fish" /// Stops the mob from slipping on water, or banana peels, or pretty much anything that doesn't have [GALOSHES_DONT_HELP] set #define TRAIT_NO_SLIP_WATER "noslip_water" @@ -909,6 +911,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FISH_AMPHIBIOUS "fish_amphibious" ///Trait needed for the lubefish evolution #define TRAIT_FISH_FED_LUBE "fish_fed_lube" +#define TRAIT_FISH_NO_HUNGER "fish_no_hunger" // common trait sources #define TRAIT_GENERIC "generic" @@ -1082,6 +1085,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// sticky nodrop sounds like a bad soundcloud rapper's name #define STICKY_NODROP "sticky-nodrop" #define SKILLCHIP_TRAIT "skillchip" +#define SKILL_TRAIT "skill" #define BUSY_FLOORBOT_TRAIT "busy-floorbot" #define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit" #define LOCKED_BORG_TRAIT "locked-borg" diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 54fe44a609b..512b528f86f 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -269,6 +269,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FISH_TOXIN_IMMUNE" = TRAIT_FISH_TOXIN_IMMUNE, "TRAIT_FISH_CROSSBREEDER" = TRAIT_FISH_CROSSBREEDER, "TRAIT_FISH_FED_LUBE" = TRAIT_FISH_FED_LUBE, + "TRAIT_FISH_NO_HUNGER" = TRAIT_FISH_NO_HUNGER, ), )) diff --git a/code/datums/components/fishing_spot.dm b/code/datums/components/fishing_spot.dm index 3f230b8754d..f88c27a7135 100644 --- a/code/datums/components/fishing_spot.dm +++ b/code/datums/components/fishing_spot.dm @@ -12,6 +12,7 @@ fish_source = configuration else return COMPONENT_INCOMPATIBLE + fish_source.on_fishing_spot_init() RegisterSignal(parent, COMSIG_ATOM_ATTACKBY, PROC_REF(handle_attackby)) RegisterSignal(parent, COMSIG_FISHING_ROD_CAST, PROC_REF(handle_cast)) diff --git a/code/datums/mind/skills.dm b/code/datums/mind/skills.dm index 5847236435b..474291d5ae0 100644 --- a/code/datums/mind/skills.dm +++ b/code/datums/mind/skills.dm @@ -18,12 +18,10 @@ experience_multiplier += experience_multiplier_reasons[key] known_skills[skill][SKILL_EXP] = max(0, known_skills[skill][SKILL_EXP] + amt*experience_multiplier) //Update exp. Prevent going below 0 known_skills[skill][SKILL_LVL] = update_skill_level(skill)//Check what the current skill level is based on that skill's exp - if(silent) - return if(known_skills[skill][SKILL_LVL] > old_level) - S.level_gained(src, known_skills[skill][SKILL_LVL], old_level) + S.level_gained(src, known_skills[skill][SKILL_LVL], old_level, silent) else if(known_skills[skill][SKILL_LVL] < old_level) - S.level_lost(src, known_skills[skill][SKILL_LVL], old_level) + S.level_lost(src, known_skills[skill][SKILL_LVL], old_level, silent) ///Set experience of a specific skill to a number /datum/mind/proc/set_experience(skill, amt, silent = FALSE) diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index ec52ebd9e96..b8438c67927 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -27,8 +27,7 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) span_nicegreen("I'm getting a little better at [name]!"), span_nicegreen("I'm getting much better at [name]!"), span_nicegreen("I feel like I've become quite proficient at [name]!"), - "After lots of practice, I've begun to truly understand the intricacies \ - and surprising depth behind [name]. I now consider myself a master [title].", + span_nicegreen("After lots of practice, I've begun to truly understand the intricacies and surprising depth behind [name]. I now consider myself a master [title]."), span_nicegreen("Through incredible determination and effort, I've reached the peak of my [name] abiltities. I'm finally able to consider myself a legendary [title]!") ) levelDownMessages = list(span_nicegreen("I have somehow completely lost all understanding of [name]. Please tell an admin if you see this."), span_nicegreen("I'm starting to forget what [name] really even is. I need more practice..."), @@ -46,13 +45,18 @@ GLOBAL_LIST_INIT(skill_types, subtypesof(/datum/skill)) * * mind - The mind that you'll want to send messages * * new_level - The newly gained level. Can check the actual level to give different messages at different levels, see defines in skills.dm * * old_level - Similar to the above, but the level you had before levelling up. + * * silent - Silences the announcement if TRUE */ -/datum/skill/proc/level_gained(datum/mind/mind, new_level, old_level)//just for announcements (doesn't go off if the xp gain is silent) +/datum/skill/proc/level_gained(datum/mind/mind, new_level, old_level, silent) + if(silent) + return to_chat(mind.current, levelUpMessages[new_level]) //new_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list /** * level_lost: See level_gained, same idea but fires on skill level-down */ -/datum/skill/proc/level_lost(datum/mind/mind, new_level, old_level) +/datum/skill/proc/level_lost(datum/mind/mind, new_level, old_level, silent) + if(silent) + return to_chat(mind.current, levelDownMessages[old_level]) //old_level will be a value from 1 to 6, so we get appropriate message from the 6-element levelUpMessages list /** diff --git a/code/datums/skills/fishing.dm b/code/datums/skills/fishing.dm index d5ecff3c8f5..ddf90e1a0a3 100644 --- a/code/datums/skills/fishing.dm +++ b/code/datums/skills/fishing.dm @@ -8,3 +8,17 @@ desc = "How empty and alone you are on this barren Earth." modifiers = list(SKILL_VALUE_MODIFIER = list(1, 1, 0, -1, -2, -4, -6)) skill_item_path = /obj/item/clothing/head/soft/fishing_hat + +/datum/skill/fishing/New() + . = ..() + levelUpMessages[SKILL_LEVEL_MASTER] = span_nicegreen("After lots of practice, I've begun to truly understand the surprising depth behind [name]. As a master [title], I can take an easier guess of what I'm trying to catch now.") + +/datum/skill/fishing/level_gained(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(new_level >= SKILL_LEVEL_MASTER && old_level < SKILL_LEVEL_MASTER) + ADD_TRAIT(mind, TRAIT_REVEAL_FISH, SKILL_TRAIT) + +/datum/skill/fishing/level_lost(datum/mind/mind, new_level, old_level, silent) + . = ..() + if(old_level >= SKILL_LEVEL_MASTER && new_level < SKILL_LEVEL_MASTER) + REMOVE_TRAIT(mind, TRAIT_REVEAL_FISH, SKILL_TRAIT) diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index f7b0ef24ffd..3b639a9ce57 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -25,11 +25,15 @@ if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb) CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, src) - experiment_handler = AddComponent( \ + var/list/operating_signals = list( + COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_autopsy_experiment), + ) + experiment_handler = AddComponent( /datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/autopsy), \ config_flags = EXPERIMENT_CONFIG_ALWAYS_ACTIVE, \ config_mode = EXPERIMENT_CONFIG_ALTCLICK, \ + experiment_signals = operating_signals, \ ) /obj/machinery/computer/operating/Destroy() diff --git a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm index faa48559100..4bea5b1335c 100644 --- a/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machines/machine_circuitboards.dm @@ -1303,6 +1303,15 @@ req_components = list( /datum/stock_part/card_reader = 1) +/obj/item/circuitboard/machine/fishing_portal_generator + name = "Fishing Portal Generator" + greyscale_colors = CIRCUIT_COLOR_SERVICE + build_path = /obj/machinery/fishing_portal_generator + req_components = list( + /datum/stock_part/matter_bin = 2, + /datum/stock_part/capacitor = 1) + needs_anchored = FALSE + //Supply /obj/item/circuitboard/machine/ore_redemption name = "Ore Redemption" diff --git a/code/modules/cargo/packs/general.dm b/code/modules/cargo/packs/general.dm index fa7a3bfa374..5bfcf01eb00 100644 --- a/code/modules/cargo/packs/general.dm +++ b/code/modules/cargo/packs/general.dm @@ -292,13 +292,6 @@ crate_value = value contents_uplink_type = uplink -/datum/supply_pack/misc/fishing_portal - name = "Fishing Portal Generator Crate" - desc = "Not enough fish near your location? Fishing portal has your back." - cost = CARGO_CRATE_VALUE * 4 - contains = list(/obj/machinery/fishing_portal_generator) - crate_name = "fishing portal crate" - /datum/supply_pack/misc/papercutter name = "Paper Cutters Crate" desc = "Contains 3 office-grade paper cutters, equipped with sharp blades that can cut any paper into two thin slips.\ diff --git a/code/modules/experisci/destructive_scanner.dm b/code/modules/experisci/destructive_scanner.dm index 3591a31cd7b..ef89dc9b94a 100644 --- a/code/modules/experisci/destructive_scanner.dm +++ b/code/modules/experisci/destructive_scanner.dm @@ -19,10 +19,17 @@ // Late load to ensure the component initialization occurs after the machines are initialized /obj/machinery/destructive_scanner/LateInitialize() . = ..() + + var/static/list/destructive_signals = list( + COMSIG_MACHINERY_DESTRUCTIVE_SCAN = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_destructive_experiment), + ) + AddComponent(/datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/scanning),\ config_mode = EXPERIMENT_CONFIG_CLICK, \ - start_experiment_callback = CALLBACK(src, PROC_REF(activate))) + start_experiment_callback = CALLBACK(src, PROC_REF(activate)), \ + experiment_signals = destructive_signals, \ + ) ///Activates the machine; checks if it can actually scan, then starts. /obj/machinery/destructive_scanner/proc/activate() diff --git a/code/modules/experisci/experiment/experiments.dm b/code/modules/experisci/experiment/experiments.dm index 8eee5bcc592..577ae59a900 100644 --- a/code/modules/experisci/experiment/experiments.dm +++ b/code/modules/experisci/experiment/experiments.dm @@ -323,7 +323,7 @@ ///Damage percent that each mech needs to be at for a scan to work. var/damage_percent -/datum/experiment/scanning/random/mecha_damage_scan/New() +/datum/experiment/scanning/random/mecha_damage_scan/New(datum/techweb/techweb) . = ..() damage_percent = rand(15, 95) //updating the description with the damage_percent var set diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index abc5d4ad1dd..29e7da95391 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -38,6 +38,7 @@ disallowed_traits = null, config_flags = null, datum/callback/start_experiment_callback = null, + list/experiment_signals ) . = ..() if(!ismovable(parent)) @@ -49,13 +50,8 @@ src.config_flags = config_flags src.start_experiment_callback = start_experiment_callback - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, PROC_REF(try_run_handheld_experiment)) - RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(ignored_handheld_experiment_attempt)) - if(istype(parent, /obj/machinery/destructive_scanner)) - RegisterSignal(parent, COMSIG_MACHINERY_DESTRUCTIVE_SCAN, PROC_REF(try_run_destructive_experiment)) - if(istype(parent, /obj/machinery/computer/operating)) - RegisterSignal(parent, COMSIG_OPERATING_COMPUTER_AUTOPSY_COMPLETE, PROC_REF(try_run_autopsy_experiment)) + for(var/signal in experiment_signals) + RegisterSignal(parent, signal, experiment_signals[signal]) // Determine UI display mode switch(config_mode) @@ -85,9 +81,9 @@ */ /datum/component/experiment_handler/proc/try_run_handheld_experiment(datum/source, atom/target, mob/user, params) SIGNAL_HANDLER - if (!should_run_handheld_experiment(source, target, user, params)) + if (!should_run_handheld_experiment(source, target, user)) return - INVOKE_ASYNC(src, PROC_REF(try_run_handheld_experiment_async), source, target, user, params) + INVOKE_ASYNC(src, PROC_REF(try_run_handheld_experiment_async), source, target, user) return COMPONENT_CANCEL_ATTACK_CHAIN /** @@ -98,7 +94,7 @@ if (!proximity_flag) return . |= COMPONENT_AFTERATTACK_PROCESSED_ITEM - if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) + if ((selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) || config_flags & EXPERIMENT_CONFIG_SILENT_FAIL) return . playsound(user, 'sound/machines/buzz-sigh.ogg', 25) to_chat(user, span_notice("[target] is not related to your currently selected experiment.")) @@ -107,7 +103,7 @@ /** * Checks that an experiment can be run using the provided target, used for preventing the cancellation of the attack chain inappropriately */ -/datum/component/experiment_handler/proc/should_run_handheld_experiment(datum/source, atom/target, mob/user, params) +/datum/component/experiment_handler/proc/should_run_handheld_experiment(datum/source, atom/target, mob/user) // Check that there is actually an experiment selected if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) return @@ -127,16 +123,17 @@ /** * This proc exists because Jared Fogle really likes async */ -/datum/component/experiment_handler/proc/try_run_handheld_experiment_async(datum/source, atom/target, mob/user, params) +/datum/component/experiment_handler/proc/try_run_handheld_experiment_async(datum/source, atom/target, mob/user) if (selected_experiment == null && !(config_flags & EXPERIMENT_CONFIG_ALWAYS_ACTIVE)) - to_chat(user, span_notice("You do not have an experiment selected!")) + if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) + to_chat(user, span_notice("You do not have an experiment selected!")) return - if(!do_after(user, 1 SECONDS, target = target)) + if(!(config_flags & EXPERIMENT_CONFIG_IMMEDIATE_ACTION) && !do_after(user, 1 SECONDS, target = target)) return if(action_experiment(source, target)) playsound(user, 'sound/machines/ping.ogg', 25) to_chat(user, span_notice("You scan [target].")) - else + else if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) playsound(user, 'sound/machines/buzz-sigh.ogg', 25) to_chat(user, span_notice("[target] is not related to your currently selected experiment.")) @@ -148,8 +145,9 @@ SIGNAL_HANDLER var/atom/movable/our_scanner = parent if (selected_experiment == null) - playsound(our_scanner, 'sound/machines/buzz-sigh.ogg', 25) - to_chat(our_scanner, span_notice("No experiment selected!")) + if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) + playsound(our_scanner, 'sound/machines/buzz-sigh.ogg', 25) + to_chat(our_scanner, span_notice("No experiment selected!")) return var/successful_scan for(var/scan_target in scanned_atoms) @@ -159,7 +157,7 @@ if(successful_scan) playsound(our_scanner, 'sound/machines/ping.ogg', 25) to_chat(our_scanner, span_notice("The scan succeeds.")) - else + else if(!(config_flags & EXPERIMENT_CONFIG_SILENT_FAIL)) playsound(src, 'sound/machines/buzz-sigh.ogg', 25) our_scanner.say("The scan did not result in anything.") @@ -261,6 +259,7 @@ /datum/component/experiment_handler/proc/link_techweb(datum/techweb/new_web) if (new_web == linked_web) return + selected_experiment?.on_unselected(src) selected_experiment = null linked_web = new_web @@ -268,6 +267,7 @@ * Unlinks this handler from the selected techweb */ /datum/component/experiment_handler/proc/unlink_techweb() + selected_experiment?.on_unselected(src) selected_experiment = null linked_web = null @@ -278,13 +278,15 @@ * * experiment - The experiment to attempt to link to */ /datum/component/experiment_handler/proc/link_experiment(datum/experiment/experiment) - if (experiment && can_select_experiment(experiment)) + if (can_select_experiment(experiment)) selected_experiment = experiment + selected_experiment.on_selected(src) /** * Unlinks this handler from the selected experiment */ /datum/component/experiment_handler/proc/unlink_experiment() + selected_experiment?.on_unselected(src) selected_experiment = null /** @@ -299,31 +301,19 @@ return FALSE // Check against the list of allowed experimentors - if (experiment.allowed_experimentors && experiment.allowed_experimentors.len) - var/matched = FALSE - for (var/experimentor in experiment.allowed_experimentors) - if (istype(parent, experimentor)) - matched = TRUE - break - if (!matched) - return FALSE + if (length(experiment.allowed_experimentors) && !is_type_in_list(parent, experiment.allowed_experimentors)) + return FALSE // Check that this experiment is visible currently - if (!linked_web || !(experiment in linked_web.available_experiments)) + if (!(experiment in linked_web?.available_experiments)) return FALSE // Check that this experiment type isn't blacklisted - for (var/badsci in blacklisted_experiments) - if (istype(experiment, badsci)) - return FALSE + if(is_type_in_list(experiment, blacklisted_experiments)) + return FALSE - // Check against the allowed experiment types - for (var/goodsci in allowed_experiments) - if (istype(experiment, goodsci)) - return TRUE - - // If we haven't returned yet then this shouldn't be allowed - return FALSE + // Finally, check against the allowed experiment types + return is_type_in_list(experiment, allowed_experiments) /datum/component/experiment_handler/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -355,12 +345,13 @@ .["techwebs"] += list(data) .["experiments"] = list() if (linked_web) - for (var/datum/experiment/experiment in linked_web.available_experiments) + for (var/datum/experiment/experiment as anything in linked_web.available_experiments) + if(!can_select_experiment(experiment)) + continue var/list/data = list( name = experiment.name, description = experiment.description, tag = experiment.exp_tag, - selectable = can_select_experiment(experiment), selected = selected_experiment == experiment, progress = experiment.check_progress(), performance_hint = experiment.performance_hint, diff --git a/code/modules/experisci/experiment/types/experiment.dm b/code/modules/experisci/experiment/types/experiment.dm index f760723f8db..add015622f6 100644 --- a/code/modules/experisci/experiment/types/experiment.dm +++ b/code/modules/experisci/experiment/types/experiment.dm @@ -22,11 +22,16 @@ /// A textual hint shown on the UI in a tooltip to help a user determine how to perform /// the experiment var/performance_hint + /** + * If set, these techweb points will be rewarded for completing the experiment. + * Useful for those loose ends not tied to any specific node discount or requirement. + */ + var/list/points_reward /** * Performs any necessary initialization of tags and other variables */ -/datum/experiment/New() +/datum/experiment/New(datum/techweb/techweb) if (traits & EXPERIMENT_TRAIT_DESTRUCTIVE) exp_tag = "Destructive [exp_tag]" @@ -60,6 +65,14 @@ /datum/experiment/proc/actionable(...) return !is_complete() +///Called when the experiment is selected by an experiment handler, for specific signals and the such. +/datum/experiment/proc/on_selected(datum/component/experiment_handler/experiment_handler) + return + +///Called when the opposite happens. +/datum/experiment/proc/on_unselected(datum/component/experiment_handler/experiment_handler) + return + /** * Proc that tries to perform the experiment, and then checks if its completed. */ diff --git a/code/modules/experisci/experiment/types/exploration.dm b/code/modules/experisci/experiment/types/exploration.dm index a6a5d2cd4cf..821e69a103a 100644 --- a/code/modules/experisci/experiment/types/exploration.dm +++ b/code/modules/experisci/experiment/types/exploration.dm @@ -52,7 +52,7 @@ /// If not null the required_condition will be picked from this list var/list/possible_random_site_types -/datum/experiment/exploration_scan/random/New() +/datum/experiment/exploration_scan/random/New(datum/techweb/techweb) . = ..() if(length(possible_random_site_types)) required_site_type = pick(possible_random_site_types) diff --git a/code/modules/experisci/experiment/types/random_scanning.dm b/code/modules/experisci/experiment/types/random_scanning.dm index e80a80b5a0e..c9d39bd47b4 100644 --- a/code/modules/experisci/experiment/types/random_scanning.dm +++ b/code/modules/experisci/experiment/types/random_scanning.dm @@ -8,7 +8,7 @@ /// Max amount of a requirement per type var/max_requirement_per_type = 100 -/datum/experiment/scanning/random/New() +/datum/experiment/scanning/random/New(datum/techweb/techweb) // Generate random contents if (possible_types.len) var/picked = 0 diff --git a/code/modules/experisci/experiment/types/scanning.dm b/code/modules/experisci/experiment/types/scanning.dm index d9bbed88c8f..54bd2ad637e 100644 --- a/code/modules/experisci/experiment/types/scanning.dm +++ b/code/modules/experisci/experiment/types/scanning.dm @@ -17,16 +17,18 @@ var/list/required_atoms = list() /// The list of atoms with sub-lists of atom references for scanned atoms contributing to the experiment (Or a count of atoms destoryed for destructive expiriments) var/list/scanned = list() + /// If set, it'll be used in place of the generic "Scan samples of \a [initial(target.name)]" in serialize_progress_stage() + var/scan_message /** * Initializes the scanned atoms lists * * Initializes the internal scanned atoms list to keep track of which atoms have already been scanned */ -/datum/experiment/scanning/New() +/datum/experiment/scanning/New(datum/techweb/techweb) . = ..() for (var/req_atom in required_atoms) - scanned[req_atom] = traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 0 : list() + scanned[req_atom] = (traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !(traits & EXPERIMENT_TRAIT_TYPECACHE)) ? 0 : list() /** * Checks if the scanning experiment is complete @@ -37,8 +39,12 @@ /datum/experiment/scanning/is_complete() . = TRUE var/destructive = traits & EXPERIMENT_TRAIT_DESTRUCTIVE + var/typecache = traits & EXPERIMENT_TRAIT_TYPECACHE for (var/req_atom in required_atoms) var/list/seen = scanned[req_atom] + ///typecache experiments work all the same whether it's destructive or not + if(typecache && length(seen) == required_atoms[req_atom]) + continue if (destructive && (!(req_atom in scanned) || scanned[req_atom] != required_atoms[req_atom])) return FALSE if (!destructive && (!seen || seen.len != required_atoms[req_atom])) @@ -65,8 +71,9 @@ * * seen_instances - The number of instances seen of this atom */ /datum/experiment/scanning/proc/serialize_progress_stage(atom/target, list/seen_instances) - var/scanned_total = traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? scanned[target] : seen_instances.len - return EXPERIMENT_PROG_INT("Scan samples of \a [initial(target.name)]", scanned_total, required_atoms[target]) + var/scanned_total = (traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !(traits & EXPERIMENT_TRAIT_TYPECACHE)) ? scanned[target] : seen_instances.len + var/message = scan_message || "Scan samples of \a [initial(target.name)]" + return EXPERIMENT_PROG_INT(message, scanned_total, required_atoms[target]) /** * Attempts to scan an atom towards the experiment's goal @@ -79,7 +86,10 @@ /datum/experiment/scanning/perform_experiment_actions(datum/component/experiment_handler/experiment_handler, atom/target) var/contributing_index_value = get_contributing_index(target) if (contributing_index_value) - scanned[contributing_index_value] += traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 1 : WEAKREF(target) + if(traits & EXPERIMENT_TRAIT_TYPECACHE) + scanned[contributing_index_value][target.type] = TRUE + else + scanned[contributing_index_value] += traits & EXPERIMENT_TRAIT_DESTRUCTIVE ? 1 : WEAKREF(target) if(traits & EXPERIMENT_TRAIT_DESTRUCTIVE && !isliving(target))//only qdel things when destructive scanning and they're not living (living things get gibbed) qdel(target) do_after_experiment(target, contributing_index_value) diff --git a/code/modules/experisci/experiment/types/scanning_fish.dm b/code/modules/experisci/experiment/types/scanning_fish.dm new file mode 100644 index 00000000000..83978010869 --- /dev/null +++ b/code/modules/experisci/experiment/types/scanning_fish.dm @@ -0,0 +1,116 @@ +///a superlist containing typecaches shared between the several fish scanning experiments for each techweb. +GLOBAL_LIST_EMPTY(scanned_fish_by_techweb) + +/** + * A special scanning experiment that unlocks further settings for the fishing portal generator. + * Mainly as an inventive solution to many a fish source being limited to maps that have it, + * and to make the fishing portal generator a bit than just gubby and goldfish. + */ +/datum/experiment/scanning/fish + name = "Fish Scanning Experiment 1" + description = "An experiment requiring different fish species to be scanned to unlock the 'Beach' setting for the fishing portal generator." + performance_hint = "Scan fish. Examine scanner to review progress. Unlock new fishing portals." + allowed_experimentors = list(/obj/item/experi_scanner, /obj/machinery/destructive_scanner, /obj/item/fishing_rod/tech) + traits = EXPERIMENT_TRAIT_TYPECACHE + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 750) + required_atoms = list(/obj/item/fish = 4) + scan_message = "Scan different species of fish" + ///Further experiments added to the techweb when this one is completed. + var/list/next_experiments = list(/datum/experiment/scanning/fish/second) + ///Completing a experiment may also enable a fish source to be used for use for the portal generator. + var/fish_source_reward = /datum/fish_source/portal/beach + +/** + * We make sure the scanned list is shared between all fish scanning experiments for this techweb, + * since this is about scanning each species, and having to redo it for each species is a hassle. + */ +/datum/experiment/scanning/fish/New(datum/techweb/techweb) + . = ..() + if(isnull(techweb)) + return + var/techweb_ref = REF(techweb) + var/list/scanned_fish = GLOB.scanned_fish_by_techweb[techweb_ref] + if(isnull(scanned_fish)) + scanned_fish = list() + GLOB.scanned_fish_by_techweb[techweb_ref] = scanned_fish + for(var/atom_type in required_atoms) + LAZYINITLIST(scanned_fish[atom_type]) + scanned = scanned_fish + +/** + * Registers a couple signals to review the fish scanned so far. + * It'd be an hassle not having any way (beside memory) to know which fish species have been scanned already otherwise. + */ +/datum/experiment/scanning/fish/on_selected(datum/component/experiment_handler/experiment_handler) + RegisterSignal(experiment_handler.parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_handler_examine)) + RegisterSignal(experiment_handler.parent, COMSIG_ATOM_EXAMINE_MORE, PROC_REF(on_handler_examine_more)) + +/datum/experiment/scanning/fish/on_unselected(datum/component/experiment_handler/experiment_handler) + UnregisterSignal(experiment_handler.parent, list(COMSIG_ATOM_EXAMINE, COMSIG_ATOM_EXAMINE_MORE)) + +/datum/experiment/scanning/fish/proc/on_handler_examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + examine_list += span_notice("Examine again to review all the species of fish scanned so far.") + +/datum/experiment/scanning/fish/proc/on_handler_examine_more(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + var/message = span_notice("Fish species scanned hitherto, if any:") + message += "" + for(var/atom_type in required_atoms) + for(var/obj/item/fish/fish_path as anything in scanned[atom_type]) + message += "[initial(fish_path.name)]" + message += "" + examine_list += message + +///Only scannable fish will contribute towards the experiment. +/datum/experiment/scanning/fish/final_contributing_index_checks(obj/item/fish/target, typepath) + return target.experisci_scannable + +/** + * After a fish scanning experiment is done, more may be unlocked. If so, add them to the techweb + * and automatically link the handler to the next experiment in the list as a bit of qol. + */ +/datum/experiment/scanning/fish/finish_experiment(datum/component/experiment_handler/experiment_handler, ...) + . = ..() + if(next_experiments) + experiment_handler.linked_web.add_experiments(next_experiments) + var/datum/experiment/next_in_line = locate(next_experiments[1]) in experiment_handler.linked_web.available_experiments + experiment_handler.link_experiment(next_in_line) + +/datum/experiment/scanning/fish/second + name = "Fish Scanning Experiment 2" + description = "An experiment requiring more fish species to be scanned to unlock the 'Chasm' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 1500) + required_atoms = list(/obj/item/fish = 8) + next_experiments = list(/datum/experiment/scanning/fish/third) + fish_source_reward = /datum/fish_source/portal/chasm + +/datum/experiment/scanning/fish/third + name = "Fish Scanning Experiment 3" + description = "An experiment requiring even more fish species to be scanned to unlock the 'Ocean' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + required_atoms = list(/obj/item/fish = 14) + next_experiments = list(/datum/experiment/scanning/fish/fourth, /datum/experiment/scanning/fish/holographic) + fish_source_reward = /datum/fish_source/portal/ocean + +/datum/experiment/scanning/fish/holographic + name = "Holographic Fish Scanning Experiment" + description = "This one actually requires holographic fish to unlock the 'Randomizer' setting for the fishing portal." + performance_hint = "Load in the 'Beach' template at the Holodeck to fish some holo-fish." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 500) + required_atoms = list(/obj/item/fish/holo = 4) + scan_message = "Scan different species of holographic fish" + next_experiments = null + fish_source_reward = /datum/fish_source/portal/random + +///holo fishes are normally unscannable, but this is an experiment for them, so we don't care for the experisci_scannable variable. +/datum/experiment/scanning/fish/holographic/final_contributing_index_checks(obj/item/fish/target, typepath) + return TRUE + +/datum/experiment/scanning/fish/fourth + name = "Fish Scanning Experiment 4" + description = "An experiment requiring lotsa fish species to unlock the 'Hyperspace' setting for the fishing portal." + points_reward = list(TECHWEB_POINT_TYPE_GENERIC = 3250) + required_atoms = list(/obj/item/fish = 21) + next_experiments = null + fish_source_reward = /datum/fish_source/portal/hyperspace diff --git a/code/modules/experisci/experiment/types/scanning_material.dm b/code/modules/experisci/experiment/types/scanning_material.dm index 714205289de..fb8a7ff354b 100644 --- a/code/modules/experisci/experiment/types/scanning_material.dm +++ b/code/modules/experisci/experiment/types/scanning_material.dm @@ -9,7 +9,7 @@ ///List of materials actually required, indexed by the atom that is required. var/required_materials = list() -/datum/experiment/scanning/random/material/New() +/datum/experiment/scanning/random/material/New(datum/techweb/techweb) . = ..() for(var/req_atom in required_atoms) var/chosen_material = pick(possible_material_types) diff --git a/code/modules/experisci/experiment/types/scanning_plants.dm b/code/modules/experisci/experiment/types/scanning_plants.dm index c34822d6e7e..b92a4cc20b4 100644 --- a/code/modules/experisci/experiment/types/scanning_plants.dm +++ b/code/modules/experisci/experiment/types/scanning_plants.dm @@ -10,7 +10,7 @@ ///List of plant genes actually required, indexed by the atom that is required. var/list/required_genes = list() -/datum/experiment/scanning/random/plants/New() +/datum/experiment/scanning/random/plants/New(datum/techweb/techweb) . = ..() if(possible_plant_genes.len) for(var/req_atom in required_atoms) diff --git a/code/modules/experisci/handheld_scanner.dm b/code/modules/experisci/handheld_scanner.dm index e0fd4d480d5..97aa034afa1 100644 --- a/code/modules/experisci/handheld_scanner.dm +++ b/code/modules/experisci/handheld_scanner.dm @@ -19,9 +19,15 @@ // Late initialize to allow for the rnd servers to initialize first /obj/item/experi_scanner/LateInitialize() . = ..() + var/static/list/handheld_signals = list( + COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt), + ) AddComponent(/datum/component/experiment_handler, \ - allowed_experiments = list(/datum/experiment/scanning, /datum/experiment/physical),\ - disallowed_traits = EXPERIMENT_TRAIT_DESTRUCTIVE) + allowed_experiments = list(/datum/experiment/scanning, /datum/experiment/physical), \ + disallowed_traits = EXPERIMENT_TRAIT_DESTRUCTIVE, \ + experiment_signals = handheld_signals, \ + ) /obj/item/experi_scanner/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] is giving in to the Great Toilet Beyond! It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index c7feab860ca..8afe053a4d5 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -190,16 +190,17 @@ if(fish.status != FISH_DEAD) render_list += "\n" - var/hunger = PERCENT(min((world.time - fish.last_feeding) / fish.feeding_frequency, 1)) - var/hunger_string = "[hunger]%" - switch(hunger) - if(0 to 60) - hunger_string = span_info(hunger_string) - if(60 to 90) - hunger_string = span_warning(hunger_string) - if(90 to 100) - hunger_string = span_alert(hunger_string) - render_list += "Hunger: [hunger_string]\n" + if(!HAS_TRAIT(fish, TRAIT_FISH_NO_HUNGER)) + var/hunger = PERCENT(min((world.time - fish.last_feeding) / fish.feeding_frequency, 1)) + var/hunger_string = "[hunger]%" + switch(hunger) + if(0 to 60) + hunger_string = span_info(hunger_string) + if(60 to 90) + hunger_string = span_warning(hunger_string) + if(90 to 100) + hunger_string = span_alert(hunger_string) + render_list += "Hunger: [hunger_string]\n" var/time_left = round(max(fish.breeding_wait - world.time, 0)/10) render_list += "Time until it can breed: [time_left] seconds" diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 21585a07546..1275886141b 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -136,6 +136,9 @@ var/min_pressure = WARNING_LOW_PRESSURE var/max_pressure = HAZARD_HIGH_PRESSURE + /// If this fish type counts towards the Fish Species Scanning experiments + var/experisci_scannable = TRUE + /obj/item/fish/Initialize(mapload, apply_qualities = TRUE) . = ..() AddComponent(/datum/component/aquarium_content, PROC_REF(get_aquarium_animation), list(COMSIG_FISH_STATUS_CHANGED,COMSIG_FISH_STIRRED)) @@ -175,7 +178,7 @@ balloon_alert(user, "[src] is dead!") return TRUE feed(item.reagents) - balloon_alert(user, "you feed [src]") + balloon_alert(user, "fed [src]") return TRUE /obj/item/fish/examine(mob/user) @@ -185,14 +188,14 @@ . += span_notice("It weighs [weight] g.") ///Randomizes weight and size. -/obj/item/fish/proc/randomize_size_and_weight(avg_size = average_size, avg_weight = average_weight, deviation = 0.2, first_run = FALSE) - var/size_deviation = 0.2 * avg_size - var/new_size = round(max(1,gaussian(avg_size, size_deviation)), 1) +/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = 0.2) + 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)) - var/weight_deviation = 0.2 * avg_weight - var/new_weight = round(max(1,gaussian(avg_weight, weight_deviation)), 1) + 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)) - update_size_and_weight(new_size, new_weight, first_run) + update_size_and_weight(new_size, new_weight) ///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) @@ -414,11 +417,14 @@ return FALSE return TRUE +/obj/item/fish/proc/is_hungry() + return !HAS_TRAIT(src, TRAIT_FISH_NO_HUNGER) && world.time - last_feeding >= feeding_frequency + /obj/item/fish/proc/process_health(seconds_per_tick) var/health_change_per_second = 0 if(!proper_environment()) health_change_per_second -= 3 //Dying here - if(world.time - last_feeding >= feeding_frequency) + if(is_hungry()) health_change_per_second -= 0.5 //Starving else health_change_per_second += 0.5 //Slowly healing @@ -541,10 +547,11 @@ #define FLOP_SINGLE_MOVE_TIME 1.5 #define JUMP_X_DISTANCE 5 #define JUMP_Y_DISTANCE 6 -/// This animation should be applied to actual parent atom instead of vc_object. -/proc/flop_animation(atom/movable/animation_target) + +/// This flopping animation played while the fish is alive. +/obj/item/fish/proc/flop_animation() var/pause_between = PAUSE_BETWEEN_PHASES + rand(1, 5) //randomized a bit so fish are not in sync - animate(animation_target, time = pause_between, loop = -1) + animate(src, time = pause_between, loop = -1) //move nose down and up for(var/_ in 1 to FLOP_COUNT) var/matrix/up_matrix = matrix() @@ -565,6 +572,7 @@ animate(time = up_time, pixel_y = JUMP_Y_DISTANCE , pixel_x=x_step, loop = -1, flags= ANIMATION_RELATIVE, easing = BOUNCE_EASING | EASE_IN) animate(time = up_time, pixel_y = -JUMP_Y_DISTANCE, pixel_x=x_step, loop = -1, flags= ANIMATION_RELATIVE, easing = BOUNCE_EASING | EASE_OUT) animate(time = PAUSE_BETWEEN_FLOPS, loop = -1) + #undef PAUSE_BETWEEN_PHASES #undef PAUSE_BETWEEN_FLOPS #undef FLOP_COUNT @@ -578,7 +586,7 @@ if(flopping) //Requires update_transform/animate_wrappers to be less restrictive. return flopping = TRUE - flop_animation(src) + flop_animation() /// Stops flopping animation /obj/item/fish/proc/stop_flopping() @@ -593,7 +601,7 @@ /obj/item/fish/proc/refresh_flopping() if(flopping) - flop_animation(src) + flop_animation() /// Returns random fish, using random_case_rarity probabilities. /proc/random_fish_type(required_fluid) diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index bec868ad24e..63de4cfdf1d 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -12,6 +12,8 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( var/diff_traits_inheritability = 50 /// fishes of types within this list are granted to have this trait, no matter the probability var/list/guaranteed_inheritance_types + /// Depending on the value, fish with trait will be reported as more or less difficult in the catalog. + var/added_difficulty = 0 /// Difficulty modifier from this mod, needs to return a list with two values /datum/fish_trait/proc/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman) @@ -161,7 +163,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/necrophage name = "Necrophage" - catalog_description = "This fish will eat the carcasses of dead fishes when hungry." + catalog_description = "This fish will eat carcasses of dead fish when hungry." incompatible_traits = list(/datum/fish_trait/vegan) /datum/fish_trait/necrophage/apply_to_fish(obj/item/fish/fish) @@ -169,7 +171,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/necrophage/proc/eat_dead_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(world.time - source.last_feeding < source.feeding_frequency || !isaquarium(source.loc)) + if(!source.is_hungry() || !isaquarium(source.loc)) return for(var/obj/item/fish/victim in source.loc) if(victim.status != FISH_DEAD || victim == source || HAS_TRAIT(victim, TRAIT_YUCKY_FISH)) @@ -233,7 +235,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( /datum/fish_trait/predator/proc/eat_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(world.time - source.last_feeding < source.feeding_frequency || !isaquarium(source.loc)) + if(!source.is_hungry() || !isaquarium(source.loc)) return var/obj/structure/aquarium/aquarium = source.loc for(var/obj/item/fish/victim in aquarium.get_fishes(TRUE, source)) @@ -334,6 +336,7 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( diff_traits_inheritability = 45 guaranteed_inheritance_types = list(/obj/item/fish/clownfish/lube) catalog_description = "This fish exudes a viscous, slippery lubrificant. It's reccomended not to step on it." + added_difficulty = 5 /datum/fish_trait/lubed/apply_to_fish(obj/item/fish/fish) fish.AddComponent(/datum/component/slippery, 8 SECONDS, SLIDE|GALOSHES_DONT_HELP) @@ -352,3 +355,26 @@ GLOBAL_LIST_INIT(fish_traits, init_subtypes_w_path_keys(/datum/fish_trait, list( ADD_TRAIT(fish, TRAIT_FISH_AMPHIBIOUS, FISH_TRAIT_DATUM) if(fish.required_fluid_type == AQUARIUM_FLUID_AIR) fish.required_fluid_type = AQUARIUM_FLUID_FRESHWATER + +/datum/fish_trait/mixotroph + name = "Mixotroph" + inheritability = 75 + diff_traits_inheritability = 25 + catalog_description = "This fish is capable of substaining itself by producing its own sources of energy (food)." + incompatible_traits = list(/datum/fish_trait/predator, /datum/fish_trait/necrophage) + +/datum/fish_trait/antigrav/apply_to_fish(obj/item/fish/fish) + ADD_TRAIT(fish, TRAIT_FISH_NO_HUNGER, FISH_TRAIT_DATUM) + +/datum/fish_trait/antigrav + name = "Anti-Gravity" + inheritability = 75 + diff_traits_inheritability = 25 + catalog_description = "This fish will invert the gravity of the bait at random. May fall upward outside after being caught." + added_difficulty = 15 + +/datum/fish_trait/antigrav/minigame_mod(obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/minigame) + minigame.special_effects |= FISHING_MINIGAME_RULE_ANTIGRAV + +/datum/fish_trait/antigrav/apply_to_fish(obj/item/fish/fish) + fish.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY) diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm index 652b0aba8aa..5ff62266ad9 100644 --- a/code/modules/fishing/fish/fish_types.dm +++ b/code/modules/fishing/fish/fish_types.dm @@ -341,7 +341,6 @@ icon_state = "sludgefish_purple" dedicated_in_aquarium_icon_state = "sludgefish_purple_small" random_case_rarity = FISH_RARITY_NOPE - random_case_rarity = FISH_RARITY_VERY_RARE fish_traits = list(/datum/fish_trait/parthenogenesis) /obj/item/fish/slimefish @@ -439,11 +438,13 @@ fillet_type = null death_text = "%SRC gently disappears." fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce + experisci_scannable = FALSE /obj/item/fish/holo/Initialize(mapload) . = ..() var/area/station/holodeck/holo_area = get_area(src) if(!istype(holo_area)) + addtimer(CALLBACK(src, PROC_REF(set_status), FISH_DEAD), 1 MINUTES) return holo_area.linked.add_to_spawned(src) @@ -488,9 +489,9 @@ sprite_height = 5 /obj/item/fish/holo/checkered - name = "unrendered holographic fish" //it's a meta joke, buddy. + name = "unrendered holographic fish" desc = "A checkered silhoutte of searing purple and pitch black presents itself before your eyes, like a tear in fabric of reality. It hurts to watch." - icon_state = "checkered" + icon_state = "checkered" //it's a meta joke, buddy. dedicated_in_aquarium_icon_state = "checkered_small" sprite_width = 4 @@ -502,3 +503,37 @@ sprite_height = 4 sprite_width = 10 average_size = 50 + +/obj/item/fish/starfish + name = "cosmostarfish" + desc = "A peculiar, gravity-defying, echinoderm-looking critter from hyperspace." + icon_state = "starfish" + dedicated_in_aquarium_icon_state = "starfish_small" + icon_state_dead = "starfish_dead" + sprite_width = 4 + average_size = 30 + average_weight = 300 + stable_population = 3 + required_fluid_type = AQUARIUM_FLUID_AIR + random_case_rarity = FISH_RARITY_NOPE + required_temperature_min = 0 + required_temperature_max = INFINITY + safe_air_limits = null + min_pressure = 0 + max_pressure = INFINITY + grind_results = list(/datum/reagent/bluespace = 10, /datum/reagent/consumable/liquidgibs = 5) + fillet_type = null + fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph) + +/obj/item/fish/starfish/Initialize(mapload) + . = ..() + update_appearance(UPDATE_OVERLAYS) + +/obj/item/fish/starfish/update_overlays() + . = ..() + if(status == FISH_ALIVE) + . += emissive_appearance(icon, "starfish_emissive", src) + +///It spins, and dimly glows in the dark. +/obj/item/fish/starfish/flop_animation() + DO_FLOATING_ANIM(src) diff --git a/code/modules/fishing/fish_catalog.dm b/code/modules/fishing/fish_catalog.dm index d41b4657e50..a0f66c2227d 100644 --- a/code/modules/fishing/fish_catalog.dm +++ b/code/modules/fishing/fish_catalog.dm @@ -68,14 +68,6 @@ if(source.catalog_description && (fish_type in source.fish_table)) spot_descriptions += source.catalog_description .["spots"] = english_list(spot_descriptions, nothing_text = "Unknown") - ///Difficulty descriptor - switch(initial(fishy.fishing_difficulty_modifier)) - if(-INFINITY to 10) - .["difficulty"] = "Easy" - if(20 to 30) - .["difficulty"] = "Medium" - else - .["difficulty"] = "Hard" var/list/fish_list_properties = collect_fish_properties() var/list/fav_bait = fish_list_properties[fishy][NAMEOF(fishy, favorite_bait)] var/list/disliked_bait = fish_list_properties[fishy][NAMEOF(fishy, disliked_bait)] @@ -91,12 +83,22 @@ // Fish traits description var/list/trait_descriptions = list() var/list/fish_traits = fish_list_properties[fishy][NAMEOF(fishy, fish_traits)] + var/fish_difficulty = initial(fishy.fishing_difficulty_modifier) for(var/fish_trait in fish_traits) var/datum/fish_trait/trait = GLOB.fish_traits[fish_trait] trait_descriptions += trait.catalog_description + fish_difficulty += trait.added_difficulty if(!length(trait_descriptions)) trait_descriptions += "This fish exhibits no special behavior." .["traits"] = trait_descriptions + ///Difficulty descriptor + switch(fish_difficulty) + if(-INFINITY to 9) + .["difficulty"] = "Easy" + if(10 to 19) + .["difficulty"] = "Medium" + else + .["difficulty"] = "Hard" return . /obj/item/book/fish_catalog/ui_assets(mob/user) diff --git a/code/modules/fishing/fishing_equipment.dm b/code/modules/fishing/fishing_equipment.dm index 6169b41fd88..3f34222ad87 100644 --- a/code/modules/fishing/fishing_equipment.dm +++ b/code/modules/fishing/fishing_equipment.dm @@ -11,7 +11,8 @@ desc = "Simple fishing line." icon = 'icons/obj/fishing.dmi' icon_state = "reel_blue" - var/fishing_line_traits = NONE + ///A list of traits that this fishing line has, checked by fish traits and the minigame. + var/list/fishing_line_traits /// Color of the fishing line var/line_color = "#808080" @@ -59,7 +60,8 @@ icon_state = "hook" w_class = WEIGHT_CLASS_TINY - var/fishing_hook_traits = NONE + /// A list of traits that this fishing hook has, checked by fish traits and the minigame + var/list/fishing_hook_traits /// icon state added to main rod icon when this hook is equipped var/rod_overlay_icon_state = "hook_overlay" /// What subtype of `/obj/item/chasm_detritus` do we fish out of chasms? Defaults to `/obj/item/chasm_detritus`. @@ -175,7 +177,7 @@ name = "jawed hook" desc = "Despite hints of rust, this gritty beartrap-like hook hybrid manages to look even more threating than the real thing. May neptune have mercy of whatever gets caught in its jaws." icon_state = "jaws" - fishing_hook_traits = FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_ENSNARE|FISHING_HOOK_KILL + fishing_hook_traits = FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_NO_ESCAPE|FISHING_HOOK_KILL rod_overlay_icon_state = "hook_jaws_overlay" /obj/item/storage/toolbox/fishing diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index c0a8c53e0b0..06ac03d64ac 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -43,8 +43,12 @@ var/fish_ai = FISH_AI_DUMB /// Rule modifiers (eg weighted bait) var/special_effects = NONE - /// Did the game get past the baiting phase, used to track if bait should be consumed afterwards - var/bait_taken = FALSE + /// A list of possible active minigame effects. If not empty, one will be picked from time to time. + var/list/active_effects + /// The cooldown between switching active effects + COOLDOWN_DECLARE(active_effect_cd) + /// The current active effect + var/current_active_effect /// Result path var/reward_path = FISHING_DUD /// Minigame difficulty @@ -61,6 +65,8 @@ var/obj/effect/fishing_lure/lure /// Background icon state from fishing_hud.dmi var/background = "background_default" + /// Fish icon state from fishing_hud.dmi + var/fish_icon = "fish" /// Fishing line visual var/datum/beam/fishing_line @@ -168,7 +174,10 @@ RegisterSignal(user, COMSIG_MOB_FISHING_REWARD_DISPENSED, PROC_REF(hurt_fish)) difficulty += comp.fish_source.calculate_difficulty(reward_path, rod, user, src) - difficulty = round(difficulty) + difficulty = clamp(round(difficulty), 1, 100) + + if(HAS_TRAIT(user, TRAIT_REVEAL_FISH)) + fish_icon = GLOB.specific_fish_icons[reward_path] || "fish" /** * If the chances are higher than 1% (100% at maximum difficulty), they'll scale @@ -219,6 +228,7 @@ /datum/fishing_challenge/proc/start(mob/living/user) /// Create fishing line visuals fishing_line = used_rod.create_fishing_line(lure, target_py = 5) + active_effects = bitfield_to_list(special_effects & FISHING_MINIGAME_ACTIVE_EFFECTS) // If fishing line breaks los / rod gets dropped / deleted RegisterSignal(fishing_line, COMSIG_QDELETING, PROC_REF(on_line_deleted)) RegisterSignal(used_rod, COMSIG_ITEM_ATTACK_SELF, PROC_REF(on_attack_self)) @@ -299,7 +309,30 @@ phase = BITING_PHASE // Trashing animation playsound(lure, 'sound/effects/fish_splash.ogg', 100) - send_alert("!!!") + if(HAS_TRAIT(user, TRAIT_REVEAL_FISH)) + switch(fish_icon) + if(FISH_ICON_DEF) + send_alert("fish!!!") + if(FISH_ICON_HOSTILE) + send_alert("hostile!!!") + if(FISH_ICON_STAR) + send_alert("starfish!!!") + if(FISH_ICON_CHUNKY) + send_alert("round fish!!!") + if(FISH_ICON_JELLYFISH) + send_alert("jellyfish!!!") + if(FISH_ICON_SLIME) + send_alert("slime!!!") + if(FISH_ICON_COIN) + send_alert("valuable!!!") + if(FISH_ICON_GEM) + send_alert("ore!!!") + if(FISH_ICON_CRAB) + send_alert("crustacean!!!") + if(FISH_ICON_BONE) + send_alert("bones!!!") + else + send_alert("!!!") animate(lure, pixel_y = 3, time = 5, loop = -1, flags = ANIMATION_RELATIVE) animate(pixel_y = -3, time = 5, flags = ANIMATION_RELATIVE) // Setup next phase @@ -350,6 +383,9 @@ RegisterSignal(user.client, COMSIG_CLIENT_MOUSEDOWN, PROC_REF(start_reeling)) RegisterSignal(user.client, COMSIG_CLIENT_MOUSEUP, PROC_REF(stop_reeling)) RegisterSignal(user, COMSIG_MOB_LOGOUT, PROC_REF(on_user_logout)) + if(length(active_effects)) + // Give the player a moment to prepare for active minigame effects + COOLDOWN_START(src, active_effect_cd, rand(5, 9) SECONDS) START_PROCESSING(SSfishing, src) ///Stop processing and remove references to the minigame hud @@ -374,11 +410,44 @@ ///Update the state of the fish, the bait and the hud /datum/fishing_challenge/process(seconds_per_tick) + if(length(active_effects) && COOLDOWN_FINISHED(src, active_effect_cd)) + select_active_effect() move_fish(seconds_per_tick) move_bait(seconds_per_tick) if(!QDELETED(fishing_hud)) update_visuals() +///The proc that handles fancy effects like flipping the hud or skewing movement +/datum/fishing_challenge/proc/select_active_effect() + ///bring forth an active effect + if(isnull(current_active_effect)) + current_active_effect = pick(active_effects) + switch(current_active_effect) + if(FISHING_MINIGAME_RULE_ANTIGRAV) + fishing_hud.icon_state = "background_antigrav" + SEND_SOUND(user, sound('sound/effects/arcade_jump.ogg', volume = 50)) + COOLDOWN_START(src, active_effect_cd, rand(6, 9) SECONDS) + if(FISHING_MINIGAME_RULE_FLIP) + fishing_hud.icon_state = "background_flip" + fishing_hud.transform = fishing_hud.transform.Scale(1, -1) + SEND_SOUND(user, sound('sound/effects/boing.ogg')) + COOLDOWN_START(src, active_effect_cd, rand(5, 6) SECONDS) + return + + ///go back to normal + switch(current_active_effect) + if(FISHING_MINIGAME_RULE_ANTIGRAV) + var/sound/inverted_sound = sound('sound/effects/arcade_jump.ogg', volume = 50) + inverted_sound.frequency = -1 + SEND_SOUND(user, inverted_sound) + COOLDOWN_START(src, active_effect_cd, rand(10, 13) SECONDS) + if(FISHING_MINIGAME_RULE_FLIP) + fishing_hud.transform = fishing_hud.transform.Scale(1, -1) + COOLDOWN_START(src, active_effect_cd, rand(8, 12) SECONDS) + + fishing_hud.icon_state = background + current_active_effect = null + ///The proc that moves the fish around, just like in the old TGUI, mostly. /datum/fishing_challenge/proc/move_fish(seconds_per_tick) var/long_chance = long_jump_chance * seconds_per_tick * 10 @@ -469,6 +538,9 @@ velocity_change = round(velocity_change) + if(current_active_effect == FISHING_MINIGAME_RULE_ANTIGRAV) + velocity_change = -velocity_change + /** * Pull the brake on the velocity if the current velocity and the acceleration * have different directions, making the bait less slippery, thus easier to control @@ -529,7 +601,7 @@ icon_state = challenge.background add_overlay("frame") hud_bait = new(null, null, challenge) - hud_fish = new + hud_fish = new(null, null, challenge) hud_completion = new(null, null, challenge) vis_contents += list(hud_bait, hud_fish, hud_completion) challenge.user.client.screen += src @@ -562,6 +634,11 @@ icon_state = "fish" vis_flags = VIS_INHERIT_ID +/atom/movable/screen/hud_fish/Initialize(mapload, datum/hud/hud_owner, datum/fishing_challenge/challenge) + . = ..() + if(challenge) + icon_state = challenge.fish_icon + /atom/movable/screen/hud_completion icon = 'icons/hud/fishing_hud.dmi' icon_state = "completion_0" diff --git a/code/modules/fishing/fishing_portal_machine.dm b/code/modules/fishing/fishing_portal_machine.dm index 3fc6b0eb938..b156a37ba05 100644 --- a/code/modules/fishing/fishing_portal_machine.dm +++ b/code/modules/fishing/fishing_portal_machine.dm @@ -1,40 +1,58 @@ /obj/machinery/fishing_portal_generator name = "fish-porter 3000" - desc = "fishing anywhere, anytime, anyway what was i talking about" - + desc = "Fishing anywhere, anytime... anyway what was I talking about?" icon = 'icons/obj/fishing.dmi' - icon_state = "portal_off" - + icon_state = "portal" idle_power_usage = 0 active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 2 - anchored = FALSE density = TRUE + circuit = /obj/item/circuitboard/machine/fishing_portal_generator - var/fishing_source = /datum/fish_source/portal + ///The current fishing spot loaded in var/datum/component/fishing_spot/active +/obj/machinery/fishing_portal_generator/on_set_panel_open() + update_appearance() + return ..() + /obj/machinery/fishing_portal_generator/wrench_act(mob/living/user, obj/item/tool) . = ..() default_unfasten_wrench(user, tool) return TOOL_ACT_TOOLTYPE_SUCCESS +/obj/machinery/fishing_portal_generator/examine(mob/user) + . = ..() + . += span_notice("You can unlock further portal settings by completing fish scanning experiments.") + +/obj/machinery/fishing_portal_generator/emag_act(mob/user, obj/item/card/emag/emag_card) + if(obj_flags & EMAGGED) + return FALSE + obj_flags |= EMAGGED + balloon_alert(user, "syndicate setting loaded") + playsound(src, SFX_SPARKS, 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + return TRUE + /obj/machinery/fishing_portal_generator/interact(mob/user, special_state) . = ..() if(active) deactivate() else - activate() + select_fish_source(user) -/obj/machinery/fishing_portal_generator/update_icon(updates) +/obj/machinery/fishing_portal_generator/update_overlays() . = ..() - if(active) - icon_state = "portal_on" - else - icon_state = "portal_off" + if(panel_open) + . += "portal_open" + if(!active) + return + . += "portal_on" + var/datum/fish_source/portal/portal = active.fish_source + . += portal.overlay_state + . += emissive_appearance(icon, "portal_emissive", src) -/obj/machinery/fishing_portal_generator/proc/activate() - active = AddComponent(/datum/component/fishing_spot, fishing_source) +/obj/machinery/fishing_portal_generator/proc/activate(datum/fish_source/selected_source) + active = AddComponent(/datum/component/fishing_spot, selected_source) use_power = ACTIVE_POWER_USE update_icon() @@ -46,3 +64,39 @@ /obj/machinery/fishing_portal_generator/on_set_is_operational(old_value) if(old_value) deactivate() + +///Create a radial menu from a list of available fish sources. If only the default is available, activate it right away. +/obj/machinery/fishing_portal_generator/proc/select_fish_source(mob/user) + var/datum/fish_source/portal/default = GLOB.preset_fish_sources[/datum/fish_source/portal] + var/list/available_fish_sources = list(default.radial_name = default) + if(obj_flags & EMAGGED) + var/datum/fish_source/portal/syndicate = GLOB.preset_fish_sources[/datum/fish_source/portal/syndicate] + available_fish_sources[syndicate.radial_name] = syndicate + for (var/datum/techweb/techweb as anything in SSresearch.techwebs) + var/get_fish_sources = FALSE + for(var/obj/machinery/rnd/server/server as anything in techweb.techweb_servers) + if(!is_valid_z_level(get_turf(server), get_turf(src))) + continue + get_fish_sources = TRUE + break + if(!get_fish_sources) + continue + for(var/experiment_type in typesof(/datum/experiment/scanning/fish)) + var/datum/experiment/scanning/fish/experiment = techweb.completed_experiments[experiment_type] + if(!experiment) + continue + var/datum/fish_source/portal/reward = GLOB.preset_fish_sources[experiment.fish_source_reward] + available_fish_sources[reward.radial_name] = reward + + if(length(available_fish_sources) == 1) + activate(default) + return + var/list/choices = list() + for(var/radial_name in available_fish_sources) + var/datum/fish_source/portal/source = available_fish_sources[radial_name] + choices[radial_name] = image(icon = 'icons/hud/radial_fishing.dmi', icon_state = source.radial_state) + + var/choice = show_radial_menu(user, src, choices, radius = 38, custom_check = CALLBACK(src, TYPE_PROC_REF(/atom, can_interact), user), tooltips = TRUE) + if(!choice || !can_interact(user)) + return + activate(available_fish_sources[choice]) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index ed9e164644e..1abba8e414c 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -67,7 +67,6 @@ /obj/item/fishing_rod/examine(mob/user) . = ..() - . += "Right-Click in your active hand to access its slots UI" var/list/equipped_stuff = list() if(line) equipped_stuff += "[icon2html(line, user)] [line.name]" @@ -79,6 +78,7 @@ . += span_notice("\a [icon2html(bait, user)] [bait] is being used as bait.") else . += span_warning("It doesn't have any bait attached. Fishing will be more tedious!") + . += span_notice("Right-Click in your active hand to access its slots UI") /** * Catch weight modifier for the given fish_type (or FISHING_DUD) @@ -185,6 +185,7 @@ return currently_hooked_item = target_atom create_fishing_line(target_atom) + SEND_SIGNAL(src, COMSIG_FISHING_ROD_HOOKED_ITEM, target_atom, user) /// Checks what can be hooked /obj/item/fishing_rod/proc/can_be_hooked(atom/movable/target) @@ -508,16 +509,34 @@ /obj/item/fishing_rod/tech name = "advanced fishing rod" desc = "An embedded universal constructor along with micro-fusion generator makes this marvel of technology never run out of bait. Interstellar treaties prevent using it outside of recreational fishing. And you can fish with this. " - ui_description = "This rod has an infinite supply of synthetic bait." + ui_description = "This rod has an infinite supply of synth-bait. Also doubles as an Experi-Scanner for fish." icon_state = "fishing_rod_science" reel_overlay = "reel_science" /obj/item/fishing_rod/tech/Initialize(mapload) . = ..() + + var/static/list/fishing_signals = list( + COMSIG_FISHING_ROD_HOOKED_ITEM = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_FISHING_ROD_CAUGHT_FISH = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_PRE_ATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, try_run_handheld_experiment), + COMSIG_ITEM_AFTERATTACK = TYPE_PROC_REF(/datum/component/experiment_handler, ignored_handheld_experiment_attempt), + ) + AddComponent(/datum/component/experiment_handler, \ + config_mode = EXPERIMENT_CONFIG_ALTCLICK, \ + allowed_experiments = list(/datum/experiment/scanning/fish), \ + config_flags = EXPERIMENT_CONFIG_SILENT_FAIL|EXPERIMENT_CONFIG_IMMEDIATE_ACTION, \ + experiment_signals = fishing_signals, \ + ) + var/obj/item/food/bait/doughball/synthetic/infinite_supply_of_bait = new(src) bait = infinite_supply_of_bait update_icon() +/obj/item/fishing_rod/tech/examine(mob/user) + . = ..() + . += span_notice("Alt-Click to access the Experiment Configuration UI") + /obj/item/fishing_rod/tech/consume_bait(atom/movable/reward) return diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm index 5a34db9ce5f..657b2f30968 100644 --- a/code/modules/fishing/sources/_fish_source.dm +++ b/code/modules/fishing/sources/_fish_source.dm @@ -1,11 +1,47 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_source, list())) +/** + * When adding new fishable rewards to a table/counts, you can specify an icon to show in place of the + * generic fish icon in the minigame UI should the user have the TRAIT_REVEAL_FISH trait, by adding it to + * this list. + * + * A lot of the icons here may be a tad inaccurate, but since we're limited to the free font awesome icons we + * have access to, we got to make do. + */ +GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list( + /mob/living/basic/carp = FISH_ICON_DEF, + /mob/living/basic/mining = FISH_ICON_HOSTILE, + /obj/effect/decal/remains = FISH_ICON_BONE, + /obj/effect/mob_spawn/corpse = FISH_ICON_BONE, + /obj/item/coin = FISH_ICON_COIN, + /obj/item/fish = FISH_ICON_DEF, + /obj/item/fish/armorfish = FISH_ICON_CRAB, + /obj/item/fish/boned = FISH_ICON_BONE, + /obj/item/fish/chasm_crab = FISH_ICON_CRAB, + /obj/item/fish/gunner_jellyfish = FISH_ICON_JELLYFISH, + /obj/item/fish/holo/crab = FISH_ICON_CRAB, + /obj/item/fish/holo/puffer = FISH_ICON_CHUNKY, + /obj/item/fish/mastodon = FISH_ICON_BONE, + /obj/item/fish/pufferfish = FISH_ICON_CHUNKY, + /obj/item/fish/slimefish = FISH_ICON_SLIME, + /obj/item/fish/sludgefish = FISH_ICON_SLIME, + /obj/item/fish/starfish = FISH_ICON_STAR, + /obj/item/storage/wallet = FISH_ICON_COIN, + /obj/item/stack/sheet/bone = FISH_ICON_BONE, + /obj/item/stack/sheet/mineral = FISH_ICON_GEM, + /obj/item/stack/ore = FISH_ICON_GEM, + /obj/structure/closet/crate = FISH_ICON_COIN, +))) + /** * Where the fish actually come from - every fishing spot has one assigned but multiple fishing holes * can share single source, ie single shared one for ocean/lavaland river */ /datum/fish_source - /// Fish catch weight table - these are relative weights + /** + * Fish catch weight table - these are relative weights + * + */ var/list/fish_table = list() /// If a key from fish_table is present here, that fish is availible in limited quantity and is reduced by one on successful fishing var/list/fish_counts = list() @@ -25,6 +61,10 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour if(!(path in fish_table)) stack_trace("path [path] found in the 'fish_counts' list but not in the fish_table one of [type]") +///Called when src is set as the fish source of a fishing spot component +/datum/fish_source/proc/on_fishing_spot_init(/datum/component/fishing_spot/spot) + return + /// Can we fish in this spot at all. Returns DENIAL_REASON or null if we're good to go /datum/fish_source/proc/reason_we_cant_fish(obj/item/fishing_rod/rod, mob/fisherman) return rod.reason_we_cant_fish(src) @@ -35,7 +75,7 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour * This includes the source's fishing difficulty, that of the fish, the rod, * favorite and disliked baits, fish traits and the fisherman skill. * - * For non-fish, it's just the source's fishing difficulty minus the fisherman skill, rod and settler modifiers. + * For non-fish, it's just the source's fishing difficulty minus the fisherman skill. */ /datum/fish_source/proc/calculate_difficulty(result, obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/challenge) . = fishing_difficulty @@ -96,7 +136,7 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour * Used to register signals or add traits and the such right after conditions have been cleared * and before the minigame starts. */ -/datum/fish_source/proc/pre_challenge_started(obj/item/fishing_rod/rod, mob/user) +/datum/fish_source/proc/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) return ///Proc called when the challenge is interrupted within the fish source code. @@ -116,7 +156,9 @@ GLOBAL_LIST_INIT(preset_fish_sources, init_subtypes_w_path_keys(/datum/fish_sour user.add_mob_memory(/datum/memory/caught_fish, protagonist = user, deuteragonist = initial(caught.name)) var/turf/fishing_spot = get_turf(source.lure) var/atom/movable/reward = dispense_reward(source.reward_path, user, fishing_spot) - source.used_rod?.consume_bait(reward) + if(source.used_rod) + SEND_SIGNAL(source.used_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, reward, user) + source.used_rod.consume_bait(reward) /// Gives out the reward if possible /datum/fish_source/proc/dispense_reward(reward_path, mob/fisherman, turf/fishing_spot) diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm index ffb37753881..e2e5491dd1d 100644 --- a/code/modules/fishing/sources/source_types.dm +++ b/code/modules/fishing/sources/source_types.dm @@ -19,11 +19,168 @@ /datum/fish_source/portal fish_table = list( - FISHING_DUD = 5, + FISHING_DUD = 7, /obj/item/fish/goldfish = 10, /obj/item/fish/guppy = 10, + /obj/item/fish/angelfish = 10, ) - catalog_description = "Fish dimension (Fishing portal generator)" + catalog_description = "Aquarium dimension (Fishing portal generator)" + ///The name of this option shown in the radial menu on the fishing portal generator + var/radial_name = "Aquarium" + ///The icon state shown for this option in the radial menu + var/radial_state = "fish_tank" + ///The icon state of the overlay shown on the machine when active. + var/overlay_state = "portal_aquarium" + +/datum/fish_source/portal/beach + fish_table = list( + FISHING_DUD = 10, + /obj/item/fish/clownfish = 10, + /obj/item/fish/pufferfish = 10, + /obj/item/fish/cardinal = 10, + /obj/item/fish/greenchromis = 10, + ) + catalog_description = "Beach dimension (Fishing portal generator)" + radial_name = "Beach" + radial_state = "palm_beach" + +/datum/fish_source/portal/chasm + background = "background_lavaland" + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/chasm_crab = 10, + /obj/item/fish/boned = 5, + /obj/item/stack/sheet/bone = 5, + ) + catalog_description = "Chasm dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Chasm" + overlay_state = "portal_chasm" + radial_state = "ground_hole" + +/datum/fish_source/portal/ocean + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/lanternfish = 5, + /obj/item/fish/firefish = 5, + /obj/item/fish/dwarf_moonfish = 5, + /obj/item/fish/gunner_jellyfish = 5, + /obj/item/fish/needlefish = 5, + /obj/item/fish/armorfish = 5, + ) + catalog_description = "Ocean dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Ocean" + overlay_state = "portal_ocean" + radial_state = "seaboat" + +/datum/fish_source/portal/hyperspace + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/starfish = 6, + /obj/item/stack/ore/bluespace_crystal = 2, + /mob/living/basic/carp = 2, + ) + fish_counts = list( + /obj/item/stack/ore/bluespace_crystal = 10, + ) + catalog_description = "Hyperspace dimension (Fishing portal generator)" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 10 + radial_name = "Hyperspace" + overlay_state = "portal_hyperspace" + radial_state = "space_rocket" + +///Unlocked by emagging the fishing portal generator with an emag. +/datum/fish_source/portal/syndicate + background = "background_lavaland" + fish_table = list( + FISHING_DUD = 5, + /obj/item/fish/donkfish = 5, + /obj/item/fish/emulsijack = 5, + ) + catalog_description = "Syndicate dimension (Fishing portal generator)" + radial_name = "Syndicate" + fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 15 + overlay_state = "portal_syndicate" + radial_state = "syndi_snake" + +/** + * A special portal fish source which fish table is populated on init with the contents of all + * portal fish sources, except for FISHING_DUD, and a couple more caveats. + */ +/datum/fish_source/portal/random + fish_table = null //It's populated the first time the source is loaded on a fishing portal generator. + 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" + +///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) + if(fish_table) + return + + ///rewards not found in other fishing portals + fish_table = list( + /obj/item/fish/holo/checkered = 1, + ) + + for(var/portal_type in GLOB.preset_fish_sources) + if(portal_type == type || !ispath(portal_type, /datum/fish_source/portal)) + continue + var/datum/fish_source/portal/preset_portal = GLOB.preset_fish_sources[portal_type] + fish_table |= preset_portal.fish_table + + ///We don't serve duds. + fish_table -= FISHING_DUD + + for(var/reward_path in fish_table) + fish_table[reward_path] = rand(1, 4) + +///Difficulty has to be calculated before the rest, because of how it influences jump chances +/datum/fish_source/portal/random/calculate_difficulty(result, obj/item/fishing_rod/rod, mob/fisherman, datum/fishing_challenge/challenge) + . = ..() + . += rand(-10, 15) + +///In the spirit of randomness, we skew a few values here and there +/datum/fish_source/portal/random/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) + challenge.bait_bounce_mult = clamp(challenge.bait_bounce_mult + (rand(-3, 3) * 0.1), 0.1, 1) + challenge.completion_loss = max(challenge.completion_loss + rand(-2, 2), 0) + challenge.completion_gain = max(challenge.completion_gain + rand(-1, 1), 2) + challenge.short_jump_velocity_limit += rand(-100, 100) + challenge.long_jump_velocity_limit += rand(-100, 100) + var/static/list/active_effects = bitfield_to_list(FISHING_MINIGAME_ACTIVE_EFFECTS) + for(var/effect in active_effects) + if(prob(30)) + challenge.special_effects |= effect + +///Cherry on top, fish caught from the randomizer portal also have (almost completely) random traits +/datum/fish_source/portal/random/spawn_reward(reward_path, mob/fisherman, turf/fishing_spot) + if(!ispath(reward_path, /obj/item/fish)) + return ..() + + var/static/list/weighted_traits + if(!weighted_traits) + weighted_traits = list() + for(var/trait_type as anything in GLOB.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + weighted_traits[trait.type] = round(trait.inheritability**2/100) + + var/obj/item/fish/caught_fish = new reward_path(get_turf(fisherman), FALSE) + var/list/fixed_traits = list() + for(var/trait_type in caught_fish.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + if(caught_fish.type in trait.guaranteed_inheritance_types) + fixed_traits += trait_type + var/list/new_traits = list() + for(var/iteration in rand(1, 4)) + new_traits |= pick_weight(weighted_traits) + caught_fish.inherit_traits(new_traits, fixed_traits = fixed_traits) + caught_fish.randomize_size_and_weight(deviation = 0.3) + caught_fish.progenitors = full_capitalize(caught_fish.name) + return caught_fish + /datum/fish_source/chasm catalog_description = "Chasm depths" @@ -99,7 +256,7 @@ fish_table = list( FISHING_DUD = 18, /obj/item/fish/sludgefish = 18, - /obj/item/fish/slimefish = 2, + /obj/item/fish/slimefish = 4, /obj/item/storage/wallet/money = 2, ) fish_counts = list( @@ -125,7 +282,7 @@ if(!istype(get_area(fisherman), /area/station/holodeck)) return "You need to be inside the Holodeck to catch holographic fish." -/datum/fish_source/holographic/pre_challenge_started(obj/item/fishing_rod/rod, mob/user) +/datum/fish_source/holographic/pre_challenge_started(obj/item/fishing_rod/rod, mob/user, datum/fishing_challenge/challenge) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(check_area)) /datum/fish_source/holographic/proc/check_area(mob/user) diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm index f9fd629c1ed..762e8e0162c 100644 --- a/code/modules/library/skill_learning/skillchip.dm +++ b/code/modules/library/skill_learning/skillchip.dm @@ -489,4 +489,13 @@ activate_message = span_notice("You recall learning from your grandmother how they baked their cookies with love.") deactivate_message = span_notice("You forget all memories imparted upon you by your grandmother. Were they even your real grandma?") +/obj/item/skillchip/master_angler + name = "Mast-Angl-Er skillchip" + auto_traits = list(TRAIT_REVEAL_FISH) + skill_name = "Fisherman's Discernment" + skill_description = "While fishing, it'll make a smidge easier to guess whatever you're trying to catch." + skill_icon = "fish" + activate_message = span_notice("You feel the knowledge and passion of several sunbaked, seasoned fishermen burn within you.") + deactivate_message = span_notice("You no longer feel like casting a fishing rod by the sunny riverside.") + #undef SKILLCHIP_CATEGORY_GENERAL diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm index 72bdaa02a95..0a2c96dddd5 100644 --- a/code/modules/research/designs/machine_designs.dm +++ b/code/modules/research/designs/machine_designs.dm @@ -1096,3 +1096,13 @@ RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ROBOTICS ) departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_ENGINEERING + +/datum/design/board/fishing_portal_generator + name = "Fishing Portal Generator Board" + desc = "The circuit board for the fishing portal generator" + id = "fishing_portal_generator" + build_path = /obj/item/circuitboard/machine/fishing_portal_generator + category = list( + RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_SERVICE + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE | DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 521504da351..8a06607ec59 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -283,7 +283,7 @@ var/datum/experiment/experiment = completed_experiment if (experiment == experiment_type) return FALSE - available_experiments += new experiment_type() + available_experiments += new experiment_type(src) /** * Adds a list of experiments to this techweb by their types, ensures that no duplicates are added. @@ -310,13 +310,21 @@ var/refund = skipped_experiment_types[completed_experiment.type] || 0 if(refund > 0) add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = refund)) - result_text += ", refunding [refund] points." + result_text += ", refunding [refund] points" // Nothing more to gain here, but we keep it in the list to prevent double dipping skipped_experiment_types[completed_experiment.type] = -1 - else - result_text += "!" + var/points_rewarded + if(completed_experiment.points_reward) + add_point_list(completed_experiment.points_reward) + points_rewarded = ",[refund > 0 ? " and" : ""] rewarding " + var/list/english_list_keys = list() + for(var/points_type in completed_experiment.points_reward) + english_list_keys += "[completed_experiment.points_reward[points_type]] [points_type]" + points_rewarded += "[english_list(english_list_keys)] points" + result_text += points_rewarded + result_text += "!" - log_research("[completed_experiment.name] ([completed_experiment.type]) has been completed on techweb [id]/[organization][refund ? ", refunding [refund] points" : ""].") + log_research("[completed_experiment.name] ([completed_experiment.type]) has been completed on techweb [id]/[organization][refund ? ", refunding [refund] points" : ""][points_rewarded].") return result_text /datum/techweb/proc/printout_points() diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index d12ebfaca1e..507199164b8 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -49,6 +49,7 @@ "extinguisher", "fax", "fishing_rod", + "fishing_portal_generator", "flashlight", "fluid_ducts", "foam_dart", @@ -1490,6 +1491,19 @@ required_experiments = list(/datum/experiment/scanning/random/plants/wild) discount_experiments = list(/datum/experiment/scanning/random/plants/traits = 3000) +/datum/techweb_node/fishing + id = "fishing" + display_name = "Fishing Technology" + description = "Cutting edge fishing advancements." + prereq_ids = list("base") + design_ids = list( + "fishing_rod_tech", + "stabilized_hook", + "fish_analyzer", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) + required_experiments = list(/datum/experiment/scanning/fish) + /datum/techweb_node/exp_tools id = "exp_tools" display_name = "Experimental Tools" @@ -2354,20 +2368,6 @@ hidden = TRUE experimental = TRUE -/datum/techweb_node/fishing - id = "fishing" - display_name = "Fishing Technology" - description = "Cutting edge fishing advancements." - prereq_ids = list("base") - design_ids = list( - "fishing_rod_tech", - "stabilized_hook", - "fish_analyzer", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - /datum/techweb_node/advanced_plastic_surgery id = "plastic_surgery" display_name = "Advanced Plastic Surgery" diff --git a/code/modules/unit_tests/fish_unit_tests.dm b/code/modules/unit_tests/fish_unit_tests.dm index 1ef15f8d0f5..d0d39227f43 100644 --- a/code/modules/unit_tests/fish_unit_tests.dm +++ b/code/modules/unit_tests/fish_unit_tests.dm @@ -28,10 +28,10 @@ var/obj/structure/aquarium/traits/aquarium = allocate(/obj/structure/aquarium/traits) TEST_ASSERT(!aquarium.sterile.try_to_reproduce(), "The test aquarium's sterile fish managed to reproduce when it shouldn't have") var/obj/item/fish/crossbreeder_jr = aquarium.crossbreeder.try_to_reproduce() - TEST_ASSERT(crossbreeder_jr, "The test aquarium's crossbreeder fish didn't manage to reproduce when it should have.") + TEST_ASSERT(crossbreeder_jr, "The test aquarium's crossbreeder fish didn't manage to reproduce when it should have") TEST_ASSERT_EQUAL(crossbreeder_jr.type, aquarium.cloner.type, "The test aquarium's crossbreeder fish mated with the wrong type of fish") var/obj/item/fish/cloner_jr = aquarium.cloner.try_to_reproduce() - TEST_ASSERT(cloner_jr, "The test aquarium's cloner fish didn't manage to reproduce when it should have.") + TEST_ASSERT(cloner_jr, "The test aquarium's cloner fish didn't manage to reproduce when it should have") TEST_ASSERT_NOTEQUAL(cloner_jr.type, aquarium.sterile.type, "The test aquarium's cloner fish mated with the sterile fish") ///Checks that fish evolutions work correctly. @@ -41,11 +41,24 @@ var/obj/structure/aquarium/evolution/aquarium = allocate(/obj/structure/aquarium/evolution) var/obj/item/fish/evolve_jr = aquarium.evolve.try_to_reproduce() TEST_ASSERT(evolve_jr, "The test aquarium's evolution fish didn't manage to reproduce when it should have") - TEST_ASSERT_NOTEQUAL(evolve_jr.type, /obj/item/fish/goldfish, "The test aquarium's evolution fish managed to pass the conditions of an impossible evolution.") + TEST_ASSERT_NOTEQUAL(evolve_jr.type, /obj/item/fish/goldfish, "The test aquarium's evolution fish managed to pass the conditions of an impossible evolution") TEST_ASSERT_EQUAL(evolve_jr.type, /obj/item/fish/clownfish, "The test aquarium's evolution fish's offspring isn't of the expected type") TEST_ASSERT(!(/datum/fish_trait/dummy in evolve_jr.fish_traits), "The test aquarium's evolution fish's offspring still has the old trait that ought to be removed by the evolution datum") TEST_ASSERT(/datum/fish_trait/dummy/two in evolve_jr.fish_traits, "The test aquarium's evolution fish's offspring doesn't have the evolution trait") +/datum/unit_test/fish_scanning + +/datum/unit_test/fish_scanning/Run() + var/scannable_fishes = 0 + for(var/obj/item/fish/fish_prototype as anything in subtypesof(/obj/item/fish)) + if(initial(fish_prototype.experisci_scannable)) + scannable_fishes++ + for(var/datum/experiment/scanning/fish/fish_scan as anything in typesof(/datum/experiment/scanning/fish)) + fish_scan = new fish_scan + var/scan_key = fish_scan.required_atoms[1] + if(fish_scan.required_atoms[scan_key] > scannable_fishes) + TEST_FAIL("[fish_scan.type] has requirements higher than the number of scannable fish types in the game: [scannable_fishes]") + ///dummy fish item used for the tests, as well with related subtypes and datums. /obj/item/fish/testdummy grind_results = list() diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index 80fb1350841..e51205c00e4 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -56,6 +56,7 @@ /obj/item/skillchip/sabrage = 2, /obj/item/skillchip/useless_adapter = 5, /obj/item/skillchip/wine_taster = 2, + /obj/item/skillchip/master_angler = 2, ), ), list( diff --git a/icons/hud/fishing_hud.dmi b/icons/hud/fishing_hud.dmi index b68acee09b76afe9a5471710bb7a2b11f946ddc1..58c478d071064cd984f4dfe1351201669a12d7ee 100644 GIT binary patch literal 4421 zcmeHLdsNcty8aObRDxFH*iK38W^FCpHF;MwyP27GRntUEv+{y@Lq$Q;k+G&sGc85U z=`xL#*G$t9P%AZ4(=Mo~XbNavAV?5F*gw$boW0LKd#!W+Jgfza_kBN}@BO~#d0tqg zx*pnxT()Kz002nG{kx9<0K`u9M8LpI+x7cJU|TkQ1et|`Q2Ow)F*k*z#glKYVdtwFAGaoKvQ zoSSu|L3<-Dee_p9-Uchfo+T~Y_D4CEJ7t{e%+K)C-!D$|({~i7`>{6EZt5}2h+n73 z%br==&VuDQwUU9oMFQQBHoZOo&}2LAwm%k4o9uV_g~p4A3y98LKN@SVcnY(+=unSI zMs2mwJz=SBzhx6->Ees1La6`P#+q-gEOT+8jsxZwW~ScfT~{>@tlE6*(jQR1j7?w-F>u8HSBV@N-CSny%NqRDiwSU`=X0}fTGn!DHp|1h6oHP zTi3znmX30|DO^O6O!84#N{*SrFGRs-ldatqA5%r)BBCZSgGZ#YD+BrMdLf@axoPIU z(z>^{qf%McEb!!#TTlAUYz=4lM^f3-B>qkozs^iT-r}sus5SGB7e@8X(I4)i;w9p? zHXR*HuarnhpS4vtm#ZY=RmO}={&wX&vY;J^ApY@i0#Aem3jgEp1>RHq<#(V>2>P_?( zb(q-9oQQXqzpf&8_SJnY8iGU1A=@x+hUaGLOM?=2M6X-?h3E&B&$Mgm)aboVvz1Qn z%62%fN#dPC-Jd(09g}Uh#>E?X_O_12>d)G~SuyEJ2Hq?Fdze{*ct>B|u$?hnTNgk5 z)~LZ1s_R2VYMm~F9O?#w6JDHwPLx7+8JjYf>fS+Kj}A&eo7(;I5@zlTeF|BbhAeG_ zA@&Ok}{?+c$k0v$^W;6$0;E=#`UD1RRo!TTt%1k+KMwK@v8hUK zuCh$vRL+?Gh&QA-&J@gva+mWMVok!v4&@jT=Wedd#nCgZm5-FtwBn*xrW_wUkX1Gnoqe(&3%$!21%#%ia(Z%jGwLj7Yi5gXLv_SGa zVgFH(rIu__?IhA>Cc!#Cmy#WwV*CD7ri1tDEM(~GnjmujKt~}~qY-A_XsN;QpuoCJ z0M?twz5$3`v7oNA@v-s2miCyf(9o2z!m1*JXvwQbE|KJTmc6rBEJhs}ARNwLe7nm= z8pGE5w*DW}y}iAb-TnPGALha(;;GAB-uU!t_-lI8&XM7BJAQn=t+KAJE@@0scU~b-{63(_ zc?HnMX6q#RYm#ASG~(G4lV%*(q&xkg*JKiEAM=5-KkDrv%|3&QeRn%=;HvcbQzo<^ zilYe0T=KzI{;aBG?SntrhzOfc*Bd^i@_}Dq+^&o3b7fi3E2D+BJFRoRTza^3*DsI=ro$^^TdohB|9!uME0fuq$s)_KQ z8VY{Wn08CU4rA9kQS9fHvA9-zlYi@4Ofs#DdWUqeR?j$Kft zEiQf@l}Lw%Ft}$P&UBO(q7{bFu2%NUafceIZH-h-65$5B14v#LME0++h!Ohn4FU&uTHOVLOmms<+5tKB1f7ns~&jx=)Hq zOe|G3NM$Z0V3=cf-lMh==?*>^V<@<}fyqJwY)y^I|Nm|N(@XPLuqcXNQG8XNd_r;8 zgQ8+Bv$y{K8|46}!nvaC;>fI(j1fc@LD3lF;K0D~kf|nSX?`yt0ZqI2Zs$>=URqPz z?HvJ!o_w|s4h}|tJH@E2t<8|rHt8$j&hKdXHDmSB*0weyJRbsqe`ih-PDag^yUjf> z&|tjt^zqTi4v9eW-6Q2wp7wm2MrX4>L89p0N3Eaz+&24}kK*XD6O7g}f6sjo6Z$4NDQDUO zKh4^On*7KLkC*NI>T{~9z7O4}=xJ)Ra%;DVoSU5UY`Z$1#xkW$S~9;z$N9-76fvWO zhGCe%&nhRT;D>gaMfe3FJ%5Vi>5uFTm<>Og+Y*{PjVq``lTT5p)O`cy-h5yp#Osmb z5`o(G7^k_F2ZZFTcM$y1RC#%b*vBJj7hH*I4AI|5dS2AX_HZap9?E|A+yx&J!e_^R zc~TdAN@Nxl6?M%kUFLW_M)%`&HsXe4&Lyq3BidR~a6C@$fvo$u|1*mUI_kuSdT?Oo z=g{>mt8&=~P3hv&>SV(~aFB_M<59VRS;@h8`KQ<2N_1asoq+GU5vGJ(g`@5B%r{Eb<)# zz);^558n);m;Pma^qn}Vun~k%SJ?(8T3HZ8@_lF~7EkVuTd01YAQ1^5zGiO8LY2z2 zbBAHHvQVyI8@{5*`Rexx(FJ*(jb&Vxmnh|xJXwg9v}bN#g(6?Q`1lBgFYI~H(`_C$ zmp6wuWk?fIT7z3!OzjeAQ+>+g?}FYi@Y(96j>3ZbNlv$w70TI@{9r?zESk%Hr-H^g zDk>sEpM%@lxm(&{QUk`oS*JQj$p*#?)eHkaE9NDe&?jnO)B9PN{eP6kUNj^QK#w!>+~Zo!?0yMI>^cr%ahsTL)Gi-x)2 zBBu!el##yKcO`%;j2CzYt8C@D3JGt{+r5*&2$TSvM)nzx%%RPsG)|J^$Y~3wIfeC z=}D2s@%g_g+VpKsvgD&wW{VY*eq-H}j5w)+RpqT~6c({%kH5VBNr%(sz zs8A0}=4BP_;hgLPaQDOH5mi>;F$!7`B(R1KQfTaxr(%0Vlj>MW%iS-Do2;4|NG^1P~2;{Ad86Pn?X=($yjR} z_{Fn>pqrz%Q}%^30Re_RxM%;R;B@2N;Gk;}b`;=n-NRe#K^bRmoCV}Kt#2D*SLQbr Rf`5+yj(ZO6F5cyH>7Scyt406- literal 2956 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 Efq!F#}IiEy?dci>lQq7t%JvD;K1;fBrOm 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 c-=RA&Vb=`*zQH|8{?@ zj%HdjEw!eqt7>X)-HuRJltMEC2w&2&(Z1ADnurYrBe@ zxtKUxIl5Xo*aHARvr&fvg`#q{y@N_xHu zh^y#w>QU7*;GPWob+bP0KHZIfD4ZKUT>y*rjlTu`t6OcJ>^rd?Bq1VR8!E`O6=YNm zjW+(~aa{^%s~!Aj`6R( zv@kPT?r|u5U)pI%d8620Q&WFvSXzUPl;E3NVyN-R@(s|gaQ2VNm)*M8d;M8lkx7lp zjBl#>UQ97^nt0*{({f*E)l^moNi3dnl?83n$J&W-zkaK)_>O9~ z0N9)(5=!~7HfakPDsUs%MJy6CLdt{vDYj-`$;VUt%LHmkgykpS=>ZpC?ls>vn(JaF$5PB_ypBArzmBgi>cjXCAlBc+<>S zE053WO;@q^&08~i$Fk2WO5`T-&{?}yC;&hLkP#PA|Cx2(5^pvcsw8>ydZ8^L#i`MZQPW&o$IV(TLyJS(>F=Wxe7Vy{o>SjdB_&~b z!LL6e@wdB!S+KK_;n#u#`pP z-Sh=9Dmto&ytsI&S@+?I>x@qhN3c3fbOu-Qh0Y8)N%mI^m3z)ah*o|d+RwiqsDLe9 z@9g1vKl{({@%gl`ZvbZ1K)^3+n}FX&f*6F^JAd>@d@vKpaLt4^@7^Z^E>zPv_525I z2FuFoV$5(8+-$%DH3>Wq!EoTTxmsvYYZ z+nm+k>s?(#gEqwlR+;bt_)7`|8e8Qg{?P_f+U>S)@kIY@yr-gy$A>DfT=tIM)|H!u z>dyat3MF5hMB8?D?4X#P!@Q(LT0PA!K6YJ%Y8B+vC=Wnw+g6_pt9)f9uYkqCLgS~n z;Najyk>TSl%&ghpxoVH)UW05P%e765DVMC|U7S)ggnBy;>%s1Mnd}k_Lb&jil1=a$ zfG?YYX@v!TF(U2b;OH9=aged#Kto5(chCNGd6g2RTv!A-w6BLTv$3T{Q0FGET=#}$ zr_vV8%1UP}vl6Fs)g}dliXGvaGY6&PXDHQzi7Jj|EnEu;TM8M;Y>-BM7@0g;E(0zS zm3?zS^$jS-^5!|7&t7q!x;Mg7_w0+7gBX^5D@>$jpBtDpVVS7t5GTj?VfSWn5zzvA zaBsPtY%E5+!u!##bWp=(cWPRHhdw%;0f|E;%KGX>Q=e-v(7)O@98M$G9c2?No{qA! zvpBdUvK>TfAl|PmYU}TB^&l2ThLe9|QKD5i^ZtCP6L>Q{W8>n#HY!z@&kPkgl9pa= z>E9H)x~|;%OHa6>*s>QM8VT^HYVmH36O$^P{wF8684T+wIbL^DA0HVN2``rp;$kqm zT^*~xRXlqxsIMYOD$6Fo7Yf}iAbXJ7neXZ`xytw8Z@!5Qe$>j^I~jhwo)};DE;3## zZ^jW=v^4V_Fl|pniO#~C`Ca^@{a#Wi3X2hKbaeF3Z7zq;s!9LBrqoOQ@Y|BFna=k} z8juVPm+u$kVhd`UBM)j)Gr!H(nW^!KiR4bo#+?9^MN4UVEXFaA-Ai%j@`t64*K@T% zY#xy{QwH9Q<=HbG0|Q1#NC^4qp8~Vl0*Qj==G1Vb)|K1aac1J=ttibedt&FMCVFy8 z^jBg*fg1T7$vN2ssVvV`9vp?m+_MSXoBhh0-X66!^GpsmG-q0-7bRpi9@MBB-wDZO zMZJ(Mp;fiDX`EeLAVwx9F;7lT$jS7VZV%FcvVSn&33y$ljaRpqSf;oo6dV>7JizKx z7a1Ii%dfvbH?98Nc_J&nSyWscfhk8!VSnhH=dtJ2$Vm)Lbk6=B*^GUjvFseerJ6{| z!RFOhA8bSkhB) zf>6znT;t;Kad7&o{;Y0#AxY05!7mG~kxe#KURr(`HYq=TT6sqfZ;U6$ zHVxUr26@Qpj=zBLDyODAZA-R!eCZ16-FiKN7vl3>bk$bJP;8V@LhGzABCM()^@7`>1Pvr z;*?5*0*ZiLgRi_SYIzb0Z5VB?n4GlZUiA5gshYu-1Ew6?t{n)7@Fc>BBs>)1hlg0A zqJgM(f$)V8T4Lm+eF4GHFr>kG#lC6Pe=i@(;acM(>I8xwMJ!L_vb2^SEJ8^M3D z=f;n*bm@eQha!DDkL2{!AUGs+WL8cafQ%d?jRrp0v38rES%{|Wr;w8D>jO_0G%U6HUwnk{QUfcyk6lZgA*XOWW){~Y})rC33uRKZ#^`8c|Y5_PnT?wWa@i&(S%L>^?{++`#Xz=kqL}I2TCnl%Q z?C}HF-8mhKe#Efd^i~FtY{H(1_%@d`9>uu2y23_-SgnIBDCQQn3#LxUc$p%PTWQ>U z9S)z@nk(N=j*s=%pp*H2wd-pe7!facA}cU&{3F z8+_xR`u%_YS&Ti*eNZ-j2k6w;q4oVt3byfGIL?S?{Yh#a>N~7olTg-Ct>1^_6zjda zpO0Ow9)v)LSHr@_sK@fk1yG3W!)x^}=))4|Y6K|7+MFQu|$_=v#K|@cMzaZ7JaAH|p1z)3f=p4Gpnz zQ7dG8YlA%U3V>aoSp!}xe{vt6_GGe66Mw$Hj5#)P>-T)t#7e#TvV6h{yuXJ9<^St; zTMT`4*-GA$W&=DGg?p8Lh`#6o(D zIshHEwqDQdbKk9${OCgerS&k3vK8eAN4?j3jv{a* zo0$=Ri9Q!D3W0WTSJ`|{!qcAjPaIR8Ah@6C=H^w1ytdQC@D!)@@Gv(jN<~!DhUXdP zj}HbfHhsH)`*!}av3Q}JFQIjEsb`qb_TH1f^4Y+Xg=I+QjhHXS9v|N1L>P zBRXKs4ydoiNjK=~sT;$SY=xULT*J;g1G69GHa#3J^ai2=FkjljZvQG1x|=ale`e@1 zDsJy)D4Yb?YWt?gU2MT@=P&jFK%W*myG>G(xxu#0UcGF8!*=>!8Z@k5Ug!4HRi5}B zsNJPjzWUR+{Q0#bnEFw$6+Z!YmJ@fPzNcgRj}q>0+*7Na)){iBzhU>IS==6In;7L^ zQ%nLDM759}W#ADtI+jJTFA%}b&Fr+k#d$v-+eTEwB&Ku~Rc%REjK z;RIC~`=^w!mXv`)!+SkZ%Y02~g#VkDZRF1^9-pbFuy7`&O4Nr-^*pb#%$ z84T5^ao?}zfpwmVbcGKVMJ)cuA)rMV1t_4bYA&$pwX$6`Zly7TJOXxT5R>5c`Ozs;3`8c~xF)LPJf z<)%{L{WX_oWW*p4h#WK(U8@h734)_V`cl+c9aFOMeEJelD>!Qf)Vpj~l8^6i-Bar7 z(P<+iLPc9!W4xc#Q?h|pp=BB#)Y2ETIMCaky%(!IhBN{mxNlC75>2X zKl!B&%JuL`U!TZy2@+Mijx_!F!mX-{8&o+b`8Nui7Ymb61-QJp3~^6GEMaIr8dFOn zV{~|bLN;VwJZ4TlWPNZh^dWML4a|%2|C-GwRk5y+(>(pj=TC6-?NWSM082oUXZw? z&!G|*w_L~ui8o8TvYzY1BwENIAUo_`VS5&5DJ@dIM`LgcpmGVHcJq7RPWEle4?ogM zs@WZ#c5zzl_+gB!6Yv_5MHtahk&3AKBf4p~qLKAxFxKwsr>9#QZCc_lTJ=^sP^4^B zd2z_loT|M4dlYjz=%OhLMwI~zanmQQ?AnnD&KMc?15^TCVYeRzOC@cjU)G?uz9#PT z1BbI9g==WL~KtT_x&Is8`2cjuG_xhH=<1`SyN*3qRR4t6T>ey2>=M!e*4y6V8!-9+afF} z%{zE>*-$QJQgW=NN1?CdD$#2f+95d9S>gvt{?KSNJ4~XAM%mc#5}6z`j7i#sRk>32 zVby3s&Zp@uuS{uWIa%Q~|3bJlJ+TD;hD<3v#!0I_DNc+6ct4TN7h*E(%)c~0R$SSx ztOav=eeIZ#l_ekCC!D>`C`ZkeIyNR79y9oZJzKhsSttI5p{&ACAH0Il!p}Xh27dAla?e05O zbD9X7UuROekfDO3<>$KNV#hz~ zohl;cawoMUIGoNwvWQ9$gtTeR<`@>ydpGyPAs!fwmSY&RSWe+$cH`3AQgvOe@t8~U zvg1k8**v*)nKAwi7G}?#H?Ux}8QZ5R8Fqjmv+T(x%^i895fO_gO}9%Oy4Nn!e8JA< zsFMwLuypwx2I5kN+{0RH_>a(HEi^<|j*+H3u*X63G)$rTEE>~&bhaq%&MtYLo+*{h z-Q-A0==j)g8K|tKfxblS1(ObmiYo)2Lqg=G6%T)yQz6aIk#J%8uejrSN=brG0}3Vy zDlexEoJHmqVqh^yY3BfzU*l2U^*EbOzrW3+(RLm^uVMXItf`7}Tsntpc*lHq+_wHe8xis>2B8>{X08dt(?sxBhEGj!Y$uO|SU%w2@u8n=6 z4d&N9Sc^ljCj5E|^@nF`H}sce^Ix~zV;NE1RZDW>yyaUf&am0zvZ6(T&{=cHy!`&9 z(jGB={RT_h#)O^UN%pa-W+n|OCN1mfd>)Z>q#YYeR(e-~jiPZ)`E$mn#wNHz`O)p| z+E^vUDo3g0(h@w@yd@FQR20;esA|4)_zxPK^)qM(8>v~epCgy>>-j0l4&IaQ5|Z$8 zwqMRnrfwEiE%E60r>BJWc6kw&^u#|K#Sv{}5qYvHihL0AM&Kj_S^8lbee7s$T7VFF zk!94TH~#ETNXMQlin$|iH;M&^f-u65aB}5q2I7ZtJNGDC#xD++=Pe+NZf-#ZuRTzS z<05Z_0t>4553CfhlD&VVGGu#U4>^*j6gyiVRA{I&U{Ch#(Nsfg6(c7t`=-1oX$hDj z0uT44_e{*A=9*!#B-RqbsojjFNZZHE)oeuadw0_ecZDr!O0AWC$FF{~3$ez>hTNE0 z1Bk%>lCX(8de=28aMfG=zC(D@c)>*e!xL0{P?+6b_2bv~h~G5y)kweEykEaV2rT== z68Yduowk4-1gz^lXH4UUl)FLf;nv;AHUhrXLRrhpzp=VovxN>O9AopIcinq+TbKJL z(gf7~CJf5DakOM|3PM&o+oVLoDT-!hl<0{`qs$Bx1p;JbT&XX*+?Wp!10iAPL?-#& z6`=!GCN)rwY5Lcf3V-zEbsKM0Vozvy7Y-t$mp0~lBW7R~L2MyIk%$_K4O#~P=SbcT zl@BRrvPKB_M@tKFq~rb&BwHYTkEZwn;SrgGx#|Tbk4q0uBRu?%&s+5hcWl%K5JM?2 z>A>YB%t2(o7aF=g7_iBcOA9bYndo0(BG$6QkIceApq)cJgv?hOzg3xIz9yi@KqcB? zf0%RbmL+0h5u}nA{yuf@jxA5>VoS+S0bRRln*Fu(8l`;>8I@&>%HLcUZ9iMjpw2;=uNE1uDaeU%?H&*vuLV zyB%_IPGpS%bG2Fp1HROvE~b4|s;5TI$eQ$oI{eBn53(cIZ;BO=Uaxgio@XA-Uq9k+ zFLAi-39y;;fBbEAI_-2x;P%jUP`!A~it5C52|#7IC|@TL7q6U!NCA zc3IywnpwLcF+pzfynfliA2|mlLQh6H$0`Xsf>z;yn)#z&<7zkNE<;o&Eo}!JmJb4c z?x1E{3jtsY^Q90(!omSVO1~%|r*cx}Yqvg9Wm_^Sf&%=q_+={ACoy56aE+V>f^j|1 z2V*ZEtGC*;)SEc!53;$v-w56real_fo4bt1VqEeTBz1^wgd#i1(5v=s`KGpZ(_{fH zW*3->Qwh$C1`Aj8q@X?uK!2_5{^jQ?eJ6Q=(_R5UntOacR#&NRSY751M%5B45oZCV zoITvJlenv)8K=4?`&s>hd-()KKVWrrRX&@pqX3*C{K7-f3c@!@hlr9Wn}Zmkt1T(O zrE0ulXW}RDf2qKWqxCuduBW3%-IY`)C0?YsO-U6nIxwu`(q{@;icZ-@_wGfh-z7PSe38uWIlB$`rS+n})*-N|Vc}^q#u@cx%_9evq~$jrqR}qM6rpLnv~70S_xKsF zzGfzJ1jinlpPckMIi4(ac%B$LxG?rv<(L-vZt%H+Zq&L3Y4|AjPXakbQ?s*vqT|3+ z9tl4@9OK{j(?i8q(D}vIQ#ql8DBuPOJwpEXn5xSD+$4v^x|1h065kd2cB~MHV#xQC z7mv<1cu+vBzLgC z>^Twng_2K?NUv;!nvX9tkA(iAMsh7!ysHuwo-$XoiKV*8AkwmPp2bXdcqQK!IJ`4i zJwdWi6gI_=ZX1-SQ zSjfiP8_3PjW`vKU&7pYlcc$=@bE1Vf)Xc)iMtAkL0-gcMm#g@sBr!+F-@_lUzrN6w zYuW}PXjQBE)H2)|ex~8}Boit5>ElEbs>ExG`wU`XQr5XM!VJeo4D|}*>FH&3StUWo zFI;uGOUCGby~H$Y1j^RMf5mN58vmM_$G}_|Ov^o`lGdQSX}F5r3#|D?yKxg17yQ`O zyb&G!g;qeo00Ubqze}Zz>s_@(Ho52mMr{b{V(W8R@n|7C812_-Q4;Vd;><#R_jEmw-z9MyWxo?5SS(lP!Ra6s8 zRYkzn-i6CkA>BrpJ&)U47}tA7>_9r~ZbKQvAtEx>1D>i&>5_I7Gam^-9=_19GV*-l zyIHqZH~5;4O_b~sgHsJMb)8sqv$Ku&jcyB7T z)8!crXjwD&>fteAc5iXHq>`wZ^H`>5gLRht;56VrlXV(uRZO$LHz(PZ-fgb$5{(E4 zhgS=*=Pz)aHM4!Uqi2G@YRrChSj`rn*Gv92^L&^4Ga966EhJl;UYjsu;P&U~8v?@G z!5*iQSzo88X^K{*b4EN_Wlwj7q~ZZ6erAF7aHs=*62QCxcE-K6_U(VH*5bjV;$T5h zJZaD1hU4tm{(69yn`(tr{Qbk zfF17I-RHUx0T#SVx$3q&;EIplnF{>p5N5E?fzDNZt^n^3hyVssyBH~Y;*O2OhULm! zw9|;o8kOWckCqdh=qRnN@*1@AyZQFyICp`IdQ`@|7NJ-DpI;fyaZl7dJ7?z3?C-}z z$_v51xf$I|1J6sLzRbUA(*5e-EJJR6%kQ=+ykD3ny?;F0B2e>wo0B6%d`?Or!S<0F zpQfJ&*VkCfXNp}$hpM7=dovi0_03g3x+1)cI@QpFd^@*tml^gy>!lGeo_WW-D-2j4 zdyMpNm?gTynEhMFTse-XJ1r=A=?L( z#f!$JEGY8+7sg0DS@nMbGG?pD4(|LB^41*ho3w(EiMO#3n(kTy+!gx+sq)q!H4YJ+89LIPPXA$5N%+iYJ- z#Me`t{g-V=3^ z_KMm$$*x7-b!3)U4YRPY(<4EH1LGw8vhlBOGbrtyyo?z1J01E0ITy!q3T{ z)DIZ^kw0nBw+#D?iYJT5wZecPIN|MyOhEx0WGoMR9?BIwdVoP1IF+GqqwJNqz4_l< zfPXBRsm$2ecWKwELZ5>wD*SgKEV=H?flw*)`iX@R&N#zwQq8eXZ{;gYo%h(|Jt0+KV4Yi&fRS_x{>M%V>TB8@{X9i)uhAe z2=%OJi94T&a(!b&mYuIJ9F*VtS5Bp;s;_5{9!U|QQ1HG_D~v%kg5Ac=d&)%trz>+S`Vt^D_K^KC6V zyG}C}$D_ob04|5m_!xU`2iz}j6c5&dbK(#Zm0D4Cd>*l_xV6~D^zk$-ZW?|lcnC>!BIbPGz z6(i0Syv1T9CIEDMQrhpG+16lT(xmHzgbtG&??Gu$eF zAmdM&JI9FVx(cOSS$#)%S>)gyuaq!qrhrgf*GJm3`OIB~Yci7u&fj~Rt;^|wA?nYl z;GPjB@-DED0BekGfveNxhPTsGr^d}EB$Y<5rdAgjeu>IgAxWcFTHP+)zlnH5i?kL2 za#wH50>tD~UEE12HH83%t=|N~F@b)9w`%xerJA^1Fa>vEoQf2RMcrsdFnfED)$ncF3z|C~i)F2?@Q zvso-_@=${D)pu8zcV4=wFu+nm)W-PRyeMmJ#0itk}FZS7D&~CT(QZR zqRhgd?8ly-ZmR|IMN2#e+1Oyj-S|iB-(-?a$h$)Zdg?|Z2(KFXlizIIF)VdbNSt^?a6D* zyB7>US)Hm2{=5?SZ%elKmJkFy)Dizc1eVK6=dU8nWk}MwKc^<(R`{N`q?s~e%9zM;>Ta4Rb-cnAx&xG%E!@03%f zXi-G%D)Mr2CjA)bV`+}FV%#qmf6|xcL@fhDl;)B$+HI?P+|RHvZsgOAjdgW@d2N31 ze_l<3u>D=GCJ7S!K802+z*1X5M|+h2&jXZyZ~w*brC?|PN``i|X0zZE!EjV0kMAP` zxB-E=9o8M2DI-#-aqbiGsn=tfj!Rel4-?tR!Eq`_)JtjT%B!NrK5a_45{zuGRR~sQ zh2bL|llJ6!d&6-_xw%Sqc8nfP{G$Hku_GfRq!IptnFN!1uu!=Q&s6hsbG(dx%(Vdu z79g$rX;bt1yT442+|1XnPJm>41DMdiQ0FF`$We3!Nbw8yf#^?L|4&%^_b%7F^M@5&+L zTr22UhDxI=2$8c9=evr>$y^l`V=?gX=&0n=N#sf=)OaCcd04&}Lf;R1U^U!~enRb| zBq#4dKes(q9Q0f zCgc+;GCZi*lOnNOWIp7FH!bZCJ!Ooo$8-egwS|p8E>WF64m#Xrs`P2a&8gP5L_+3i zWxgx+WPgH%Rl9yx@PB*V@N=bt*gG&A=Vq{QO6DiB97iX1r1B&ny-{27Q&;3}>GTMQ z|3?eB5HJ~kbJITEBA#5$9i7;JRZ%s=PY_lIY^fu3_J~Rbt3cA>Ls$@eF@cH01 ztjasRs?+Bx2|Wj6R%(`qSO9001`f05J~x_mtDdiw78bdUb#Ae(M~q3$WwXo!6_j@g z_FU*nLdH&3IKa#Y^$X$ZX9COGr+<+k3@;E}C|N#CAO1qZGzoS=4_9Zu+2t#o-M8KD zja&qOJ>NPQf1$=^wC4teg^xE{O(k6!;}83fnKi`TtQlpr#9HH{HiJ|D&PjUB@R(d* zUdt{LC#s})EXKs1#57tiy?n z!be})G$74<9}!%UzSlRfBFlK0INUqvyR>9Y?>2^s_NMh(*p7zqGdP{d{5IP)QWDS* zXm3>tD9nEEl;(mUw@I_XbL%PJk@W4qf?Rl~*}j~hZrg&LJ|h@ry4B%l?(CvBl+@{2 zo`yj}M#kK-d4*nHAmF@JkrYK){2_i2#Y4@J+?a~>fYjnSh?ox|Wj;*kO?!E!Cqs~-5)_^ph|i%lxfqf z(p{t_JCzYeTw`)^z_lVL0w%=J)ji@RCZ<{q!${a}(mp)*1*1S;VRlgejdIo*`cZ16 z%T=pQ3V0Cu_)#oKo+9`Drd7K|Ub=sQ8YiTho6rwVP_g3#Udr$uvL+@qO8xN=ApVQv zoc(nvsj7Rf#;h3&8vn$Q-*Nz1T{B{i_>A~XYgkAbjg(Fy&MdZ8F@W4ZLpY9ha>$O25K*y zZrM}*+2&b(FU-}?sX=75W?qvA@iWi07F;PUocBoPIJXoDkUA~ygyqS|JVQmGwOU$j zu+Vt^DQCWXRvQIo)dY?DGv)e%hcKPU>A%?=}7y69T?cTV8R@fYZ;aY_)fBJ@__FDZQA{|FSZ zezS-t#__RO{~xzvXwVZy3H&so67YW}S-ki#rh};g*E5|@PH_Q|v#fQ1g~@+PJ#nbI zce{AAUfn5vAE&vAk3QS~gx&cYO?od*_WWIWQ4OB;Yo0n!SEQ)F4%Z!zSQeWoaFpFq z*MdZSvfpPL0P0#AXr1?IP>FwjVK2k`FIhjQ_AH2k2hpw6v%+WIdShzkS`icFzUpZk zw-Md~-gZy#&B7GziMSrPw9z7H#(BD1pu4$!o!Vb!HSd!&5El!#TYrM--Or#ks3}aD zSv9z2^tPk4_xFvkoQ$#&cQIv$ID%4N1)RS6-$5ux;b8_a}*ctI1+!T}esl=^s?Kc2a3~&89Mob?xHp7&rr9Momf9f>Ksz@?&vB zeI{OSzKU8|k^DmSjH~yaq8!xltN%{1iu)sfc)FM@hZg~uWB#R514s*egy;Bz*Tc|?!o)eZ6-8Dhp8s>l*KGwlS z3O${Jg(<2MO>cSPnOzVw68jDq&j9EU9Qdy{@5Ne0u9GP2BYe*hzkCB2h(Zpju+1p# z1Y}3FC<EReRU^?r) ztCO+9W?5u(Cpn3f0eNh@q=sxBsEl98Q6h}{D3FQFZ*Fd16X+c!O`ox#Q~B>zt%1*O z>+k-lOJ=0BCrMk3zD^t7>XXNkJUi>}UiN;WZDFw#M3?&<-5MTJ zM{=wMw7Qt|Kb-T&SfIRmvaJWGl|Ko54Gm|dW z3puF-2^8f^1_mo0MbUy6Sc{#SsiPyrzj-+MXrOq-iyZ6VPa0~S2N$=}dCL66?Czl) zUzwvu`JNHNKHda$fBh9CFTh?Z_PT<-PFAwDC5I^Wr39>*zl|Jy=kUXm9htnv@W-qV zpYpC=R#z*O6zJZhH=Zj28q8MvZ!)GcM9Mi!%S4}qfOOmJHQ^6gWKzERZy3f@SF{70 z^2a~Ysiu;%NNH)ywQgl}m`Z_>u7I`3ya&kl3S0N~ zt7Kb_BICunIK`sdHhmVTZc6BX-x8uZ>Aqxk1=N}Fc9Xb=W#0bDbYX@?FnEuNnEN4D zHlQhGYYU%WqK%iG;!m*g_HaWX92<^-N;^P3winUVZ)IagMZ$vPf4xE*o!$QB%#0pl zSs5uMYpD0p z;_XtX1OcystYg`1X)xI&mS}%rcw{8i(ckaqkJipp+2p@Zix#%}8~^N((9%XEH$_Zr zCdg`PVu6W$f|RCQnF$4^&m322gY%t0#jel-mJQ5Be8i$z65^2mf*cXAO7O<&eu6t~ zZPOe$*q(1ThXqqz&log`Z zR?g@+Xo`9^>~__Y(D?hzJ!HAZPFCtzW@-|pKkB9H7o3h=VYCG63H*}>a2|bpV=HU2 z2J+{NiztT5=5?iz6&^@eE)oeY)G^Vw7N@-X%>3lh17-tE&CHxupG;q=DJgFTv4M_* zm|F2EDH5uxiM(z+1nC#fFU5!!nxE@WHLuc%3rmabo6(`_m3%`CD?B$dJCkiD!#EkN zteX~yhh;Xl%#wO6Qo*V!$SLk{T;4%=2&;tlr}(f}&(Oe+JvkLEpp^Je=%^Y44vMZ^ zKcRS}m=HiRmtJt!n523%rguur$xR=WAnbn(-6Dlyg4iGKz8d34tHr%ezPHS?6hm-s zYg{}F;@U-T*(&=cEh$E|Oji$1!CSW5LKOxJJ5aGACn6Sl`!=2|5{}; z!Kj~=?d-22s!|U-J}9{-CE|#Q$Y7#kc~*2P$wcpnr)CpxB!qKPtvPfVehmu(gZZjz zYR|T_q=|`%G)zoGwp?oZ`c>UZva-APC-eGuGqRAw&n?T9LSM`p3l~aZ*$3xkhxB-V zc@aEo?G#CS%P7Zd64P9YmyPYKNs>pH5@4yp_|2$QL=`#zwpY& zrj)VK(a`3B8B7{mh6gQM5#$^?sVI)^Rc#v;gtrlqbZS2+#44~!;z8dnQ3J+|U@G@Sh3IjnO zoGwgq%H%{6T-di$tR9CH;5tpUaH)jJ5G3q$ zR+G@M;1Z?WsjcSDVLPF&kioqdE!#&)z2y_N$s^p*qLr$Y=?G3wb+zr~_c)#3P6ev+ zv1fzdFeC)mMus5%MmY0teIFB322}m5lL4mc!JZAz7F{w}#fP89q;m ztb*sZURXG3y)RuxYrBTAw0Kp*M}stU~(^GiZkdloJGVWP_^PI+a{`C~en-hLhLq7WE+ z8<9$g<9ZLYw-&Ayz+oi(Y)}54Mj7wXj40=bGhBa8#HL!}X;I0dXS{%?j4M;XX`V_$ zUcPnn6x^d-45r7IC}ztV8WO<<1%Rt5o+Hv3hX)5nb=nJfGY8aZ5ra+R1K{?d<2^te z15D}{eLlGo^dciC7gOEeV-)vOQ!yx9^4~3BB)Srb_4Q}khjLTI2EQ*uv4pWyj5ngP zYq-xM2ihVMZ%sT_zPmkQq%pS1%VuTL(9Q=Y28txb^;-ZBBEepzsv`q2#zERzGOzxu zBEEo*DP@Soy-^p-=X=kPI$#AIf+v&H6xtgPO~v%Vq+()$N{|rlX^UvGi>zHhF{GG1 zRPR|>?wEx~Fyit+tFI#Hf?{L9fll6VNK&(bI0f#C{Ny3dWSwb2b z+L6MJO>EThp^;l1F3D~nh;%bbCph&+Ix(82~F~5xtL>d zy>6YdL_TpCLPA2qq(v&~<1r9oVPWA%opxDyIVmY=KxZdE*gN?~!Bs$fqqL~$KDm86 zsG+fqtM?0-JGh|lUunSFt0?i0M#lZv|$1jH%x) z_6I-)itZD_M|>;1q7g^clh7fBd2XX%@~qMtK0X_B2dBs-b)y`(-c06E=Z=DJtLp;I zizd+bLLTr|8&~K3t2lrDv2MtX*hZZ2qqX}e8~dG!s`MbG-d@q5BO@aZ3=coikX|Ls zjO7h{EQPSKu@$YJlp7en!eCGHkN{mVVKf@!I0cflrWzMmiNJ+0-clqnZHfpt=EGER zevS%?q7-?p+E>}XZ*WD4aH*+EO{6^L&@ES(cP@k{fnv8a`qaCtAk(49Re(F#) zY90{AMx*;^PmaIFB_hv%SBcNL#;$~p_mOHoriDx_xW+-ahzo2ai~Cq`t>DIx4oV?I zhFe=e+Ha3b3_Qqcshm{`EI^QYp{HOH#P!z52n%ksN@~Njk2}0&)}YBRm1u= zKlBi+SCPJrp+5QAP)lEgFXt@6dmTTo4>(A~pbvu+p1N+4pG5|tzc=57I*jf0bK%Gh zBf*9*Pd746d9=VvH-@;FTQkEn{oO4(OKtcCY-QK$8m{mc3dHy`_ z+N%f(^n1<>FO;aarvx~Rw}FLo;%;;t{M$<8-8OaQ&8DR^=q0sDtyD2PlZ@-)Qte<5VOvI9ViYto}wz;JZqkza-bz%WMmD!ZB+6)Ug;nssDdbfsTMuV}2MS z2Gspf=z!q2=nVod#ITr|F$5uEPj}_Jy@mZR0O2Zh`Tw_WK#UiS_p}^NpdIBR(|7r5 zcd0}nb3jc=z)i*QUwNTRISU16URfy-#!-be&yid8Oc6^&y2a<5MTG5IqYQ(7YkUwK z3S?dscy*{N+cB;7f*ML>_Mkff1ngWQ`ft3LQ&&~_CnbgZ5OCp?&;7UKjwlwB{s?## z7~It=GkEPt&`@6K5AfLFuNDoYk1{a8^d361(#rRDpP)d+>bsw>ux^|Dx6Xmci;{#g zWUfSRtW$UU<}9n6#7KTlD`n1pe8wDO5UqBlLynfo^H z`8-p7+d!a?Ea2^=Tj7rj?a%@{bGTPpX59^yXf*6EeR~bM$oTqF0S2pOVsr=9rsY*S4U(8ii`Eya+GAc+NuyUPGfS191_1uYRR^hy zFnbdH_izwY^>ohF)`gH19vo3Ouu4Y05^(nJUzKM+2(3$M}|S2M8%q>NbqNxg53jquDsvf zPBBnwvnR6<de9AIAz2Ia7G5GaK(6|%+22VO9B{z<%GI+ z3TiE)xSuTbK=jXZx)oc&`wHSerM&M~;*M%ugN$8RVBJFN3;qE&Iv6<8)*!9jteg@n zDt(S8`$SL#78x;#;x=>gv^gVzmcP?%FZ|Po<`yDcF=j8v#^?+Q6D(4l+Y4_G!RND& z-augEcY-PYsehHeYdXTC89i9#pEsnoddr0%kitb%^+LyA4D7Ud_jh(8ID>~EK5;Dx zn__Q+@xCCq3|13Z`X~5>Xm@pdUxNSyZ>P`-F}Li4Qef2UprNq<_74a7B|8(7_r0NpphoF_ z80o-7{8=Jtoz1_Owynyu%b12}JTQzM0T$&cjhU31IoP5>Xm83d<=-MY<$orYxcHFp z8@CpJ=DW55F@l8Pc1oavz+E6t!-s>kDv4;LmvnfEBs{`FZ|&1Jd-%f5jo#f){X^2+ z0=Cj$&Yt6?e6c+bp)?%hz`xT%pIP*^ooMk$Q)^@mx7y~6ut9xd;<}9qDjp%HAHVN1 z@dwaMtV*A)*rP#?3p_=TW9^SBtarrI$R}a1nMzj}L$q?dlfZv5tLJ>beWYPrFV=N- ziMKLN(wZBsmN$8j;w(+C)OePEV;pQhG!{~wKgWn3J=)8;I0!QBb&i@RG01PGGgE(uP8y9Cz+SqOy1 z3Blc6g9Hd3+=EMSz2X1+}{1%^-&WbSXIb z3%wo=;t?bEZ_D)xEC@T8FLwp3cSlOT;diVKuV*6S?HM`F)|DmtUK|W{8R;t}4!vri ziz!-$kAVH}3o2T+4YtXL{HMh|C(`B{GV#!ITi{cpY?EuDb#b= zqj`~f9LH5&jEsz|*Y5^8$8%7hMyzf z-XO1(eZ-UCO7Zpx5tUlN-KsQhE%q1OZD4L4a9XRZWai*+)wV`F7ZQimcnLrz~cz_A19t)T*a@W`R64n_(i{pS1QBT8!l;X z=h__TMZDb^)#D`P}giBzE)l z^#6ok685xlcF`jYiuh!{F_5^uuv#6i9^d%z5y}T6d;M8{RCR}esx$_~@4mkDRPQb1 z&l%TtJmQTeCO!#k-1JTBmEQ+8AlI#xnhulw#s?o&PS@ zRwM|fQf=VN^l*R-*UQslsEtE?$gW4MLEMXPQu}C8)<63BtLR0ao-^E~Na1hT+z>8u zVX9N)ije_8a2R7FTamksxD%XDBmmxC!NijWg6Je%Ao8be>5p+74c|1gOb zK638IFOHV8c@TUf@2{UhDmrD2PVGIC@`bJUig3J0m-AgzE-8!exyTTdCjRW+MC*WU zLOsv5wx{+%_@6L1{+wHc!$p*}SVsNfCvWeyPjNNo&qrSPchXt_ee< zpVC9F`Lo+N#xibOTqs%$yln{GEkVFRS5QFt^3|4+jW=Oq*d*Eoey=Srah~=4rjtsR ztRpogBapr$%a|%)#6l_sn_7IJ{eHgvGYqB#CIdiV2FXB%nhi{^ z{>PEda<%VLVn<~Co#h+h@|<^l_BiOzn1+5&D1dIfYvMJ_jW-h%eni4o!soSNl->^$ zu{*-%rPms868x90T>U<^6-)XcYNpLGwKZm0_3JDD>a^hj!m5kGd_aLRzQxWW%+0#6 zQlWJ<6z)h&TNnX)#p%Y*1i#SM)5j#WSW$t;pts-ZB~9B)><+a;Q7&-}YNG z#1;7>q1P!0{sd{V`VJ7Eb&iN&Ex)Csj67D~>$y=chW8j@Lr%;A^Q^{PgU>|;u;(A} zb#YNUK!(9a^|*IA38wLsy)JG+_<1h*vAJm!G)>ZhxH?$0;CxGg-|@t*p5`%d_8Ozs zp(2qiN49HzAS*hRYm9Cjo0GSfrVraf>62IDb7K7wgN3I!SX}JVESh3x1zPGuTT_Cp z4S^smx@H3j6U` zS@gL%DW)m**F3id_>*3Pw>c?DdceVRauQ7ume*rR%!dR34P~;H)Ml+FZ1BVQQTuK0Zq|{pg&xLa4LOT(LDT^d-O(0f;WwlNlCff4pBjLO5QRdQ9sjv8TMc(jt`# zLdV=n2)Gi?Ss^4Sap)OFvpcHd&VwrN!WgKRs$T!OA2e7C;z3Olx-`c2y<^2$4k)a- zO|I{0ohdQBsN`%hY)eo&Y_C>_?@>4g$lctUv@<8*-pvfISlIAj{KEH!M~5iiy& zi<&Si34Z)i0QEoA-#MB)8j>)(t&6Cg37|+n5d~j^;b+1!KAu`6L}23aMd9G|HOPnM zK=Sc4tNuzE`O?%vsxzOcbG?cZRE_?YZ|Hb@pewZK0LGhEL6TN1jw zU)uItx?I{u%n*IU9iiHH>ePL4LUU{df7Whr^=zRzfwK!Y9Kbg%Jdvo3X( zxwB);<)XS#e0$Oe5X z?UBRzwx#fce;wZbzK1`0JeqU}&G3^BF||^S`_ixpySmynJ-UjS*k9i(_Ut9Af8i!x zh_$n@kc>>wtzl`~-^SsK#9a*YztHjR$^6Cr2X@6MEmz;hTC&&b#J_6 zSqix>5qjR!|8}9b&nUxJLQT5dGQa%qfL>Z4ciEivndM)4QYv@=qo-`9xpXIO9L0UI zFXZ8_=o^G)e!`F@kc342x%|w8gSXRSPdbi2Yl)apN}z@hb9H24qa?u1l_?)lRye-^ zsxyaV8FxDNS%w@-OJZYioTh`mJAui?N&7*oy360!2YppjLnq^`1k>UdFs|*1kGqJc zD;Bnfk7wl5u2X0P_(y8-y|*(Y2od|t>o(DW#y@Yahi1$7;h?d%VK>y;h=toNh~_4w$tiHu-%7$9DTvaC3ix|COO(?M3S;;*<)_B zuahlCqCA%EK3K}$N=hLdPQ309%l5<|f(xHlcU9Fc>xIlty2*NQ;d>s(B38vU=#Y}$ z<9ihLKUYhRTwR-SJ{}1XcI$|k9L74!xRDlyXKK+TfIl)sO?x_paLgO71bT{iT|B%w zP!!wcl@{2TBqwl>+4ZCXyxRBM2AO~Q`Mc()97wQ*z)&^iAP2_xmrfUnrY%`- zm|8bPd?^05TIr(i@GV*!3NQXqZvKa+UgUXp63n70t0Ovn^~1c}y?qHtM+ z@?@He&y>%8dR>@;*iN^$dC2p;?+gn03i;#qJEJU7KtdaQI7sg<&5_xdnK(P9nOHID zDk9sca6)Q&fci#{ARA(JV$<}^^PBFcL;cTqm22IpMqB(mW(;dwl-kbxg?pB*IomBg z%RWwvgiY_7C1X@qvl}o`i87ul5R_b2>6srtsxLdkFsgY$es4Z3F^p&qCH>O*p_`8s z>!&F~k13QP1RXb|GXaZ98Vf~^Hx=OdpC{~or^y?AsDTqq==0P^R+-Ok@%Qc+0> z+#D{x?M7Sc$Mcyh5RX$@70A&7P*72~e;dxu!I~a=k$mnIN&p@(Cj!Y5q6+Um?|uBJ zgQ_`?x&;FiOMus@z%Zw#fOPeoy+Ha1C`8D{h9%66Eg6G|h-hr@e0q*8eDb1q6WEFe z6!V_y;euqj3y?n}#6Skujd-9Ph0$b`l=7f7KvqtUEK9#{mHH5r1{wMsIRah!3@vcZ zzD`o&Gl09Y=jZB5NZH>Wl<3vxWXNu_IVkiC+~aq}Ax ziNn+*d-r6#sOjl9<&9-xVq!#`oSYcxBg7?h6&0ZBrRHbg%Lp}liE@@R%;8)7y%+?6 ze+d9kXZdb+P*TEq|BhbaZ))YY;2}vejdWsaDj&F7W*QSs_#hCR!H&`5M?SMY6_J-xjUU~PTfOk7l)3pUj1$PF8M`c6$lL-YM-MJ3oi&hW$e zHVn9b`7`^*p6+1_ucJYSLoqVlXZ0JwR&&r zFLhXi_EWx5HiQh-sp?%G1HP|b9_kpoTuOA~^%TLlN=ez>Ey}e7=l3zyrgW$#$ zYZg%&85u>Dm2vfgDd_UCQMTkkx;hmpZlk8jBfE~bx0j0^%O$g@IZ8mcH(?BVhjy1T zV4eFP7f@D?Jf4S(d_)0j;F|xg&4$|Vf}K8s61PrySO+n+v_t}ysV=t_H{$Oj*TW|z zag7j2@gmXr`1p*-T~$<~b3h%fK1hg(`3#2QvMl)nHx_USANT(fghtvIZ;aNf0s$O< z7^bJeIV7~e7-j<3r90$ClsiOFI=mZ_J`%=f^Q$2vzL^tjld`{43(>I2wMYf=tQPC= zp945JxqUDA|4KVV*Q=}=4xFhgWAOL~rf$=XE zft{1TClUwD#!`!dwzYruc!DdBhIkNbkL>PmWf{;+btN#Z>*q_)$k`^CwUz|~EwhscemVnk+pl88BT2f2YHFt}MMrzT*_LLK+BR2MeT1|h zJ@`RWUyU6uqXJOUm)WlR1^Xlkz%y)Ylq!P(v_ce?P~fG}WA)EHHzEdh9wLQ#!ETYO zw2B2@!e|0!9}+;?N9l6ow2pj@@=g^uche#^m^9xR_Tuu`(vj2U&oNlQko3N1o8Is% zfy;6e`cPqbi{snUDFQbaY)R_f&cBbGNF5%{s`vLAB*dMjEDCyQcpB=jICkrSaYxiw zX{u=|cnM9Am#l%S8jsbzpcHwY4*0-IyCN?&V&9W} zB$^bTz9px!m2exUe*&c@beNBMe!TW!Bl(rbU%@9?Njy>@Kqf0oLTkgnB{2ZJIEud9 zzNy+`NU+AkHN;!~S(9Rm#-<6Ii;IU^qgj1Pr>^3{#Aky)wh5I`Xrtc2?=0D`d8qr~Of|fuA|4xE>P@ zS)s|iC0Y`hV?&EA$|t+pr39o)$1xT;*~9@;P%9ipY?HP__aw9+5AeI$DKrv~OZ#wt zl^$lzbPFu6K$a$%e32HFe-e1bX+F?|z;sEQK!#VdLjR+(LljqJdRI zo)5{o9f6C>vX%I;F9z3Pb4)SL0w-Fol;BzNRNin_f5QaY$8BC976112hxY?RDj{L74N9HO_@XnC0tus_)xOncMJU&!3(W-_}>Iios8-} zR8TTBSV;NtHgTsqFOOkmr3B=wTie@mx#P4VB6^_Qf!2oSgqUl>*o=&fGIJ#J1oP*i z8k6lpeSLjUVPO^qU!*JfgdkdC_(BH9{%qB=k$yFVm0o5c=4dBX(APjefAU}YrOPLs z^x7p>fS$bSK7+!pnACn>{ezVQ~XIG!>zWRK~Y!8N+v(6Ejyvt^xWfB=%l-c9whgsx#m&UG)hI z9z2%0Nt;0xq|IXDf3jMu{-P36*+va4pZ__%a(t+6r0Kiy_McbSGfmGX16Sj77vrw3 zJW1oRA@cz~VCFJ9XY?W+~#dcWIW7V*) z6(8&j;>HNc?ny0V@zB)jb8<|8QIs^e=PNhgh<9iVH)`h8h1%uvJqSj^!gze%xsJ@4 z#Xo4dwRbFkbt=j>n}Gue!-eiCOXZG}h!=u~;j&%;m!rDGTQ4f9evgAIF~qo*nTJ0c zel;d*Y)o#Ni3=Y=PLw;2p3Zho1VQkL{N0Jab@Oel z^~l%c%pPCagy1+KA{aT6dI(C)`^zG5GP(Fme(g99O1fpi96GD+qa^f$%_GR0p;1IH zi?1-5!hNVm?gs1VFMBciw_EzSe=Q$dP7iL50Naf3%E`N-jad0gJB{oNaq zaQ7%Y4>Y&1kl=E%wZ%W&w;9bes`S6VVF%^KKKTI1lCX3%n4FXjfTgvyF;RK?Pk->0yYzH)otvJ1etum2$DupB0R{gsU*Cr# zAA0y-9<2$Za=%E-#E!j>m>D%z-ll2sbZ%fSLXwWfbrlqNkNo=gn`v324ElWw+rPL> zj8QHDY{oJDuPeY|UHmdXc*Oc6nPb5iDb9aljsgI1T8srbID9+Gv+7v~^KHG;vRcLb z!CmA}%eOFYlT6e4`Bhg@8MMY-6)?sJmF$Z*tuYypw<<}dakn@jFB9hRqj(72Tw8-= zyW?z{?t8r&b}M2T_2^LKJPlu#+{mGa zcGQ*mwy@)1uM{tDaJ~u*W6zhYz^$IMj^MlB$xYfIm?BWON*%hff&QrV&RI0zRD}}a zv`>8IcCmjUPOb<`-@V17hjm-;^iT5&fZ+M4s;hUMMCU~UsREM|m(7x`o~%pMGPq8# zl$5Yo3L!O-U#_toB=Zlmm-Seh^Ov<))jE$@Va->mU(Hu)1Z478o&1-=rg~*3r}$ka zv{Pa8BtN$~*y1?A~K0-!oA-+o$F_4W2P4yT=j zao62f9yyUM99*8CGoGEF8$Fx$fBTk1n@wk6*R*aI-uZnhW#|XH9rM~d9)fDv&}-wi zV`m8^{f$43pndxrZ>@M+vvevE@#rq`IK}_qzXO4* zgLpOBotj}=FR;ddPqn~eH3J#Q-XqzMywrc{{2%s?cS=x%8Ev|I6b?o@?f2u#cgH4z z7ON8RzZ5FLJL5l<0#j|SpGrK1QR4V8X4^?!^=2mL)Ow6x@5)L}(=#Z2wCL^Tf!6X{ ztXLm$q@;G5Ua3eUY%DR_g3Qy)%gfS`3rBRo2kh@8Sj|BDE+U|dDuvpCiC>!!#zeT< z#QlD%oFiIsN-({+7KxL%`IWShe>Tt@^me50U@R6hv?*_-iv-3~WU!$~FrphfjH{~> z{NDAXJ|dicX&rB=jOgDko2@Qpr1zPOKZOk^6zlA{aMwh4yPiLZT~*CKexudaJawb> z&^rfmUK!uA79s3tLo)5Tch`TfY0BQyuYV8`F`OW-dTRJt`!afIX(^LedRu(U{$3Za zg`Wh-A-gBX@G4;0C>p@@pQ_Ww2B+qO%74A`lpG2yzX>{dNb|@D+J#He^P93M&MEuGxqFvbgc{Pm7cE0Cxw3{NbfZD zWX__kVG?_5EjVY&gIG|H-D$oTeiL~>$EkZh3jZA0nw57(*txF!Qe9?kjnJ^+iVJAl ztG(X7tCRDCxvZ`=gPMZqIfZ_F?fqg1`FQ(roaWNp^h^la>W0=W#1(#bM;7yr*8X4c zxFfd0!eTboxe*H3>68)VF5DK7w6m8x^?-_Y#cqxFNnz-I=*^1uAX2N~BBlR|KIA2R zGiWQj{SdJ(P9tF4Gq~Zo>eD&&zH8V9kUdWGR-DP82bh$`wsQ8dP`W+3F5X|+{lcR~ z*G;30&z3}!*^VdY#>mMlEeUNBR+{af9HUcxNtoD>dKAY)8gu-7AL-r9a;sunT9*7c zpNMd&6b6__*_S*`Zi04OH5hS77C!E=qzu8j9(rj(!ewE%6hhw)X&k&Rb~Z?t3E3%lMKo@b;AsVh13NYSK*q)^_tX4E0)B7 zH~T{g^qE5;ImAA7oezYj3A{H5+Mw&QNj?qg53ST{1_ac)wU`}w9TC|>VNR-QYInIM zL;-gQ8eG@Z0Byj}OEZ>Rvw>|yuoo+6&95tLOO4TpCnEheHw}Km6A&y*9x!1JJ4n6J z@K%h?FGpUKJ3st(&>C%&dAn-&dKEiK$5m(16S$LLPK=Yy=rgNsCT0jd5!PKlFt^yf u{ru#ku|qmnp0tmJLNEG1^W`y*sLHn4cwro@bKqYF0m=$$@@2B7!T$?6$N*jd diff --git a/icons/obj/fishing.dmi b/icons/obj/fishing.dmi index 39bcc85344200514b219e29278beff427e20320d..f7ab9fc1ad9c2a019a918f42aa05cda10ca7b8b7 100644 GIT binary patch literal 16887 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 literal 4692 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 literal 0 HcmV?d00001 diff --git a/sound/effects/boing.ogg b/sound/effects/boing.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8328cc33926133cc0960e7d348d589478ad4bb02 GIT binary patch literal 28224 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 NFjyXtgTY8i{~y$7yF&l~ literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 972ed35951e..2fe8275a014 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -39,7 +39,6 @@ #include "code\__DEFINES\antagonists.dm" #include "code\__DEFINES\apc_defines.dm" #include "code\__DEFINES\appearance.dm" -#include "code\__DEFINES\aquarium.dm" #include "code\__DEFINES\area_editor.dm" #include "code\__DEFINES\art.dm" #include "code\__DEFINES\assemblies.dm" @@ -93,7 +92,7 @@ #include "code\__DEFINES\external_organs.dm" #include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\firealarm.dm" -#include "code\__DEFINES\fishing.dm" +#include "code\__DEFINES\fish.dm" #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\flora.dm" #include "code\__DEFINES\font_awesome_icons.dm" @@ -3759,6 +3758,7 @@ #include "code\modules\experisci\experiment\types\physical_experiment.dm" #include "code\modules\experisci\experiment\types\random_scanning.dm" #include "code\modules\experisci\experiment\types\scanning.dm" +#include "code\modules\experisci\experiment\types\scanning_fish.dm" #include "code\modules\experisci\experiment\types\scanning_machinery.dm" #include "code\modules\experisci\experiment\types\scanning_material.dm" #include "code\modules\experisci\experiment\types\scanning_people.dm" diff --git a/tgui/packages/tgui/interfaces/ExperimentConfigure.js b/tgui/packages/tgui/interfaces/ExperimentConfigure.js index e515c2bfb94..02cc759dd7f 100644 --- a/tgui/packages/tgui/interfaces/ExperimentConfigure.js +++ b/tgui/packages/tgui/interfaces/ExperimentConfigure.js @@ -142,7 +142,7 @@ export const ExperimentConfigure = (props, context) => { {experiments.map((exp, i) => { - return ; + return ; })} @@ -168,44 +168,24 @@ export const ExperimentConfigure = (props, context) => { export const Experiment = (props, context) => { const { act, data } = useBackend(context); - const { exp, controllable } = props; - const { - name, - description, - tag, - selectable, - selected, - progress, - performance_hint, - ref, - } = exp; + const { exp } = props; + const { name, description, tag, selected, progress, performance_hint, ref } = + exp; return (