Fish infusion (#87030)
## About The Pull Request I'm adding a new infusion ~~(actually four, but two of them are just holders for specific organs tied to a couple fish traits)~~ to the game. As the title says, it's about fish. The infusion is composed of three primary organs, plus another few that can be gotten from fish with specific traits. The primary organs are: - Gills (lungs): Instead of breathing oxygen, you now need to stay wet or breathe water vapor. - fish-DNA infused stomach: Can safely eat raw fish. - fish tail: On its own, it only speeds you up on water turfs, but it has another effect once past the organ set threshold. It also makes you waddle and flop like a fish while crawling (I still gotta finish sprites on this one) Other organs are: - semi-aquatic lungs: A subtype of gills from fish with the 'amphibious' trait, falls back on oxygen if there's no water. Can also be gotten from frogs, axolotl and crabs. - fish-DNA infused liver: From fish with the 'toxic' trait. Uses tetrodotoxin as a healing chem instead of a toxin. Also better tolerance to alcohol if you want to drink like a fish (ba dum tsh). - inky tongue: From fish with the 'ink production' trait. Gives mobs the ability to spit ink on a cooldown, blinding and confusion foes temporarily. The main gimmick of this infusion revolves around being drenched in water to benefit from it, In the case you get the gills organ, this also becomes a necessity, to not suffocate to death (alternatively, you can breathe water vapor, without any benefit). To enable the bonus of the organs set, three organs need to be infused. They can be gills, stomach, tail and/or liver, while the inky tongue doesn't count towards it. Once the threshold is reached, the following bonus are enabled: - Wetness decays a lot slower and resists fire a bit more. - Ink spit becomes stronger, allowing it to very briefly knock down foes. - Fishing bonuses and experience - Resistance to high pressures - Slightly expanded FOV - drinking water and showers mildly heal you over time. - for felinids: You won't hate getting sprayed by water or taking a shower. - While wet: - - If the fish tail is implanted, crawling speed is boosted. - - You no longer slip on wet tiles. - - You also become slippery when lying on the floor. - - You get a very mild damage resistance and passive stamina regeneration, and cool down faster. - - You resist grabs better. - - get a very weak positive moodlet. - However, being dry will make you quite squisher, especially against fire damage, slower and give you a modest negative moodlet. While working on it, I've also noticed a few things that explained why tetrodotoxin (TTX) did jackshit at low doses, because livers have a set toxin tolerance value, below which, any amount of toxin does nothing. Also I've felt like reagents like multiver & co were a bit too strong against a reagent that's supposed to work at very low doses, with slow metabolization, so I've added a couple variables to buff TTX a bit, making it harder to purge and resistant to liver toxin tolerance (also added a bit of lungs damage). ## Why It's Good For The Game I wanted to take a shot at coding a DNA infusion and see how chock-full I could make it. DNA infusions are like a middle point between "aha, small visual trinket" and organs with generally ok effects. I seek to make something a bit more complex ~~(also tied to fishing ofc because that's more or less the recurrent gag of my recent features)~~ primaly focused around the unique theme of being strong when wet and weaker when dry. EDIT: The PR is now ready, have a set of screenshots of the (fairly mid) fish tails (and gills, barely visible) on randomly generated spessman and one consistent joe:  ## Changelog 🆑 add: Added a new infusion to the game: Fish. Its main gimmick revolves around being stronger and slippery when wet while weaker when dry. balance: Buffed tetrodotoxin a little against liver tolerance and purging reagents. /🆑
@@ -60,6 +60,7 @@
|
||||
#define DNA_MOTH_MARKINGS_BLOCK 13
|
||||
#define DNA_MUSHROOM_CAPS_BLOCK 14
|
||||
#define DNA_POD_HAIR_BLOCK 15
|
||||
#define DNA_FISH_TAIL_BLOCK 16
|
||||
|
||||
// Hey! Listen up if you're here because you're adding a species feature!
|
||||
//
|
||||
@@ -68,7 +69,7 @@
|
||||
// (Which means having a DNA block for a feature tied to a mob without DNA is entirely pointless.)
|
||||
|
||||
/// Total amount of DNA blocks, must be equal to the highest DNA block number
|
||||
#define DNA_FEATURE_BLOCKS 15
|
||||
#define DNA_FEATURE_BLOCKS 16
|
||||
|
||||
#define DNA_SEQUENCE_LENGTH 4
|
||||
#define DNA_MUTATION_BLOCKS 8
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#define ALERT_TOO_MUCH_NITRO "too_much_nitro"
|
||||
#define ALERT_NOT_ENOUGH_NITRO "not_enough_nitro"
|
||||
|
||||
#define ALERT_NOT_ENOUGH_WATER "not_enough_water"
|
||||
|
||||
/** Mob related */
|
||||
#define ALERT_SUCCUMB "succumb"
|
||||
#define ALERT_BUCKLED "buckled"
|
||||
|
||||
@@ -48,3 +48,6 @@
|
||||
|
||||
///from /datum/component/on_hit_effect/send_signal(): (user, target, hit_zone)
|
||||
#define COMSIG_ON_HIT_EFFECT "comsig_on_hit_effect"
|
||||
|
||||
///from /datum/component/bubble_icon_override/get_bubble_icon(): (list/holder)
|
||||
#define COMSIG_GET_BUBBLE_ICON "get_bubble_icon"
|
||||
|
||||
@@ -272,6 +272,9 @@
|
||||
#define COMSIG_LIVING_GRAB "living_grab"
|
||||
// Return COMPONENT_CANCEL_ATTACK_CHAIN / COMPONENT_SKIP_ATTACK_CHAIN to stop the grab
|
||||
|
||||
/// From /datum/component/edible/get_perceived_food_quality(): (datum/component/edible/edible, list/extra_quality)
|
||||
#define COMSIG_LIVING_GET_PERCEIVED_FOOD_QUALITY "get_perceived_food_quality"
|
||||
|
||||
///Called when living finish eat (/datum/component/edible/proc/On_Consume)
|
||||
#define COMSIG_LIVING_FINISH_EAT "living_finish_eat"
|
||||
|
||||
|
||||
@@ -376,6 +376,8 @@
|
||||
#define SLIP_WHEN_CRAWLING (1<<4)
|
||||
/// the mob won't slip if the turf has the TRAIT_TURF_IGNORE_SLIPPERY trait.
|
||||
#define SLIPPERY_TURF (1<<5)
|
||||
/// For mobs who are slippery, this requires the mob holding it to be lying down.
|
||||
#define SLIPPERY_WHEN_LYING_DOWN (1<<6)
|
||||
|
||||
#define MAX_CHICKENS 50
|
||||
|
||||
|
||||
@@ -122,3 +122,7 @@
|
||||
/// Meaning that if the message is visual, and sourced from a blind mob, they will not see it.
|
||||
/// This flag skips that behavior, and will always show the self message to the mob.
|
||||
#define ALWAYS_SHOW_SELF_MESSAGE (1<<1)
|
||||
|
||||
///Defines for priorities for the bubble_icon_override comp
|
||||
#define BUBBLE_ICON_PRIORITY_ACCESSORY 2
|
||||
#define BUBBLE_ICON_PRIORITY_ORGAN 1
|
||||
|
||||
@@ -185,6 +185,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_DISGUISED "disguised"
|
||||
/// Use when you want a mob to be able to metabolize plasma temporarily (e.g. plasma fixation disease symptom)
|
||||
#define TRAIT_PLASMA_LOVER_METABOLISM "plasma_lover_metabolism"
|
||||
/// The mob is not harmed by tetrodotoxin. Instead, it heals them like omnizine
|
||||
#define TRAIT_TETRODOTOXIN_HEALING "tetrodotoxin_healing"
|
||||
#define TRAIT_EASYDISMEMBER "easy_dismember"
|
||||
#define TRAIT_LIMBATTACHMENT "limb_attach"
|
||||
#define TRAIT_NOLIMBDISABLE "no_limb_disable"
|
||||
@@ -247,6 +249,16 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_MESSAGE_IN_A_BOTTLE_LOCATION "message_in_a_bottle_location"
|
||||
/// Stops other objects of the same type from being inserted inside the same aquarium it's in.
|
||||
#define TRAIT_UNIQUE_AQUARIUM_CONTENT "unique_aquarium_content"
|
||||
/// Mobs that hate showers, being sprayed with water etc.
|
||||
#define TRAIT_WATER_HATER "water_hater"
|
||||
/// Improved boons from showers and some features centered around water, should also suppress TRAIT_WATER_HATER
|
||||
#define TRAIT_WATER_ADAPTATION "water_adaptation"
|
||||
/// Tells us that the mob urrently has the fire_handler/wet_stacks status effect
|
||||
#define TRAIT_IS_WET "is_wet"
|
||||
/// Mobs with this trait stay wet for longer and resist fire decaying wetness
|
||||
#define TRAIT_WET_FOR_LONGER "wet_for_longer"
|
||||
/// Mobs with this trait will be immune to slipping while also being slippery themselves when lying on the floor
|
||||
#define TRAIT_SLIPPERY_WHEN_WET "slippery_when_wet"
|
||||
/// This trait lets you evaluate someone's fitness level against your own
|
||||
#define TRAIT_EXAMINE_FITNESS "reveal_power_level"
|
||||
/// These mobs have particularly hygienic tongues
|
||||
@@ -724,6 +736,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_HONKSPAMMING "trait_honkspamming"
|
||||
/// Required by the waddling element since there are multiple sources of it.
|
||||
#define TRAIT_WADDLING "trait_waddling"
|
||||
/// Mobs with trait will still waddle even when lying on the floor and make a different footstep sound when doing so.
|
||||
#define TRAIT_FLOPPING "trait_flopping"
|
||||
/// Required by the on_hit_effect element, which is in turn added by other elements.
|
||||
#define TRAIT_ON_HIT_EFFECT "trait_on_hit_effect"
|
||||
|
||||
@@ -839,6 +853,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_EVIL "evil"
|
||||
#define TRAIT_FRIENDLY "friendly"
|
||||
#define TRAIT_GRABWEAKNESS "grab_weakness"
|
||||
#define TRAIT_GRABRESISTANCE "grab_resistance"
|
||||
#define TRAIT_SNOB "snob"
|
||||
#define TRAIT_BALD "bald"
|
||||
#define TRAIT_SHAVED "shaved"
|
||||
|
||||
@@ -248,6 +248,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS,
|
||||
"TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE,
|
||||
"TRAIT_FLOORED" = TRAIT_FLOORED,
|
||||
"TRAIT_FLOPPING" = TRAIT_FLOPPING,
|
||||
"TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION" = TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION,
|
||||
"TRAIT_FORCED_GRAVITY" = TRAIT_FORCED_GRAVITY,
|
||||
"TRAIT_FORCED_STANDING" = TRAIT_FORCED_STANDING,
|
||||
@@ -265,6 +266,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_GIANT" = TRAIT_GIANT,
|
||||
"TRAIT_GODMODE" = TRAIT_GODMODE,
|
||||
"TRAIT_GOOD_HEARING" = TRAIT_GOOD_HEARING,
|
||||
"TRAIT_GRABRESISTANCE" = TRAIT_GRABRESISTANCE,
|
||||
"TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS,
|
||||
"TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED,
|
||||
"TRAIT_GUNFLIP" = TRAIT_GUNFLIP,
|
||||
@@ -300,6 +302,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_INVISIBLE_MAN" = TRAIT_INVISIBLE_MAN,
|
||||
"TRAIT_INVISIMIN" = TRAIT_INVISIMIN,
|
||||
"TRAIT_IN_CALL" = TRAIT_IN_CALL,
|
||||
"TRAIT_IS_WET" = TRAIT_IS_WET,
|
||||
"TRAIT_IWASBATONED" = TRAIT_IWASBATONED,
|
||||
"TRAIT_JOLLY" = TRAIT_JOLLY,
|
||||
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
|
||||
@@ -463,6 +466,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
|
||||
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
|
||||
"TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE,
|
||||
"TRAIT_SLIPPERY_WHEN_WET" = TRAIT_SLIPPERY_WHEN_WET,
|
||||
"TRAIT_SMOKER" = TRAIT_SMOKER,
|
||||
"TRAIT_SNEAK" = TRAIT_SNEAK,
|
||||
"TRAIT_SNOB" = TRAIT_SNOB,
|
||||
@@ -503,6 +507,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_TENACIOUS" = TRAIT_TENACIOUS,
|
||||
"TRAIT_TENTACLE_IMMUNE" = TRAIT_TENTACLE_IMMUNE,
|
||||
"TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE,
|
||||
"TRAIT_TETRODOTOXIN_HEALING" = TRAIT_TETRODOTOXIN_HEALING,
|
||||
"TRAIT_THERMAL_VISION" = TRAIT_THERMAL_VISION,
|
||||
"TRAIT_THINKING_IN_CHARACTER" = TRAIT_THINKING_IN_CHARACTER,
|
||||
"TRAIT_THROWINGARM" = TRAIT_THROWINGARM,
|
||||
@@ -536,9 +541,12 @@ GLOBAL_LIST_INIT(traits_by_type, list(
|
||||
"TRAIT_VIRUS_RESISTANCE" = TRAIT_VIRUS_RESISTANCE,
|
||||
"TRAIT_VORACIOUS" = TRAIT_VORACIOUS,
|
||||
"TRAIT_WAS_EVOLVED" = TRAIT_WAS_EVOLVED,
|
||||
"TRAIT_WATER_ADAPTATION" = TRAIT_WATER_ADAPTATION,
|
||||
"TRAIT_WATER_HATER" = TRAIT_WATER_HATER,
|
||||
"TRAIT_WEAK_SOUL" = TRAIT_WEAK_SOUL,
|
||||
"TRAIT_WEB_SURFER" = TRAIT_WEB_SURFER,
|
||||
"TRAIT_WEB_WEAVER" = TRAIT_WEB_WEAVER,
|
||||
"TRAIT_WET_FOR_LONGER" = TRAIT_WET_FOR_LONGER,
|
||||
"TRAIT_WINE_TASTER" = TRAIT_WINE_TASTER,
|
||||
"TRAIT_WING_BUFFET" = TRAIT_WING_BUFFET,
|
||||
"TRAIT_WING_BUFFET_TIRED" = TRAIT_WING_BUFFET_TIRED,
|
||||
|
||||
@@ -121,6 +121,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_GIANT" = TRAIT_GIANT,
|
||||
"TRAIT_GODMODE" = TRAIT_GODMODE,
|
||||
"TRAIT_GOOD_HEARING" = TRAIT_GOOD_HEARING,
|
||||
"TRAIT_GRABRESISTANCE" = TRAIT_GRABRESISTANCE,
|
||||
"TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS,
|
||||
"TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED,
|
||||
"TRAIT_GUNFLIP" = TRAIT_GUNFLIP,
|
||||
@@ -262,6 +263,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
|
||||
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
|
||||
"TRAIT_SLEEPIMMUNE" = TRAIT_SLEEPIMMUNE,
|
||||
"TRAIT_SLIPPERY_WHEN_WET" = TRAIT_SLIPPERY_WHEN_WET,
|
||||
"TRAIT_SMOKER" = TRAIT_SMOKER,
|
||||
"TRAIT_SNOB" = TRAIT_SNOB,
|
||||
"TRAIT_SOFTSPOKEN" = TRAIT_SOFTSPOKEN,
|
||||
@@ -283,6 +285,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_TAGGER" = TRAIT_TAGGER,
|
||||
"TRAIT_TENTACLE_IMMUNE" = TRAIT_TENTACLE_IMMUNE,
|
||||
"TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE,
|
||||
"TRAIT_TETRODOTOXIN_HEALING" = TRAIT_TETRODOTOXIN_HEALING,
|
||||
"TRAIT_THERMAL_VISION" = TRAIT_THERMAL_VISION,
|
||||
"TRAIT_THROWINGARM" = TRAIT_THROWINGARM,
|
||||
"TRAIT_TIME_STOP_IMMUNE" = TRAIT_TIME_STOP_IMMUNE,
|
||||
@@ -308,11 +311,14 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
|
||||
"TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE,
|
||||
"TRAIT_VIRUS_RESISTANCE" = TRAIT_VIRUS_RESISTANCE,
|
||||
"TRAIT_VORACIOUS" = TRAIT_VORACIOUS,
|
||||
"TRAIT_WOUND_LICKER" = TRAIT_WOUND_LICKER,
|
||||
"TRAIT_WATER_ADAPTATION" = TRAIT_WATER_ADAPTATION,
|
||||
"TRAIT_WATER_HATER" = TRAIT_WATER_HATER,
|
||||
"TRAIT_WEAK_SOUL" = TRAIT_WEAK_SOUL,
|
||||
"TRAIT_WEB_SURFER" = TRAIT_WEB_SURFER,
|
||||
"TRAIT_WEB_WEAVER" = TRAIT_WEB_WEAVER,
|
||||
"TRAIT_WET_FOR_LONGER" = TRAIT_WET_FOR_LONGER,
|
||||
"TRAIT_WINE_TASTER" = TRAIT_WINE_TASTER,
|
||||
"TRAIT_WOUND_LICKER" = TRAIT_WOUND_LICKER,
|
||||
"TRAIT_XENO_HOST" = TRAIT_XENO_HOST,
|
||||
"TRAIT_XENO_IMMUNE" = TRAIT_XENO_IMMUNE,
|
||||
"TRAIT_XRAY_HEARING" = TRAIT_XRAY_HEARING,
|
||||
|
||||
@@ -183,6 +183,11 @@
|
||||
desc = "There's sleeping gas in the air and you're breathing it in. Find some fresh air. The box in your backpack has an oxygen tank and breath mask in it."
|
||||
icon_state = ALERT_TOO_MUCH_N2O
|
||||
|
||||
/atom/movable/screen/alert/not_enough_water
|
||||
name = "Choking (No H2O)"
|
||||
desc = "You're not getting enough water. Drench yourself in some water (e.g. showers) or get some water vapor before you pass out!"
|
||||
icon_state = ALERT_NOT_ENOUGH_WATER
|
||||
|
||||
//End gas alerts
|
||||
|
||||
/atom/movable/screen/alert/gross
|
||||
|
||||
@@ -43,9 +43,10 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity
|
||||
var/list/tail_spines_list
|
||||
|
||||
//Mutant Human bits
|
||||
var/list/tails_list_human
|
||||
var/list/tails_list_felinid
|
||||
var/list/tails_list_lizard
|
||||
var/list/tails_list_monkey
|
||||
var/list/tails_list_fish
|
||||
var/list/ears_list
|
||||
var/list/wings_list
|
||||
var/list/wings_open_list
|
||||
@@ -87,9 +88,11 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity
|
||||
socks_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/socks)[DEFAULT_SPRITE_LIST]
|
||||
|
||||
lizard_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/lizard_markings, add_blank = TRUE)[DEFAULT_SPRITE_LIST]
|
||||
tails_list_human = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, add_blank = TRUE)[DEFAULT_SPRITE_LIST]
|
||||
tails_list_felinid = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/felinid, add_blank = TRUE)[DEFAULT_SPRITE_LIST]
|
||||
tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard)[DEFAULT_SPRITE_LIST]
|
||||
tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey)[DEFAULT_SPRITE_LIST]
|
||||
//tails fo fish organ infusions, not for prefs.
|
||||
tails_list_fish = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/fish)[DEFAULT_SPRITE_LIST]
|
||||
snouts_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts)[DEFAULT_SPRITE_LIST]
|
||||
horns_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, add_blank = TRUE)[DEFAULT_SPRITE_LIST]
|
||||
ears_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, add_blank = TRUE)[DEFAULT_SPRITE_LIST]
|
||||
|
||||
@@ -127,15 +127,21 @@
|
||||
if(ORGAN_COLOR_INHERIT)
|
||||
draw_color = bodypart_owner.draw_color
|
||||
if(ORGAN_COLOR_HAIR)
|
||||
var/datum/species/species = bodypart_owner.owner?.dna?.species
|
||||
var/fixed_color = species?.get_fixed_hair_color(bodypart_owner)
|
||||
if(!ishuman(bodypart_owner.owner))
|
||||
draw_color = fixed_color
|
||||
return
|
||||
var/mob/living/carbon/human/human_owner = bodypart_owner.owner
|
||||
var/obj/item/bodypart/head/my_head = human_owner.get_bodypart(BODY_ZONE_HEAD) //not always the same as bodypart_owner
|
||||
//head hair color takes priority, owner hair color is a backup if we lack a head or something
|
||||
if(my_head)
|
||||
draw_color = my_head.hair_color
|
||||
else
|
||||
draw_color = human_owner.hair_color
|
||||
if(!my_head)
|
||||
draw_color = fixed_color || human_owner.hair_color
|
||||
return
|
||||
if(my_head.head_flags & (HEAD_HAIR|HEAD_FACIAL_HAIR))
|
||||
draw_color = my_head.fixed_hair_color || my_head.hair_color
|
||||
else //inherit mutant color of the bodypart if the owner doesn't have hair.
|
||||
draw_color = bodypart_owner.draw_color
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
99
code/datums/components/bubble_icon_override.dm
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* A component that overrides the bubble_icon variable when equipped or implanted
|
||||
* while having a simple priority system, so accessories have higher priority than
|
||||
* organs, for example.
|
||||
*/
|
||||
/datum/component/bubble_icon_override
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
can_transfer = TRUE //sure why not
|
||||
///The override to the default bubble icon for the atom
|
||||
var/bubble_icon
|
||||
///The priority of this bubble icon compared to others
|
||||
var/priority
|
||||
|
||||
/datum/component/bubble_icon_override/Initialize(bubble_icon, priority)
|
||||
if(!isclothing(parent) && !isorgan(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
src.bubble_icon = bubble_icon
|
||||
src.priority = priority
|
||||
|
||||
/datum/component/bubble_icon_override/RegisterWithParent()
|
||||
if(isclothing(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped))
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped))
|
||||
else if(isorgan(parent))
|
||||
RegisterSignal(parent, COMSIG_ORGAN_IMPLANTED, PROC_REF(on_organ_implanted))
|
||||
RegisterSignal(parent, COMSIG_ORGAN_REMOVED, PROC_REF(on_organ_removed))
|
||||
var/mob/living/target = get_bubble_icon_target()
|
||||
if(target)
|
||||
register_owner(target)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/register_owner(mob/living/owner)
|
||||
RegisterSignal(owner, COMSIG_GET_BUBBLE_ICON, PROC_REF(return_bubble_icon))
|
||||
get_bubble_icon(owner)
|
||||
|
||||
/datum/component/bubble_icon_override/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_ITEM_EQUIPPED,
|
||||
COMSIG_ITEM_DROPPED,
|
||||
COMSIG_ORGAN_IMPLANTED,
|
||||
COMSIG_ORGAN_REMOVED,
|
||||
))
|
||||
var/mob/living/target = get_bubble_icon_target()
|
||||
if(target)
|
||||
unregister_owner(target)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/unregister_owner(mob/living/owner)
|
||||
UnregisterSignal(owner, list(COMSIG_GET_BUBBLE_ICON))
|
||||
get_bubble_icon(owner)
|
||||
|
||||
///Returns the potential wearer/owner of the object when the component is un/registered to/from it
|
||||
/datum/component/bubble_icon_override/proc/get_bubble_icon_target()
|
||||
if(isclothing(parent))
|
||||
var/obj/item/clothing/clothing = parent
|
||||
if(istype(clothing, /obj/item/clothing/accessory))
|
||||
clothing = clothing.loc
|
||||
if(!istype(clothing))
|
||||
return null
|
||||
var/mob/living/wearer = clothing.loc
|
||||
if(istype(wearer) && (wearer.get_slot_by_item(clothing) & clothing.slot_flags))
|
||||
return parent
|
||||
else if(isorgan(parent))
|
||||
var/obj/item/organ/organ = parent
|
||||
return organ.owner
|
||||
|
||||
/datum/component/bubble_icon_override/proc/on_equipped(obj/item/source, mob/equipper, slot)
|
||||
SIGNAL_HANDLER
|
||||
if(slot & source.slot_flags)
|
||||
register_owner(equipper)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/on_dropped(obj/item/source, mob/dropper)
|
||||
SIGNAL_HANDLER
|
||||
unregister_owner(dropper)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/on_organ_implanted(obj/item/organ/source, mob/owner)
|
||||
SIGNAL_HANDLER
|
||||
register_owner(owner)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/on_organ_removed(obj/item/organ/source, mob/owner)
|
||||
SIGNAL_HANDLER
|
||||
unregister_owner(owner)
|
||||
|
||||
/**
|
||||
* Get the bubble icon with the highest priority from all instances of bubble_icon_override
|
||||
* currently registered with the target.
|
||||
*/
|
||||
/datum/component/bubble_icon_override/proc/get_bubble_icon(mob/living/target)
|
||||
if(QDELETED(parent))
|
||||
return
|
||||
var/list/holder = list(null)
|
||||
SEND_SIGNAL(target, COMSIG_GET_BUBBLE_ICON, holder)
|
||||
var/bubble_icon = holder[1]
|
||||
target.bubble_icon = bubble_icon || initial(target.bubble_icon)
|
||||
|
||||
/datum/component/bubble_icon_override/proc/return_bubble_icon(datum/source, list/holder)
|
||||
SIGNAL_HANDLER
|
||||
var/enemy_priority = holder[holder[1]]
|
||||
if(enemy_priority < priority)
|
||||
holder[1] = bubble_icon
|
||||
holder[bubble_icon] = priority
|
||||
@@ -599,8 +599,12 @@ Behavior that's still missing from this component that original food items had t
|
||||
return food.crafting_complexity + complexity_to_add
|
||||
|
||||
/// Get food quality adjusted according to eater's preferences
|
||||
/datum/component/edible/proc/get_perceived_food_quality(mob/living/carbon/human/eater)
|
||||
/datum/component/edible/proc/get_perceived_food_quality(mob/living/eater)
|
||||
var/food_quality = get_recipe_complexity()
|
||||
var/list/extra_quality = list()
|
||||
SEND_SIGNAL(eater, COMSIG_LIVING_GET_PERCEIVED_FOOD_QUALITY, src, extra_quality)
|
||||
for(var/quality in extra_quality)
|
||||
food_quality += quality
|
||||
|
||||
if(HAS_TRAIT(parent, TRAIT_FOOD_SILVER)) // it's not real food
|
||||
if(!isjellyperson(eater)) //if you aren't a jellyperson, it makes you sick no matter how nice it looks
|
||||
|
||||
@@ -38,14 +38,11 @@
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(Slip),
|
||||
)
|
||||
|
||||
///what we give to connect_loc if we're an item and get equipped by a mob. makes slippable mobs moving over our holder slip
|
||||
var/static/list/holder_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(Slip_on_wearer),
|
||||
///what we give to connect_loc if we're an item and get equipped by a mob, or if we're a mob. makes slippable mobs moving over the mob slip
|
||||
var/static/list/mob_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(slip_on_mob),
|
||||
)
|
||||
|
||||
/// The connect_loc_behalf component for the holder_connections list.
|
||||
var/datum/weakref/holder_connect_loc_behalf
|
||||
|
||||
/**
|
||||
* Initialize the slippery component behaviour
|
||||
*
|
||||
@@ -79,14 +76,14 @@
|
||||
src.slot_whitelist = slot_whitelist
|
||||
|
||||
add_connect_loc_behalf_to_parent()
|
||||
if(ismovable(parent))
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
|
||||
RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses))
|
||||
RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses))
|
||||
else
|
||||
if(!ismovable(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_ENTERED, PROC_REF(Slip))
|
||||
else if(isitem(parent))
|
||||
src.lube_flags |= SLIPPERY_WHEN_LYING_DOWN
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip))
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_drop))
|
||||
RegisterSignal(parent, COMSIG_ITEM_APPLY_FANTASY_BONUSES, PROC_REF(apply_fantasy_bonuses))
|
||||
RegisterSignal(parent, COMSIG_ITEM_REMOVE_FANTASY_BONUSES, PROC_REF(remove_fantasy_bonuses))
|
||||
|
||||
/datum/component/slippery/Destroy(force)
|
||||
can_slip_callback = null
|
||||
@@ -114,8 +111,13 @@
|
||||
lube_flags = previous_lube_flags
|
||||
|
||||
/datum/component/slippery/proc/add_connect_loc_behalf_to_parent()
|
||||
if(ismovable(parent))
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, default_connections)
|
||||
var/list/connections_to_use
|
||||
if(isliving(parent))
|
||||
connections_to_use = mob_connections
|
||||
else if(ismovable(parent))
|
||||
connections_to_use = default_connections
|
||||
if(connections_to_use)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, connections_to_use)
|
||||
|
||||
/datum/component/slippery/InheritComponent(
|
||||
datum/component/slippery/component,
|
||||
@@ -184,7 +186,7 @@
|
||||
if((!LAZYLEN(slot_whitelist) || (slot in slot_whitelist)) && isliving(equipper))
|
||||
holder = equipper
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, holder, mob_connections)
|
||||
RegisterSignal(holder, COMSIG_QDELETING, PROC_REF(holder_deleted))
|
||||
|
||||
/**
|
||||
@@ -227,10 +229,11 @@
|
||||
* * source - the source of the signal
|
||||
* * arrived - the atom/movable that slipped on us.
|
||||
*/
|
||||
/datum/component/slippery/proc/Slip_on_wearer(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
/datum/component/slippery/proc/slip_on_mob(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(holder.body_position == LYING_DOWN && !holder.buckled)
|
||||
var/mob/living/living = holder || parent
|
||||
if(!(lube_flags & SLIPPERY_WHEN_LYING_DOWN) || (living.body_position == LYING_DOWN && !living.buckled))
|
||||
Slip(source, arrived)
|
||||
|
||||
/datum/component/slippery/UnregisterFromParent()
|
||||
|
||||
@@ -71,4 +71,5 @@
|
||||
if(can_splat_on && is_type_in_typecache(hit_atom, GLOB.splattable))
|
||||
hit_atom.AddComponent(/datum/component/face_decal/splat, icon_state, layer, splat_color || source.color, memory_type, moodlet_type)
|
||||
SEND_SIGNAL(source, COMSIG_MOVABLE_SPLAT, hit_atom)
|
||||
qdel(source)
|
||||
if(!isprojectile(source))
|
||||
qdel(source)
|
||||
|
||||
@@ -223,7 +223,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
if(features["lizard_markings"])
|
||||
L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list))
|
||||
if(features["tail_cat"])
|
||||
L[DNA_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human))
|
||||
L[DNA_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_felinid.Find(features["tail_cat"]), length(SSaccessories.tails_list_felinid))
|
||||
if(features["tail_lizard"])
|
||||
L[DNA_LIZARD_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard))
|
||||
if(features["snout"])
|
||||
@@ -246,6 +246,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
L[DNA_MUSHROOM_CAPS_BLOCK] = construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list))
|
||||
if(features["pod_hair"])
|
||||
L[DNA_POD_HAIR_BLOCK] = construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list))
|
||||
if(features["fish_tail"])
|
||||
L[DNA_FISH_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_fish.Find(features["fish_tail"]), length(SSaccessories.tails_list_fish))
|
||||
|
||||
for(var/blocknum in 1 to DNA_FEATURE_BLOCKS)
|
||||
. += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters)
|
||||
@@ -367,7 +369,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
if(DNA_LIZARD_MARKINGS_BLOCK)
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list)))
|
||||
if(DNA_TAIL_BLOCK)
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human)))
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_felinid.Find(features["tail_cat"]), length(SSaccessories.tails_list_felinid)))
|
||||
if(DNA_LIZARD_TAIL_BLOCK)
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard)))
|
||||
if(DNA_SNOUT_BLOCK)
|
||||
@@ -390,6 +392,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list)))
|
||||
if(DNA_POD_HAIR_BLOCK)
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list)))
|
||||
if(DNA_FISH_TAIL_BLOCK)
|
||||
set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_fish.Find(features["fish_tail"]), length(SSaccessories.tails_list_fish)))
|
||||
|
||||
//Please use add_mutation or activate_mutation instead
|
||||
/datum/dna/proc/force_give(datum/mutation/human/human_mutation)
|
||||
@@ -672,7 +676,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
if(dna.features["spines"])
|
||||
dna.features["spines"] = SSaccessories.spines_list[deconstruct_block(get_uni_feature_block(features, DNA_SPINES_BLOCK), length(SSaccessories.spines_list))]
|
||||
if(dna.features["tail_cat"])
|
||||
dna.features["tail_cat"] = SSaccessories.tails_list_human[deconstruct_block(get_uni_feature_block(features, DNA_TAIL_BLOCK), length(SSaccessories.tails_list_human))]
|
||||
dna.features["tail_cat"] = SSaccessories.tails_list_felinid[deconstruct_block(get_uni_feature_block(features, DNA_TAIL_BLOCK), length(SSaccessories.tails_list_felinid))]
|
||||
if(dna.features["tail_lizard"])
|
||||
dna.features["tail_lizard"] = SSaccessories.tails_list_lizard[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_TAIL_BLOCK), length(SSaccessories.tails_list_lizard))]
|
||||
if(dna.features["ears"])
|
||||
@@ -691,6 +695,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
dna.features["caps"] = SSaccessories.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), length(SSaccessories.caps_list))]
|
||||
if(dna.features["pod_hair"])
|
||||
dna.features["pod_hair"] = SSaccessories.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), length(SSaccessories.pod_hair_list))]
|
||||
if(dna.features["fish_tail"])
|
||||
dna.features["fish_tail"] = SSaccessories.tails_list_fish[deconstruct_block(get_uni_feature_block(features, DNA_FISH_TAIL_BLOCK), length(SSaccessories.tails_list_fish))]
|
||||
|
||||
for(var/obj/item/organ/organ in organs)
|
||||
organ.mutate_feature(features, src)
|
||||
|
||||
@@ -71,7 +71,10 @@
|
||||
|
||||
if(source.body_position == LYING_DOWN) //play crawling sound if we're lying
|
||||
if(turf.footstep)
|
||||
playsound(turf, 'sound/effects/footstep/crawl1.ogg', 15 * volume, falloff_distance = 1, vary = sound_vary)
|
||||
var/sound = 'sound/effects/footstep/crawl1.ogg'
|
||||
if(HAS_TRAIT(source, TRAIT_FLOPPING))
|
||||
sound = pick(SFX_FISH_PICKUP, 'sound/mobs/non-humanoids/fish/fish_drop1.ogg')
|
||||
playsound(turf, sound, 15 * volume, falloff_distance = 1, vary = sound_vary)
|
||||
return
|
||||
|
||||
if(iscarbon(source) && source.move_intent == MOVE_INTENT_WALK)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
return
|
||||
if(isliving(moved))
|
||||
var/mob/living/living_moved = moved
|
||||
if (living_moved.incapacitated || living_moved.body_position == LYING_DOWN)
|
||||
if (living_moved.incapacitated || (living_moved.body_position == LYING_DOWN && !HAS_TRAIT(living_moved, TRAIT_FLOPPING)))
|
||||
return
|
||||
waddling_animation(moved)
|
||||
|
||||
|
||||
@@ -2,3 +2,8 @@
|
||||
name = "Mutant Organ"
|
||||
icon_file = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/mutant_organs.json'
|
||||
|
||||
/datum/greyscale_config/fish_tail
|
||||
name = "Fish Tail"
|
||||
icon_file = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
json_config = 'code/datums/greyscale/json_configs/fish_tail.json'
|
||||
|
||||
15
code/datums/greyscale/json_configs/fish_tail.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"fish_tail": [
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "fish_tail",
|
||||
"blend_mode": "overlay",
|
||||
"color_ids": [ 1 ]
|
||||
},
|
||||
{
|
||||
"type": "icon_state",
|
||||
"icon_state": "fish_tail_meat",
|
||||
"blend_mode": "overlay"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7,3 +7,11 @@
|
||||
description = "There's a lot that could be on your mind right now. But this feeling of contentedness, a universal calling to simply sit back and observe is washing over you..."
|
||||
mood_change = 10
|
||||
special_screen_obj = "mood_gondola"
|
||||
|
||||
/datum/mood_event/fish_waterless
|
||||
mood_change = -3
|
||||
description = "It sucks to be dry. I feel like a fish out of water."
|
||||
|
||||
/datum/mood_event/fish_water
|
||||
mood_change = 1
|
||||
description = "Glug glug!"
|
||||
|
||||
@@ -1744,6 +1744,23 @@
|
||||
/// Describes which tail spine sprites to use, if any.
|
||||
var/spine_key = NONE
|
||||
|
||||
///Used for fish-infused tails, which come in different flavors.
|
||||
/datum/sprite_accessory/tails/fish
|
||||
icon = 'icons/mob/human/fish_features.dmi'
|
||||
color_src = HAIR_COLOR
|
||||
|
||||
/datum/sprite_accessory/tails/fish/default
|
||||
name = "Fish"
|
||||
icon_state = "fish"
|
||||
|
||||
/datum/sprite_accessory/tails/fish/shark
|
||||
name = "Shark"
|
||||
icon_state = "shark"
|
||||
|
||||
/datum/sprite_accessory/tails/fish/orca
|
||||
name = "Orca"
|
||||
icon_state = "orca"
|
||||
|
||||
/datum/sprite_accessory/tails/lizard
|
||||
icon = 'icons/mob/human/species/lizard/lizard_tails.dmi'
|
||||
spine_key = SPINE_KEY_LIZARD
|
||||
@@ -1774,7 +1791,7 @@
|
||||
icon_state = "short"
|
||||
spine_key = NONE
|
||||
|
||||
/datum/sprite_accessory/tails/human/cat
|
||||
/datum/sprite_accessory/tails/felinid/cat
|
||||
name = "Cat"
|
||||
icon = 'icons/mob/human/cat_features.dmi'
|
||||
icon_state = "default"
|
||||
|
||||
@@ -300,12 +300,45 @@
|
||||
|
||||
enemy_types = list(/datum/status_effect/fire_handler/fire_stacks)
|
||||
stack_modifier = -1
|
||||
///If the mob has the TRAIT_SLIPPERY_WHEN_WET trait, the mob gets this component while it's wet
|
||||
var/datum/component/slippery/slipperiness
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/on_apply()
|
||||
. = ..()
|
||||
RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_WET_FOR_LONGER), SIGNAL_REMOVETRAIT(TRAIT_WET_FOR_LONGER)), PROC_REF(update_wet_stack_modifier))
|
||||
update_wet_stack_modifier()
|
||||
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_SLIPPERY_WHEN_WET), PROC_REF(become_slippery))
|
||||
RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_SLIPPERY_WHEN_WET), PROC_REF(no_longer_slippery))
|
||||
if(HAS_TRAIT(owner, TRAIT_SLIPPERY_WHEN_WET))
|
||||
become_slippery()
|
||||
ADD_TRAIT(owner, TRAIT_IS_WET, TRAIT_STATUS_EFFECT(id))
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/on_remove()
|
||||
. = ..()
|
||||
REMOVE_TRAIT(owner, TRAIT_IS_WET, TRAIT_STATUS_EFFECT(id))
|
||||
if(HAS_TRAIT(owner, TRAIT_SLIPPERY_WHEN_WET))
|
||||
no_longer_slippery()
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/proc/update_wet_stack_modifier()
|
||||
SIGNAL_HANDLER
|
||||
stack_modifier = HAS_TRAIT(owner, TRAIT_WET_FOR_LONGER) ? -3.5 : -1
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/proc/become_slippery()
|
||||
SIGNAL_HANDLER
|
||||
slipperiness = owner.AddComponent(/datum/component/slippery, 5 SECONDS, lube_flags = SLIPPERY_WHEN_LYING_DOWN)
|
||||
ADD_TRAIT(owner, TRAIT_NO_SLIP_WATER, TRAIT_STATUS_EFFECT(id))
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/proc/no_longer_slippery()
|
||||
SIGNAL_HANDLER
|
||||
QDEL_NULL(slipperiness)
|
||||
REMOVE_TRAIT(owner, TRAIT_NO_SLIP_WATER, TRAIT_STATUS_EFFECT(id))
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/get_examine_text()
|
||||
return "[owner.p_They()] look[owner.p_s()] a little soaked."
|
||||
|
||||
/datum/status_effect/fire_handler/wet_stacks/tick(seconds_between_ticks)
|
||||
adjust_stacks(-0.5 * seconds_between_ticks)
|
||||
var/decay = HAS_TRAIT(owner, TRAIT_WET_FOR_LONGER) ? -0.035 : -0.5
|
||||
adjust_stacks(decay * seconds_between_ticks)
|
||||
if(stacks <= 0)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -615,10 +615,10 @@
|
||||
desc = "A good wash fills me with energy!"
|
||||
icon_state = "shower_regen"
|
||||
|
||||
/atom/movable/screen/alert/status_effect/shower_regen/catgirl
|
||||
/atom/movable/screen/alert/status_effect/shower_regen/hater
|
||||
name = "Washing"
|
||||
desc = "Waaater... Fuck this WATER!!"
|
||||
icon_state = "shower_regen_catgirl"
|
||||
icon_state = "shower_regen_hater"
|
||||
|
||||
/datum/status_effect/shower_regen
|
||||
id = "shower_regen"
|
||||
@@ -630,11 +630,17 @@
|
||||
|
||||
/datum/status_effect/shower_regen/on_apply()
|
||||
. = ..()
|
||||
if(isfelinid(owner))
|
||||
alert_type = /atom/movable/screen/alert/status_effect/shower_regen/catgirl
|
||||
|
||||
if(HAS_TRAIT(owner, TRAIT_WATER_HATER) && !HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION))
|
||||
alert_type = /atom/movable/screen/alert/status_effect/shower_regen/hater
|
||||
|
||||
/datum/status_effect/shower_regen/tick(seconds_between_ticks)
|
||||
. = ..()
|
||||
var/heal_or_deal = isfelinid(owner) ? 1 : -1
|
||||
var/water_adaptation = HAS_TRAIT(owner, TRAIT_WATER_ADAPTATION)
|
||||
var/heal_or_deal = HAS_TRAIT(owner, TRAIT_WATER_HATER) && !water_adaptation ? 1 : -1
|
||||
if(water_adaptation) //very mild healing for those with the water adaptation trait (fish infusion)
|
||||
owner.adjustOxyLoss(-1 * seconds_between_ticks, updating_health = FALSE, required_biotype = MOB_ORGANIC)
|
||||
owner.adjustFireLoss(-0.6 * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
|
||||
owner.adjustToxLoss(-0.6 * seconds_between_ticks, updating_health = FALSE, required_biotype = MOB_ORGANIC)
|
||||
owner.adjustBruteLoss(-0.6 * seconds_between_ticks, updating_health = FALSE, required_bodytype = BODYTYPE_ORGANIC)
|
||||
heal_or_deal *= 1.5
|
||||
owner.adjustStaminaLoss(stamina_heal_per_tick * heal_or_deal * seconds_between_ticks)
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
// Valid organ successfully picked.
|
||||
new_organ = new new_organ()
|
||||
new_organ.replace_into(src)
|
||||
//make sure bodypart overlays are correctly displayed.
|
||||
update_body_parts()
|
||||
return TRUE
|
||||
|
||||
/// Picks a random mutated organ from the given infuser entry which is also compatible with this human.
|
||||
|
||||
61
code/game/machinery/dna_infuser/infuser_actions.dm
Normal file
@@ -0,0 +1,61 @@
|
||||
///Action from the inky tongue, from fish with the ink production trait.
|
||||
/datum/action/cooldown/ink_spit
|
||||
name = "Spit Ink"
|
||||
desc = "Spits ink at someone, blinding them temporarily."
|
||||
button_icon = 'icons/hud/radial_fishing.dmi'
|
||||
button_icon_state = "oil"
|
||||
base_background_icon_state = "bg_default"
|
||||
active_background_icon_state = "bg_default_on"
|
||||
check_flags = AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_INCAPACITATED
|
||||
click_to_activate = TRUE
|
||||
unset_after_click = TRUE
|
||||
cooldown_time = 21 SECONDS
|
||||
|
||||
/datum/action/cooldown/ink_spit/IsAvailable(feedback = FALSE)
|
||||
var/mob/living/carbon/as_carbon = owner
|
||||
if(istype(as_carbon) && as_carbon.is_mouth_covered(ITEM_SLOT_MASK))
|
||||
return FALSE
|
||||
if(!isturf(owner.loc))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/action/cooldown/ink_spit/set_click_ability(mob/on_who)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
to_chat(on_who, span_notice("You prepare your ink glands. <B>Right-click to fire at a target!</B>"))
|
||||
build_all_button_icons()
|
||||
|
||||
/datum/action/cooldown/ink_spit/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
build_all_button_icons()
|
||||
|
||||
// We do this in InterceptClickOn() instead of Activate()
|
||||
// because we use the click parameters for aiming the projectile
|
||||
// (or something like that)
|
||||
/datum/action/cooldown/ink_spit/InterceptClickOn(mob/living/caller, params, atom/target)
|
||||
if(!LAZYACCESS(params2list(params), RIGHT_CLICK))
|
||||
return
|
||||
. = ..()
|
||||
|
||||
var/modifiers = params2list(params)
|
||||
caller.visible_message(
|
||||
span_danger("[caller] spits ink!"),
|
||||
span_bold("You spit ink."),
|
||||
)
|
||||
var/obj/projectile/ink_spit/ink = new /obj/projectile/ink_spit(caller.loc)
|
||||
ink.preparePixelProjectile(target, caller, modifiers)
|
||||
ink.firer = caller
|
||||
ink.fire()
|
||||
playsound(caller, 'sound/items/weapons/pierce.ogg', 20, TRUE, -1)
|
||||
caller.newtonian_move(get_angle(target, caller))
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
// Has to return TRUE, otherwise is skipped.
|
||||
/datum/action/cooldown/ink_spit/Activate(atom/target)
|
||||
return TRUE
|
||||
@@ -105,3 +105,86 @@
|
||||
infusion_desc = "kafkaesque" // Gregor Samsa !!
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/roach
|
||||
|
||||
/datum/infuser_entry/fish
|
||||
name = "Fish"
|
||||
infuse_mob_name = "fish"
|
||||
desc = "Aquatic life comes in several forms. A fisherman could tell you more about it, but that's beside the point. \
|
||||
This infusion comes with many benefits and one potential major drawback being fish-mutated lungs, with \
|
||||
additional organs depending on the traits of the fish used for the infusion."
|
||||
threshold_desc = "While wet, you're slightly sturdier, immune to slips, and both slippery and faster while crawling. \
|
||||
Drinking water and showers heal you, and it takes longer to dry out, however you're weaker when dry. \
|
||||
Finally, you resist high pressures and are better at fishing. "
|
||||
qualities = list(
|
||||
"faster in water",
|
||||
"resistant to food diseases",
|
||||
"enjoy eating raw fish",
|
||||
"flopping and waddling",
|
||||
"fishing is easier",
|
||||
"Need water. badly!",
|
||||
"possibly more",
|
||||
)
|
||||
input_obj_or_mob = list(
|
||||
/obj/item/fish,
|
||||
)
|
||||
output_organs = list(
|
||||
/obj/item/organ/internal/lungs/fish,
|
||||
/obj/item/organ/internal/stomach/fish,
|
||||
/obj/item/organ/external/tail/fish,
|
||||
)
|
||||
infusion_desc = "piscine"
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/fish
|
||||
|
||||
/datum/infuser_entry/squid
|
||||
name = "Ink Production"
|
||||
infuse_mob_name = "ink-producing sealife"
|
||||
desc = "Some marine mollusks like cuttlefish, squids and octopus release ink when threatened as a smokescreen for their escape. \
|
||||
This kind of infusion enhances the salivary glands, producing excessive quantities of ink which can later be spat to blind foes."
|
||||
threshold_desc = DNA_INFUSION_NO_THRESHOLD
|
||||
qualities = list(
|
||||
"spit ink to blind foes",
|
||||
)
|
||||
output_organs = list(
|
||||
/obj/item/organ/internal/tongue/inky
|
||||
)
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
|
||||
/datum/infuser_entry/ttx_healing
|
||||
name = "TTX healing"
|
||||
infuse_mob_name = "Tetraodontiformes"
|
||||
desc = "Fish of the Tetraodontiformes (pufferfish etc.) order are known for the highly poisonous tetrodotoxin (TTX) in their bodies. \
|
||||
Extracting their DNA can provide a way to utilize it for healing instead. It also enables better alcohol metabolization."
|
||||
threshold_desc = DNA_INFUSION_NO_THRESHOLD
|
||||
qualities = list(
|
||||
"TTX healing",
|
||||
"drink like a fish",
|
||||
)
|
||||
output_organs = list(
|
||||
/obj/item/organ/internal/liver/fish
|
||||
)
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
unreachable_effect = TRUE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/fish
|
||||
|
||||
/datum/infuser_entry/amphibious
|
||||
name = "Amphibious"
|
||||
infuse_mob_name = "Semi-aquatic critters"
|
||||
desc = "Some animals breathe air, some breath water, a few can breath both, even if none (at least on Earth) can breathe in space."
|
||||
threshold_desc = DNA_INFUSION_NO_THRESHOLD
|
||||
qualities = list(
|
||||
"no need to breathe while wet",
|
||||
"can beathe water vapor",
|
||||
)
|
||||
input_obj_or_mob = list(
|
||||
/mob/living/basic/frog,
|
||||
/mob/living/basic/axolotl,
|
||||
/mob/living/basic/crab,
|
||||
)
|
||||
output_organs = list(
|
||||
/obj/item/organ/internal/lungs/fish/amphibious,
|
||||
)
|
||||
infusion_desc = "semi-aquatic"
|
||||
tier = DNA_MUTANT_TIER_ONE
|
||||
unreachable_effect = TRUE
|
||||
status_effect_type = /datum/status_effect/organ_set_bonus/fish
|
||||
|
||||
@@ -28,8 +28,16 @@ GLOBAL_LIST_INIT(infuser_entries, prepare_infuser_entries())
|
||||
)
|
||||
/// status effect type of the corresponding bonus, if it has one. tier zero won't ever set this.
|
||||
var/status_effect_type
|
||||
/// essentially how difficult it is to get this infusion, and if it will be locked behind some progression. see defines for more info
|
||||
/// ...overwrite this, please
|
||||
/**
|
||||
* This var clarifies that while the infuser entry has organs that contribute towards an organ set bonus
|
||||
* It cannot reach the organ threshold of the bonus on its own, meaning it relies on some other infuser entry for that.
|
||||
* This is mainly the case for fish organs from fish with specific traits, for example. We don't want the unit test to bith about it.
|
||||
*/
|
||||
var/unreachable_effect = FALSE
|
||||
/**
|
||||
* essentially how difficult it is to get this infusion, and if it will be locked behind some progression. see defines for more info
|
||||
* ...overwrite this, please
|
||||
*/
|
||||
var/tier = DNA_MUTANT_UNOBTAINABLE
|
||||
|
||||
//-- Vars for DNA Infuser Machine --//
|
||||
|
||||
388
code/game/machinery/dna_infuser/organ_sets/fish_organs.dm
Normal file
@@ -0,0 +1,388 @@
|
||||
#define FISH_ORGAN_COLOR "#875652" //dark moderate magenta
|
||||
#define FISH_SCLERA_COLOR COLOR_WHITE
|
||||
#define FISH_PUPIL_COLOR COLOR_BLUE
|
||||
#define FISH_COLORS FISH_ORGAN_COLOR + FISH_SCLERA_COLOR + FISH_PUPIL_COLOR
|
||||
|
||||
///bonus of the observing gondola: you can ignore environmental hazards
|
||||
/datum/status_effect/organ_set_bonus/fish
|
||||
id = "organ_set_bonus_fish"
|
||||
tick_interval = 1 SECONDS
|
||||
organs_needed = 3
|
||||
bonus_activate_text = span_notice("Fish DNA is deeply infused with you! While wet, you crawl faster, are slippery, and cannot slip, and it takes longer to dry out. \
|
||||
You're also more resistant to high pressure, better at fishing, but less resilient when dry, especially against burns.")
|
||||
bonus_deactivate_text = span_notice("You no longer feel as fishy. The moisture around your body begins to dissipate faster...")
|
||||
bonus_traits = list(
|
||||
TRAIT_RESISTHIGHPRESSURE,
|
||||
TRAIT_EXPERT_FISHER,
|
||||
TRAIT_EXAMINE_FISH,
|
||||
TRAIT_EXAMINE_DEEPER_FISH,
|
||||
TRAIT_REVEAL_FISH,
|
||||
TRAIT_EXAMINE_FISHING_SPOT,
|
||||
TRAIT_WET_FOR_LONGER,
|
||||
TRAIT_SLIPPERY_WHEN_WET,
|
||||
TRAIT_EXPANDED_FOV, //fish vision
|
||||
TRAIT_WATER_ADAPTATION,
|
||||
)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/enable_bonus()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
RegisterSignals(owner, list(COMSIG_CARBON_GAIN_ORGAN, COMSIG_CARBON_LOSE_ORGAN), PROC_REF(check_tail))
|
||||
RegisterSignals(owner, list(SIGNAL_ADDTRAIT(TRAIT_IS_WET), SIGNAL_REMOVETRAIT(TRAIT_IS_WET)), PROC_REF(update_wetness))
|
||||
RegisterSignals(owner, COMSIG_LIVING_GET_PERCEIVED_FOOD_QUALITY, PROC_REF(get_perceived_food_quality))
|
||||
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human = owner
|
||||
human.physiology.damage_resistance += 8 //base 8% damage resistance, much wow.
|
||||
if(!HAS_TRAIT(owner, TRAIT_IS_WET))
|
||||
apply_debuff()
|
||||
else
|
||||
ADD_TRAIT(owner, TRAIT_GRABRESISTANCE, REF(src))
|
||||
owner.add_mood_event("fish_organs_bonus", /datum/mood_event/fish_water)
|
||||
if(HAS_TRAIT(owner, TRAIT_IS_WET) && istype(owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL), /obj/item/organ/external/tail/fish))
|
||||
add_speed_buff()
|
||||
owner.mind?.adjust_experience(/datum/skill/fishing, SKILL_EXP_JOURNEYMAN, silent = TRUE)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/disable_bonus()
|
||||
. = ..()
|
||||
UnregisterSignal(owner, list(
|
||||
COMSIG_CARBON_GAIN_ORGAN,
|
||||
COMSIG_CARBON_LOSE_ORGAN,
|
||||
SIGNAL_ADDTRAIT(TRAIT_IS_WET),
|
||||
SIGNAL_REMOVETRAIT(TRAIT_IS_WET),
|
||||
COMSIG_LIVING_TREAT_MESSAGE,
|
||||
COMSIG_LIVING_GET_PERCEIVED_FOOD_QUALITY,
|
||||
))
|
||||
if(!HAS_TRAIT(owner, TRAIT_IS_WET))
|
||||
remove_debuff()
|
||||
else
|
||||
REMOVE_TRAIT(owner, TRAIT_GRABRESISTANCE, REF(src))
|
||||
owner.clear_mood_event("fish_organs_bonus")
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/human = owner
|
||||
human.physiology.damage_resistance -= 8
|
||||
if(HAS_TRAIT(owner, TRAIT_IS_WET) && istype(owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL), /obj/item/organ/external/tail/fish))
|
||||
remove_speed_buff()
|
||||
owner.mind?.adjust_experience(/datum/skill/fishing, -SKILL_EXP_JOURNEYMAN, silent = TRUE)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/get_perceived_food_quality(datum/source, datum/component/edible/edible, list/extra_quality)
|
||||
SIGNAL_HANDLER
|
||||
if(HAS_TRAIT(edible.parent, TRAIT_GREAT_QUALITY_BAIT))
|
||||
extra_quality += LIKED_FOOD_QUALITY_CHANGE * 3
|
||||
else if(HAS_TRAIT(edible.parent, TRAIT_GOOD_QUALITY_BAIT))
|
||||
extra_quality += LIKED_FOOD_QUALITY_CHANGE * 2
|
||||
else if(HAS_TRAIT(edible.parent, TRAIT_BASIC_QUALITY_BAIT))
|
||||
extra_quality += LIKED_FOOD_QUALITY_CHANGE
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/tick(seconds_between_ticks)
|
||||
. = ..()
|
||||
if(!bonus_active || !HAS_TRAIT(owner, TRAIT_IS_WET))
|
||||
return
|
||||
owner.adjust_bodytemperature(-2 * seconds_between_ticks, min_temp = owner.get_body_temp_normal())
|
||||
owner.adjustStaminaLoss(-1.5 * seconds_between_ticks)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/update_wetness(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
if(HAS_TRAIT(owner, TRAIT_IS_WET)) //remove the debuffs from being dry
|
||||
remove_debuff()
|
||||
if(istype(owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL), /obj/item/organ/external/tail/fish))
|
||||
add_speed_buff()
|
||||
return
|
||||
apply_debuff()
|
||||
if(istype(owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL), /obj/item/organ/external/tail/fish))
|
||||
remove_speed_buff()
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/apply_debuff()
|
||||
REMOVE_TRAIT(owner, TRAIT_GRABRESISTANCE, REF(src))
|
||||
owner.add_movespeed_modifier(/datum/movespeed_modifier/fish_waterless)
|
||||
owner.add_mood_event("fish_organs_bonus", /datum/mood_event/fish_waterless)
|
||||
if(!ishuman(owner))
|
||||
return
|
||||
var/mob/living/carbon/human/human = owner
|
||||
human.physiology.burn_mod *= 1.5
|
||||
human.physiology.heat_mod *= 1.2
|
||||
human.physiology.brute_mod *= 1.1
|
||||
human.physiology.stun_mod *= 1.1
|
||||
human.physiology.knockdown_mod *= 1.1
|
||||
human.physiology.stamina_mod *= 1.1
|
||||
human.physiology.damage_resistance -= 16 //from +8% to -8%
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/remove_debuff()
|
||||
ADD_TRAIT(owner, TRAIT_GRABRESISTANCE, REF(src)) //harder to grab when wet.
|
||||
owner.remove_movespeed_modifier(/datum/movespeed_modifier/fish_waterless)
|
||||
owner.add_mood_event("fish_organs_bonus", /datum/mood_event/fish_water)
|
||||
if(!ishuman(owner))
|
||||
return
|
||||
var/mob/living/carbon/human/human = owner
|
||||
human.physiology.burn_mod /= 1.5
|
||||
human.physiology.heat_mod /= 1.2
|
||||
human.physiology.brute_mod /= 1.1
|
||||
human.physiology.stun_mod /= 1.1
|
||||
human.physiology.knockdown_mod /= 1.1
|
||||
human.physiology.stamina_mod /= 1.1
|
||||
human.physiology.damage_resistance += 16 //from -8% to +8%
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/check_tail(mob/living/carbon/source, obj/item/organ/organ, special)
|
||||
SIGNAL_HANDLER
|
||||
if(!HAS_TRAIT(owner, TRAIT_IS_WET) || !istype(organ, /obj/item/organ/external/tail/fish))
|
||||
return
|
||||
var/obj/item/organ/tail = owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL)
|
||||
if(tail != organ)
|
||||
remove_speed_buff()
|
||||
return
|
||||
add_speed_buff()
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/add_speed_buff(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(check_body_position))
|
||||
check_body_position()
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/remove_speed_buff(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION)
|
||||
owner.remove_movespeed_modifier(/datum/movespeed_modifier/fish_flopping)
|
||||
|
||||
/datum/status_effect/organ_set_bonus/fish/proc/check_body_position(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
if(owner.body_position == LYING_DOWN)
|
||||
owner.add_movespeed_modifier(/datum/movespeed_modifier/fish_flopping)
|
||||
else
|
||||
owner.remove_movespeed_modifier(/datum/movespeed_modifier/fish_flopping)
|
||||
|
||||
|
||||
///Tail for fish DNA-infused spacemen. It provides a speed buff while in water. It's also needed for the crawl speed bonus once the threshold is reached.
|
||||
/obj/item/organ/external/tail/fish
|
||||
name = "fish tail"
|
||||
desc = "A severed tail from some sort of marine creature... or a fish-infused spaceman. It's smooth, faintly wet and definitely not flopping."
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "fish_tail"
|
||||
greyscale_config = /datum/greyscale_config/fish_tail
|
||||
greyscale_colors = FISH_ORGAN_COLOR
|
||||
|
||||
bodypart_overlay = /datum/bodypart_overlay/mutant/tail/fish
|
||||
dna_block = DNA_FISH_TAIL_BLOCK
|
||||
wag_flags = WAG_ABLE
|
||||
organ_traits = list(TRAIT_FLOPPING)
|
||||
|
||||
/obj/item/organ/external/tail/fish/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fish)
|
||||
|
||||
/obj/item/organ/external/tail/fish/on_mob_insert(mob/living/carbon/owner)
|
||||
. = ..()
|
||||
owner.AddElementTrait(TRAIT_WADDLING, type, /datum/element/waddling)
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_location))
|
||||
check_location(owner, null)
|
||||
|
||||
/obj/item/organ/external/tail/fish/on_mob_remove(mob/living/carbon/owner)
|
||||
. = ..()
|
||||
owner.remove_traits(list(TRAIT_WADDLING, TRAIT_NO_STAGGER), type)
|
||||
owner.remove_movespeed_modifier(/datum/movespeed_modifier/fish_on_water)
|
||||
owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/fish_on_water)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/obj/item/organ/external/tail/fish/get_greyscale_color_from_draw_color()
|
||||
set_greyscale(bodypart_overlay.draw_color)
|
||||
|
||||
/obj/item/organ/external/tail/fish/proc/check_location(mob/living/carbon/source, atom/movable/old_loc, dir, forced)
|
||||
SIGNAL_HANDLER
|
||||
var/was_water = istype(old_loc, /turf/open/water)
|
||||
var/is_water = istype(source.loc, /turf/open/water) && !HAS_TRAIT(source.loc, TRAIT_TURF_IGNORE_SLOWDOWN)
|
||||
if(was_water && !is_water)
|
||||
source.remove_movespeed_modifier(/datum/movespeed_modifier/fish_on_water)
|
||||
source.remove_actionspeed_modifier(/datum/actionspeed_modifier/fish_on_water)
|
||||
source.add_traits(list(TRAIT_OFF_BALANCE_TACKLER, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), type)
|
||||
else if(!was_water && is_water)
|
||||
source.add_movespeed_modifier(/datum/movespeed_modifier/fish_on_water)
|
||||
source.add_actionspeed_modifier(/datum/actionspeed_modifier/fish_on_water)
|
||||
source.add_traits(list(TRAIT_OFF_BALANCE_TACKLER, TRAIT_NO_STAGGER, TRAIT_NO_THROW_HITPUSH), type)
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/fish
|
||||
feature_key = "fish_tail"
|
||||
color_source = ORGAN_COLOR_HAIR
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/fish/on_mob_insert(obj/item/organ/parent, mob/living/carbon/receiver)
|
||||
//Initialize the related dna feature block if we don't have any so it doesn't error out.
|
||||
//This isn't tied to any species, but I kinda want it to be mutable instead of having a fixed sprite accessory.
|
||||
if(imprint_on_next_insertion && !receiver.dna.features["fish_tail"])
|
||||
receiver.dna.features["fish_tail"] = pick(SSaccessories.tails_list_fish)
|
||||
receiver.dna.update_uf_block(DNA_FISH_TAIL_BLOCK)
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/fish/get_global_feature_list()
|
||||
return SSaccessories.tails_list_fish
|
||||
|
||||
|
||||
///Lungs that replace the need of oxygen with water vapor or being wet
|
||||
/obj/item/organ/internal/lungs/fish
|
||||
name = "mutated gills"
|
||||
desc = "Fish DNA infused on what once was a normal pair of lungs that now require spacemen to breathe water vapor, or keep themselves covered in water."
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "gills"
|
||||
|
||||
safe_oxygen_min = 0 //We don't breathe this
|
||||
///The required partial pressure of water_vapor for not drowing
|
||||
var/safe_water_level = 29
|
||||
|
||||
/// Bodypart overlay applied to the chest where the lungs are in
|
||||
var/datum/bodypart_overlay/simple/gills/gills
|
||||
|
||||
var/has_gills = TRUE
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/Initialize(mapload)
|
||||
. = ..()
|
||||
add_gas_reaction(/datum/gas/water_vapor, always = PROC_REF(breathe_water))
|
||||
respiration_type |= RESPIRATION_OXYGEN //after all, we get oxygen from water
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fish)
|
||||
if(has_gills)
|
||||
gills = new()
|
||||
AddElement(/datum/element/noticable_organ, "%PRONOUN_Theyve a set of gills on %PRONOUN_their neck.", BODY_ZONE_PRECISE_MOUTH)
|
||||
AddComponent(/datum/component/bubble_icon_override, "fish", BUBBLE_ICON_PRIORITY_ORGAN)
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/Destroy()
|
||||
QDEL_NULL(gills)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/on_bodypart_insert(obj/item/bodypart/limb)
|
||||
. = ..()
|
||||
if(gills)
|
||||
limb.add_bodypart_overlay(gills)
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/on_bodypart_remove(obj/item/bodypart/limb)
|
||||
. = ..()
|
||||
if(gills)
|
||||
limb.remove_bodypart_overlay(gills)
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/on_mob_remove(mob/living/carbon/owner)
|
||||
. = ..()
|
||||
owner.clear_alert(ALERT_NOT_ENOUGH_WATER)
|
||||
|
||||
/// Requires the spaceman to have either water vapor or be wet.
|
||||
/obj/item/organ/internal/lungs/fish/proc/breathe_water(mob/living/carbon/breather, datum/gas_mixture/breath, water_pp, old_water_pp)
|
||||
var/need_to_breathe = !HAS_TRAIT(src, TRAIT_SPACEBREATHING) && !HAS_TRAIT(breather, TRAIT_IS_WET)
|
||||
if(water_pp < safe_water_level && need_to_breathe)
|
||||
on_low_water(breather, breath, water_pp)
|
||||
return
|
||||
|
||||
if(old_water_pp < safe_water_level || breather.failed_last_breath)
|
||||
breather.failed_last_breath = FALSE
|
||||
breather.clear_alert(ALERT_NOT_ENOUGH_WATER)
|
||||
|
||||
if(need_to_breathe)
|
||||
breathe_gas_volume(breath, /datum/gas/water_vapor, /datum/gas/carbon_dioxide)
|
||||
// Heal mob if not in crit.
|
||||
if(breather.health >= breather.crit_threshold && breather.oxyloss)
|
||||
breather.adjustOxyLoss(-5)
|
||||
|
||||
/// Called when there isn't enough water to breath
|
||||
/obj/item/organ/internal/lungs/fish/proc/on_low_water(mob/living/carbon/breather, datum/gas_mixture/breath, water_pp)
|
||||
breather.throw_alert(ALERT_NOT_ENOUGH_WATER, /atom/movable/screen/alert/not_enough_water)
|
||||
var/gas_breathed = handle_suffocation(breather, water_pp, safe_water_level, breath.gases[/datum/gas/water_vapor][MOLES])
|
||||
if(water_pp)
|
||||
breathe_gas_volume(breath, /datum/gas/water_vapor, /datum/gas/carbon_dioxide, volume = gas_breathed)
|
||||
|
||||
// Simple overlay so we can add gills to those with fish lungs
|
||||
/datum/bodypart_overlay/simple/gills
|
||||
icon = 'icons/mob/human/fish_features.dmi'
|
||||
icon_state = "gills"
|
||||
layers = EXTERNAL_ADJACENT
|
||||
|
||||
/datum/bodypart_overlay/simple/gills/get_image(image_layer, obj/item/bodypart/limb)
|
||||
return image(
|
||||
icon = icon,
|
||||
icon_state = "[icon_state]_[mutant_bodyparts_layertext(image_layer)]",
|
||||
layer = image_layer,
|
||||
)
|
||||
|
||||
/// Subtype of gills that allow the mob to optionally breathe water.
|
||||
/obj/item/organ/internal/lungs/fish/amphibious
|
||||
name = "mutated semi-aquatic lungs"
|
||||
desc = "DNA from an amphibious or semi-aquatic creature infused on a pair lungs. Enjoy breathing underwater without drowning outside water."
|
||||
safe_oxygen_min = /obj/item/organ/internal/lungs::safe_oxygen_min
|
||||
safe_water_level = 19
|
||||
has_gills = FALSE
|
||||
/**
|
||||
* If false, we don't breathe air since we've got water instead.
|
||||
* Set to FALSE at the start of each cycle and TRUE on on_low_water()
|
||||
*/
|
||||
var/should_breathe_oxygen = FALSE
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/amphibious/Initialize(mapload)
|
||||
. = ..()
|
||||
/**
|
||||
* We're setting the gas reaction for breathing oxygen here,
|
||||
* since gas reation procs are run in the order they're added,
|
||||
* and we want breathe_water() to run before breathe_oxygen,
|
||||
* so that if we're breathing water vapor (or are wet), we won't have to breathe oxygen.
|
||||
*/
|
||||
safe_oxygen_min = /obj/item/organ/internal/lungs::safe_oxygen_min
|
||||
add_gas_reaction(/datum/gas/oxygen, always = PROC_REF(breathe_oxygen))
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/amphibious/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather)
|
||||
should_breathe_oxygen = FALSE //assume we don't have to breathe oxygen until we fail to breathe water
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/amphibious/on_low_water(mob/living/carbon/breather, datum/gas_mixture/breath, water_pp)
|
||||
should_breathe_oxygen = TRUE
|
||||
return
|
||||
|
||||
/obj/item/organ/internal/lungs/fish/amphibious/breathe_oxygen(mob/living/carbon/breather, datum/gas_mixture/breath, o2_pp, old_o2_pp)
|
||||
if(!should_breathe_oxygen)
|
||||
if(breather.failed_last_breath) //in case we had neither oxygen nor water last tick.
|
||||
breather.clear_alert(ALERT_NOT_ENOUGH_OXYGEN)
|
||||
return
|
||||
return ..()
|
||||
|
||||
///Fish infuser organ, allows mobs to safely eat raw fish.
|
||||
/obj/item/organ/internal/stomach/fish
|
||||
name = "mutated fish-stomach"
|
||||
desc = "Fish DNA infused into a stomach now parmated by the faint smell of salt and slightly putrified fish."
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "stomach"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = FISH_COLORS
|
||||
|
||||
organ_traits = list(TRAIT_STRONG_STOMACH, TRAIT_FISH_EATER)
|
||||
disgust_metabolism = 2.5
|
||||
|
||||
/obj/item/organ/internal/stomach/fish/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fish)
|
||||
|
||||
|
||||
///Organ from fish with the ink production trait. Doesn't count toward the organ set bonus but is buffed once it's active.
|
||||
/obj/item/organ/internal/tongue/inky
|
||||
name = "ink-secreting tongue"
|
||||
desc = "A black tongue linked to two swollen black sacs underneath the palate."
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "inky_tongue"
|
||||
actions_types = list(/datum/action/cooldown/ink_spit)
|
||||
|
||||
/obj/item/organ/internal/tongue/inky/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/noticable_organ, "Slick black ink seldom rivulets from %PRONOUN_their mouth.", BODY_ZONE_PRECISE_MOUTH)
|
||||
|
||||
///Organ from fish with the toxic trait. Allows the user to use tetrodotoxin as a healing chem instead of a toxin.
|
||||
/obj/item/organ/internal/liver/fish
|
||||
name = "mutated fish-liver"
|
||||
desc = "Fish DNA infused into a stomach that now uses tetrodotoxin as regenerative material. It also processes alcohol quite well."
|
||||
icon = 'icons/obj/medical/organs/infuser_organs.dmi'
|
||||
icon_state = "liver"
|
||||
greyscale_config = /datum/greyscale_config/mutant_organ
|
||||
greyscale_colors = FISH_COLORS
|
||||
|
||||
organ_traits = list(TRAIT_TETRODOTOXIN_HEALING, TRAIT_ALCOHOL_TOLERANCE) //drink like a fish :^)
|
||||
liver_resistance = parent_type::liver_resistance * 1.5
|
||||
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/iron = 5, /datum/reagent/toxin/tetrodotoxin = 5)
|
||||
grind_results = list(/datum/reagent/consumable/nutriment/peptides = 5, /datum/reagent/toxin/tetrodotoxin = 5)
|
||||
|
||||
/obj/item/organ/internal/liver/fish/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/fish)
|
||||
|
||||
#undef FISH_ORGAN_COLOR
|
||||
#undef FISH_SCLERA_COLOR
|
||||
#undef FISH_PUPIL_COLOR
|
||||
#undef FISH_COLORS
|
||||
@@ -402,7 +402,12 @@
|
||||
duration = 6
|
||||
|
||||
/obj/effect/temp_visual/impact_effect/neurotoxin
|
||||
icon_state = "impact_neurotoxin"
|
||||
icon_state = "impact_spit"
|
||||
color = "#5BDD04"
|
||||
|
||||
/obj/effect/temp_visual/impact_effect/ink_spit
|
||||
icon_state = "impact_spit"
|
||||
color = COLOR_NEARLY_ALL_BLACK
|
||||
|
||||
/obj/effect/temp_visual/heart
|
||||
name = "heart"
|
||||
|
||||
3
code/modules/actionspeed/modifiers/mobs.dm
Normal file
@@ -0,0 +1,3 @@
|
||||
///speed bonus given by the fish tail organ when inside water.
|
||||
/datum/actionspeed_modifier/fish_on_water
|
||||
multiplicative_slowdown = -0.15
|
||||
@@ -1,32 +1,32 @@
|
||||
/datum/preference/choiced/tail_human
|
||||
savefile_key = "feature_human_tail"
|
||||
/datum/preference/choiced/tail_felinid
|
||||
savefile_key = "feature_human_tail" //savefile keys cannot be changed, blame whoever named them this way.
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
|
||||
can_randomize = FALSE
|
||||
relevant_external_organ = /obj/item/organ/external/tail/cat
|
||||
|
||||
/datum/preference/choiced/tail_human/init_possible_values()
|
||||
return assoc_to_keys_features(SSaccessories.tails_list_human)
|
||||
/datum/preference/choiced/tail_felinid/init_possible_values()
|
||||
return assoc_to_keys_features(SSaccessories.tails_list_felinid)
|
||||
|
||||
/datum/preference/choiced/tail_human/apply_to_human(mob/living/carbon/human/target, value)
|
||||
/datum/preference/choiced/tail_felinid/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.dna.features["tail_cat"] = value
|
||||
|
||||
/datum/preference/choiced/tail_human/create_default_value()
|
||||
var/datum/sprite_accessory/tails/human/cat/tail = /datum/sprite_accessory/tails/human/cat
|
||||
/datum/preference/choiced/tail_felinid/create_default_value()
|
||||
var/datum/sprite_accessory/tails/felinid/cat/tail = /datum/sprite_accessory/tails/felinid/cat
|
||||
return initial(tail.name)
|
||||
|
||||
/datum/preference/choiced/ears
|
||||
savefile_key = "feature_human_ears"
|
||||
/datum/preference/choiced/felinid_ears
|
||||
savefile_key = "feature_human_ears" //savefile keys cannot be changed, blame whoever named them this way.
|
||||
savefile_identifier = PREFERENCE_CHARACTER
|
||||
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
|
||||
can_randomize = FALSE
|
||||
relevant_external_organ = /obj/item/organ/internal/ears/cat
|
||||
|
||||
/datum/preference/choiced/ears/init_possible_values()
|
||||
/datum/preference/choiced/felinid_ears/init_possible_values()
|
||||
return assoc_to_keys_features(SSaccessories.ears_list)
|
||||
|
||||
/datum/preference/choiced/ears/apply_to_human(mob/living/carbon/human/target, value)
|
||||
/datum/preference/choiced/felinid_ears/apply_to_human(mob/living/carbon/human/target, value)
|
||||
target.dna.features["ears"] = value
|
||||
|
||||
/datum/preference/choiced/ears/create_default_value()
|
||||
/datum/preference/choiced/felinid_ears/create_default_value()
|
||||
return /datum/sprite_accessory/ears/cat::name
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
desc = "Fills you with the conviction of JUSTICE. Lawyers tend to want to show it to everyone they meet."
|
||||
icon_state = "lawyerbadge"
|
||||
|
||||
/obj/item/clothing/accessory/lawyers_badge/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/bubble_icon_override, "lawyer", BUBBLE_ICON_PRIORITY_ACCESSORY)
|
||||
|
||||
/obj/item/clothing/accessory/lawyers_badge/interact(mob/user)
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
@@ -12,11 +16,9 @@
|
||||
|
||||
/obj/item/clothing/accessory/lawyers_badge/accessory_equipped(obj/item/clothing/under/clothes, mob/living/user)
|
||||
RegisterSignal(user, COMSIG_LIVING_SLAM_TABLE, PROC_REF(table_slam))
|
||||
user.bubble_icon = "lawyer"
|
||||
|
||||
/obj/item/clothing/accessory/lawyers_badge/accessory_dropped(obj/item/clothing/under/clothes, mob/living/user)
|
||||
UnregisterSignal(user, COMSIG_LIVING_SLAM_TABLE)
|
||||
user.bubble_icon = initial(user.bubble_icon)
|
||||
|
||||
/obj/item/clothing/accessory/lawyers_badge/proc/table_slam(mob/living/source, obj/structure/table/the_table)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -1308,6 +1308,23 @@
|
||||
. = ..()
|
||||
aquarium_vc_color = color || initial(aquarium_vc_color)
|
||||
|
||||
/obj/item/fish/get_infusion_entry()
|
||||
var/amphibious = required_fluid_type == AQUARIUM_FLUID_AIR || HAS_TRAIT(src, TRAIT_FISH_AMPHIBIOUS)
|
||||
var/list/possible_infusions = list(/datum/infuser_entry/fish)
|
||||
for(var/type in fish_traits)
|
||||
var/datum/fish_trait/trait = GLOB.fish_traits[type]
|
||||
if(!trait.infusion_entry)
|
||||
continue
|
||||
possible_infusions |= trait.infusion_entry
|
||||
if(!length(possible_infusions) && !amphibious)
|
||||
return GLOB.infuser_entries[/datum/infuser_entry/fish]
|
||||
var/datum/infuser_entry/fish/entry = new
|
||||
if(amphibious)
|
||||
entry.output_organs -= /obj/item/organ/internal/lungs/fish
|
||||
for(var/key in possible_infusions)
|
||||
var/datum/infuser_entry/infusion = GLOB.infuser_entries[key]
|
||||
entry.output_organs |= infusion.output_organs
|
||||
|
||||
/// Returns random fish, using random_case_rarity probabilities.
|
||||
/proc/random_fish_type(required_fluid)
|
||||
var/static/probability_table
|
||||
|
||||
@@ -39,6 +39,8 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
var/added_difficulty = 0
|
||||
/// 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
|
||||
/// If set, the fish may return this infusion entry when get_infusion_entry is called instead of /datum/infuser_entry/fish
|
||||
var/infusion_entry
|
||||
|
||||
/// Difficulty modifier from this mod, needs to return a list with two values
|
||||
/datum/fish_trait/proc/difficulty_mod(obj/item/fishing_rod/rod, mob/fisherman)
|
||||
@@ -427,6 +429,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
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 = 1)
|
||||
infusion_entry = /datum/infuser_entry/ttx_healing
|
||||
///The amount of venom injected if the fish has a stinger is multiplied by this value.
|
||||
var/venom_mult = 1
|
||||
|
||||
@@ -472,6 +475,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish contains carpotoxin. Definitely not safe for consumption."
|
||||
diff_traits_inheritability = 50
|
||||
reagents_to_add = list(/datum/reagent/toxin/carpotoxin = 4)
|
||||
infusion_entry = null
|
||||
venom_mult = 6
|
||||
|
||||
/datum/fish_trait/toxin_immunity
|
||||
@@ -543,6 +547,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
inheritability = 80
|
||||
diff_traits_inheritability = 40
|
||||
catalog_description = "This fish has developed a primitive adaptation to life on both land and water."
|
||||
infusion_entry = /datum/infuser_entry/amphibious
|
||||
|
||||
/datum/fish_trait/amphibious/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
@@ -721,6 +726,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
|
||||
catalog_description = "This fish possess a sac that produces ink."
|
||||
diff_traits_inheritability = 70
|
||||
spontaneous_manifest_types = list(/obj/item/fish/squid = 35)
|
||||
infusion_entry = /datum/infuser_entry/squid
|
||||
|
||||
/datum/fish_trait/ink/apply_to_fish(obj/item/fish/fish)
|
||||
. = ..()
|
||||
|
||||
@@ -69,6 +69,11 @@
|
||||
|
||||
update_appearance()
|
||||
|
||||
//Bane effect that make it extra-effective against mobs with water adaptation (read: fish infusion)
|
||||
AddElement(/datum/element/bane, target_type = /mob/living, damage_multiplier = 1.25)
|
||||
RegisterSignal(src, COMSIG_OBJECT_PRE_BANING, PROC_REF(attempt_bane))
|
||||
RegisterSignal(src, COMSIG_OBJECT_ON_BANING, PROC_REF(bane_effects))
|
||||
|
||||
/obj/item/fishing_rod/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
||||
if(src == held_item)
|
||||
if(currently_hooked)
|
||||
@@ -135,6 +140,19 @@
|
||||
QDEL_NULL(bait)
|
||||
update_icon()
|
||||
|
||||
///Fishing rodss should only bane fish DNA-infused spessman
|
||||
/obj/item/fishing_rod/proc/attempt_bane(datum/source, mob/living/fish)
|
||||
SIGNAL_HANDLER
|
||||
if(!force || !HAS_TRAIT(fish, TRAIT_WATER_ADAPTATION))
|
||||
return COMPONENT_CANCEL_BANING
|
||||
|
||||
///Fishing rods should hard-counter fish DNA-infused spessman
|
||||
/obj/item/fishing_rod/proc/bane_effects(datum/source, mob/living/fish)
|
||||
SIGNAL_HANDLER
|
||||
fish.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH, 4 SECONDS)
|
||||
fish.adjust_confusion_up_to(1.5 SECONDS, 3 SECONDS)
|
||||
fish.adjust_wet_stacks(-4)
|
||||
|
||||
/obj/item/fishing_rod/interact(mob/user)
|
||||
if(currently_hooked)
|
||||
reel(user)
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
return ..()
|
||||
|
||||
/datum/hallucination/fire/start()
|
||||
hallucinator.set_fire_stacks(max(hallucinator.fire_stacks, 0.1)) //Placebo flammability
|
||||
fire_overlay = image(fire_icon, hallucinator, fire_icon_state, ABOVE_MOB_LAYER)
|
||||
hallucinator.client?.images |= fire_overlay
|
||||
to_chat(hallucinator, span_userdanger("You're set on fire!"))
|
||||
@@ -47,7 +46,6 @@
|
||||
return TRUE
|
||||
|
||||
/datum/hallucination/fire/Destroy()
|
||||
hallucinator.adjust_fire_stacks(-0.1)
|
||||
hallucinator.clear_alert(ALERT_FIRE, clear_override = TRUE)
|
||||
hallucinator.clear_alert(ALERT_TEMPERATURE, clear_override = TRUE)
|
||||
if(fire_overlay)
|
||||
|
||||
@@ -2002,7 +2002,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
|
||||
*
|
||||
* Returns a color string or null.
|
||||
*/
|
||||
/datum/species/proc/get_fixed_hair_color(mob/living/carbon/human/for_mob)
|
||||
/datum/species/proc/get_fixed_hair_color(mob/living/carbon/for_mob)
|
||||
ASSERT(!isnull(for_mob))
|
||||
switch(hair_color_mode)
|
||||
if(USE_MUTANT_COLOR)
|
||||
|
||||
@@ -115,7 +115,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
|
||||
target.dna.features["moth_wings"] = get_consistent_feature_entry(SSaccessories.moth_wings_list)
|
||||
target.dna.features["snout"] = get_consistent_feature_entry(SSaccessories.snouts_list)
|
||||
target.dna.features["spines"] = get_consistent_feature_entry(SSaccessories.spines_list)
|
||||
target.dna.features["tail_cat"] = get_consistent_feature_entry(SSaccessories.tails_list_human) // it's a lie
|
||||
target.dna.features["tail_cat"] = get_consistent_feature_entry(SSaccessories.tails_list_felinid) // it's a lie
|
||||
target.dna.features["tail_lizard"] = get_consistent_feature_entry(SSaccessories.tails_list_lizard)
|
||||
target.dna.features["tail_monkey"] = get_consistent_feature_entry(SSaccessories.tails_list_monkey)
|
||||
target.dna.features["pod_hair"] = get_consistent_feature_entry(SSaccessories.pod_hair_list)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
TRAIT_CATLIKE_GRACE,
|
||||
TRAIT_HATED_BY_DOGS,
|
||||
TRAIT_USES_SKINTONES,
|
||||
TRAIT_WATER_HATER,
|
||||
)
|
||||
changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT
|
||||
species_language_holder = /datum/language_holder/felinid
|
||||
|
||||
@@ -1204,8 +1204,11 @@
|
||||
var/altered_grab_state = pulledby.grab_state
|
||||
if((body_position == LYING_DOWN || HAS_TRAIT(src, TRAIT_GRABWEAKNESS) || get_timed_status_effect_duration(/datum/status_effect/staggered)) && pulledby.grab_state < GRAB_KILL) //If prone, resisting out of a grab is equivalent to 1 grab state higher. won't make the grab state exceed the normal max, however
|
||||
altered_grab_state++
|
||||
var/resist_chance = BASE_GRAB_RESIST_CHANCE /// see defines/combat.dm, this should be baseline 60%
|
||||
resist_chance = (resist_chance/altered_grab_state) ///Resist chance divided by the value imparted by your grab state. It isn't until you reach neckgrab that you gain a penalty to escaping a grab.
|
||||
if(HAS_TRAIT(src, TRAIT_GRABRESISTANCE))
|
||||
altered_grab_state--
|
||||
// see defines/combat.dm, this should be baseline 60%
|
||||
// Resist chance divided by the value imparted by your grab state. It isn't until you reach neckgrab that you gain a penalty to escaping a grab.
|
||||
var/resist_chance = altered_grab_state ? (BASE_GRAB_RESIST_CHANCE / altered_grab_state) : 100
|
||||
if(prob(resist_chance))
|
||||
visible_message(span_danger("[src] breaks free of [pulledby]'s grip!"), \
|
||||
span_danger("You break free of [pulledby]'s grip!"), null, null, pulledby)
|
||||
|
||||
@@ -175,3 +175,17 @@
|
||||
|
||||
/datum/movespeed_modifier/magic_ties
|
||||
multiplicative_slowdown = 0.5
|
||||
|
||||
///movespeed modifier that makes you go faster when wet and lying on the floor once past the fish organ set threshold.
|
||||
/datum/movespeed_modifier/fish_flopping
|
||||
blacklisted_movetypes = MOVETYPES_NOT_TOUCHING_GROUND
|
||||
multiplicative_slowdown = - (CRAWLING_ADD_SLOWDOWN * 0.71)
|
||||
|
||||
///speed bonus given by the fish tail organ when inside water.
|
||||
/datum/movespeed_modifier/fish_on_water
|
||||
blacklisted_movetypes = MOVETYPES_NOT_TOUCHING_GROUND
|
||||
multiplicative_slowdown = - /turf/open/water::slowdown
|
||||
|
||||
///speed malus given by the fish organ set when dry
|
||||
/datum/movespeed_modifier/fish_waterless
|
||||
multiplicative_slowdown = 0.36
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
/obj/projectile/neurotoxin
|
||||
name = "neurotoxin spit"
|
||||
icon_state = "neurotoxin"
|
||||
damage = 65
|
||||
damage_type = STAMINA
|
||||
armor_flag = BIO
|
||||
impact_effect_type = /obj/effect/temp_visual/impact_effect/neurotoxin
|
||||
armour_penetration = 50
|
||||
|
||||
/obj/projectile/neurotoxin/on_hit(atom/target, blocked = 0, pierce_hit)
|
||||
if(isalien(target))
|
||||
damage = 0
|
||||
return ..()
|
||||
|
||||
/obj/projectile/neurotoxin/damaging //for ai controlled aliums
|
||||
damage = 30
|
||||
paralyze = 0 SECONDS
|
||||
58
code/modules/projectiles/projectile/special/spit.dm
Normal file
@@ -0,0 +1,58 @@
|
||||
/obj/projectile/neurotoxin
|
||||
name = "neurotoxin spit"
|
||||
icon_state = "neurotoxin"
|
||||
damage = 65
|
||||
damage_type = STAMINA
|
||||
armor_flag = BIO
|
||||
impact_effect_type = /obj/effect/temp_visual/impact_effect/neurotoxin
|
||||
armour_penetration = 50
|
||||
|
||||
/obj/projectile/neurotoxin/on_hit(atom/target, blocked = 0, pierce_hit)
|
||||
if(isalien(target))
|
||||
damage = 0
|
||||
return ..()
|
||||
|
||||
/obj/projectile/neurotoxin/damaging //for ai controlled aliums
|
||||
damage = 30
|
||||
paralyze = 0 SECONDS
|
||||
|
||||
/obj/projectile/ink_spit
|
||||
name = "ink spit"
|
||||
icon_state = "ink_spit"
|
||||
damage = 5
|
||||
damage_type = STAMINA
|
||||
armor_flag = BIO
|
||||
impact_effect_type = /obj/effect/temp_visual/impact_effect/ink_spit
|
||||
armour_penetration = 50
|
||||
hitsound = SFX_DESECRATION
|
||||
hitsound_wall = SFX_DESECRATION
|
||||
|
||||
/obj/projectile/ink_spit/Initialize(mapload)
|
||||
. = ..()
|
||||
if(isliving(firer))
|
||||
var/mob/living/living = firer
|
||||
var/datum/status_effect/organ_set_bonus/fish/bonus = living?.has_status_effect(/datum/status_effect/organ_set_bonus/fish)
|
||||
if(bonus?.bonus_active)
|
||||
damage = 12
|
||||
armour_penetration = 65
|
||||
|
||||
AddComponent(/datum/component/splat, \
|
||||
memory_type = /datum/memory/witnessed_inking, \
|
||||
smudge_type = /obj/effect/decal/cleanable/food/squid_ink, \
|
||||
moodlet_type = /datum/mood_event/inked, \
|
||||
splat_color = COLOR_NEARLY_ALL_BLACK, \
|
||||
hit_callback = CALLBACK(src, PROC_REF(blind_em)), \
|
||||
)
|
||||
|
||||
/obj/projectile/ink_spit/proc/blind_em(mob/living/victim, can_splat_on)
|
||||
if(!can_splat_on)
|
||||
return
|
||||
var/powered_up = FALSE
|
||||
if(isliving(firer))
|
||||
var/mob/living/living = firer
|
||||
var/datum/status_effect/organ_set_bonus/fish/bonus = living?.has_status_effect(/datum/status_effect/organ_set_bonus/fish)
|
||||
powered_up = bonus?.bonus_active
|
||||
victim.adjust_temp_blindness_up_to((powered_up ? 6.5 : 4.5) SECONDS, 10 SECONDS)
|
||||
victim.adjust_confusion_up_to((powered_up ? 3 : 1.5) SECONDS, 6 SECONDS)
|
||||
if(powered_up)
|
||||
victim.Knockdown(2 SECONDS) //splat!
|
||||
@@ -40,7 +40,7 @@
|
||||
if(belly)
|
||||
amount += belly.reagents.get_reagent_amount(toxin.type)
|
||||
|
||||
if(amount <= liver_tolerance)
|
||||
if(amount <= liver_tolerance * toxin.liver_tolerance_multiplier)
|
||||
owner.reagents.remove_reagent(toxin.type, toxin.metabolization_rate * owner.metabolism_efficiency * seconds_per_tick)
|
||||
continue
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
var/list/metabolized_traits
|
||||
/// A list of traits to apply while the reagent is in a mob.
|
||||
var/list/added_traits
|
||||
/// Multiplier of the amount purged by reagents such as calomel, multiver, syniver etc.
|
||||
var/purge_multiplier = 1
|
||||
|
||||
///The default reagent container for the reagent, used for icon generation
|
||||
var/obj/item/reagent_containers/default_container = /obj/item/reagent_containers/cup/bottle
|
||||
|
||||
@@ -388,16 +388,13 @@
|
||||
var/need_mob_update
|
||||
need_mob_update = affected_mob.adjustToxLoss(-0.5 * min(medibonus, 3 * normalise_creation_purity()) * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype) //not great at healing but if you have nothing else it will work
|
||||
need_mob_update += affected_mob.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.5 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags) //kills at 40u
|
||||
for(var/r2 in affected_mob.reagents.reagent_list)
|
||||
var/datum/reagent/the_reagent2 = r2
|
||||
if(the_reagent2 == src)
|
||||
continue
|
||||
var/amount2purge = 3
|
||||
if(holder.has_reagent(/datum/reagent/toxin/anacea))
|
||||
amount2purge = 0
|
||||
if(medibonus >= 3 && istype(the_reagent2, /datum/reagent/medicine)) //3 unique meds (2+multiver) | (1 + pure multiver) will make it not purge medicines
|
||||
continue
|
||||
affected_mob.reagents.remove_reagent(the_reagent2.type, amount2purge * REM * seconds_per_tick)
|
||||
if(!holder.has_reagent(/datum/reagent/toxin/anacea))
|
||||
for(var/datum/reagent/second_reagent as anything in affected_mob.reagents.reagent_list)
|
||||
if(second_reagent == src)
|
||||
continue
|
||||
if(medibonus >= 3 && istype(second_reagent, /datum/reagent/medicine)) //3 unique meds (2+multiver) | (1 + pure multiver) will make it not purge medicines
|
||||
continue
|
||||
affected_mob.reagents.remove_reagent(second_reagent.type, 3 * second_reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
if(need_mob_update)
|
||||
return UPDATE_MOB_HEALTH
|
||||
|
||||
@@ -468,10 +465,10 @@
|
||||
var/need_mob_update
|
||||
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_LIVER, 0.1 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags)
|
||||
need_mob_update += affected_mob.adjustToxLoss(-1.5 * REM * seconds_per_tick * normalise_creation_purity(), updating_health = FALSE, required_biotype = affected_biotype)
|
||||
for(var/datum/reagent/R in affected_mob.reagents.reagent_list)
|
||||
if(issyrinormusc(R))
|
||||
for(var/datum/reagent/reagent as anything in affected_mob.reagents.reagent_list)
|
||||
if(issyrinormusc(reagent))
|
||||
continue
|
||||
affected_mob.reagents.remove_reagent(R.type, 0.2 * REM * seconds_per_tick)
|
||||
affected_mob.reagents.remove_reagent(reagent.type, 0.2 * reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
if(need_mob_update)
|
||||
return UPDATE_MOB_HEALTH
|
||||
|
||||
|
||||
@@ -432,18 +432,17 @@
|
||||
|
||||
/datum/reagent/medicine/calomel/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
for(var/datum/reagent/target_reagent in affected_mob.reagents.reagent_list)
|
||||
for(var/datum/reagent/target_reagent as anything in affected_mob.reagents.reagent_list)
|
||||
if(istype(target_reagent, /datum/reagent/medicine/calomel))
|
||||
continue
|
||||
affected_mob.reagents.remove_reagent(target_reagent.type, 3 * REM * seconds_per_tick)
|
||||
affected_mob.reagents.remove_reagent(target_reagent.type, 3 * target_reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
var/toxin_amount = round(affected_mob.health / 40, 0.1)
|
||||
if(affected_mob.adjustToxLoss(toxin_amount * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype))
|
||||
return UPDATE_MOB_HEALTH
|
||||
|
||||
/datum/reagent/medicine/calomel/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
for(var/datum/reagent/medicine/calomel/target_reagent in affected_mob.reagents.reagent_list)
|
||||
affected_mob.reagents.remove_reagent(target_reagent.type, 2 * REM * seconds_per_tick)
|
||||
affected_mob.reagents.remove_reagent(type, 2 * REM * seconds_per_tick)
|
||||
if(affected_mob.adjustToxLoss(2.5 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype))
|
||||
return UPDATE_MOB_HEALTH
|
||||
|
||||
@@ -467,7 +466,7 @@
|
||||
var/toxin_chem_amount = 0
|
||||
for(var/datum/reagent/toxin/target_reagent in affected_mob.reagents.reagent_list)
|
||||
toxin_chem_amount += 1
|
||||
affected_mob.reagents.remove_reagent(target_reagent.type, 5 * REM * seconds_per_tick)
|
||||
affected_mob.reagents.remove_reagent(target_reagent.type, 5 * target_reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
var/toxin_amount = round(affected_mob.getBruteLoss() / 15, 0.1) + round(affected_mob.getFireLoss() / 30, 0.1) - 3
|
||||
if(affected_mob.adjustToxLoss(toxin_amount * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype))
|
||||
. = UPDATE_MOB_HEALTH
|
||||
@@ -512,9 +511,9 @@
|
||||
. = ..()
|
||||
if(affected_mob.adjustToxLoss(-2 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype))
|
||||
. = UPDATE_MOB_HEALTH
|
||||
for(var/datum/reagent/R in affected_mob.reagents.reagent_list)
|
||||
if(R != src)
|
||||
affected_mob.reagents.remove_reagent(R.type, 2 * REM * seconds_per_tick)
|
||||
for(var/datum/reagent/reagent as anything in affected_mob.reagents.reagent_list)
|
||||
if(reagent != src)
|
||||
affected_mob.reagents.remove_reagent(reagent.type, 2 * reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
|
||||
/datum/reagent/medicine/sal_acid
|
||||
name = "Salicylic Acid"
|
||||
@@ -1339,8 +1338,8 @@
|
||||
|
||||
/datum/reagent/medicine/haloperidol/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
for(var/datum/reagent/drug/R in affected_mob.reagents.reagent_list)
|
||||
affected_mob.reagents.remove_reagent(R.type, 5 * REM * seconds_per_tick)
|
||||
for(var/datum/reagent/drug/reagent in affected_mob.reagents.reagent_list)
|
||||
affected_mob.reagents.remove_reagent(reagent.type, 5 * reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
affected_mob.adjust_drowsiness(4 SECONDS * REM * seconds_per_tick)
|
||||
|
||||
if(affected_mob.get_timed_status_effect_duration(/datum/status_effect/jitter) >= 6 SECONDS)
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
if(methods & VAPOR)
|
||||
exposed_mob.adjust_wet_stacks(reac_volume * WATER_TO_WET_STACKS_FACTOR_VAPOR) // Spraying someone with water with the hope to put them out is just simply too funny to me not to add it.
|
||||
|
||||
if(!isfelinid(exposed_mob))
|
||||
if(!HAS_TRAIT(exposed_mob, TRAIT_WATER_HATER) || HAS_TRAIT(exposed_mob, TRAIT_WATER_ADAPTATION))
|
||||
return
|
||||
|
||||
exposed_mob.incapacitate(1) // startles the felinid, canceling any do_after
|
||||
@@ -290,9 +290,18 @@
|
||||
|
||||
/datum/reagent/water/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
var/water_adaptation = HAS_TRAIT(affected_mob, TRAIT_WATER_ADAPTATION)
|
||||
if(affected_mob.blood_volume)
|
||||
affected_mob.blood_volume += 0.1 * REM * seconds_per_tick // water is good for you!
|
||||
affected_mob.adjust_drunk_effect(-0.25 * REM * seconds_per_tick) // and even sobers you up slowly!!
|
||||
var/blood_restored = water_adaptation ? 0.3 : 0.1
|
||||
affected_mob.blood_volume += blood_restored * REM * seconds_per_tick // water is good for you!
|
||||
var/drunkness_restored = water_adaptation ? -0.5 : -0.25
|
||||
affected_mob.adjust_drunk_effect(drunkness_restored * REM * seconds_per_tick) // and even sobers you up slowly!!
|
||||
if(water_adaptation)
|
||||
var/need_mob_update = FALSE
|
||||
need_mob_update = affected_mob.adjustToxLoss(-0.2 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype)
|
||||
need_mob_update += affected_mob.adjustFireLoss(-0.2 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_bodytype)
|
||||
need_mob_update += affected_mob.adjustBruteLoss(-0.2 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_bodytype)
|
||||
return need_mob_update ? UPDATE_MOB_HEALTH : .
|
||||
|
||||
// For weird backwards situations where water manages to get added to trays nutrients, as opposed to being snowflaked away like usual.
|
||||
/datum/reagent/water/on_hydroponics_apply(obj/machinery/hydroponics/mytray, mob/user)
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
var/toxpwr = 1.5
|
||||
///The amount to multiply the liver damage this toxin does by (Handled solely in liver code)
|
||||
var/liver_damage_multiplier = 1
|
||||
///The multiplier of the liver toxin tolerance, below which any amount toxin will be simply metabolized out with no effect.
|
||||
var/liver_tolerance_multiplier = 1
|
||||
///won't produce a pain message when processed by liver/life() if there isn't another non-silent toxin present if true
|
||||
var/silent_toxin = FALSE
|
||||
///The afflicted must be above this health value in order for the toxin to deal damage
|
||||
@@ -956,9 +958,9 @@
|
||||
if(prob(50))
|
||||
constructed_flags |= MOB_VOMIT_STUN
|
||||
affected_mob.vomit(vomit_flags = constructed_flags, distance = rand(0,4))
|
||||
for(var/datum/reagent/toxin/R in affected_mob.reagents.reagent_list)
|
||||
if(R != src)
|
||||
affected_mob.reagents.remove_reagent(R.type, 1)
|
||||
for(var/datum/reagent/toxin/reagent in affected_mob.reagents.reagent_list)
|
||||
if(reagent != src)
|
||||
affected_mob.reagents.remove_reagent(reagent.type, 1 * reagent.purge_multiplier * REM * seconds_per_tick)
|
||||
|
||||
/datum/reagent/toxin/spewium/overdose_process(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
@@ -1051,8 +1053,8 @@
|
||||
if(holder.has_reagent(/datum/reagent/medicine/calomel) || holder.has_reagent(/datum/reagent/medicine/pen_acid))
|
||||
remove_amt = 0.5
|
||||
. = ..()
|
||||
for(var/datum/reagent/medicine/R in affected_mob.reagents.reagent_list)
|
||||
affected_mob.reagents.remove_reagent(R.type, remove_amt * REM * normalise_creation_purity() * seconds_per_tick)
|
||||
for(var/datum/reagent/medicine/reagent in affected_mob.reagents.reagent_list)
|
||||
affected_mob.reagents.remove_reagent(reagent.type, remove_amt * reagent.purge_multiplier * REM * normalise_creation_purity() * seconds_per_tick)
|
||||
|
||||
//ACID
|
||||
|
||||
@@ -1293,6 +1295,9 @@
|
||||
reagent_state = SOLID
|
||||
color = COLOR_VERY_LIGHT_GRAY
|
||||
metabolization_rate = 0.1 * REAGENTS_METABOLISM
|
||||
liver_tolerance_multiplier = 0.1
|
||||
liver_damage_multiplier = 1.25
|
||||
purge_multiplier = 0.15
|
||||
toxpwr = 0
|
||||
taste_mult = 0
|
||||
chemical_flags = REAGENT_NO_RANDOM_RECIPE|REAGENT_CAN_BE_SYNTHESIZED
|
||||
@@ -1305,9 +1310,22 @@
|
||||
|
||||
/datum/reagent/toxin/tetrodotoxin/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
var/need_mob_update
|
||||
if(HAS_TRAIT(affected_mob, TRAIT_TETRODOTOXIN_HEALING))
|
||||
toxpwr = 0
|
||||
liver_tolerance_multiplier = 0
|
||||
silent_toxin = TRUE
|
||||
remove_paralysis()
|
||||
need_mob_update += affected_mob.adjustOxyLoss(-0.7 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype, required_respiration_type = affected_respiration_type)
|
||||
need_mob_update = affected_mob.adjustToxLoss(-0.75 * REM * seconds_per_tick, updating_health = FALSE, required_biotype = affected_biotype)
|
||||
need_mob_update += affected_mob.adjustBruteLoss(-1.2 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_bodytype)
|
||||
need_mob_update += affected_mob.adjustFireLoss(-1.35 * REM * seconds_per_tick, updating_health = FALSE, required_bodytype = affected_bodytype)
|
||||
return need_mob_update ? UPDATE_MOB_HEALTH : .
|
||||
|
||||
liver_tolerance_multiplier = initial(liver_tolerance_multiplier)
|
||||
|
||||
//be ready for a cocktail of symptoms, including:
|
||||
//numbness, nausea, vomit, breath loss, weakness, paralysis and nerve damage/impairment and eventually a heart attack if enough time passes.
|
||||
var/need_mob_update
|
||||
switch(current_cycle)
|
||||
if(7 to 13)
|
||||
if(SPT_PROB(20, seconds_per_tick))
|
||||
@@ -1338,6 +1356,7 @@
|
||||
if(21 to 29)
|
||||
toxpwr = 1
|
||||
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5)
|
||||
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_LUNGS, 0.7)
|
||||
if(SPT_PROB(40, seconds_per_tick))
|
||||
affected_mob.losebreath += 2 * REM * seconds_per_tick
|
||||
need_mob_update = TRUE
|
||||
@@ -1354,13 +1373,14 @@
|
||||
if(29 to INFINITY)
|
||||
toxpwr = 1.5
|
||||
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1, BRAIN_DAMAGE_DEATH)
|
||||
need_mob_update = affected_mob.adjustOrganLoss(ORGAN_SLOT_LUNGS, 1.4)
|
||||
affected_mob.set_silence_if_lower(3 SECONDS * REM * seconds_per_tick)
|
||||
need_mob_update += affected_mob.adjustStaminaLoss(5 * REM * seconds_per_tick, updating_stamina = FALSE)
|
||||
affected_mob.adjust_disgust(2 * REM * seconds_per_tick)
|
||||
if(SPT_PROB(15, seconds_per_tick))
|
||||
paralyze_limb(affected_mob)
|
||||
need_mob_update = TRUE
|
||||
if(SPT_PROB(10, seconds_per_tick))
|
||||
if(SPT_PROB(20, seconds_per_tick))
|
||||
affected_mob.adjust_confusion(rand(6 SECONDS, 8 SECONDS))
|
||||
|
||||
if(current_cycle > 38 && !length(traits_not_applied) && SPT_PROB(5, seconds_per_tick) && !affected_mob.undergoing_cardiac_arrest())
|
||||
@@ -1376,6 +1396,11 @@
|
||||
var/added_trait = pick_n_take(traits_not_applied)
|
||||
ADD_TRAIT(affected_mob, added_trait, REF(src))
|
||||
|
||||
/datum/reagent/toxin/tetrodotoxin/on_mob_add(mob/living/affected_mob)
|
||||
. = ..()
|
||||
if(HAS_TRAIT(affected_mob, TRAIT_TETRODOTOXIN_HEALING))
|
||||
liver_tolerance_multiplier = 0
|
||||
|
||||
/datum/reagent/toxin/tetrodotoxin/on_mob_metabolize(mob/living/affected_mob)
|
||||
. = ..()
|
||||
RegisterSignal(affected_mob, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(block_breath))
|
||||
@@ -1383,6 +1408,9 @@
|
||||
/datum/reagent/toxin/tetrodotoxin/on_mob_end_metabolize(mob/living/affected_mob)
|
||||
. = ..()
|
||||
UnregisterSignal(affected_mob, COMSIG_CARBON_ATTEMPT_BREATHE, PROC_REF(block_breath))
|
||||
remove_paralysis(affected_mob)
|
||||
|
||||
/datum/reagent/toxin/tetrodotoxin/proc/remove_paralysis(mob/living/affected_mob)
|
||||
// the initial() proc doesn't work for lists.
|
||||
var/list/initial_list = list(
|
||||
TRAIT_PARALYSIS_L_ARM = BODY_ZONE_L_ARM,
|
||||
@@ -1395,5 +1423,5 @@
|
||||
|
||||
/datum/reagent/toxin/tetrodotoxin/proc/block_breath(mob/living/source)
|
||||
SIGNAL_HANDLER
|
||||
if(current_cycle > 28)
|
||||
if(current_cycle > 28 && !HAS_TRAIT(source, TRAIT_TETRODOTOXIN_HEALING))
|
||||
return COMSIG_CARBON_BLOCK_BREATH
|
||||
|
||||
@@ -158,9 +158,6 @@
|
||||
|
||||
wag_flags = WAG_ABLE
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/get_global_feature_list()
|
||||
return SSaccessories.tails_list_human
|
||||
|
||||
/obj/item/organ/external/tail/cat/get_butt_sprite()
|
||||
return icon('icons/mob/butts.dmi', BUTT_SPRITE_CAT)
|
||||
|
||||
@@ -169,6 +166,9 @@
|
||||
feature_key = "tail_cat"
|
||||
color_source = ORGAN_COLOR_HAIR
|
||||
|
||||
/datum/bodypart_overlay/mutant/tail/cat/get_global_feature_list()
|
||||
return SSaccessories.tails_list_felinid
|
||||
|
||||
/obj/item/organ/external/tail/monkey
|
||||
name = "monkey tail"
|
||||
preference = "feature_monkey_tail"
|
||||
|
||||
@@ -240,6 +240,15 @@
|
||||
|
||||
color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail
|
||||
|
||||
if(greyscale_config)
|
||||
get_greyscale_color_from_draw_color()
|
||||
else
|
||||
color = bodypart_overlay.draw_color // so a pink felinid doesn't drop a gray tail
|
||||
|
||||
///Here we define how draw_color from the bodypart overlay sets the greyscale colors of organs that use GAGS
|
||||
/obj/item/organ/proc/get_greyscale_color_from_draw_color()
|
||||
color = bodypart_overlay.draw_color //Defaults to the legacy behaviour of applying the color to the item.
|
||||
|
||||
/// In space station videogame, nothing is sacred. If somehow an organ is removed unexpectedly, handle it properly
|
||||
/obj/item/organ/proc/forced_removal()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
inserted_organs += organ
|
||||
|
||||
// Search for added Status Effect.
|
||||
var/datum/status_effect/organ_set_bonus/added_status = locate(/datum/status_effect/organ_set_bonus) in lab_rat.status_effects
|
||||
var/datum/status_effect/organ_set_bonus/added_status
|
||||
if(!infuser_entry.unreachable_effect)
|
||||
added_status = locate(/datum/status_effect/organ_set_bonus) in lab_rat.status_effects
|
||||
|
||||
// If threshold_desc is filled-in, it implies the organ_set_bonus Status Effect should be activated.
|
||||
// Without it, we'll assume there isn't a Status Effect to look for.
|
||||
|
||||
|
Before Width: | Height: | Size: 841 KiB After Width: | Height: | Size: 901 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 35 KiB |
BIN
icons/mob/human/fish_features.dmi
Normal file
|
After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 141 KiB |
@@ -35,6 +35,7 @@ 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.
|
||||
Fishing rods are particularly effective melee weapons against spacemen deeply infused with fish DNA from genetics.
|
||||
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.
|
||||
|
||||
@@ -1062,6 +1062,7 @@
|
||||
#include "code\datums\components\boomerang.dm"
|
||||
#include "code\datums\components\boss_music.dm"
|
||||
#include "code\datums\components\breeding.dm"
|
||||
#include "code\datums\components\bubble_icon_override.dm"
|
||||
#include "code\datums\components\bullet_intercepting.dm"
|
||||
#include "code\datums\components\bumpattack.dm"
|
||||
#include "code\datums\components\burning.dm"
|
||||
@@ -2163,12 +2164,14 @@
|
||||
#include "code\game\machinery\computer\records\security.dm"
|
||||
#include "code\game\machinery\dna_infuser\dna_infuser.dm"
|
||||
#include "code\game\machinery\dna_infuser\dna_infusion.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_actions.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_book.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_entry.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_entries\infuser_tier_one_entries.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_entries\infuser_tier_two_entries.dm"
|
||||
#include "code\game\machinery\dna_infuser\infuser_entries\infuser_tier_zero_entries.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\carp_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\fish_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\fly_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\fox_organs.dm"
|
||||
#include "code\game\machinery\dna_infuser\organ_sets\goliath_organs.dm"
|
||||
@@ -2865,6 +2868,7 @@
|
||||
#include "code\modules\actionspeed\modifiers\addiction.dm"
|
||||
#include "code\modules\actionspeed\modifiers\base.dm"
|
||||
#include "code\modules\actionspeed\modifiers\drugs.dm"
|
||||
#include "code\modules\actionspeed\modifiers\mobs.dm"
|
||||
#include "code\modules\actionspeed\modifiers\mood.dm"
|
||||
#include "code\modules\actionspeed\modifiers\status_effects.dm"
|
||||
#include "code\modules\actionspeed\modifiers\wound.dm"
|
||||
@@ -5661,10 +5665,10 @@
|
||||
#include "code\modules\projectiles\projectile\special\ion.dm"
|
||||
#include "code\modules\projectiles\projectile\special\meteor.dm"
|
||||
#include "code\modules\projectiles\projectile\special\mindflayer.dm"
|
||||
#include "code\modules\projectiles\projectile\special\neurotoxin.dm"
|
||||
#include "code\modules\projectiles\projectile\special\plasma.dm"
|
||||
#include "code\modules\projectiles\projectile\special\rocket.dm"
|
||||
#include "code\modules\projectiles\projectile\special\saboteur.dm"
|
||||
#include "code\modules\projectiles\projectile\special\spit.dm"
|
||||
#include "code\modules\projectiles\projectile\special\temperature.dm"
|
||||
#include "code\modules\projectiles\projectile\special\wormhole.dm"
|
||||
#include "code\modules\reagents\chem_splash.dm"
|
||||
|
||||