diff --git a/code/__DEFINES/experisci.dm b/code/__DEFINES/experisci.dm index c74290ff5f7..a1ffbc0b4b8 100644 --- a/code/__DEFINES/experisci.dm +++ b/code/__DEFINES/experisci.dm @@ -39,3 +39,5 @@ #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) +/// Experiment handlers with this flag will announce when an experiment is completed even if it isn't compatible with them. +#define EXPERIMENT_CONFIG_ALWAYS_ANNOUNCE (1 << 4) diff --git a/code/datums/components/aquarium.dm b/code/datums/components/aquarium.dm index f9ba8b5164e..bfbea45913b 100644 --- a/code/datums/components/aquarium.dm +++ b/code/datums/components/aquarium.dm @@ -395,8 +395,8 @@ ///Check if an offspring of two fish (or one if self-reproducing) can evolve. /datum/component/aquarium/proc/check_evolution(atom/movable/source, obj/item/fish/fish, obj/item/fish/mate, datum/fish_evolution/evolution) SIGNAL_HANDLER - //chances are halved if only one parent has this evolution. - var/real_probability = (mate && (evolution.type in mate.evolution_types)) ? evolution.probability : evolution.probability * 0.5 + //chances are halved if it isn't asexual reproduction and one parent doesn't have the evolution. + var/real_probability = (isnull(mate) || (evolution.type in mate.evolution_types)) ? evolution.probability : evolution.probability * 0.5 if(HAS_TRAIT(fish, TRAIT_FISH_MUTAGENIC) || (mate && HAS_TRAIT(mate, TRAIT_FISH_MUTAGENIC))) real_probability *= 3 if(!prob(real_probability)) diff --git a/code/modules/experisci/experiment/handlers/experiment_handler.dm b/code/modules/experisci/experiment/handlers/experiment_handler.dm index 10c15c4eba7..f6c80a17248 100644 --- a/code/modules/experisci/experiment/handlers/experiment_handler.dm +++ b/code/modules/experisci/experiment/handlers/experiment_handler.dm @@ -163,20 +163,6 @@ playsound(source, 'sound/machines/ping.ogg', 25) source.say("New unique autopsy successfully catalogued.") - -/** - * Announces a message to all experiment handlers - * - * Arguments: - * * message - The message to announce - */ -/datum/component/experiment_handler/proc/announce_message_to_all(message) - for(var/datum/component/experiment_handler/experi_handler as anything in GLOB.experiment_handlers) - if(experi_handler.linked_web != linked_web) - continue - var/atom/movable/experi_parent = experi_handler.parent - experi_parent.say(message) - /** * Announces a message to this experiment handler * @@ -292,6 +278,17 @@ * * experiment - The experiment to check */ /datum/component/experiment_handler/proc/can_select_experiment(datum/experiment/experiment) + // Check that this experiment is visible currently + if (!(experiment in linked_web?.available_experiments)) + return FALSE + + return is_compatible_experiment(experiment) + +/** + * Checks if an experiment could be selected by the handler if it were available in the linked web. + * Basically, it skips the available_experiments check, unlike can_select_experiment. + */ +/datum/component/experiment_handler/proc/is_compatible_experiment(datum/experiment/experiment) // Check that this experiments has no disallowed traits if (experiment.traits & disallowed_traits) return FALSE @@ -300,10 +297,6 @@ if (length(experiment.allowed_experimentors) && !is_type_in_list(parent, experiment.allowed_experimentors)) return FALSE - // Check that this experiment is visible currently - if (!(experiment in linked_web?.available_experiments)) - return FALSE - // Check that this experiment type isn't blacklisted if(is_type_in_list(experiment, blacklisted_experiments)) return FALSE diff --git a/code/modules/experisci/experiment/physical_experiments.dm b/code/modules/experisci/experiment/physical_experiments.dm index 11075d1c75e..0fba29f6644 100644 --- a/code/modules/experisci/experiment/physical_experiments.dm +++ b/code/modules/experisci/experiment/physical_experiments.dm @@ -26,7 +26,7 @@ if(istype(proj, /obj/projectile/beam/emitter)) finish_experiment(linked_experiment_handler) -/datum/experiment/physical/meat_wall_explosion/finish_experiment(datum/component/experiment_handler/experiment_handler) +/datum/experiment/physical/meat_wall_explosion/finish_experiment(datum/component/experiment_handler/experiment_handler, datum/techweb/linked_web_override) . = ..() new /obj/effect/gibspawner/generic(currently_scanned_atom) var/turf/meat_wall = currently_scanned_atom diff --git a/code/modules/experisci/experiment/types/experiment.dm b/code/modules/experisci/experiment/types/experiment.dm index b7e7175d840..494655694b2 100644 --- a/code/modules/experisci/experiment/types/experiment.dm +++ b/code/modules/experisci/experiment/types/experiment.dm @@ -95,11 +95,30 @@ /** * Called when you complete an experiment, makes sure the techwebs knows the experiment was finished, and tells everyone it happend, yay! */ -/datum/experiment/proc/finish_experiment(datum/component/experiment_handler/experiment_handler) +/datum/experiment/proc/finish_experiment(datum/component/experiment_handler/experiment_handler, datum/techweb/linked_web_override) completed = TRUE - experiment_handler.selected_experiment = null - var/announcetext = experiment_handler.linked_web.complete_experiment(src) - experiment_handler.announce_message_to_all(announcetext) + if(!experiment_handler && !linked_web_override) + CRASH("finish_experiment() called without either experiment_handler or linked_web_override being set") + experiment_handler?.selected_experiment = null + var/datum/techweb/linked_web = linked_web_override || experiment_handler.linked_web + var/announcetext = linked_web.complete_experiment(src) + announce_message_to_all(announcetext, linked_web) + +/** + * Announces a message to all experiment handlers + * + * Arguments: + * * message - The message to announce + * * linked_web - the linked techweb we want to target. Prevent experiment handlers not linked to said techweb from receiving the message + */ +/datum/experiment/proc/announce_message_to_all(message, datum/techweb/linked_web) + for(var/datum/component/experiment_handler/experi_handler as anything in GLOB.experiment_handlers) + if(experi_handler.linked_web != linked_web) + continue + if(!(experi_handler.config_flags & EXPERIMENT_CONFIG_ALWAYS_ANNOUNCE) && !experi_handler.is_compatible_experiment(src)) + continue + var/atom/movable/experi_parent = experi_handler.parent + experi_parent.say(message) /datum/experiment/proc/get_points_reward_text() var/list/english_list_keys = list() diff --git a/code/modules/experisci/experiment/types/scanning_fish.dm b/code/modules/experisci/experiment/types/scanning_fish.dm index 96832cd8672..38209a9d281 100644 --- a/code/modules/experisci/experiment/types/scanning_fish.dm +++ b/code/modules/experisci/experiment/types/scanning_fish.dm @@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(scanned_fish_by_techweb) * 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, ...) +/datum/experiment/scanning/fish/finish_experiment(datum/component/experiment_handler/experiment_handler, datum/techweb/linked_web_override) . = ..() if(next_experiments) experiment_handler.linked_web.add_experiments(next_experiments) diff --git a/code/modules/experisci/handheld_scanner.dm b/code/modules/experisci/handheld_scanner.dm index f89fda97f3f..a89fcfd16d7 100644 --- a/code/modules/experisci/handheld_scanner.dm +++ b/code/modules/experisci/handheld_scanner.dm @@ -28,6 +28,7 @@ AddComponent(/datum/component/experiment_handler, \ allowed_experiments = list(/datum/experiment/scanning, /datum/experiment/physical), \ disallowed_traits = EXPERIMENT_TRAIT_DESTRUCTIVE, \ + config_flags = EXPERIMENT_CONFIG_ALWAYS_ANNOUNCE, \ experiment_signals = handheld_signals, \ ) diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm index e5402acc84e..efe4e2a648c 100644 --- a/code/modules/fishing/aquarium/aquarium.dm +++ b/code/modules/fishing/aquarium/aquarium.dm @@ -163,7 +163,7 @@ /datum/component/aquarium,\ min_px = 6,\ max_px = 26,\ - min_py = 6,\ + min_py = 7,\ max_py = 24,\ default_beauty = 100,\ reagents_size = src.reagent_size,\ @@ -248,6 +248,11 @@ force = min(2 + (GET_FISH_WEIGHT_RANK(current_summed_weight) * 3), 21) throwforce = force +/obj/item/fish_tank/examine(mob/user) + . = ..() + if(HAS_TRAIT_FROM(src, TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH, INNATE_TRAIT)) + . += span_warning("It's cramped in there. There's no more room for fish to reproduce and grow!") + ///The lawyer's own pet goldfish's fish tank. It used to be an aquarium, but now it can be held and carried around. /obj/item/fish_tank/lawyer init_mode = AQUARIUM_MODE_SAFE diff --git a/code/modules/fishing/aquarium/fish_analyzer.dm b/code/modules/fishing/aquarium/fish_analyzer.dm index 9202420ee1f..64b4798e911 100644 --- a/code/modules/fishing/aquarium/fish_analyzer.dm +++ b/code/modules/fishing/aquarium/fish_analyzer.dm @@ -89,11 +89,11 @@ SIGNAL_HANDLER unregister_scanned() -/obj/item/fish_analyzer/ui_interact(mob/user, datum/tgui/ui) +/obj/item/fish_analyzer/ui_interact(mob/living/user, datum/tgui/ui) if(isnull(scanned_object)) balloon_alert(user, "no specimen data!") return TRUE - if(!(scanned_object in view(7, get_turf(src)))) + if(istype(user) && !(scanned_object in (view(7, get_turf(src)) | user.get_equipped_items(INCLUDE_HELD)))) balloon_alert(user, "specimen data lost!") unregister_scanned() return TRUE @@ -103,8 +103,10 @@ ui = new(user, src, "FishAnalyzer") ui.open() -/obj/item/fish_analyzer/ui_status(mob/user, datum/ui_state/state) - if(!scanned_object || !(scanned_object in view(7, get_turf(src)))) +/obj/item/fish_analyzer/ui_status(mob/living/user, datum/ui_state/state) + if(!istype(user)) //observers shouldn't disrupt things. + return ..() + if(!scanned_object || !(scanned_object in (view(7, get_turf(src)) | user.get_equipped_items(INCLUDE_HELD)))) balloon_alert(user, "specimen data lost!") unregister_scanned() return UI_CLOSE diff --git a/code/modules/fishing/fish/fish_traits.dm b/code/modules/fishing/fish/fish_traits.dm index 40cad34c20a..fe2fa6171ba 100644 --- a/code/modules/fishing/fish/fish_traits.dm +++ b/code/modules/fishing/fish/fish_traits.dm @@ -343,7 +343,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) /datum/fish_trait/necrophage/proc/eat_dead_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(source.get_hunger() > 0.75 || !source.loc || !HAS_TRAIT(source.loc, TRAIT_IS_AQUARIUM)) + if(source.get_hunger() < 0.75 || !source.loc || !HAS_TRAIT(source.loc, TRAIT_IS_AQUARIUM)) return for(var/obj/item/fish/victim in source.loc) if(victim.status != FISH_DEAD || victim == source || HAS_TRAIT(victim, TRAIT_YUCKY_FISH)) @@ -434,12 +434,12 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits()) /datum/fish_trait/predator/proc/eat_fishes(obj/item/fish/source, seconds_per_tick) SIGNAL_HANDLER - if(source.get_hunger() > 0.75 || !source.loc || !HAS_TRAIT(source.loc, TRAIT_IS_AQUARIUM)) + if(source.get_hunger() < 0.75 || !source.loc || !HAS_TRAIT(source.loc, TRAIT_IS_AQUARIUM)) return for(var/obj/item/fish/victim as anything in source.get_aquarium_fishes(TRUE, source)) - if(victim.size < source.size * 0.7) // It's a big fish eat small fish world + if(victim.size >= source.size * 0.7) // It's a big fish eat small fish world continue - if(victim.status != FISH_ALIVE || victim == source || HAS_TRAIT(victim, TRAIT_YUCKY_FISH) || SPT_PROB(80, seconds_per_tick)) + if(victim.status != FISH_ALIVE || HAS_TRAIT(victim, TRAIT_YUCKY_FISH) || SPT_PROB(80, seconds_per_tick)) continue eat_fish(source, victim) return diff --git a/code/modules/fishing/fish_mount.dm b/code/modules/fishing/fish_mount.dm index f20f3a977b0..a4edf9f89e5 100644 --- a/code/modules/fishing/fish_mount.dm +++ b/code/modules/fishing/fish_mount.dm @@ -130,7 +130,6 @@ AddElement(/datum/element/beauty, get_fish_beauty()) RegisterSignals(fish, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW), PROC_REF(on_fish_attack_hand)) - rotate_fish(dir) if(from_persistence) persistence_loaded_fish = TRUE fish.add_traits(list(TRAIT_NO_FISHING_ACHIEVEMENT, TRAIT_FISH_LOW_PRICE), INNATE_TRAIT) @@ -144,20 +143,6 @@ beauty += main_material.beauty_modifier * mounted_fish.weight return round(beauty) -/obj/structure/fish_mount/proc/rotate_fish(direction, old_direction) - var/rotation = angle2dir(REVERSE_DIR(direction)) - if(old_direction) - rotation -= angle2dir(REVERSE_DIR(old_direction)) - - if(!rotation) - return - mounted_fish.transform = mounted_fish.transform.Turn(rotation) - -/obj/structure/fish_mount/setDir(newdir) - var/old_dir = dir - . = ..() - rotate_fish(dir, old_dir) - /obj/structure/fish_mount/proc/on_fish_attack_hand(datum/source, mob/living/user) SIGNAL_HANDLER INVOKE_ASYNC(src, PROC_REF(remove_fish), user) @@ -195,7 +180,6 @@ return ..() RemoveElement(/datum/element/beauty, get_fish_beauty()) if(!QDELETED(mounted_fish) && (!persistence_loaded_fish || roll_for_safe_removal())) - rotate_fish(0, dir) UnregisterSignal(mounted_fish, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW)) mounted_fish.vis_flags &= ~(VIS_INHERIT_PLANE|VIS_INHERIT_LAYER) mounted_fish.interaction_flags_item |= INTERACT_ITEM_ATTACK_HAND_PICKUP diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index 5d465b6e7ef..74aad213448 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -258,7 +258,7 @@ GLOBAL_LIST_EMPTY(fishing_challenges_by_user) float.update_appearance(UPDATE_OVERLAYS) if(special_effects & FISHING_MINIGAME_AUTOREEL) addtimer(CALLBACK(src, PROC_REF(auto_spin)), 0.2 SECONDS) - playsound(float, 'sound/machines/ping.ogg', 10, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + playsound(float, 'sound/machines/ping.ogg', 20, TRUE, MEDIUM_RANGE_SOUND_EXTRARANGE) /datum/fishing_challenge/proc/auto_spin() if(phase != WAIT_PHASE || !float.spin_ready) diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index eca4e8a7ebf..69387aa293e 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -151,13 +151,13 @@ var/list/block = list() var/get_percent = HAS_MIND_TRAIT(user, TRAIT_EXAMINE_DEEPER_FISH) block += span_info("You think you can cast it up to [get_cast_range()] tiles away.") - block += get_stat_info(get_percent, difficulty_modifier * 0.01, "Fishing will be", "easier", "harder", "with this fishing rod", offset = 0) - block += get_stat_info(get_percent, experience_multiplier, "You will gain experience", "faster", "slower") - block += get_stat_info(get_percent, completion_speed_mult, "You should complete the minigame", "faster", "slower") - block += get_stat_info(get_percent, bait_speed_mult, "Reeling is", "faster", "slower") - block += get_stat_info(get_percent, deceleration_mult, "Deceleration is", "faster", "slower", less_is_better = TRUE) - block += get_stat_info(get_percent, bounciness_mult, "This fishing rod is ", "bouncier", "less bouncy", "than a normal one", less_is_better = TRUE) - block += get_stat_info(get_percent, gravity_mult, "The lure will sink", "faster", "slower", span_info = TRUE) + block += get_stat_info(get_percent, difficulty_modifier * 0.01, "Fishing will be", "easier", "harder", "with this fishing rod") + block += get_stat_info(get_percent, experience_multiplier - 1, "You will gain experience", "faster", "slower") + block += get_stat_info(get_percent, completion_speed_mult - 1, "The minigame completion speed is", "faster", "slower") + block += get_stat_info(get_percent, bait_speed_mult - 1, "Reeling is", "faster", "slower") + block += get_stat_info(get_percent, deceleration_mult - 1, "Deceleration is", "faster", "slower") + block += get_stat_info(get_percent, bounciness_mult - 1, "This fishing rod is ", "bouncier", "less bouncy", "than a normal one", less_is_better = TRUE) + block += get_stat_info(get_percent, gravity_mult - 1, "The lure will sink", "faster", "slower", span_info = TRUE) list_clear_nulls(block) . += boxed_message(block.Join("\n")) @@ -184,10 +184,9 @@ . += boxed_message(block.Join("\n")) ///Used in examine_more to reduce all the copypasta when getting more information about the various stats of the fishing rod. -/obj/item/fishing_rod/proc/get_stat_info(get_percent, value, prefix, easier, harder, suffix = "with this fishing rod", span_info = FALSE, less_is_better = FALSE, offset = 1) - if(value == 1) +/obj/item/fishing_rod/proc/get_stat_info(get_percent, value, prefix, easier, harder, suffix = "with this fishing rod", span_info = FALSE, less_is_better = FALSE) + if(!value) return - value -= offset var/percent = get_percent ? "[abs(value * 100)]% " : "" var/harder_easier = value > 0 ? easier : harder . = "[prefix] [percent][harder_easier] [suffix]." diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 589cdf310e6..bf297eb7052 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -558,10 +558,6 @@ if(experiment.type != paper_to_add.experiment_path) continue - experiment.completed = TRUE - var/announcetext = complete_experiment(experiment) - if(length(GLOB.experiment_handlers)) - var/datum/component/experiment_handler/handler = GLOB.experiment_handlers[1] - handler.announce_message_to_all(announcetext) + experiment.finish_experiment(linked_web_override = src) return TRUE