mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-19 12:05:59 +01:00
Fish (ya know, from fishing) is now edible (#86110)
## About The Pull Request Fish (the item that you catch with a fishing rod) now has an edible component attached to it, making it possible to eat them if you really have to, at the cost of eventually killing and deleting the fish, however, you normally shouldn't. Along with the seafood and meat foodtypes flags, it possess the gore and raw foodtypes too, making them pretty awful to eat unless you're a (non-vegan) lizard, felinid, or wearing the strange bandana*, which can only be found in the cqc kit case. Furthermore, it carry diseases like the ones from food left on the floors for too long, so a strong stomach is required to safely eat it even if you actually like it, dummy... UNLESS you fry or grill it, thus killing the diseases (as well as the fish) and removing both the gore and raw food types, then it becomes an actually ok meal... UNLESS you're dumb enough to eat a pufferfish, a donkfish or a slimefish. That is more or less the general rule. A few fish stray for it. For example, lavaloops are never raw (still gorey). The skeleton fish are never edibles, and holodeck fish is, well, holographic and thus disappears if you try to eat it. *the strange bandana is a reference to MSG, and this is a reference to the MGS3 fish eating animation. This is WIP btw, I'll have to test it and add some then polish it. ## Why It's Good For The Game Whole unprocessed fish should be technically edible, even if not safe to eat nine times out of ten. Also I kinda need this if I want to add a tasty fishing spot to the kitchen deepfriers. ## Changelog 🆑 add: Whole, unprocessed fish is now edible. However it's pretty much reccomended to grill or fry it for over 30 spess seconds before attempting to eat it. fix: germ-covered, dirty food no longer tries to infect you through contact. /🆑
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
#define COMSIG_FISH_LIFE "fish_life"
|
||||
///From /datum/fish_trait/eat_fish: (predator)
|
||||
#define COMSIG_FISH_EATEN_BY_OTHER_FISH "fish_eaten_by_other_fish"
|
||||
///From /obj/item/fish/generate_reagents_to_add, which returns a holder when the fish is eaten or composted for example: (list/reagents)
|
||||
#define COMSIG_GENERATE_REAGENTS_TO_ADD "generate_reagents_to_add"
|
||||
///From /obj/item/fish/feed: (fed_reagents, fed_reagent_type)
|
||||
#define COMSIG_FISH_FED "fish_on_fed"
|
||||
///from /obj/item/fish/pet_fish
|
||||
|
||||
@@ -141,6 +141,10 @@
|
||||
#define FISH_WEIGHT_SLOWDOWN_EXPONENT 0.54
|
||||
///Used to calculate the force of the fish by comparing (1 + log(weight/this_define)) and the w_class of the item.
|
||||
#define FISH_WEIGHT_FORCE_DIVISOR 250
|
||||
///The multiplier used in the FISH_WEIGHT_BITE_DIVISOR define
|
||||
#define FISH_WEIGHT_GRIND_TO_BITE_MULT 0.4
|
||||
///Used to calculate how many bites a fish can take and therefore the amount of reagents it has.
|
||||
#define FISH_WEIGHT_BITE_DIVISOR (FISH_GRIND_RESULTS_WEIGHT_DIVISOR * FISH_WEIGHT_GRIND_TO_BITE_MULT)
|
||||
|
||||
///The breeding timeout for newly instantiated fish is multiplied by this.
|
||||
#define NEW_FISH_BREEDING_TIMEOUT_MULT 2
|
||||
@@ -190,6 +194,9 @@
|
||||
/// The height of the minigame slider. Not in pixels, but minigame units.
|
||||
#define FISHING_MINIGAME_AREA 1000
|
||||
|
||||
///The fish needs to be cooked for at least this long so that it can be safely eaten
|
||||
#define FISH_SAFE_COOKING_DURATION 30 SECONDS
|
||||
|
||||
///Defines for fish properties from the collect_fish_properties proc
|
||||
#define FISH_PROPERTIES_FAV_BAIT "fav_bait"
|
||||
#define FISH_PROPERTIES_BAD_BAIT "bad_bait"
|
||||
|
||||
@@ -170,12 +170,21 @@ GLOBAL_LIST_INIT(food_buffs, list(
|
||||
#define FOOD_IN_CONTAINER (1<<0)
|
||||
/// Finger food can be eaten while walking / running around
|
||||
#define FOOD_FINGER_FOOD (1<<1)
|
||||
/// Examining this edible won't show infos on food types, bites and remote tasting etc.
|
||||
#define FOOD_NO_EXAMINE (1<<2)
|
||||
/// This food item doesn't track bitecounts, use responsibly.
|
||||
#define FOOD_NO_BITECOUNT (1<<3)
|
||||
|
||||
DEFINE_BITFIELD(food_flags, list(
|
||||
"FOOD_FINGER_FOOD" = FOOD_FINGER_FOOD,
|
||||
"FOOD_IN_CONTAINER" = FOOD_IN_CONTAINER,
|
||||
"FOOD_NO_EXAMINE" = FOOD_NO_EXAMINE,
|
||||
"FOOD_NO_BITECOUNT" = FOOD_NO_BITECOUNT,
|
||||
))
|
||||
|
||||
///Define for return value of the after_eat callback that will call OnConsume if it hasn't already.
|
||||
#define FOOD_AFTER_EAT_CONSUME_ANYWAY 2
|
||||
|
||||
#define STOP_SERVING_BREAKFAST (15 MINUTES)
|
||||
|
||||
#define FOOD_MEAT_HUMAN 50
|
||||
|
||||
@@ -221,6 +221,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_NO_STAGGER "no_stagger"
|
||||
/// Getting hit by thrown movables won't push you away
|
||||
#define TRAIT_NO_THROW_HITPUSH "no_throw_hitpush"
|
||||
/// This mob likes to eat fish. Raw, uncut fish.
|
||||
#define TRAIT_FISH_EATER "fish_eater"
|
||||
///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"
|
||||
///This trait gets you a list of fishes that can be caught when examining a fishing spot.
|
||||
@@ -741,6 +743,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_T_RAY_VISIBLE "t-ray-visible"
|
||||
/// If this item's been fried
|
||||
#define TRAIT_FOOD_FRIED "food_fried"
|
||||
/// If this item's been bbq grilled
|
||||
#define TRAIT_FOOD_BBQ_GRILLED "food_bbq_grilled"
|
||||
/// This is a silver slime created item
|
||||
#define TRAIT_FOOD_SILVER "food_silver"
|
||||
/// If this item's been made by a chef instead of being map-spawned or admin-spawned or such
|
||||
@@ -802,6 +806,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_HAUNTED "haunted"
|
||||
/// An item that, if it has contents, will ignore its contents when scanning for contraband.
|
||||
#define TRAIT_CONTRABAND_BLOCKER "contraband_blocker"
|
||||
/// For edible items that cannot be composted inside hydro trays
|
||||
#define TRAIT_UNCOMPOSTABLE "uncompostable"
|
||||
|
||||
//quirk traits
|
||||
#define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance"
|
||||
@@ -838,6 +844,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_THROWINGARM "throwing_arm"
|
||||
#define TRAIT_SETTLER "settler"
|
||||
#define TRAIT_STRONG_STOMACH "strong_stomach"
|
||||
#define TRAIT_VEGETARIAN "trait_vegetarian"
|
||||
|
||||
/// This mob always lands on their feet when they fall, for better or for worse.
|
||||
#define TRAIT_CATLIKE_GRACE "catlike_grace"
|
||||
@@ -962,6 +969,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_WELL_COOKED "fish_well_cooked"
|
||||
#define TRAIT_FISH_NO_HUNGER "fish_no_hunger"
|
||||
///It comes from a fish case. Relevant for bounties so far.
|
||||
#define TRAIT_FISH_FROM_CASE "fish_from_case"
|
||||
|
||||
@@ -238,6 +238,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_FEARLESS" = TRAIT_FEARLESS,
|
||||
"TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER,
|
||||
"TRAIT_FINGERPRINT_PASSTHROUGH" = TRAIT_FINGERPRINT_PASSTHROUGH,
|
||||
"TRAIT_FISH_EATER" = TRAIT_FISH_EATER,
|
||||
"TRAIT_FIST_MINING" = TRAIT_FIST_MINING,
|
||||
"TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS,
|
||||
"TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE,
|
||||
@@ -523,6 +524,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_USER_SCOPED" = TRAIT_USER_SCOPED,
|
||||
"TRAIT_USES_SKINTONES" = TRAIT_USES_SKINTONES,
|
||||
"TRAIT_VATGROWN" = TRAIT_VATGROWN,
|
||||
"TRAIT_VEGETARIAN" = TRAIT_VEGETARIAN,
|
||||
"TRAIT_VENTCRAWLER_ALWAYS" = TRAIT_VENTCRAWLER_ALWAYS,
|
||||
"TRAIT_VENTCRAWLER_NUDE" = TRAIT_VENTCRAWLER_NUDE,
|
||||
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
|
||||
@@ -557,6 +559,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_CUSTOM_TAP_SOUND" = TRAIT_CUSTOM_TAP_SOUND,
|
||||
"TRAIT_DANGEROUS_OBJECT" = TRAIT_DANGEROUS_OBJECT,
|
||||
"TRAIT_FISHING_BAIT" = TRAIT_FISHING_BAIT,
|
||||
"TRAIT_FOOD_BBQ_GRILLED" = TRAIT_FOOD_BBQ_GRILLED,
|
||||
"TRAIT_GERM_SENSITIVE" = TRAIT_GERM_SENSITIVE,
|
||||
"TRAIT_GOOD_QUALITY_BAIT" = TRAIT_GOOD_QUALITY_BAIT,
|
||||
"TRAIT_GREAT_QUALITY_BAIT" = TRAIT_GREAT_QUALITY_BAIT,
|
||||
@@ -577,6 +580,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_T_RAY_VISIBLE" = TRAIT_T_RAY_VISIBLE,
|
||||
"TRAIT_TRANSFORM_ACTIVE" = TRAIT_TRANSFORM_ACTIVE,
|
||||
"TRAIT_UNCATCHABLE" = TRAIT_UNCATCHABLE,
|
||||
"TRAIT_UNCOMPOSTABLE" = TRAIT_UNCOMPOSTABLE,
|
||||
"TRAIT_UNIQUE_AQUARIUM_CONTENT" = TRAIT_UNIQUE_AQUARIUM_CONTENT,
|
||||
"TRAIT_WIELDED" = TRAIT_WIELDED,
|
||||
),
|
||||
@@ -619,6 +623,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_FISH_STINGER" = TRAIT_FISH_STINGER,
|
||||
"TRAIT_FISH_TOXIN_IMMUNE" = TRAIT_FISH_TOXIN_IMMUNE,
|
||||
"TRAIT_RESIST_EMULSIFY" = TRAIT_RESIST_EMULSIFY,
|
||||
"TRAIT_FISH_WELL_COOKED" = TRAIT_FISH_WELL_COOKED,
|
||||
"TRAIT_YUCKY_FISH" = TRAIT_YUCKY_FISH,
|
||||
),
|
||||
/obj/item/fishing_rod = list(
|
||||
|
||||
@@ -101,6 +101,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_FAT" = TRAIT_FAT,
|
||||
"TRAIT_FEARLESS" = TRAIT_FEARLESS,
|
||||
"TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER,
|
||||
"TRAIT_FISH_EATER" = TRAIT_FISH_EATER,
|
||||
"TRAIT_FIST_MINING" = TRAIT_FIST_MINING,
|
||||
"TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS,
|
||||
"TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE,
|
||||
@@ -299,6 +300,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_UNSTABLE" = TRAIT_UNSTABLE,
|
||||
"TRAIT_USED_DNA_VAULT" = TRAIT_USED_DNA_VAULT,
|
||||
"TRAIT_USES_SKINTONES" = TRAIT_USES_SKINTONES,
|
||||
"TRAIT_VEGETARIAN" = TRAIT_VEGETARIAN,
|
||||
"TRAIT_VENTCRAWLER_ALWAYS" = TRAIT_VENTCRAWLER_ALWAYS,
|
||||
"TRAIT_VENTCRAWLER_NUDE" = TRAIT_VENTCRAWLER_NUDE,
|
||||
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
|
||||
|
||||
@@ -40,8 +40,6 @@ Behavior that's still missing from this component that original food items had t
|
||||
var/volume = 50
|
||||
///The flavortext for taste (haha get it flavor text)
|
||||
var/list/tastes
|
||||
///Whether to tell the examiner that this is edible or not.
|
||||
var/show_examine = TRUE
|
||||
|
||||
/datum/component/edible/Initialize(
|
||||
list/initial_reagents,
|
||||
@@ -57,7 +55,6 @@ Behavior that's still missing from this component that original food items had t
|
||||
datum/callback/on_consume,
|
||||
datum/callback/check_liked,
|
||||
reagent_purity = 0.5,
|
||||
show_examine = TRUE,
|
||||
)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -73,7 +70,6 @@ Behavior that's still missing from this component that original food items had t
|
||||
src.on_consume = on_consume
|
||||
src.tastes = string_assoc_list(tastes)
|
||||
src.check_liked = check_liked
|
||||
src.show_examine = show_examine
|
||||
|
||||
setup_initial_reagents(initial_reagents, reagent_purity)
|
||||
|
||||
@@ -81,9 +77,9 @@ Behavior that's still missing from this component that original food items had t
|
||||
RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(examine))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_ANIMAL, PROC_REF(UseByAnimal))
|
||||
RegisterSignal(parent, COMSIG_ATOM_CHECKPARTS, PROC_REF(OnCraft))
|
||||
RegisterSignal(parent, COMSIG_ATOM_CREATEDBY_PROCESSING, PROC_REF(OnProcessed))
|
||||
RegisterSignal(parent, COMSIG_FOOD_INGREDIENT_ADDED, PROC_REF(edible_ingredient_added))
|
||||
RegisterSignal(parent, COMSIG_OOZE_EAT_ATOM, PROC_REF(on_ooze_eat))
|
||||
RegisterSignal(parent, COMSIG_FOOD_INGREDIENT_ADDED, PROC_REF(edible_ingredient_added))
|
||||
RegisterSignal(parent, COMSIG_ATOM_CREATEDBY_PROCESSING, PROC_REF(OnProcessed))
|
||||
|
||||
if(isturf(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(on_entered))
|
||||
@@ -216,7 +212,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/atom/owner = parent
|
||||
if(!show_examine)
|
||||
if(food_flags & FOOD_NO_EXAMINE)
|
||||
return
|
||||
if(foodtypes)
|
||||
var/list/types = bitfield_to_list(foodtypes, FOOD_FLAGS)
|
||||
@@ -316,7 +312,6 @@ Behavior that's still missing from this component that original food items had t
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/atom/this_food = parent
|
||||
|
||||
for(var/obj/item/food/crafted_part in parts_list)
|
||||
if(!crafted_part.reagents)
|
||||
continue
|
||||
@@ -325,7 +320,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
|
||||
this_food.reagents.maximum_volume = ROUND_UP(this_food.reagents.maximum_volume) // Just because I like whole numbers for this.
|
||||
|
||||
BLACKBOX_LOG_FOOD_MADE(this_food.type)
|
||||
BLACKBOX_LOG_FOOD_MADE(parent.type)
|
||||
|
||||
///Makes sure the thing hasn't been destroyed or fully eaten to prevent eating phantom edibles
|
||||
/datum/component/edible/proc/IsFoodGone(atom/owner, mob/living/feeder)
|
||||
@@ -462,7 +457,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
|
||||
var/atom/owner = parent
|
||||
|
||||
if(!owner?.reagents)
|
||||
if(!owner.reagents)
|
||||
stack_trace("[eater] failed to bite [owner], because [owner] had no reagents.")
|
||||
return FALSE
|
||||
if(eater.satiety > -200)
|
||||
@@ -479,7 +474,8 @@ Behavior that's still missing from this component that original food items had t
|
||||
if(bitecount == 0)
|
||||
apply_buff(eater)
|
||||
|
||||
var/fraction = min(bite_consumption / owner.reagents.total_volume, 1)
|
||||
var/fraction = 0.3
|
||||
fraction = min(bite_consumption / owner.reagents.total_volume, 1)
|
||||
owner.reagents.trans_to(eater, bite_consumption, transferred_by = feeder, methods = INGEST)
|
||||
bitecount++
|
||||
|
||||
@@ -489,8 +485,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
On_Consume(eater, feeder)
|
||||
|
||||
//Invoke our after eat callback if it is valid
|
||||
if(after_eat)
|
||||
after_eat.Invoke(eater, feeder, bitecount)
|
||||
after_eat?.Invoke(eater, feeder, bitecount)
|
||||
|
||||
//Invoke the eater's stomach's after_eat callback if valid
|
||||
if(iscarbon(eater))
|
||||
@@ -531,7 +526,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
if(recipe_complexity <= 0)
|
||||
return
|
||||
var/obj/item/food/food = parent
|
||||
if(!isnull(food.crafted_food_buff))
|
||||
if(istype(food) && !isnull(food.crafted_food_buff))
|
||||
buff = food.crafted_food_buff
|
||||
else
|
||||
buff = pick_weight(GLOB.food_buffs[min(recipe_complexity, FOOD_COMPLEXITY_5)])
|
||||
@@ -666,7 +661,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
/datum/component/edible/proc/UseByAnimal(datum/source, mob/living/basic/pet/dog/doggy)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!isdog(doggy))
|
||||
if(!isdog(doggy) || (food_flags & FOOD_NO_BITECOUNT)) //this entirely relies on bitecounts alas
|
||||
return
|
||||
|
||||
var/atom/food = parent
|
||||
|
||||
@@ -8,43 +8,78 @@
|
||||
var/weak_infection_chance = 10
|
||||
|
||||
|
||||
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in, weak = FALSE)
|
||||
if(islist(_diseases))
|
||||
diseases = _diseases
|
||||
else
|
||||
diseases = list(_diseases)
|
||||
/datum/component/infective/Initialize(list/datum/disease/diseases, expire_in, weak = FALSE, weak_infection_chance = 10)
|
||||
if(!ismovable(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if(!islist(diseases))
|
||||
diseases = islist(diseases)
|
||||
|
||||
///Make sure the diseases list is populated with instances of diseases so that it doesn't have to be for each AddComponent call.
|
||||
for(var/datum/disease/disease as anything in diseases)
|
||||
if(!disease) //empty entry, remove.
|
||||
diseases -= disease
|
||||
if(ispath(disease, /datum/disease))
|
||||
var/datum/disease/instance = new disease
|
||||
diseases -= disease
|
||||
diseases += instance
|
||||
else if(!istype(disease))
|
||||
stack_trace("found [isdatum(disease) ? "an instance of [disease.type]" : disease] inside the diseases list argument for [type]")
|
||||
diseases -= disease
|
||||
|
||||
src.diseases = diseases
|
||||
|
||||
if(expire_in)
|
||||
expire_time = world.time + expire_in
|
||||
QDEL_IN(src, expire_in)
|
||||
|
||||
if(!ismovable(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
is_weak = weak
|
||||
src.weak_infection_chance = weak_infection_chance
|
||||
|
||||
/datum/component/infective/Destroy()
|
||||
QDEL_NULL(diseases)
|
||||
return ..()
|
||||
|
||||
/datum/component/infective/RegisterWithParent()
|
||||
if(is_weak && isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat))
|
||||
RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat))
|
||||
else
|
||||
var/static/list/disease_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(try_infect_crossed),
|
||||
)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections)
|
||||
return
|
||||
var/static/list/disease_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(try_infect_crossed),
|
||||
)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections)
|
||||
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(try_infect_buckle))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(try_infect_collide))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(try_infect_impact_zone))
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(try_infect_attack_zone))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(try_infect_attack))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(try_infect_equipped))
|
||||
RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat))
|
||||
RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat))
|
||||
if(istype(parent, /obj/item/reagent_containers/cup))
|
||||
RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink))
|
||||
if(isorgan(parent))
|
||||
RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion))
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, PROC_REF(try_infect_buckle))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, PROC_REF(try_infect_collide))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(try_infect_impact_zone))
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, PROC_REF(try_infect_attack_zone))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, PROC_REF(try_infect_attack))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(try_infect_equipped))
|
||||
RegisterSignal(parent, COMSIG_FOOD_EATEN, PROC_REF(try_infect_eat))
|
||||
RegisterSignal(parent, COMSIG_PILL_CONSUMED, PROC_REF(try_infect_eat))
|
||||
if(istype(parent, /obj/item/reagent_containers/cup))
|
||||
RegisterSignal(parent, COMSIG_GLASS_DRANK, PROC_REF(try_infect_drink))
|
||||
if(isorgan(parent))
|
||||
RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_insertion))
|
||||
|
||||
/datum/component/infective/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_FOOD_EATEN,
|
||||
COMSIG_PILL_CONSUMED,
|
||||
COMSIG_COMPONENT_CLEAN_ACT,
|
||||
COMSIG_MOVABLE_BUMP,
|
||||
COMSIG_MOVABLE_IMPACT_ZONE,
|
||||
COMSIG_ITEM_ATTACK_ZONE,
|
||||
COMSIG_ITEM_ATTACK,
|
||||
COMSIG_ITEM_EQUIPPED,
|
||||
COMSIG_GLASS_DRANK,
|
||||
COMSIG_ORGAN_IMPLANTED,
|
||||
))
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
/datum/component/infective/proc/on_organ_insertion(obj/item/organ/target, mob/living/carbon/receiver)
|
||||
SIGNAL_HANDLER
|
||||
@@ -62,16 +97,16 @@
|
||||
|
||||
eater.add_mood_event("disgust", /datum/mood_event/disgust/dirty_food)
|
||||
|
||||
if(is_weak && !prob(weak_infection_chance))
|
||||
return
|
||||
|
||||
for(var/datum/disease/disease in diseases)
|
||||
for(var/datum/disease/disease as anything in diseases)
|
||||
if(is_weak && !prob(weak_infection_chance))
|
||||
continue
|
||||
if(!disease.has_required_infectious_organ(eater, ORGAN_SLOT_STOMACH))
|
||||
continue
|
||||
|
||||
eater.ForceContractDisease(disease)
|
||||
|
||||
try_infect(feeder, BODY_ZONE_L_ARM)
|
||||
if(!is_weak)
|
||||
try_infect(feeder, BODY_ZONE_L_ARM)
|
||||
|
||||
/datum/component/infective/proc/try_infect_drink(datum/source, mob/living/drinker, mob/living/feeder)
|
||||
SIGNAL_HANDLER
|
||||
@@ -79,11 +114,14 @@
|
||||
if(HAS_TRAIT(drinker, TRAIT_STRONG_STOMACH))
|
||||
return
|
||||
|
||||
var/appendage_zone = feeder.held_items.Find(source)
|
||||
appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM
|
||||
try_infect(feeder, appendage_zone)
|
||||
if(!is_weak)
|
||||
var/appendage_zone = feeder.held_items.Find(source)
|
||||
appendage_zone = appendage_zone == 0 ? BODY_ZONE_CHEST : (appendage_zone % 2 ? BODY_ZONE_R_ARM : BODY_ZONE_L_ARM)
|
||||
try_infect(feeder, appendage_zone)
|
||||
|
||||
for(var/datum/disease/disease in diseases)
|
||||
for(var/datum/disease/disease as anything in diseases)
|
||||
if(is_weak && !prob(weak_infection_chance))
|
||||
continue
|
||||
if(!disease.has_required_infectious_organ(drinker, ORGAN_SLOT_STOMACH))
|
||||
continue
|
||||
|
||||
@@ -163,19 +201,3 @@
|
||||
/datum/component/infective/proc/try_infect(mob/living/L, target_zone)
|
||||
for(var/V in diseases)
|
||||
L.ContactContractDisease(V, target_zone)
|
||||
|
||||
/datum/component/infective/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_FOOD_EATEN,
|
||||
COMSIG_PILL_CONSUMED,
|
||||
COMSIG_COMPONENT_CLEAN_ACT,
|
||||
COMSIG_MOVABLE_BUMP,
|
||||
COMSIG_MOVABLE_IMPACT_ZONE,
|
||||
COMSIG_ITEM_ATTACK_ZONE,
|
||||
COMSIG_ITEM_ATTACK,
|
||||
COMSIG_ITEM_EQUIPPED,
|
||||
COMSIG_GLASS_DRANK,
|
||||
COMSIG_ORGAN_IMPLANTED,
|
||||
))
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
switch(stage)
|
||||
if(2)
|
||||
if(SPT_PROB(1, seconds_per_tick) && affected_mob.stat == CONSCIOUS)
|
||||
if(SPT_PROB(1, seconds_per_tick) && affected_mob.stat == CONSCIOUS && affected_mob.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL))
|
||||
to_chat(affected_mob, span_warning("You want to wag your tail..."))
|
||||
affected_mob.emote("wag")
|
||||
if(3)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
/datum/element/consumable_mob/proc/on_consume(atom/movable/source, mob/living/consumer)
|
||||
SIGNAL_HANDLER
|
||||
if(!consumer.combat_mode || !consumer.reagents)
|
||||
if(!consumer.combat_mode || !consumer.reagents || HAS_TRAIT(consumer, TRAIT_PACIFISM))
|
||||
return
|
||||
for(var/reagent_type in reagents_list)
|
||||
if(isnull(reagents_list[reagent_type]))
|
||||
|
||||
@@ -17,28 +17,27 @@
|
||||
var/atom/this_food = target
|
||||
|
||||
switch(fry_time)
|
||||
if(0 to 15)
|
||||
if(0 to 15 SECONDS)
|
||||
this_food.add_atom_colour(fried_colors[1], FIXED_COLOUR_PRIORITY)
|
||||
this_food.name = "lightly-fried [this_food.name]"
|
||||
this_food.desc += " It's been lightly fried in a deep fryer."
|
||||
|
||||
if(15 to 50)
|
||||
if(15 SECONDS to 50 SECONDS)
|
||||
this_food.add_atom_colour(fried_colors[2], FIXED_COLOUR_PRIORITY)
|
||||
this_food.name = "fried [this_food.name]"
|
||||
this_food.desc += " It's been fried, increasing its tastiness value by [rand(1, 75)]%."
|
||||
|
||||
if(50 to 85)
|
||||
if(50 SECONDS to 85 SECONDS)
|
||||
this_food.add_atom_colour(fried_colors[3], FIXED_COLOUR_PRIORITY)
|
||||
this_food.name = "deep-fried [this_food.name]"
|
||||
this_food.desc += " Deep-fried to perfection."
|
||||
|
||||
if(85 to INFINITY)
|
||||
if(85 SECONDS to INFINITY)
|
||||
this_food.add_atom_colour(fried_colors[4], FIXED_COLOUR_PRIORITY)
|
||||
this_food.name = "\proper the physical manifestation of the very concept of fried foods"
|
||||
this_food.desc = "A heavily-fried... something. Who can tell anymore?"
|
||||
|
||||
ADD_TRAIT(this_food, TRAIT_FOOD_FRIED, ELEMENT_TRAIT(type))
|
||||
SEND_SIGNAL(this_food, COMSIG_ITEM_FRIED, fry_time)
|
||||
// Already edible items will inherent these parameters
|
||||
// Otherwise, we will become edible.
|
||||
this_food.AddComponent( \
|
||||
@@ -49,6 +48,7 @@
|
||||
foodtypes = FRIED, \
|
||||
volume = this_food.reagents?.maximum_volume, \
|
||||
)
|
||||
SEND_SIGNAL(this_food, COMSIG_ITEM_FRIED, fry_time)
|
||||
|
||||
/datum/element/fried_item/Detach(atom/source, ...)
|
||||
for(var/color in fried_colors)
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
if(grill_time > 30 SECONDS && isnull(this_food.GetComponent(/datum/component/edible)))
|
||||
this_food.AddComponent(/datum/component/edible, foodtypes = FRIED)
|
||||
|
||||
SEND_SIGNAL(this_food, COMSIG_ITEM_BARBEQUE_GRILLED)
|
||||
SEND_SIGNAL(this_food, COMSIG_ITEM_BARBEQUE_GRILLED, grill_time)
|
||||
ADD_TRAIT(this_food, TRAIT_FOOD_BBQ_GRILLED, ELEMENT_TRAIT(type))
|
||||
|
||||
/datum/element/grilled_item/Detach(atom/source, ...)
|
||||
source.name = initial(source.name)
|
||||
source.desc = initial(source.desc)
|
||||
qdel(source.GetComponent(/datum/component/edible)) // Don't care if it was initially edible
|
||||
REMOVE_TRAIT(src, TRAIT_FOOD_BBQ_GRILLED, ELEMENT_TRAIT(type))
|
||||
return ..()
|
||||
|
||||
@@ -49,3 +49,8 @@
|
||||
|
||||
/datum/mood_event/food/top
|
||||
quality = FOOD_QUALITY_TOP
|
||||
|
||||
/datum/mood_event/pacifist_eating_fish_item
|
||||
description = "I shouldn't be eating living creatures..."
|
||||
mood_change = -1 //The disgusting food moodlet already has a pretty big negative value, this is just for context.
|
||||
timeout = 4 MINUTES
|
||||
|
||||
@@ -7,17 +7,4 @@
|
||||
lose_text = span_notice("You feel like eating meat isn't that bad.")
|
||||
medical_record_text = "Patient reports a vegetarian diet."
|
||||
mail_goodies = list(/obj/effect/spawner/random/food_or_drink/salad)
|
||||
|
||||
/datum/quirk/vegetarian/add(client/client_source)
|
||||
var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
if(!tongue)
|
||||
return
|
||||
tongue.liked_foodtypes &= ~MEAT
|
||||
tongue.disliked_foodtypes |= MEAT
|
||||
|
||||
/datum/quirk/vegetarian/remove()
|
||||
var/obj/item/organ/internal/tongue/tongue = quirk_holder.get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
if(!tongue)
|
||||
return
|
||||
tongue.liked_foodtypes = initial(tongue.liked_foodtypes)
|
||||
tongue.disliked_foodtypes = initial(tongue.disliked_foodtypes)
|
||||
mob_trait = TRAIT_VEGETARIAN
|
||||
|
||||
@@ -690,10 +690,10 @@
|
||||
created_atoms.Add(created_atom)
|
||||
to_chat(user, span_notice("You manage to create [amount_to_create] [initial(atom_to_create.gender) == PLURAL ? "[initial(atom_to_create.name)]" : "[initial(atom_to_create.name)][plural_s(initial(atom_to_create.name))]"] from [src]."))
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_PROCESSED, user, process_item, created_atoms)
|
||||
UsedforProcessing(user, process_item, chosen_option)
|
||||
UsedforProcessing(user, process_item, chosen_option, created_atoms)
|
||||
return
|
||||
|
||||
/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option)
|
||||
/atom/proc/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option, list/created_atoms)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
// "It is called a cigarette"
|
||||
AddComponent(/datum/component/edible,\
|
||||
initial_reagents = list_reagents,\
|
||||
food_flags = null,\
|
||||
food_flags = FOOD_NO_EXAMINE,\
|
||||
foodtypes = JUNKFOOD,\
|
||||
volume = 50,\
|
||||
eat_time = 0 SECONDS,\
|
||||
@@ -208,7 +208,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
junkiness = 0,\
|
||||
reagent_purity = null,\
|
||||
on_consume = CALLBACK(src, PROC_REF(on_consume)),\
|
||||
show_examine = FALSE, \
|
||||
)
|
||||
|
||||
/obj/item/cigarette/Destroy()
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
food_reagents = list(
|
||||
/datum/reagent/consumable/nutriment/protein = 4,
|
||||
/datum/reagent/consumable/nutriment/vitamin = 3,
|
||||
/datum/reagent/consumable/nutriment/fat/oil = 2,
|
||||
/datum/reagent/consumable/nutriment/fat = 2,
|
||||
)
|
||||
bite_consumption = 4.5
|
||||
crafting_complexity = FOOD_COMPLEXITY_1
|
||||
@@ -99,14 +99,20 @@
|
||||
|
||||
/obj/item/food/fishmeat/gunner_jellyfish
|
||||
name = "filleted gunner jellyfish"
|
||||
desc = "A gunner jellyfish with the stingers removed. Mildly hallucinogenic."
|
||||
desc = "A gunner jellyfish with the stingers removed. Mildly hallucinogenic when raw."
|
||||
icon = 'icons/obj/food/lizard.dmi'
|
||||
icon_state = "jellyfish_fillet"
|
||||
food_reagents = list(
|
||||
/datum/reagent/consumable/nutriment/protein = 4,
|
||||
/datum/reagent/toxin/mindbreaker = 2,
|
||||
/datum/reagent/consumable/nutriment/protein = 4, //The halluginogen comes from the fish trait.
|
||||
)
|
||||
|
||||
///Premade gunner jellyfish fillets from supply orders. Contains the halluginogen that'd be normally from the fish trait.
|
||||
/obj/item/food/fishmeat/gunner_jellyfish/supply
|
||||
|
||||
/obj/item/food/fishmeat/gunner_jellyfish/supply/Initialize(mapload)
|
||||
food_reagents[/datum/reagent/toxin/mindbreaker/fish] = 2
|
||||
return ..()
|
||||
|
||||
/obj/item/food/fishmeat/armorfish
|
||||
name = "cleaned armorfish"
|
||||
desc = "An armorfish with its guts and shell removed, ready for use in cooking."
|
||||
|
||||
@@ -301,7 +301,7 @@
|
||||
new /obj/item/food/fishmeat/armorfish(src)
|
||||
new /obj/item/food/fishmeat/carp(src)
|
||||
new /obj/item/food/fishmeat/moonfish(src)
|
||||
new /obj/item/food/fishmeat/gunner_jellyfish(src)
|
||||
new /obj/item/food/fishmeat/gunner_jellyfish/supply(src)
|
||||
|
||||
/obj/item/storage/box/ingredients/salads
|
||||
theme_name = "salads"
|
||||
|
||||
@@ -410,6 +410,7 @@
|
||||
desc = "A bandana. It seems to have a little carp embroidered on the inside, as well as the kanji '魚'."
|
||||
icon_state = "snake_eater"
|
||||
inhand_icon_state = null
|
||||
clothing_traits = list(TRAIT_FISH_EATER)
|
||||
|
||||
/obj/item/clothing/head/costume/knight
|
||||
name = "fake medieval helmet"
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
drop_sound = 'sound/creatures/fish/fish_drop1.ogg'
|
||||
pickup_sound = SFX_FISH_PICKUP
|
||||
sound_vary = TRUE
|
||||
///The grind results of the fish. They scale with the weight of the fish.
|
||||
grind_results = list(/datum/reagent/blood = 5, /datum/reagent/consumable/liquidgibs = 5)
|
||||
obj_flags = UNIQUE_RENAME
|
||||
item_flags = IMMUTABLE_SLOW|SLOWS_WHILE_IN_HAND
|
||||
|
||||
@@ -150,6 +148,14 @@
|
||||
///have we recently pet this fish
|
||||
var/recently_petted = FALSE
|
||||
|
||||
/**
|
||||
* If you wonder why this isn't being tracked by the edible component instead:
|
||||
* We reset the this value when revived, and slowly chip it away as we heal.
|
||||
* Of course, it would be daunting to get this to be handled by the edible component
|
||||
* given its complexity.
|
||||
*/
|
||||
var/bites_amount = 0
|
||||
|
||||
/obj/item/fish/Initialize(mapload, apply_qualities = TRUE)
|
||||
. = ..()
|
||||
//It's important that we register the signals before the component is attached.
|
||||
@@ -163,6 +169,7 @@
|
||||
RegisterSignal(src, COMSIG_ATOM_TEMPORARY_ANIMATION_START, PROC_REF(on_temp_animation))
|
||||
check_environment()
|
||||
if(status != FISH_DEAD)
|
||||
ADD_TRAIT(src, TRAIT_UNCOMPOSTABLE, REF(src)) //Composting a food that is not real food wouldn't work anyway.
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
//stops new fish from being able to reproduce right away.
|
||||
@@ -175,6 +182,174 @@
|
||||
|
||||
register_evolutions()
|
||||
|
||||
///Main proc that makes the fish edible.
|
||||
/obj/item/fish/proc/make_edible()
|
||||
var/foodtypes = get_food_types()
|
||||
if(foodtypes & RAW)
|
||||
AddComponent(/datum/component/infective, GLOB.floor_diseases.Copy(), weak = TRUE, weak_infection_chance = PERFORM_ALL_TESTS(edible_fish) ? 100 : 15)
|
||||
else
|
||||
AddComponent(/datum/component/germ_sensitive)
|
||||
var/bites_to_finish = weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
create_reagents(INFINITY) //We'll set this to the total volume of the reagents right after generate_fish_reagents() is over
|
||||
generate_fish_reagents(bites_to_finish)
|
||||
reagents.maximum_volume = round(reagents.total_volume * 1.25) //make some meager space for condiments.
|
||||
AddComponent(/datum/component/edible, \
|
||||
food_flags = FOOD_NO_EXAMINE|FOOD_NO_BITECOUNT, \
|
||||
foodtypes = foodtypes, \
|
||||
volume = reagents.total_volume, \
|
||||
eat_time = 1.5 SECONDS, \
|
||||
bite_consumption = reagents.total_volume / bites_to_finish, \
|
||||
after_eat = CALLBACK(src, PROC_REF(after_eat)), \
|
||||
check_liked = CALLBACK(src, PROC_REF(check_liked)), \
|
||||
reagent_purity = 1, \
|
||||
)
|
||||
RegisterSignals(src, list(COMSIG_ITEM_FRIED, COMSIG_ITEM_BARBEQUE_GRILLED), PROC_REF(on_fish_cooked))
|
||||
|
||||
///A proc that returns the food types the edible component has when initialized.
|
||||
/obj/item/fish/proc/get_food_types()
|
||||
return SEAFOOD|MEAT|RAW|GORE
|
||||
|
||||
///Kill the fish, remove the raw and gore food types, and the infectiveness too if not under-cooked.
|
||||
/obj/item/fish/proc/on_fish_cooked(datum/source, cooking_time)
|
||||
SIGNAL_HANDLER
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
adjust_health(0)
|
||||
|
||||
//Remove the blood from the reagents holder and reward the player with some extra nutriment added to the fish.
|
||||
var/datum/reagent/consumable/nutriment/protein/protein = reagents.has_reagent(/datum/reagent/consumable/nutriment/protein, check_subtypes = TRUE)
|
||||
var/datum/reagent/blood/blood = reagents.has_reagent(/datum/reagent/blood)
|
||||
var/old_blood_volume = blood?.volume
|
||||
reagents.del_reagent(/datum/reagent/blood)
|
||||
|
||||
///Make space for the additional nutriment
|
||||
var/volume_mult = 1
|
||||
if(bites_amount)
|
||||
var/initial_bites_left = weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
var/bites_left = initial_bites_left - bites_amount
|
||||
volume_mult = initial_bites_left / bites_left
|
||||
adjust_reagents_capacity((protein?.volume - old_blood_volume) * volume_mult)
|
||||
|
||||
///Add the extra nutriment
|
||||
if(protein)
|
||||
reagents.multiply_single_reagent(/datum/reagent/consumable/nutriment/protein, 2)
|
||||
|
||||
var/datum/component/edible/edible = GetComponent(/datum/component/edible)
|
||||
edible.foodtypes &= ~(RAW|GORE)
|
||||
if(cooking_time >= FISH_SAFE_COOKING_DURATION)
|
||||
well_cooked()
|
||||
|
||||
///override the signals so they don't mess with blood and proteins again.
|
||||
RegisterSignals(src, list(COMSIG_ITEM_FRIED, COMSIG_ITEM_BARBEQUE_GRILLED), PROC_REF(on_fish_cooked_again), TRUE)
|
||||
|
||||
///Just kill the fish, again, and perhaps remove the infective comp.
|
||||
/obj/item/fish/proc/on_fish_cooked_again(datum/source, cooking_time)
|
||||
SIGNAL_HANDLER
|
||||
adjust_health(0)
|
||||
if(cooking_time >= FISH_SAFE_COOKING_DURATION)
|
||||
well_cooked()
|
||||
|
||||
///The fish is well cooked. Change how the fish tastes, remove the infective comp and add the relative trait.
|
||||
/obj/item/fish/proc/well_cooked()
|
||||
qdel(GetComponent(/datum/component/infective))
|
||||
AddComponent(/datum/component/germ_sensitive)
|
||||
ADD_TRAIT(src, TRAIT_FISH_WELL_COOKED, INNATE_TRAIT)
|
||||
var/datum/reagent/consumable/nutriment/protein/protein = reagents.has_reagent(/datum/reagent/consumable/nutriment/protein, check_subtypes = TRUE)
|
||||
if(protein)
|
||||
protein.data = get_fish_taste_cooked()
|
||||
|
||||
///Checks if the fish is liked or not when eaten by a human.
|
||||
/obj/item/fish/proc/check_liked(mob/living/eater)
|
||||
if(HAS_TRAIT(eater, TRAIT_PACIFISM) && (status == FISH_ALIVE ||HAS_MIND_TRAIT(eater, TRAIT_NAIVE)))
|
||||
eater.add_mood_event("eating_fish", /datum/mood_event/pacifist_eating_fish_item)
|
||||
return FOOD_TOXIC
|
||||
if(HAS_TRAIT(eater, TRAIT_AGEUSIA))
|
||||
return
|
||||
if(HAS_TRAIT(eater, TRAIT_FISH_EATER) && !HAS_TRAIT(eater, TRAIT_VEGETARIAN))
|
||||
return FOOD_LIKED
|
||||
|
||||
/**
|
||||
* Fish is not a reagent holder yet it's edible, so it doen't behave like most other snacks
|
||||
* which means it has its own way of handling being bitten, which is defined here.
|
||||
*/
|
||||
/obj/item/fish/proc/after_eat(mob/living/eater, mob/living/feeder)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(!reagents.total_volume)
|
||||
return
|
||||
bites_amount++
|
||||
var/bites_to_finish = weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
adjust_health(health - (initial(health) / bites_to_finish) * 3)
|
||||
if(status == FISH_ALIVE && prob(50) && feeder.is_holding(src) && feeder.dropItemToGround(src))
|
||||
to_chat(feeder, span_warning("[src] slips out of your hands in pain!"))
|
||||
var/turf/target_turf = get_ranged_target_turf(get_turf(src), pick(GLOB.alldirs), 2)
|
||||
throw_at(target_turf)
|
||||
|
||||
///A proc that returns a static reagent holder with a set reagents that you'd get when eating this fish.
|
||||
/obj/item/fish/proc/generate_fish_reagents(multiplier = 1)
|
||||
SHOULD_NOT_OVERRIDE(TRUE)
|
||||
var/list/reagents_to_add = get_base_edible_reagents_to_add()
|
||||
SEND_SIGNAL(src, COMSIG_GENERATE_REAGENTS_TO_ADD, reagents_to_add)
|
||||
if(multiplier != 1)
|
||||
for(var/reagent in reagents_to_add)
|
||||
reagents_to_add[reagent] *= multiplier
|
||||
reagents.add_reagent_list(reagents_to_add, added_purity = 1)
|
||||
var/datum/reagent/consumable/nutriment/protein/protein = reagents.has_reagent(/datum/reagent/consumable/nutriment/protein, check_subtypes = TRUE)
|
||||
if(protein)
|
||||
protein.data = HAS_TRAIT(src, TRAIT_FISH_WELL_COOKED) ? get_fish_taste_cooked() : get_fish_taste()
|
||||
|
||||
/obj/item/fish/proc/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "scales" = 1)
|
||||
|
||||
/obj/item/fish/proc/get_fish_taste_cooked()
|
||||
return list("cooked fish" = 2)
|
||||
|
||||
///The proc that adds in the main reagents this fish has when eaten (without accounting for traits)
|
||||
/obj/item/fish/proc/get_base_edible_reagents_to_add()
|
||||
var/return_list = list(
|
||||
/datum/reagent/consumable/nutriment/protein = 2,
|
||||
/datum/reagent/blood = 1,
|
||||
)
|
||||
//It has been at the very least under-cooked.
|
||||
if(HAS_TRAIT(src, TRAIT_FOOD_FRIED) || HAS_TRAIT(src, TRAIT_FOOD_BBQ_GRILLED))
|
||||
return_list[/datum/reagent/consumable/nutriment/protein] *= 2
|
||||
return_list -= /datum/reagent/blood
|
||||
if(required_fluid_type == AQUARIUM_FLUID_SALTWATER)
|
||||
return_list[/datum/reagent/consumable/salt] = 0.4
|
||||
return return_list
|
||||
|
||||
///adjusts the maximum volume of the fish reagents holder and update the amount of food to bite
|
||||
/obj/item/fish/proc/adjust_reagents_capacity(amount_to_add)
|
||||
if(!reagents)
|
||||
return
|
||||
reagents.maximum_volume += amount_to_add
|
||||
var/bites_to_finish = weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
///updates how many units of reagent one bite takes if edible.
|
||||
if(IS_EDIBLE(src))
|
||||
AddComponent(/datum/component/edible, bite_consumption = reagents.maximum_volume / bites_to_finish)
|
||||
|
||||
///Grinding a fish replaces some the protein it has with blood and gibs. You ain't getting a clean smoothie out of it.
|
||||
/obj/item/fish/on_grind()
|
||||
. = ..()
|
||||
if(!reagents)
|
||||
return
|
||||
reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/consumable/liquidgibs, 0.4, include_source_subtypes = TRUE)
|
||||
reagents.convert_reagent(/datum/reagent/consumable/nutriment/protein, /datum/reagent/blood, 0.2, include_source_subtypes = TRUE)
|
||||
|
||||
///When processed, the reagents inside this fish will be passed to the created atoms.
|
||||
/obj/item/fish/UsedforProcessing(mob/living/user, obj/item/used_item, list/chosen_option, list/created_atoms)
|
||||
var/created_len = length(created_atoms)
|
||||
for(var/atom/movable/created as anything in created_atoms)
|
||||
if(!created.reagents)
|
||||
continue
|
||||
for(var/datum/reagent/reagent as anything in reagents.reagent_list)
|
||||
var/transfer_vol = reagent.volume / created_len
|
||||
var/datum/reagent/result_reagent = created.reagents.has_reagent(reagent.type)
|
||||
if(!result_reagent)
|
||||
created.reagents.add_reagent(reagent.type, transfer_vol, reagents.copy_data(reagent), reagents.chem_temp, reagent.purity, reagent.ph, no_react = TRUE)
|
||||
continue
|
||||
var/multiplier = transfer_vol / result_reagent.volume
|
||||
created.reagents.multiply_single_reagent(reagent.type, multiplier)
|
||||
return ..()
|
||||
|
||||
/obj/item/fish/update_icon_state()
|
||||
if(status == FISH_DEAD && icon_state_dead)
|
||||
icon_state = icon_state_dead
|
||||
@@ -214,6 +389,8 @@
|
||||
. += span_notice("It weighs [weight] g.")
|
||||
if(HAS_TRAIT(src, TRAIT_FISHING_BAIT))
|
||||
. += span_smallnoticeital("It can be used as a fishing bait.")
|
||||
if(bites_amount)
|
||||
. += span_warning("It's been bitten by someone.")
|
||||
|
||||
///Randomizes weight and size.
|
||||
/obj/item/fish/proc/randomize_size_and_weight(base_size = average_size, base_weight = average_weight, deviation = weight_size_deviation)
|
||||
@@ -272,11 +449,32 @@
|
||||
num_fillets = amount
|
||||
AddElement(/datum/element/processable, TOOL_KNIFE, fillet_type, num_fillets, 0.5 SECONDS * num_fillets, screentip_verb = "Cut")
|
||||
|
||||
var/make_edible = TRUE
|
||||
if(weight)
|
||||
for(var/reagent_type in grind_results)
|
||||
grind_results[reagent_type] /= FLOOR(weight/FISH_GRIND_RESULTS_WEIGHT_DIVISOR, 0.1)
|
||||
if(reagents) //This fish has reagents. Adjust the maximum volume of the reagent holder and do some math to adjut the reagents too.
|
||||
var/new_weight_ratio = new_weight / weight
|
||||
var/volume_diff = reagents.maximum_volume * new_weight_ratio - reagents.maximum_volume
|
||||
if(new_weight_ratio > weight)
|
||||
adjust_reagents_capacity(volume_diff)
|
||||
///As always, we want to maintain proportions here, so we need to get the ratio of bites left and initial bites left.
|
||||
var/weight_diff = new_weight - weight
|
||||
var/multiplier = weight_diff / FISH_WEIGHT_BITE_DIVISOR
|
||||
var/initial_bites_left = weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
var/bites_left = initial_bites_left - bites_amount
|
||||
var/amount_to_gen = bites_left / initial_bites_left * multiplier
|
||||
generate_fish_reagents(amount_to_gen)
|
||||
else
|
||||
reagents.multiply_reagents(new_weight_ratio)
|
||||
adjust_reagents_capacity(volume_diff)
|
||||
make_edible = FALSE
|
||||
|
||||
weight = new_weight
|
||||
|
||||
if(make_edible)
|
||||
make_edible()
|
||||
|
||||
if(weight >= FISH_WEIGHT_SLOWDOWN)
|
||||
slowdown = round(((weight/FISH_WEIGHT_SLOWDOWN_DIVISOR)**FISH_WEIGHT_SLOWDOWN_EXPONENT)-1.3, 0.1)
|
||||
drag_slowdown = round(slowdown * 0.5, 1)
|
||||
@@ -492,12 +690,15 @@
|
||||
if(FISH_ALIVE)
|
||||
status = FISH_ALIVE
|
||||
health = initial(health) // since the fishe has been revived
|
||||
regenerate_bites(bites_amount)
|
||||
last_feeding = world.time //reset hunger
|
||||
check_environment()
|
||||
START_PROCESSING(SSobj, src)
|
||||
ADD_TRAIT(src, TRAIT_UNCOMPOSTABLE, INNATE_TRAIT)
|
||||
if(FISH_DEAD)
|
||||
status = FISH_DEAD
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
REMOVE_TRAIT(src, TRAIT_UNCOMPOSTABLE, INNATE_TRAIT)
|
||||
stop_flopping()
|
||||
if(!silent)
|
||||
var/message = span_notice(replacetext(death_text, "%SRC", "[src]"))
|
||||
@@ -652,10 +853,28 @@
|
||||
health_change_per_second += 0.5 //Slowly healing
|
||||
adjust_health(health + health_change_per_second * seconds_per_tick)
|
||||
|
||||
/obj/item/fish/proc/adjust_health(amt)
|
||||
health = clamp(amt, 0, initial(health))
|
||||
/obj/item/fish/proc/adjust_health(amount)
|
||||
if(status == FISH_DEAD || amount == health)
|
||||
return
|
||||
var/pre_health = health
|
||||
var/initial_health = initial(health)
|
||||
health = clamp(amount, 0, initial_health)
|
||||
if(health <= 0)
|
||||
set_status(FISH_DEAD)
|
||||
return
|
||||
if(amount < pre_health || !bites_amount)
|
||||
return
|
||||
var/health_to_pre_health_diff = amount - pre_health
|
||||
var/init_health_to_pre_diff = initial_health - pre_health
|
||||
var/bites_to_recover = bites_amount * (health_to_pre_health_diff / init_health_to_pre_diff)
|
||||
regenerate_bites(bites_to_recover)
|
||||
|
||||
/obj/item/fish/proc/regenerate_bites(amount)
|
||||
amount = min(amount, bites_amount)
|
||||
if(amount <= 0)
|
||||
return
|
||||
bites_amount -= amount
|
||||
generate_fish_reagents(amount)
|
||||
|
||||
/obj/item/fish/proc/ready_to_reproduce(being_targeted = FALSE)
|
||||
var/obj/structure/aquarium/aquarium = loc
|
||||
@@ -845,6 +1064,7 @@
|
||||
if(HAS_TRAIT(src, TRAIT_FISH_FROM_CASE)) //Avoid printing money by simply ordering fish and sending it back.
|
||||
calculated_price *= 0.05
|
||||
return round(calculated_price)
|
||||
|
||||
/obj/item/fish/proc/get_happiness_value()
|
||||
var/happiness_value = 0
|
||||
if(recently_petted)
|
||||
@@ -858,7 +1078,11 @@
|
||||
happiness_value++
|
||||
if(ISINRANGE(aquarium.fluid_temp, required_temperature_min, required_temperature_max))
|
||||
happiness_value++
|
||||
return happiness_value
|
||||
if(bites_amount) // ouch
|
||||
happiness_value -= 2
|
||||
if(health < initial(health) * 0.6)
|
||||
happiness_value -= 1
|
||||
return clamp(happiness_value, FISH_SAD, FISH_VERY_HAPPY)
|
||||
|
||||
/obj/item/fish/proc/pet_fish(mob/living/user)
|
||||
if(recently_petted)
|
||||
|
||||
@@ -37,7 +37,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
var/list/fish_whitelist
|
||||
/// Depending on the value, fish with trait will be reported as more or less difficult in the catalog.
|
||||
var/added_difficulty = 0
|
||||
/// Reagents added to the fish when gained
|
||||
/// Reagents to add to the fish whenever the COMSIG_GENERATE_REAGENTS_TO_ADD signal is sent. Their values will be multiplied later.
|
||||
var/list/reagents_to_add
|
||||
|
||||
/// Difficulty modifier from this mod, needs to return a list with two values
|
||||
@@ -57,10 +57,8 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
/// Applies some special qualities to the fish that has been spawned
|
||||
/datum/fish_trait/proc/apply_to_fish(obj/item/fish/fish)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(reagents_to_add)
|
||||
for(var/reagent in reagents_to_add)
|
||||
add_to_reagents(fish, reagent, reagents_to_add[reagent])
|
||||
RegisterSignal(fish, COMSIG_ATOM_PROCESSED, PROC_REF(process_reagents))
|
||||
if(length(reagents_to_add))
|
||||
RegisterSignal(fish, COMSIG_GENERATE_REAGENTS_TO_ADD, PROC_REF(add_reagents))
|
||||
|
||||
/// Applies some special qualities to basic mobs generated by fish (i.e. chasm chrab --> young lobstrosity --> lobstrosity).
|
||||
/datum/fish_trait/proc/apply_to_mob(mob/living/basic/mob)
|
||||
@@ -79,25 +77,15 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
SEND_SIGNAL(prey, COMSIG_FISH_EATEN_BY_OTHER_FISH, predator)
|
||||
qdel(prey)
|
||||
|
||||
/// Proc that inserts a reagent to the grind_results list of the fish. You'll still have to set the processed comsig proc yourself.
|
||||
/datum/fish_trait/proc/add_to_reagents(obj/item/fish/fish, reagent_type, amount)
|
||||
LAZYINITLIST(fish.grind_results)
|
||||
fish.grind_results.Insert(1, reagent_type)
|
||||
fish.grind_results[reagent_type] = amount
|
||||
|
||||
/// Proc that handles adding reagents from the trait to the fillets from butchered fish.
|
||||
/datum/fish_trait/proc/process_reagents(obj/item/fish/source, mob/living/user, obj/item/process_item, list/results)
|
||||
/**
|
||||
* Signal sent when we need to generate an abstract holder containing
|
||||
* reagents to be transfered, usually as a result of the fish being eaten by someone
|
||||
*/
|
||||
/datum/fish_trait/proc/add_reagents(obj/item/fish/fish, list/reagents)
|
||||
SIGNAL_HANDLER
|
||||
var/results_with_reagents = 0
|
||||
for(var/atom/result as anything in results)
|
||||
if(result.reagents)
|
||||
results_with_reagents++
|
||||
if(!results_with_reagents)
|
||||
return
|
||||
for(var/reagent in reagents_to_add)
|
||||
var/amount = round(source.grind_results[reagent] / results_with_reagents, 0.1)
|
||||
for(var/atom/result as anything in results)
|
||||
result.reagents?.add_reagent(reagent, amount)
|
||||
reagents[reagent] += reagents_to_add[reagent]
|
||||
|
||||
/// Proc that adds or changes the venomous when the fish size and/or weight are updated
|
||||
/datum/fish_trait/proc/add_venom(obj/item/fish/source, venom_path, new_weight, mult = 0.25)
|
||||
@@ -413,7 +401,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
/datum/fish_trait/yucky
|
||||
name = "Yucky"
|
||||
catalog_description = "This fish tastes so repulsive, other fishes won't try to eat it."
|
||||
reagents_to_add = list(/datum/reagent/yuck = 3)
|
||||
reagents_to_add = list(/datum/reagent/yuck = 1.2)
|
||||
|
||||
/datum/fish_trait/yucky/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
@@ -423,7 +411,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
name = "Toxic"
|
||||
catalog_description = "This fish contains toxins. Feeding it to predatory fishes or people is not recommended."
|
||||
diff_traits_inheritability = 25
|
||||
reagents_to_add = list(/datum/reagent/toxin/tetrodotoxin = 2.5)
|
||||
reagents_to_add = list(/datum/reagent/toxin/tetrodotoxin = 1)
|
||||
|
||||
/datum/fish_trait/toxic/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
@@ -512,6 +500,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
spontaneous_manifest_types = list(/obj/item/fish/clownfish/lube = 100)
|
||||
catalog_description = "This fish exudes a viscous, slippery lubrificant. It's recommended not to step on it."
|
||||
added_difficulty = 5
|
||||
reagents_to_add = list(/datum/reagent/lube = 1.2)
|
||||
|
||||
/datum/fish_trait/lubed/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
@@ -597,11 +586,30 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
inheritability = 60
|
||||
diff_traits_inheritability = 30
|
||||
catalog_description = "This fish is electroreceptive, and will generate electric fields. Can be harnessed inside a bioelectric generator."
|
||||
reagents_to_add = list(/datum/reagent/consumable/liquidelectricity = 1.5)
|
||||
|
||||
/datum/fish_trait/electrogenesis/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
ADD_TRAIT(fish, TRAIT_FISH_ELECTROGENESIS, FISH_TRAIT_DATUM)
|
||||
RegisterSignal(fish, COMSIG_FISH_FORCE_UPDATED, PROC_REF(on_force_updated))
|
||||
RegisterSignals(fish, list(COMSIG_ITEM_FRIED, TRAIT_FOOD_BBQ_GRILLED), PROC_REF(on_fish_cooked))
|
||||
|
||||
/datum/fish_trait/electrogenesis/proc/on_fish_cooked(obj/item/fish/fish, cooked_time)
|
||||
SIGNAL_HANDLER
|
||||
if(cooked_time >= FISH_SAFE_COOKING_DURATION)
|
||||
fish.reagents.del_reagent(/datum/reagent/consumable/liquidelectricity)
|
||||
else
|
||||
fish.reagents.multiply_single_reagent(/datum/reagent/consumable/liquidelectricity, 0.66)
|
||||
|
||||
/datum/fish_trait/electrogenesis/add_reagents(obj/item/fish/fish, list/reagents)
|
||||
. = ..()
|
||||
if(HAS_TRAIT(fish, TRAIT_FISH_WELL_COOKED)) // Cooking it well removes all liquid electricity
|
||||
reagents -= /datum/reagent/consumable/liquidelectricity
|
||||
else
|
||||
reagents -= /datum/reagent/blood
|
||||
//Otherwise, undercooking it will remove 2/3 of it.
|
||||
if(!HAS_TRAIT(fish, TRAIT_FOOD_FRIED) && !HAS_TRAIT(fish, TRAIT_FOOD_BBQ_GRILLED))
|
||||
reagents[/datum/reagent/consumable/liquidelectricity] -= 1
|
||||
|
||||
/datum/fish_trait/electrogenesis/proc/on_force_updated(obj/item/fish/fish, weight_rank, bonus_or_malus)
|
||||
SIGNAL_HANDLER
|
||||
@@ -670,6 +678,15 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
return
|
||||
change_venom_on_death(source, /datum/reagent/toxin/venom, 0.7, 0.3)
|
||||
|
||||
/datum/fish_trait/hallucinogenic
|
||||
name = "Hallucinogenic"
|
||||
catalog_description = "This fish is coated with hallucinogenic neurotoxin. We advise cooking it before consumption."
|
||||
reagents_to_add = list(/datum/reagent/toxin/mindbreaker/fish = 1)
|
||||
|
||||
/datum/fish_trait/hallucinogenic/add_reagents(obj/item/fish/fish, list/reagents)
|
||||
if(!HAS_TRAIT(src, TRAIT_FOOD_FRIED) && !HAS_TRAIT(src, TRAIT_FOOD_BBQ_GRILLED))
|
||||
return ..()
|
||||
|
||||
/datum/fish_trait/ink
|
||||
name = "Ink Production"
|
||||
catalog_description = "This fish possess a sac that produces ink."
|
||||
|
||||
@@ -40,6 +40,12 @@
|
||||
),
|
||||
)
|
||||
|
||||
/obj/item/fish/sand_crab/get_fish_taste()
|
||||
return list("raw crab" = 2)
|
||||
|
||||
/obj/item/fish/sand_crab/get_fish_taste_cooked()
|
||||
return list("cooked crab" = 2)
|
||||
|
||||
/obj/item/fish/bumpy
|
||||
name = "bump-fish"
|
||||
desc = "An misshapen fish-thing all covered in stubby little tendrils"
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
fillet_type = /obj/item/food/fishmeat/salmon
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/sockeye_salmon/get_base_edible_reagents_to_add()
|
||||
var/return_list = ..()
|
||||
return_list[/datum/reagent/consumable/nutriment/fat] = 1
|
||||
return return_list
|
||||
|
||||
/obj/item/fish/arctic_char
|
||||
name = "arctic char"
|
||||
desc = "A cold-water anadromous fish widespread around the Northern Hemisphere of Earth, yet it has somehow found a way here."
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
compatible_types = list(/obj/item/fish/goldfish, /obj/item/fish/goldfish/three_eyes)
|
||||
fish_traits = list(/datum/fish_trait/recessive)
|
||||
|
||||
/obj/item/fish/goldfish/gill/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "objection" = 1)
|
||||
|
||||
/obj/item/fish/goldfish/three_eyes
|
||||
name = "three-eyed goldfish"
|
||||
desc = "A goldfish with an extra half a pair of eyes. You wonder what it's been feeding on lately..."
|
||||
@@ -50,6 +53,9 @@
|
||||
),
|
||||
)
|
||||
|
||||
/obj/item/fish/goldfish/three_eyes/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "chemical waste" = 0.5)
|
||||
|
||||
/obj/item/fish/goldfish/three_eyes/gill
|
||||
name = "McGill"
|
||||
desc = "A great rubber duck tool for Lawyers who can't get a grasp over their case. It looks kinda different today..."
|
||||
@@ -59,6 +65,9 @@
|
||||
stable_population = 1
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
/obj/item/fish/goldfish/three_eyes/gill/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "objection" = 1)
|
||||
|
||||
/obj/item/fish/angelfish
|
||||
name = "angelfish"
|
||||
desc = "Young Angelfish often live in groups, while adults prefer solitary life. They become territorial and aggressive toward other fish when they reach adulthood."
|
||||
@@ -142,6 +151,9 @@
|
||||
electrogenesis_power = 6.7 MEGA JOULES
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/zipzap/get_fish_taste()
|
||||
return list("raw fish" = 2, "anxiety" = 1)
|
||||
|
||||
/obj/item/fish/tadpole
|
||||
name = "tadpole"
|
||||
desc = "The larval spawn of an amphibian. A very minuscle, round creature with a long tail it uses to swim around."
|
||||
@@ -167,6 +179,9 @@
|
||||
RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks))
|
||||
RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth))
|
||||
|
||||
/obj/item/fish/tadpole/make_edible()
|
||||
return
|
||||
|
||||
/obj/item/fish/tadpole/set_status(new_status, silent = FALSE)
|
||||
. = ..()
|
||||
if(status == FISH_DEAD)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
average_size = /obj/item/fish/goldfish::average_size
|
||||
average_weight = /obj/item/fish/goldfish::average_weight
|
||||
required_fluid_type = AQUARIUM_FLUID_ANADROMOUS
|
||||
grind_results = null
|
||||
fillet_type = null
|
||||
death_text = "%SRC gently disappears."
|
||||
fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce
|
||||
@@ -28,6 +27,9 @@
|
||||
return
|
||||
holo_area.linked.add_to_spawned(src)
|
||||
|
||||
/obj/item/fish/holo/make_edible(weight_val)
|
||||
return
|
||||
|
||||
/obj/item/fish/holo/set_status(new_status, silent = FALSE)
|
||||
. = ..()
|
||||
if(status == FISH_DEAD)
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks))
|
||||
RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth))
|
||||
|
||||
/obj/item/fish/chasm_crab/get_fish_taste()
|
||||
return list("raw crab" = 2)
|
||||
|
||||
/obj/item/fish/chasm_crab/get_fish_taste_cooked()
|
||||
return list("cooked crab" = 2)
|
||||
|
||||
///A chasm crab growth speed is determined by its initial weight and size, ergo bigger crabs for faster lobstrosities
|
||||
/obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight)
|
||||
. = ..()
|
||||
@@ -125,6 +131,9 @@
|
||||
evolution_types = list(/datum/fish_evolution/mastodon)
|
||||
beauty = FISH_BEAUTY_UGLY
|
||||
|
||||
/obj/item/fish/boned/make_edible(weight_val)
|
||||
return //it's all bones and no meat.
|
||||
|
||||
/obj/item/fish/lavaloop
|
||||
name = "lavaloop fish"
|
||||
desc = "Due to its curvature, it can be used as make-shift boomerang."
|
||||
@@ -164,6 +173,12 @@
|
||||
effect_on_success = /obj/effect/temp_visual/guardian/phase,\
|
||||
)
|
||||
|
||||
/obj/item/fish/lavaloop/get_fish_taste()
|
||||
return list("chewy fish" = 2)
|
||||
|
||||
/obj/item/fish/lavaloop/get_food_types()
|
||||
return SEAFOOD|MEAT|GORE //Well-cooked in lava
|
||||
|
||||
/obj/item/fish/lavaloop/proc/explode_on_user(mob/living/user)
|
||||
var/obj/item/bodypart/arm/active_arm = user.get_active_hand()
|
||||
active_arm?.dismember()
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
fish_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/amphibious, /datum/fish_trait/revival, /datum/fish_trait/carnivore, /datum/fish_trait/predator, /datum/fish_trait/aggressive)
|
||||
beauty = FISH_BEAUTY_BAD
|
||||
|
||||
/obj/item/fish/mastodon/make_edible(weight_val)
|
||||
return //it's all bones and gibs.
|
||||
|
||||
///From the cursed spring
|
||||
/obj/item/fish/soul
|
||||
name = "soulfish"
|
||||
@@ -50,6 +53,15 @@
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+38
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
/obj/item/fish/soul/get_food_types()
|
||||
return MEAT|RAW|GORE //Not-so-quite-seafood
|
||||
|
||||
/obj/item/fish/soul/get_fish_taste()
|
||||
return list("meat" = 2, "soulfulness" = 1)
|
||||
|
||||
/obj/item/fish/soul/get_fish_taste_cooked()
|
||||
return list("cooked meat" = 2)
|
||||
|
||||
///From the cursed spring
|
||||
/obj/item/fish/skin_crab
|
||||
name = "skin crab"
|
||||
@@ -71,3 +83,8 @@
|
||||
fillet_type = /obj/item/food/meat/slab/rawcrab
|
||||
random_case_rarity = FISH_RARITY_NOPE
|
||||
|
||||
/obj/item/fish/skin_crab/get_fish_taste()
|
||||
return list("raw crab" = 2)
|
||||
|
||||
/obj/item/fish/skin_crab/get_fish_taste_cooked()
|
||||
return list("cooked crab" = 2)
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+22
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+30
|
||||
|
||||
/obj/item/fish/clownfish/get_fish_taste()
|
||||
return list("raw fish" = 2, "something funny" = 1)
|
||||
|
||||
/obj/item/fish/clownfish/lube
|
||||
name = "lubefish"
|
||||
desc = "A clownfish exposed to cherry-flavored lube for far too long. First discovered the days following a cargo incident around the seas of Europa, when thousands of thousands of thousands..."
|
||||
@@ -227,9 +230,15 @@
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+26
|
||||
fish_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/carnivore, /datum/fish_trait/predator, /datum/fish_trait/ink, /datum/fish_trait/camouflage, /datum/fish_trait/wary)
|
||||
|
||||
/obj/item/fish/squid/get_fish_taste()
|
||||
return list("raw mollusk" = 2)
|
||||
|
||||
/obj/item/fish/squid/get_fish_taste_cooked()
|
||||
return list("cooked mollusk" = 2, "tenderness" = 0.5)
|
||||
|
||||
/obj/item/fish/monkfish
|
||||
name = "monkfish"
|
||||
desc = "A member of the Lophiid family of anglerfish. It goes by several different names, however none of them will make it look any prettier, nor any less delicious."
|
||||
desc = "A member of the Lophiid family of anglerfish. It goes by several different names, however none of them will make it look any prettier, nor be any less delicious."
|
||||
icon_state = "monkfish"
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
sprite_height = 7
|
||||
|
||||
@@ -20,6 +20,20 @@
|
||||
)
|
||||
beauty = FISH_BEAUTY_DISGUSTING
|
||||
|
||||
/obj/item/fish/ratfish/get_fish_taste()
|
||||
return list("vermin" = 2, "maintenance" = 1)
|
||||
|
||||
/obj/item/fish/ratfish/get_fish_taste_cooked()
|
||||
return list("cooked vermin" = 2, "burned fur" = 0.5)
|
||||
|
||||
/obj/item/fish/ratfish/get_food_types()
|
||||
return MEAT|RAW|GORE //Not-so-quite-seafood
|
||||
|
||||
/obj/item/fish/ratfish/get_base_edible_reagents_to_add()
|
||||
var/list/return_list = ..()
|
||||
return_list[/datum/reagent/rat_spit] = 1
|
||||
return return_list
|
||||
|
||||
/obj/item/fish/ratfish/Initialize(mapload, apply_qualities = TRUE)
|
||||
. = ..()
|
||||
//stable pop reflects the config for how many mice migrate. powerful...
|
||||
@@ -43,6 +57,9 @@
|
||||
evolution_types = list(/datum/fish_evolution/purple_sludgefish)
|
||||
beauty = FISH_BEAUTY_NULL
|
||||
|
||||
/obj/item/fish/sludgefish/get_fish_taste()
|
||||
return list("raw fish" = 2, "eau de toilet" = 1)
|
||||
|
||||
/obj/item/fish/sludgefish/purple
|
||||
name = "purple sludgefish"
|
||||
desc = "A misshapen, fragile, loosely fish-like living goop. This one has developed sexual reproduction mechanisms, and a purple tint to boot."
|
||||
@@ -63,7 +80,6 @@
|
||||
stable_population = 4
|
||||
health = 150
|
||||
fillet_type = /obj/item/slime_extract/grey
|
||||
grind_results = list(/datum/reagent/toxin/slimejelly = 10)
|
||||
fish_traits = list(/datum/fish_trait/toxin_immunity, /datum/fish_trait/crossbreeder)
|
||||
favorite_bait = list(
|
||||
list(
|
||||
@@ -78,3 +94,9 @@
|
||||
)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+20
|
||||
beauty = FISH_BEAUTY_GREAT
|
||||
|
||||
/obj/item/fish/slimefish/get_food_types()
|
||||
return SEAFOOD|TOXIC
|
||||
|
||||
/obj/item/fish/slimefish/get_base_edible_reagents_to_add()
|
||||
return list(/datum/reagent/toxin/slimejelly = 5)
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+40
|
||||
beauty = FISH_BEAUTY_BAD
|
||||
|
||||
/obj/item/fish/emulsijack/get_fish_taste()
|
||||
return list("raw fish" = 2, "acid" = 1) //no scales
|
||||
|
||||
/obj/item/fish/donkfish
|
||||
name = "donk co. company patent donkfish"
|
||||
desc = "A lab-grown donkfish. Its invention was an accident for the most part, as it was intended to be consumed in donk pockets. Unfortunately, it tastes horrible, so it has now become a pseudo-mascot."
|
||||
@@ -94,6 +97,9 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/update_icon_updates_onmob)
|
||||
|
||||
/obj/item/fish/chainsawfish/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "anger" = 1)
|
||||
|
||||
/obj/item/fish/chainsawfish/update_icon_state()
|
||||
if(status == FISH_DEAD)
|
||||
inhand_icon_state = "chainsawfish_dead"
|
||||
@@ -202,6 +208,12 @@
|
||||
/obj/item/fish,
|
||||
)
|
||||
|
||||
/obj/item/fish/pike/armored/get_fish_taste()
|
||||
return list("raw fish" = 2.5, "metal" = 1)
|
||||
|
||||
/obj/item/fish/pike/armored/get_fish_taste()
|
||||
return list("cooked fish" = 2.5, "metal" = 1)
|
||||
|
||||
/obj/item/fish/swordfish/get_force_rank()
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY)
|
||||
|
||||
@@ -24,10 +24,21 @@
|
||||
required_fluid_type = AQUARIUM_FLUID_SALTWATER
|
||||
stable_population = 4
|
||||
fillet_type = /obj/item/food/fishmeat/gunner_jellyfish
|
||||
fish_traits = list(/datum/fish_trait/hallucinogenic)
|
||||
required_temperature_min = MIN_AQUARIUM_TEMP+24
|
||||
required_temperature_max = MIN_AQUARIUM_TEMP+32
|
||||
beauty = FISH_BEAUTY_GOOD
|
||||
|
||||
/obj/item/fish/gunner_jellyfish/Initialize(mapload, apply_qualities = TRUE)
|
||||
. = ..()
|
||||
AddElement(/datum/element/quality_food_ingredient, FOOD_COMPLEXITY_2)
|
||||
|
||||
/obj/item/fish/gunner_jellyfish/get_fish_taste()
|
||||
return list("cold jelly" = 2)
|
||||
|
||||
/obj/item/fish/gunner_jellyfish/get_fish_taste_cooked()
|
||||
return list("crunchy tenderness" = 2)
|
||||
|
||||
/obj/item/fish/needlefish
|
||||
name = "needlefish"
|
||||
desc = "A tiny, transparent fish which resides in large schools in the oceans of Tizira. A common food for other, larger fish."
|
||||
@@ -67,3 +78,9 @@
|
||||
/obj/item/fish/armorfish/Initialize(mapload, apply_qualities = TRUE)
|
||||
. = ..()
|
||||
add_traits(list(TRAIT_FISHING_BAIT, TRAIT_GOOD_QUALITY_BAIT), INNATE_TRAIT)
|
||||
|
||||
/obj/item/fish/chasm_crab/get_fish_taste()
|
||||
return list("raw prawn" = 2)
|
||||
|
||||
/obj/item/fish/chasm_crab/get_fish_taste_cooked()
|
||||
return list("cooked prawn" = 2)
|
||||
|
||||
@@ -704,4 +704,7 @@
|
||||
override_origin_pixel_x = lefthand ? lefthand_n_px : righthand_n_px
|
||||
override_origin_pixel_y = lefthand ? lefthand_n_py : righthand_n_py
|
||||
|
||||
override_origin_pixel_x += origin.pixel_x
|
||||
override_origin_pixel_y += origin.pixel_y
|
||||
|
||||
#undef FISHING_ROD_REEL_CAST_RANGE
|
||||
|
||||
@@ -154,7 +154,7 @@ GLOBAL_LIST_INIT(oilfry_blacklisted_items, typecacheof(list(
|
||||
reagents.trans_to(frying, oil_use * seconds_per_tick, multiplier = fry_speed * 3) //Fried foods gain more of the reagent thanks to space magic
|
||||
grease_level += prob(grease_increase_chance) * grease_Increase_amount
|
||||
|
||||
cook_time += fry_speed * seconds_per_tick
|
||||
cook_time += fry_speed * seconds_per_tick SECONDS
|
||||
if(cook_time >= DEEPFRYER_COOKTIME && !frying_fried)
|
||||
frying_fried = TRUE //frying... frying... fried
|
||||
playsound(src.loc, 'sound/machines/ding.ogg', 50, TRUE)
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
|
||||
// Everything else will just get fried
|
||||
if(isnull(ingredient.reagents) && !is_type_in_list(ingredient, required_ingredients))
|
||||
ingredient.AddElement(/datum/element/fried_item, 30)
|
||||
ingredient.AddElement(/datum/element/fried_item, 30 SECONDS)
|
||||
continue
|
||||
|
||||
// Things that had reagents or ingredients in the soup will get deleted
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
/obj/item/food/grown/onion/red/make_processable()
|
||||
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/onion_slice/red, 2, 15, screentip_verb = "Cut")
|
||||
|
||||
/obj/item/food/grown/onion/UsedforProcessing(mob/living/user, obj/item/I, list/chosen_option)
|
||||
/obj/item/food/grown/onion/UsedforProcessing(mob/living/user, obj/item/I, list/chosen_option, list/created_atoms)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/cry_about_it = new //Since the onion is destroyed when it's sliced,
|
||||
var/splat_location = get_turf(src) //we need to set up the smoke beforehand
|
||||
cry_about_it.attach(splat_location)
|
||||
|
||||
@@ -139,8 +139,8 @@
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Lock mutation"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
// Edibles and pills can be composted.
|
||||
if(IS_EDIBLE(held_item) || istype(held_item, /obj/item/reagent_containers/pill))
|
||||
// Edibles can be composted (most of the times).
|
||||
if(IS_EDIBLE(held_item) && HAS_TRAIT(held_item, TRAIT_UNCOMPOSTABLE))
|
||||
context[SCREENTIP_CONTEXT_LMB] = "Compost"
|
||||
return CONTEXTUAL_SCREENTIP_SET
|
||||
|
||||
@@ -855,7 +855,10 @@
|
||||
var/visi_msg = ""
|
||||
var/transfer_amount
|
||||
|
||||
if(IS_EDIBLE(reagent_source) || istype(reagent_source, /obj/item/reagent_containers/pill))
|
||||
if(IS_EDIBLE(reagent_source))
|
||||
if(HAS_TRAIT(reagent_source, TRAIT_UNCOMPOSTABLE))
|
||||
to_chat(user, "[reagent_source] cannot be composted in its current state")
|
||||
return
|
||||
visi_msg="[user] composts [reagent_source], spreading it through [target]"
|
||||
transfer_amount = reagent_source.reagents.total_volume
|
||||
SEND_SIGNAL(reagent_source, COMSIG_ITEM_ON_COMPOSTED, user)
|
||||
|
||||
@@ -52,27 +52,31 @@
|
||||
return NONE
|
||||
|
||||
/mob/living/carbon/get_liked_foodtypes()
|
||||
var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
// No tongue, no tastin'
|
||||
if(!tongue?.sense_of_taste || HAS_TRAIT(src, TRAIT_AGEUSIA))
|
||||
if(HAS_TRAIT(src, TRAIT_AGEUSIA))
|
||||
return NONE
|
||||
// Handled in here since the brain trauma can't modify taste directly (/datum/brain_trauma/severe/flesh_desire)
|
||||
if(HAS_TRAIT(src, TRAIT_FLESH_DESIRE))
|
||||
return GORE | MEAT
|
||||
return tongue.liked_foodtypes
|
||||
var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
. = tongue.liked_foodtypes
|
||||
if(HAS_TRAIT(src, TRAIT_VEGETARIAN))
|
||||
. &= ~MEAT
|
||||
|
||||
/**
|
||||
* Gets food flags that this mob dislikes
|
||||
**/
|
||||
/mob/living/proc/get_disliked_foodtypes()
|
||||
if(HAS_TRAIT(src, TRAIT_VEGETARIAN))
|
||||
return MEAT
|
||||
return NONE
|
||||
|
||||
/mob/living/carbon/get_disliked_foodtypes()
|
||||
var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
// No tongue, no tastin'
|
||||
if(!tongue?.sense_of_taste || HAS_TRAIT(src, TRAIT_AGEUSIA))
|
||||
if(HAS_TRAIT(src, TRAIT_AGEUSIA))
|
||||
return NONE
|
||||
return tongue.disliked_foodtypes
|
||||
var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
. = tongue.disliked_foodtypes
|
||||
if(HAS_TRAIT(src, TRAIT_VEGETARIAN))
|
||||
. |= MEAT
|
||||
|
||||
/**
|
||||
* Gets food flags that this mob hates
|
||||
@@ -83,9 +87,8 @@
|
||||
|
||||
/mob/living/carbon/get_toxic_foodtypes()
|
||||
var/obj/item/organ/internal/tongue/tongue = get_organ_slot(ORGAN_SLOT_TONGUE)
|
||||
// No tongue, no tastin'
|
||||
if(!tongue)
|
||||
return TOXIC
|
||||
return ..()
|
||||
if(HAS_TRAIT(src, TRAIT_FLESH_DESIRE))
|
||||
return VEGETABLES | DAIRY | FRUIT | FRIED
|
||||
return tongue.toxic_foodtypes
|
||||
|
||||
@@ -204,11 +204,12 @@
|
||||
*
|
||||
* * [list_reagents][list] - list to add. Format it like this: list(/datum/reagent/toxin = 10, "beer" = 15)
|
||||
* * [data][list] - additional data to add
|
||||
* * [added_purity][number] - an override to the default purity for each reagent to add.
|
||||
*/
|
||||
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data = null)
|
||||
/datum/reagents/proc/add_reagent_list(list/list_reagents, list/data = null, added_purity = null)
|
||||
for(var/r_id in list_reagents)
|
||||
var/amt = list_reagents[r_id]
|
||||
add_reagent(r_id, amt, data)
|
||||
add_reagent(r_id, amt, data, added_purity = added_purity)
|
||||
|
||||
/**
|
||||
* Removes a specific reagent. can supress reactions if needed
|
||||
@@ -589,10 +590,11 @@
|
||||
*/
|
||||
/datum/reagents/proc/multiply_reagents(multiplier = 1)
|
||||
var/list/cached_reagents = reagent_list
|
||||
if(!total_volume)
|
||||
if(!total_volume || multiplier == 1)
|
||||
return
|
||||
var/change = (multiplier - 1) //Get the % change
|
||||
for(var/datum/reagent/reagent as anything in cached_reagents)
|
||||
_multiply_reagent(reagent, change)
|
||||
if(change > 0)
|
||||
add_reagent(reagent.type, reagent.volume * change, added_purity = reagent.purity, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)
|
||||
else
|
||||
@@ -601,6 +603,28 @@
|
||||
update_total()
|
||||
handle_reactions()
|
||||
|
||||
/**
|
||||
* Multiplies a single inside this holder by a specific amount
|
||||
* Arguments
|
||||
* * reagent_path - The path of the reagent we want to multiply the volume of.
|
||||
* * multiplier - the amount to multiply each reagent by
|
||||
*/
|
||||
/datum/reagents/proc/multiply_single_reagent(reagent_path, multiplier = 1)
|
||||
var/datum/reagent/reagent = locate(reagent_path) in reagent_list
|
||||
if(!reagent || multiplier == 1)
|
||||
return
|
||||
var/change = (multiplier - 1) //Get the % change
|
||||
_multiply_reagent(reagent, change)
|
||||
update_total()
|
||||
handle_reactions()
|
||||
|
||||
///Proc containing the operations called by both multiply_reagents() and multiply_single_reagent()
|
||||
/datum/reagents/proc/_multiply_reagent(datum/reagent/reagent, change)
|
||||
if(change > 0)
|
||||
add_reagent(reagent.type, reagent.volume * change, added_purity = reagent.purity, ignore_splitting = reagent.chemical_flags & REAGENT_DONOTSPLIT)
|
||||
else
|
||||
remove_reagent(reagent.type, abs(reagent.volume * change)) //absolute value to prevent a double negative situation (removing -50% would be adding 50%)
|
||||
|
||||
/// Updates [/datum/reagents/var/total_volume]
|
||||
/datum/reagents/proc/update_total()
|
||||
var/list/cached_reagents = reagent_list
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
return
|
||||
|
||||
exposed_obj.visible_message(span_warning("[exposed_obj] rapidly fries as it's splashed with hot oil! Somehow."))
|
||||
exposed_obj.AddElement(/datum/element/fried_item, volume)
|
||||
exposed_obj.reagents.add_reagent(src.type, reac_volume)
|
||||
exposed_obj.AddElement(/datum/element/fried_item, volume SECONDS)
|
||||
exposed_obj.reagents.add_reagent(src.type, reac_volume, reagtemp = holder.chem_temp)
|
||||
|
||||
/datum/reagent/consumable/nutriment/fat/expose_mob(mob/living/exposed_mob, methods = TOUCH, reac_volume, show_message = TRUE, touch_protection = 0)
|
||||
. = ..()
|
||||
|
||||
@@ -326,6 +326,19 @@
|
||||
else
|
||||
affected_mob.adjust_hallucinations(10 SECONDS * REM * seconds_per_tick)
|
||||
|
||||
/datum/reagent/toxin/mindbreaker/fish
|
||||
name = "Jellyfish Hallucinogen"
|
||||
description = "A hallucinogen structurally similar to the mindbreaker toxin, but with weaker molecular bonds, making it easily degradeable by heat."
|
||||
|
||||
/datum/reagent/toxin/mindbreaker/fish/on_new(data)
|
||||
. = ..()
|
||||
if(holder?.my_atom)
|
||||
RegisterSignals(holder.my_atom, list(COMSIG_ITEM_FRIED, TRAIT_FOOD_BBQ_GRILLED), PROC_REF(on_atom_cooked))
|
||||
|
||||
/datum/reagent/toxin/mindbreaker/fish/proc/on_atom_cooked(datum/source, cooking_time)
|
||||
SIGNAL_HANDLER
|
||||
holder.del_reagent(type)
|
||||
|
||||
/datum/reagent/toxin/plantbgone
|
||||
name = "Plant-B-Gone"
|
||||
description = "A harmful toxic mixture to kill plantlife. Do not ingest!"
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
required_other = TRUE
|
||||
|
||||
/datum/chemical_reaction/sodiumchloride/pre_reaction_other_checks(datum/reagents/holder)
|
||||
. = ..()
|
||||
. = ..()
|
||||
if(holder.has_reagent(/datum/reagent/consumable/liquidelectricity) || holder.has_reagent(/datum/reagent/consumable/liquidelectricity/enriched))
|
||||
return FALSE
|
||||
|
||||
@@ -990,3 +990,16 @@
|
||||
var/location = get_turf(holder.my_atom)
|
||||
for(var/i in 1 to created_volume)
|
||||
new /obj/item/stack/sheet/hauntium(location)
|
||||
|
||||
/datum/chemical_reaction/fish_hallucinogen_degradation
|
||||
results = list(/datum/reagent/consumable/nutriment/protein = 0.1)
|
||||
required_reagents = list(/datum/reagent/toxin/mindbreaker/fish = 1)
|
||||
required_temp = 363.15 // 90°
|
||||
optimal_temp = 450
|
||||
rate_up_lim = 8
|
||||
temp_exponent_factor = 1.5
|
||||
optimal_ph_min = 2
|
||||
optimal_ph_max = 10
|
||||
thermic_constant = 80
|
||||
H_ion_release = 2
|
||||
reaction_tags = REACTION_TAG_EASY
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
var/obj/item/food_item = new chosen(T)
|
||||
ADD_TRAIT(food_item, TRAIT_FOOD_SILVER, INNATE_TRAIT)
|
||||
if(prob(5))//Fry it!
|
||||
food_item.AddElement(/datum/element/fried_item, rand(15, 60))
|
||||
food_item.AddElement(/datum/element/fried_item, rand(15, 60) SECONDS)
|
||||
if(prob(5))//Grill it!
|
||||
food_item.AddElement(/datum/element/grilled_item, rand(30 SECONDS, 100 SECONDS))
|
||||
if(prob(50))
|
||||
|
||||
@@ -595,7 +595,7 @@ GLOBAL_LIST_INIT(english_to_zombie, list())
|
||||
say_mod = "meows"
|
||||
liked_foodtypes = SEAFOOD | ORANGES | BUGS | GORE
|
||||
disliked_foodtypes = GROSS | CLOTH | RAW
|
||||
organ_traits = list(TRAIT_WOUND_LICKER)
|
||||
organ_traits = list(TRAIT_WOUND_LICKER, TRAIT_FISH_EATER)
|
||||
|
||||
/obj/item/organ/internal/tongue/jelly
|
||||
name = "jelly tongue"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#define TRAIT_FISH_TESTING "made_you_read_this"
|
||||
#define FISH_REAGENT_AMOUNT (10 * FISH_WEIGHT_GRIND_TO_BITE_MULT)
|
||||
|
||||
///Ensures that all fish have an aquarium icon state and that sprite_width and sprite_height have been set.
|
||||
/datum/unit_test/fish_aquarium_icons
|
||||
@@ -21,7 +22,10 @@
|
||||
|
||||
/datum/unit_test/fish_size_weight/Run()
|
||||
var/obj/item/fish/fish = allocate(/obj/item/fish/testdummy)
|
||||
TEST_ASSERT_EQUAL(fish.grind_results[/datum/reagent], 20, "the test fish has [fish.grind_results[/datum/reagent]] units of reagent when it should have 20")
|
||||
var/datum/reagent/reagent = fish.reagents?.has_reagent(/datum/reagent/fishdummy)
|
||||
TEST_ASSERT(reagent, "the test fish doesn't have the test reagent.[fish.reagents ? "" : " It doesn't even have a reagent holder."]")
|
||||
var/expected_units = FISH_REAGENT_AMOUNT * fish.weight / FISH_WEIGHT_BITE_DIVISOR
|
||||
TEST_ASSERT_EQUAL(reagent.volume, expected_units, "the test fish has [reagent.volume] units of the test reagent when it should have [expected_units]")
|
||||
TEST_ASSERT_EQUAL(fish.w_class, WEIGHT_CLASS_BULKY, "the test fish has w_class of [fish.w_class] when it should have been [WEIGHT_CLASS_BULKY]")
|
||||
var/expected_num_fillets = round(FISH_SIZE_BULKY_MAX / FISH_FILLET_NUMBER_SIZE_DIVISOR * 2, 1)
|
||||
TEST_ASSERT_EQUAL(fish.num_fillets, expected_num_fillets, "the test fish has [fish.num_fillets] number of fillets when it should have [expected_num_fillets]")
|
||||
@@ -93,7 +97,7 @@
|
||||
incompatible_traits = list(/datum/fish_trait/dummy/two)
|
||||
inheritability = 100
|
||||
diff_traits_inheritability = 100
|
||||
reagents_to_add = list(/datum/reagent = 10)
|
||||
reagents_to_add = list(/datum/reagent/fishdummy = FISH_REAGENT_AMOUNT)
|
||||
|
||||
/datum/fish_trait/dummy/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
@@ -102,6 +106,10 @@
|
||||
/datum/fish_trait/dummy/two
|
||||
incompatible_traits = list(/datum/fish_trait/dummy)
|
||||
|
||||
/datum/reagent/fishdummy
|
||||
name = "fish test reagent"
|
||||
description = "It smells fishy."
|
||||
|
||||
/obj/structure/aquarium/traits
|
||||
allow_breeding = TRUE
|
||||
var/obj/item/fish/testdummy/crossbreeder/crossbreeder
|
||||
@@ -283,12 +291,63 @@
|
||||
/datum/fish_source/unit_test
|
||||
fish_table = list(
|
||||
/obj/item/wrench = 1,
|
||||
/obj/item/screwdriver = INFINITY,
|
||||
/obj/item/screwdriver = INFINITY, //infinite weight, so if fish counts doesn't work as intended, this'll be always picked.
|
||||
)
|
||||
fish_counts = list(
|
||||
/obj/item/wrench = 1,
|
||||
/obj/item/screwdriver = 0,
|
||||
/obj/item/screwdriver = 0, //this should never be picked.
|
||||
)
|
||||
|
||||
/datum/unit_test/edible_fish
|
||||
|
||||
/datum/unit_test/edible_fish/Run()
|
||||
var/obj/item/fish/fish = allocate(/obj/item/fish/testdummy/food)
|
||||
var/datum/component/edible/edible = fish.GetComponent(/datum/component/edible)
|
||||
TEST_ASSERT(edible, "Fish is not edible")
|
||||
edible.eat_time = 0
|
||||
TEST_ASSERT(fish.GetComponent(/datum/component/infective), "Fish doesn't have the infective component")
|
||||
var/bite_size = edible.bite_consumption
|
||||
|
||||
var/mob/living/carbon/human/consistent/gourmet = allocate(/mob/living/carbon/human/consistent)
|
||||
|
||||
var/food_quality = edible.get_perceived_food_quality(gourmet)
|
||||
TEST_ASSERT(food_quality < 0, "Humans don't seem to dislike raw, unprocessed fish when they should")
|
||||
ADD_TRAIT(gourmet, TRAIT_FISH_EATER, TRAIT_FISH_TESTING)
|
||||
food_quality = edible.get_perceived_food_quality(gourmet)
|
||||
TEST_ASSERT(food_quality >= LIKED_FOOD_QUALITY_CHANGE, "mobs with the TRAIT_FISH_EATER traits don't seem to like fish when they should")
|
||||
REMOVE_TRAIT(gourmet, TRAIT_FISH_EATER, TRAIT_FISH_TESTING)
|
||||
|
||||
fish.attack(gourmet, gourmet)
|
||||
TEST_ASSERT(gourmet.has_reagent(/datum/reagent/consumable/nutriment/protein), "Human doesn't have ingested protein after eating fish")
|
||||
TEST_ASSERT(gourmet.has_reagent(/datum/reagent/blood), "Human doesn't have ingested blood after eating fish")
|
||||
TEST_ASSERT(gourmet.has_reagent(/datum/reagent/fishdummy), "Human doesn't have the reagent from /datum/fish_trait/dummy after eating fish")
|
||||
|
||||
TEST_ASSERT_EQUAL(fish.status, FISH_DEAD, "The fish is not dead, despite having sustained enough damage that it should. health: [fish.health]")
|
||||
|
||||
var/obj/item/organ/internal/stomach/belly = gourmet.get_organ_slot(ORGAN_SLOT_STOMACH)
|
||||
belly.reagents.clear_reagents()
|
||||
|
||||
fish.set_status(FISH_ALIVE)
|
||||
TEST_ASSERT(!fish.bites_amount, "bites_amount wasn't reset after the fish revived")
|
||||
|
||||
fish.update_size_and_weight(fish.size, FISH_WEIGHT_BITE_DIVISOR)
|
||||
fish.AddElement(/datum/element/fried_item, FISH_SAFE_COOKING_DURATION)
|
||||
TEST_ASSERT_EQUAL(fish.status, FISH_DEAD, "The fish didn't die after being cooked")
|
||||
TEST_ASSERT(bite_size < edible.bite_consumption, "The bite_consumption value hasn't increased after being cooked (it removes blood but doubles protein). Value: [bite_size]")
|
||||
TEST_ASSERT(!(edible.foodtypes & (RAW|GORE)), "Fish still has the GORE and/or RAW foodtypes flags after being cooked")
|
||||
TEST_ASSERT(!fish.GetComponent(/datum/component/infective), "Fish still has the infective component after being cooked for long enough")
|
||||
|
||||
|
||||
food_quality = edible.get_perceived_food_quality(gourmet)
|
||||
TEST_ASSERT(food_quality >= 0, "Humans still dislike fish, even when it's cooked")
|
||||
fish.attack(gourmet, gourmet)
|
||||
TEST_ASSERT(!gourmet.has_reagent(/datum/reagent/blood), "Human has ingested blood from eating a fish when it shouldn't since the fish has been cooked")
|
||||
|
||||
TEST_ASSERT(QDELETED(fish), "The fish is not being deleted, despite having sustained enough bites. Reagents volume left: [fish.reagents.total_volume]")
|
||||
|
||||
/obj/item/fish/testdummy/food
|
||||
average_weight = FISH_WEIGHT_BITE_DIVISOR * 2 //One bite, it's death; the other, it's gone.
|
||||
|
||||
#undef FISH_REAGENT_AMOUNT
|
||||
#undef TRAIT_FISH_TESTING
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ The fishing portal generator has different modules, all of which can be unlocked
|
||||
A fish's traits influence how you can catch them. Carnivore fish will ignore dough balls, and herbivore fish ignore anything that's not from botany.
|
||||
Telescopic fishing rods can be bought from cargo.
|
||||
Once grown from chrabs and tamed, lobstrosities can be heeded to fish on fishing spots for you.
|
||||
Aquariums can be upgraded to bioelectricity generators can a specific kit. From there, you can add electric-generating fish like the anxious zip zap to generate power.
|
||||
Aquariums can be upgraded to bioelectricity generators with a specific kit. From there, you can add electric-generating fish like the anxious zip zap to generate power for the station.
|
||||
Getting better at fishing will net you some small additional advantages, such as receiving more information when examining a fish or a fishing spot.
|
||||
The size and weight of a fish can influence the amount of reagents and fillets you can harvest from them, their force as a weapon and how easy it is to store them in containers.
|
||||
While most fish make for shoddy weapons, a few, like the swordfish and the chainsawfish, can be quite powerful. In general, the bigger they are, the more forceful they get.
|
||||
@@ -33,12 +33,14 @@ Some species of fish can be bred into new species under the right conditions.
|
||||
Most fish don't survive outside water, so get them somewhere safe like an aquarium or a fish case, or even a toilet or a moisture trap!
|
||||
No matter how you look at it, most people won't care about fishing. Don't let that stop you. They're just jealous.
|
||||
To fish on ice you have to puncture the ice layer with a pick or shovel first.
|
||||
Depending on the kind of fish inside it and whether they're alive or dead, an aquarium can improve the beauty of the room or worsen it.
|
||||
Depending on the kinds of fish inside it and whether they're alive or dead, an aquarium can improve the beauty of the room or worsen it.
|
||||
Almost all fish can be ground in an All-in-one-Grinder. Don't think too hard about how you're fitting a giant fish into a blender. Nanotrasen technology is weird like that.
|
||||
The sludgefish from the toilets can be used as a steady supply of cheap fish and fillets due to its self-reproducing behaviour. However it's quite fragile.
|
||||
In a jiffy, you can scoop tadpoles from ponds with your bare hands, place them inside aquariums and quickly raise them into frogs.
|
||||
The legendary fishing hat isn't just cosmetic. Space carps (as well as young lobstrosities and frogs) do truly fear those who wear it.
|
||||
Have you ever heard a lobster or crab talk? Well, neither have I, but they say they're quite the fishy punsters.
|
||||
You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) for research.
|
||||
You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) to research.
|
||||
Fish is, of course, edible. Is it safe to eat raw? Well, if you've strong stomach, otherwise your best option is to cook it for a at least half a spessman minute if you don't want to catch nasty diseases.
|
||||
After researching the Advanced Fishing Technology Node, you can print special fishing gloves that let you fish without having to carry around a fishing rod. There's one pair that even trains athletics on top of fishing.You can get an experiscanner from science to perform fish scanning experiments, which can unlock more modules for the fishing portal, as well as fishing technology nodes (better equipment) for research.
|
||||
If you have enough credits, you can buy a set of fishing lures from cargo. Each lure allows you to catch different species of fish and won't get consumed, however they need to be spun at intervals to work.
|
||||
This may sound silly, but squids and their ink sacs can be used as weapons to temporarily blind people.
|
||||
This may sound silly, but squids and their ink sacs can be used to temporarily blind foes.
|
||||
Reference in New Issue
Block a user