Rift Fishing (#88619)

## About The Pull Request

Adds rift fishing to the game.


![image](https://github.com/user-attachments/assets/044304ca-e7a0-45e9-baaf-b445328d3982)

Drained and undrained influences can be fished in, the latter only by
heretics. Fishing in an undrained influence shows a bobber floating over
nothing to other people, so don't be stupid!

The loot pool includes the following:

- Knowledge. Great for heretics, bad for crew. Only actually gives
knowledge if fished up in an unopened rift, opening it.
One of each heretic potion type.
- A wild Fire Shark, hostile to all.
- One of each heretic potion, and two flasks of eldritch essence.
- Several new fish:

![image](https://github.com/user-attachments/assets/259bd1ee-3b1e-47db-bcfd-c23b7908f66f)
In order:
1. Chrystarfish
Cosmostarfishe that snuck into the bluespace compartment of a shuttle
engine. Teleports around when eaten. Can be cut into bluespace crystals.
Very pointy.
2. Flumpulus
Probably not an actual fish. Contains flumpuline, which is in many ways
an upgrade to oculine. Except for it occasionally popping your eyes out
and replacing them with fungus. It also gets flattened if you land on
it, cushioning your fall.

![image](https://github.com/user-attachments/assets/02b398b0-22ac-4002-a828-cb73281ecef6)

3. Gullion
This fish can be cut into two diamonds, and needs no mate to reproduce,
making it an excellent way to replenish the station's diamond supply!
However, it needs silicon in the fish tank to survive.
4. Walro-Dolphish
Weird, amphibious creature. Amazing weapon - high damage, strong
piercing wounds, decent block chances. However, it will bite you if you
hold it for too long, so be careful!

More fish are planned to be added. The PR was split in two to reduce
review complexity as the latter half of the fish were increasingly
convoluted.

Any fishing rod will do for fishing, but heretics are now able to infuse
their fishing rod with a grasp:

![image](https://github.com/user-attachments/assets/37cfb7da-9269-4db7-b05f-4bbf4a6957f2)

Infusing the rod will temporarily improve its fishing modifier and give
it a unique trait that lets heretics gather 2 influence, rather than 1,
from a fished-up rift.

If crew fish up a glimpse of the Mansus, they will recieve the same
effects as if they examined the rift, and a curse hand will shoot out at
them.

influences cannot be bombed for fish.
## Why It's Good For The Game

Rifts are _extremely_ close to basically just being eldritch pools of
liquid that some heretic spilled over the station. It's always stuck out
like a sore thumb that we can't fish in them, but now we _can_. (Also,
someone needs to PR fishing in a bucket for clowns and mimes.)

Fishing in a rift is just one of those things you see some random,
innocent assistant do while doing an errand, passively enhancing the
round with the sheer ridiculousness of it. Coming back, it's likely
you'll see them running from a wild Fire Shark they unwisely dug up from
messing with eldritch influences.

For Heretics, this is for the most part actively a worse alternative
than just doing things normally. But sometimes you don't want to be
optimal. Infusing their fishing rod is almost entirely an amusing twist
on the blade infusion that blade path has, and they can even infuse
other people's rods - make fish not war.

Ghommie gave me the fish sprites, and I interpreted them the silliest
and most interesting ways I could think of.
> Chrystarfish

Bluespace's technobabble has finally reached fish. Much like the
Gullion, the intention here was primarily some additional, risky way to
procure some amount of bluespace crystals and dust that doesn't depend
on Mining to do their job, either for the station or for your own stupid
plans. (Obviously mining is still the best way to get it, but it's not
healthy for the game for them to be the ONLY way to do so!)

>Flumpulus


![image](https://static.wikia.nocookie.net/oots/images/3/38/OOTS0074.jpeg/revision/latest?cb=20150609013601)

Imagine taking a pill of 'Super oculine!' and suddenly your eyes pop out
and are replaced with fungeyes. 10/10

>Gullion

Diamonds are extremely scarce on the station and the only way to get
more is by mining. I thought adding some rare, restricted way of getting
more would be fun for the game, and encourage fish breeding.
Parthenogenesis may be a bit much admittedly, but let's just see what
happens

> Walro-Dolphish

The name for this thing kinda sucks. I like the idea of an amphibious
fish-weapon like the pikes that actually kinda just hates being wielded
around like a stick. It's also piercing to differentiate.


![image](https://github.com/user-attachments/assets/a1cb58fb-af16-4f9c-9675-aaaa15172674)
## Changelog
🆑
Carlarc, Ghommie
add: Adds rift fishing to the game. Includes new wacky fish!
add: Drained and undrained influences can be fished in, the latter only
by heretics. Fishing in an undrained influence shows a bobber floating
over nothing to other people, so don't be stupid!
add: influences cannot be bombed for fish.
add: Heretics can now infuse their fishing rod, and fish for knowledge.
/🆑

---------

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
carlarctg
2024-12-27 11:25:12 +00:00
committed by GitHub
co-authored by Ghom
parent 8db12edbbc
commit 4d84d0de9b
31 changed files with 664 additions and 42 deletions
+4
View File
@@ -4,6 +4,8 @@
#define FISHING_RANDOM_SEED "Random seed"
///Used in the surgery fishing spot to define a random organ reward
#define FISHING_RANDOM_ORGAN "Random organ"
///Used in the dimensional rift fishing spot to define influence gain
#define FISHING_INFLUENCE "Influence"
// Baseline fishing difficulty levels
#define FISHING_DEFAULT_DIFFICULTY 15
@@ -272,6 +274,8 @@
#define FISH_SOURCE_FLAG_NO_BLUESPACE_ROD (1<<1)
/// When examined by someone with enough fishing skill, this will also display fish that doesn't have FISH_FLAG_SHOW_IN_CATALOG
#define FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG (1<<2)
/// This fish source will not spawn fish on explosions
#define FISH_SOURCE_FLAG_EXPLOSIVE_NONE (1<<3)
/**
* A macro to ensure the wikimedia filenames of fish icons are unique, especially since there're a couple fish that have
+3
View File
@@ -806,6 +806,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_ROD_ATTRACT_SHINY_LOVERS "rod_attract_shiny_lovers"
/// This rod can be used to fish on lava
#define TRAIT_ROD_LAVA_USABLE "rod_lava_usable"
/// This rod was infused by a heretic, making it awesome and improving influence gain
#define TRAIT_ROD_MANSUS_INFUSED "rod_infused"
/// Stuff that can go inside fish cases and aquariums
#define TRAIT_AQUARIUM_CONTENT "aquarium_content"
/// If the item can be used as a bit.
@@ -1030,6 +1032,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
///fish traits
#define TRAIT_FISH_STASIS "fish_stasis"
#define TRAIT_FISH_FLOPPING "fish_flopping"
#define TRAIT_RESIST_PSYCHIC "resist_psychic"
#define TRAIT_RESIST_EMULSIFY "resist_emulsify"
#define TRAIT_FISH_SELF_REPRODUCE "fish_self_reproduce"
#define TRAIT_FISH_NO_MATING "fish_no_mating"
+2
View File
@@ -667,6 +667,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_FISH_QUICK_GROWTH" = TRAIT_FISH_QUICK_GROWTH,
"TRAIT_FISH_TOXIN_IMMUNE" = TRAIT_FISH_TOXIN_IMMUNE,
"TRAIT_RESIST_EMULSIFY" = TRAIT_RESIST_EMULSIFY,
"TRAIT_RESIST_PSYCHIC" = TRAIT_RESIST_PSYCHIC,
"TRAIT_FISH_WELL_COOKED" = TRAIT_FISH_WELL_COOKED,
"TRAIT_YUCKY_FISH" = TRAIT_YUCKY_FISH,
),
@@ -675,6 +676,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_ROD_IGNORE_ENVIRONMENT" = TRAIT_ROD_IGNORE_ENVIRONMENT,
"TRAIT_ROD_LAVA_USABLE" = TRAIT_ROD_LAVA_USABLE,
"TRAIT_ROD_REMOVE_FISHING_DUD" = TRAIT_ROD_REMOVE_FISHING_DUD,
"TRAIT_ROD_MANSUS_INFUSED" = TRAIT_ROD_MANSUS_INFUSED,
),
/obj/item/integrated_circuit = list(
"TRAIT_CIRCUIT_UI_OPEN" = TRAIT_CIRCUIT_UI_OPEN,
+1
View File
@@ -379,6 +379,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_ROD_IGNORE_ENVIRONMENT" = TRAIT_ROD_IGNORE_ENVIRONMENT,
"TRAIT_ROD_LAVA_USABLE" = TRAIT_ROD_LAVA_USABLE,
"TRAIT_ROD_REMOVE_FISHING_DUD" = TRAIT_ROD_REMOVE_FISHING_DUD,
"TRAIT_ROD_MANSUS_INFUSED" = TRAIT_ROD_MANSUS_INFUSED,
),
/obj/item/organ/liver = list(
"TRAIT_BALLMER_SCIENTIST" = TRAIT_BALLMER_SCIENTIST,
+1
View File
@@ -187,6 +187,7 @@
damagetype = STAMINA,
)
to_chat(victim, span_userdanger("[weapon] embedded in your [limb.plaintext_zone] jostles and stings!"))
embed_data.jostle_callback?.Invoke(victim, weapon, embed_data)
/// Called when then item randomly falls out of a carbon. This handles the damage and descriptors, then calls safe_remove()
+23 -18
View File
@@ -6,37 +6,42 @@
*
* It's an element that squishes things. After the duration passes, it reverses the transformation it squished with, taking into account if they are a different orientation than they started (read: rotationally-fluid)
*
* Normal squishes apply vertically, as if the target is being squished from above, but you can set reverse to TRUE if you want to squish them from the sides, like if they pancake into a wall from the East or West
* Normal squishes apply vertically, as if the target is being squished from above, but you can set horizontal_squish to TRUE if you want to squish them from the sides, like if they pancake into a wall from the East or West
*/
/datum/element/squish
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY
/datum/element/squish/Attach(datum/target, duration=20 SECONDS, reverse=FALSE)
/datum/element/squish/Attach(atom/target, duration=20 SECONDS, horizontal_squish=FALSE)
. = ..()
if(!iscarbon(target))
if(!isatom(target))
return ELEMENT_INCOMPATIBLE
var/mob/living/carbon/C = target
var/was_lying = C.body_position == LYING_DOWN
addtimer(CALLBACK(src, PROC_REF(Detach), C, was_lying, reverse), duration)
var/was_lying = FALSE
if(iscarbon(target))
var/mob/living/carbon/carboniucus = target
was_lying = carboniucus.body_position == LYING_DOWN
addtimer(CALLBACK(src, PROC_REF(Detach), target, was_lying, horizontal_squish), duration)
if(reverse)
C.transform = C.transform.Scale(SHORT, TALL)
if(horizontal_squish)
target.transform = target.transform.Scale(SHORT, TALL)
else
C.transform = C.transform.Scale(TALL, SHORT)
target.transform = target.transform.Scale(TALL, SHORT)
/datum/element/squish/Detach(mob/living/carbon/C, was_lying, reverse)
/datum/element/squish/Detach(atom/target, was_lying, horizontal_squish)
. = ..()
if(istype(C))
var/is_lying = C.body_position == LYING_DOWN
var/is_lying = FALSE
if(iscarbon(target))
var/mob/living/carbon/carboniucus = target
is_lying = carboniucus.body_position == LYING_DOWN
if(reverse)
is_lying = !is_lying
if(horizontal_squish)
is_lying = !is_lying
if(was_lying == is_lying)
C.transform = C.transform.Scale(SHORT, TALL)
else
C.transform = C.transform.Scale(TALL, SHORT)
if(was_lying == is_lying)
target.transform = target.transform.Scale(SHORT, TALL)
else
target.transform = target.transform.Scale(TALL, SHORT)
#undef SHORT
#undef TALL
+3
View File
@@ -35,6 +35,8 @@ GLOBAL_LIST_INIT(embed_by_type, generate_embed_type_cache())
var/jostle_chance = 5
/// Coefficient of multiplication for the damage the item does while
var/jostle_pain_mult = 1
/// Call this proc on jostling, if it exists!
var/datum/callback/jostle_callback
/// This percentage of all pain will be dealt as stam damage rather than brute (0-1)
var/pain_stam_pct = 0
@@ -51,5 +53,6 @@ GLOBAL_LIST_INIT(embed_by_type, generate_embed_type_cache())
data.ignore_throwspeed_threshold = !isnull(ignore_throwspeed_threshold) ? ignore_throwspeed_threshold : src.ignore_throwspeed_threshold
data.jostle_chance = !isnull(jostle_chance) ? jostle_chance : src.jostle_chance
data.jostle_pain_mult = !isnull(jostle_pain_mult) ? jostle_pain_mult : src.jostle_pain_mult
data.jostle_callback = !isnull(jostle_callback) ? jostle_callback : src.jostle_callback
data.pain_stam_pct = !isnull(pain_stam_pct) ? pain_stam_pct : src.pain_stam_pct
return data
@@ -122,9 +122,14 @@
/datum/mood_event/heretics
description = "THE HIGHER I RISE, THE MORE I SEE."
mood_change = 10 //maybe being a cultist isnt that bad after all
mood_change = 10 //maybe being a heretic isnt that bad after all
hidden = TRUE
/datum/mood_event/rift_fishing
description = "THE MORE I FISH, THE HIGHER I RISE."
mood_change = 7
timeout = 5 MINUTES
/datum/mood_event/family_heirloom
description = "My family heirloom is safe with me."
mood_change = 1
@@ -85,6 +85,7 @@
/obj/effect/visible_heretic_influence/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(show_presence)), 15 SECONDS)
AddComponent(/datum/component/fishing_spot, GLOB.preset_fish_sources[/datum/fish_source/dimensional_rift])
var/image/silicon_image = image('icons/effects/eldritch.dmi', src, null, OBJ_LAYER)
silicon_image.override = TRUE
@@ -175,6 +176,7 @@
AddElement(/datum/element/block_turf_fingerprints)
AddComponent(/datum/component/redirect_attack_hand_from_turf, interact_check = CALLBACK(src, PROC_REF(verify_user_can_see)))
AddComponent(/datum/component/fishing_spot, GLOB.preset_fish_sources[/datum/fish_source/dimensional_rift])
/obj/effect/heretic_influence/proc/verify_user_can_see(mob/user)
return (user.mind in GLOB.reality_smash_track.tracked_heretics)
@@ -109,9 +109,10 @@
bloodiest_wound.adjust_blood_flow(-0.5 * seconds_between_ticks)
/// Torment the target with a frightening hand
/proc/fire_curse_hand(mob/living/carbon/victim)
/proc/fire_curse_hand(mob/living/carbon/victim, turf/forced_turf)
var/grab_dir = turn(victim.dir, pick(-90, 90, 180, 180)) // Not in front, favour behind
var/turf/spawn_turf = get_ranged_target_turf(victim, grab_dir, 8)
spawn_turf = forced_turf ? forced_turf : spawn_turf
if (isnull(spawn_turf))
return
new /obj/effect/temp_visual/dir_setting/curse/grasp_portal(spawn_turf, victim.dir)
@@ -25,6 +25,39 @@ GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge())
cost = 0
is_starting_knowledge = TRUE
// Heretics can enhance their fishing rods to fish better - fishing content.
// Lasts until succesfully fishing something up.
/datum/heretic_knowledge/spell/basic/on_gain(mob/user, datum/antagonist/heretic/our_heretic)
..()
RegisterSignal(user, COMSIG_TOUCH_HANDLESS_CAST, PROC_REF(on_grasp_cast))
/datum/heretic_knowledge/spell/basic/proc/on_grasp_cast(mob/living/carbon/cast_on, datum/action/cooldown/spell/touch/touch_spell)
SIGNAL_HANDLER
// Not a grasp, we dont want this to activate with say star or mending touch.
if(!istype(touch_spell, action_to_add))
return NONE
var/obj/item/fishing_rod/held_rod = cast_on.get_active_held_item()
if(!istype(held_rod, /obj/item/fishing_rod) || HAS_TRAIT(held_rod, TRAIT_ROD_MANSUS_INFUSED))
return NONE
INVOKE_ASYNC(cast_on, TYPE_PROC_REF(/atom/movable, say), message = "R'CH T'H F'SH!", forced = "fishing rod infusion invocation")
playsound(cast_on, /datum/action/cooldown/spell/touch/mansus_grasp::sound, 15)
cast_on.visible_message(span_notice("[cast_on] snaps [cast_on.p_their()] fingers next to [held_rod], covering it in a burst of purple flames!"))
ADD_TRAIT(held_rod, TRAIT_ROD_MANSUS_INFUSED, REF(held_rod))
held_rod.difficulty_modifier -= 20
RegisterSignal(held_rod, COMSIG_FISHING_ROD_CAUGHT_FISH, PROC_REF(unfuse))
held_rod.add_filter("mansus_infusion", 2, list("type" = "outline", "color" = COLOR_VOID_PURPLE, "size" = 1))
return COMPONENT_CAST_HANDLESS
/datum/heretic_knowledge/spell/basic/proc/unfuse(obj/item/fishing_rod/item, reward, mob/user)
if(reward == FISHING_INFLUENCE || prob(35))
item.remove_filter("mansus_infusion")
REMOVE_TRAIT(item, TRAIT_ROD_MANSUS_INFUSED, REF(item))
item.difficulty_modifier += 20
/**
* The Living Heart heretic knowledge.
*
+6
View File
@@ -386,6 +386,9 @@
bites_amount++
var/bites_to_finish = weight / FISH_WEIGHT_BITE_DIVISOR
adjust_health(health - (initial(health) / bites_to_finish) * 3)
flinch_on_eat(eater, feeder)
/obj/item/fish/proc/flinch_on_eat(mob/living/eater, mob/living/feeder)
if(status == FISH_ALIVE && prob(50) && feeder.is_holding(src) && feeder.dropItemToGround(src))
to_chat(feeder, span_warning("[src] slips out of your hands in pain!"))
var/turf/target_turf = get_ranged_target_turf(get_turf(src), pick(GLOB.alldirs), 2)
@@ -927,6 +930,9 @@
stop_flopping()
/obj/item/fish/process(seconds_per_tick)
do_fish_process(seconds_per_tick)
/obj/item/fish/proc/do_fish_process(seconds_per_tick)
if(HAS_TRAIT(src, TRAIT_FISH_STASIS) || status != FISH_ALIVE)
return
+7 -4
View File
@@ -73,7 +73,7 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/// Proc used by both the predator and necrophage traits.
/datum/fish_trait/proc/eat_fish(obj/item/fish/predator, obj/item/fish/prey)
var/message = prey.status == FISH_DEAD ? "[src] eats [prey]'s carcass." : "[src] hunts down and eats [prey]."
var/message = prey.status == FISH_DEAD ? "[predator] eats [prey]'s carcass." : "[predator] hunts down and eats [prey]."
predator.loc.visible_message(span_warning(message))
SEND_SIGNAL(prey, COMSIG_FISH_EATEN_BY_OTHER_FISH, predator)
qdel(prey)
@@ -286,11 +286,13 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
/datum/fish_trait/emulsijack
name = "Emulsifier"
catalog_description = "This fish emits an invisible toxin that emulsifies other fish for it to feed on."
var/list/resistance_traits = list(TRAIT_RESIST_EMULSIFY, TRAIT_FISH_TOXIN_IMMUNE)
var/trait_to_add = TRAIT_RESIST_EMULSIFY
/datum/fish_trait/emulsijack/apply_to_fish(obj/item/fish/fish)
. = ..()
RegisterSignal(fish, COMSIG_FISH_LIFE, PROC_REF(emulsify))
ADD_TRAIT(fish, TRAIT_RESIST_EMULSIFY, FISH_TRAIT_DATUM)
ADD_TRAIT(fish, trait_to_add, FISH_TRAIT_DATUM)
/datum/fish_trait/emulsijack/proc/emulsify(obj/item/fish/source, seconds_per_tick)
SIGNAL_HANDLER
@@ -298,8 +300,9 @@ GLOBAL_LIST_INIT(spontaneous_fish_traits, populate_spontaneous_fish_traits())
return
var/emulsified = FALSE
for(var/obj/item/fish/victim in source.loc)
if(HAS_TRAIT(victim, TRAIT_RESIST_EMULSIFY) || HAS_TRAIT(victim, TRAIT_FISH_TOXIN_IMMUNE)) //no team killing
continue
for(var/trait in resistance_traits)
if(HAS_TRAIT(victim, trait))
continue
victim.adjust_health(victim.health - 3 * seconds_per_tick) //the victim may heal a bit but this will quickly kill
emulsified = TRUE
if(emulsified)
+5 -1
View File
@@ -89,6 +89,7 @@
grind_results = list(/datum/reagent/bluespace = 10)
fillet_type = null
fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph)
compatible_types = list(/obj/item/fish/starfish/chrystarfish)
beauty = FISH_BEAUTY_GREAT
/obj/item/fish/starfish/Initialize(mapload, apply_qualities = TRUE)
@@ -97,8 +98,11 @@
/obj/item/fish/starfish/update_overlays()
. = ..()
. += add_emissive()
/obj/item/fish/starfish/proc/add_emissive()
if(status == FISH_ALIVE)
. += emissive_appearance(icon, "starfish_emissive", src)
return emissive_appearance(icon, "starfish_emissive", src)
///It spins, and dimly glows in the dark.
/obj/item/fish/starfish/flop_animation()
+395
View File
@@ -0,0 +1,395 @@
/obj/item/fish/starfish/chrystarfish
name = "chrystarfish"
fish_id = "chrystarfish"
desc = "This is what happens when a cosmostarfish sneaks into the bluespace compartment of a hyperspace engine. Very pointy and damaging - leading cause of spaceship explosions in 2554."
icon = 'icons/obj/aquarium/rift.dmi'
dedicated_in_aquarium_icon = 'icons/obj/aquarium/rift.dmi'
icon_state = "chrystarfish"
force = 12
sharpness = SHARP_POINTY
wound_bonus = -10
bare_wound_bonus = 15
armour_penetration = 6
demolition_mod = 1.2
throwforce = 11
throw_range = 8
throw_speed = 4
embed_type = /datum/embed_data/chrystarfish
attack_verb_continuous = list("stabs", "jabs")
attack_verb_simple = list("stab", "jab")
hitsound = SFX_SHATTER
pickup_sound = 'sound/items/handling/materials/glass_pick_up.ogg'
drop_sound = 'sound/items/handling/materials/glass_drop.ogg'
sprite_width = 7
sprite_height = 9
average_size = 40
average_weight = 1500
food = /datum/reagent/bluespace
feeding_frequency = 10 MINUTES
health = 50
death_text = "%SRC splinters apart into shards!"
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
fillet_type = /obj/item/stack/ore/bluespace_crystal
num_fillets = 3
stable_population = 3
compatible_types = list(/obj/item/fish/starfish)
fish_traits = list(/datum/fish_trait/antigrav)
beauty = FISH_BEAUTY_EXCELLENT
fish_movement_type = /datum/fish_movement/accelerando
fishing_difficulty_modifier = 15
favorite_bait = list(/obj/item/stack/ore/bluespace_crystal)
// something something bluespace
electrogenesis_power = 9 MEGA JOULES
// Basically a ninja star that's highly likely to embed and teleports you around if you don't stop to remove it. However it doesn't deal that much damage!
/datum/embed_data/chrystarfish
pain_mult = 1
embed_chance = 85
fall_chance = 3
pain_chance = 9
impact_pain_mult = 1
remove_pain_mult = 2
rip_time = 1.5 SECONDS
ignore_throwspeed_threshold = TRUE // basically shaped like a shuriken
jostle_chance = 15
jostle_pain_mult = 1
// about to be set!
jostle_callback = null
/datum/embed_data/chrystarfish/New()
..()
jostle_callback = CALLBACK(src, PROC_REF(teleport))
/datum/embed_data/chrystarfish/proc/teleport(mob/victim, atom/embed_parent, datum/embed_data/real_data)
do_teleport(victim, get_turf(victim), 3, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
victim.visible_message(span_danger("[victim] teleports as [embed_parent] jostles inside [victim.p_them()]!"))
/obj/item/fish/starfish/chrystarfish/set_status(new_status, silent)
. = ..()
if(new_status == FISH_DEAD)
new fillet_type(get_turf(src))
playsound(src, SFX_SHATTER, 50)
qdel(src)
/obj/item/fish/starfish/chrystarfish/add_emissive()
return
/obj/item/fish/starfish/chrystarfish/get_base_edible_reagents_to_add()
var/list/return_list = ..()
return_list[/datum/reagent/bluespace] = 5
return return_list
/obj/item/fish/starfish/chrystarfish/flinch_on_eat(mob/living/eater, mob/living/feeder)
if(status != FISH_ALIVE)
return
to_chat(feeder, span_warning("[src] slips out of the spacetime in pain!"))
var/tp_range = 6 * clamp(weight/average_weight, 3, 9) // usually 6, plus or minus fish weight
// teleports itself if on a turf otherwise its container - whatever it is
do_teleport(isturf(loc) ? src : loc, get_turf(feeder), tp_range, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/item/fish/starfish/chrystarfish/suicide_act(mob/living/user)
visible_message(span_suicide("[user] swallows [src] whole! It looks like they're trying to commit suicide!"))
forceMove(user)
// *everything*
for(var/obj/thing in user.get_contents())
if(QDELETED(thing) || istype(thing, /obj/item/bodypart/chest))
continue // don't want a gib
stoplag(0.1 SECONDS)
playsound(src, 'sound/effects/phasein.ogg', 15, TRUE)
do_teleport(thing, get_turf(user), 2, asoundin = null, channel = TELEPORT_CHANNEL_BLUESPACE)
qdel(src)
return MANUAL_SUICIDE
// Prevents the first 2 messages from spamming on each patience update.
#define PATIENCE_FLINCH "PATIENCE_FLINCH"
#define PATIENCE_UNCOMFY "PATIENCE_UNCOMFY"
/obj/item/fish/dolphish
name = "walro-dolphish"
fish_id = "walro-dolphish"
desc = "Strange bloodthirsty apex predator from beyond. A powerful weapon, but it -hates- being held."
icon = 'icons/obj/aquarium/wide.dmi'
dedicated_in_aquarium_icon = 'icons/obj/aquarium/rift.dmi'
icon_state = "dolphish"
lefthand_file = 'icons/mob/inhands/fish_lefthand.dmi'
righthand_file = 'icons/mob/inhands/fish_righthand.dmi'
force = 19
sharpness = SHARP_POINTY
wound_bonus = -5
bare_wound_bonus = 20
armour_penetration = 12
block_chance = 33
throwforce = 7
throw_range = 4
attack_verb_continuous = list("bites", "impales", "rams")
attack_verb_simple = list("bite", "impale", "ram")
hitsound = 'sound/items/weapons/bladeslice.ogg'
block_sound = 'sound/items/weapons/parry.ogg'
drop_sound = 'sound/mobs/non-humanoids/fish/fish_drop1.ogg'
pickup_sound = SFX_FISH_PICKUP
sound_vary = TRUE
base_pixel_x = -16
pixel_x = -16
sprite_width = 13
sprite_height = 9
required_fluid_type = AQUARIUM_FLUID_AIR
required_temperature_min = BODYTEMP_COLD_DAMAGE_LIMIT // you mean just like a human? that's odd...
required_temperature_max = BODYTEMP_HEAT_DAMAGE_LIMIT
food = /datum/reagent/blood
health = 600 // apex predator
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
fillet_type = /obj/item/food/fishmeat/fish_tail
num_fillets = 1
stable_population = 3
fish_traits = list(/datum/fish_trait/wary, /datum/fish_trait/carnivore, /datum/fish_trait/necrophage, /datum/fish_trait/predator, /datum/fish_trait/territorial, /datum/fish_trait/stinger)
fish_movement_type = /datum/fish_movement/choppy
fishing_difficulty_modifier = 30
favorite_bait = list()
disliked_bait = list()
average_size = 150
average_weight = 2750
weight_size_deviation = 0.5
safe_air_limits = list(
/datum/gas/oxygen = list(12, 100),
/datum/gas/nitrogen,
/datum/gas/carbon_dioxide = list(0, 10),
)
min_pressure = HAZARD_LOW_PRESSURE
max_pressure = HAZARD_HIGH_PRESSURE
beauty = FISH_BEAUTY_GREAT
/// Maximum patience for below var.
var/max_patience = 20
/// Counter of how much patience the fish currently has before it attacks its wielder.
var/patience = 20
/// Ensures the last warning fx isn't repeated
var/last_effect
/obj/item/fish/dolphish/get_force_rank()
var/multiplier = 1
switch(w_class)
if(WEIGHT_CLASS_TINY)
multiplier = 0.35
if(WEIGHT_CLASS_SMALL)
multiplier = 0.5
if(WEIGHT_CLASS_NORMAL)
multiplier = 0.75
// bulky is avergae
if(WEIGHT_CLASS_HUGE)
multiplier = 1.15
if(WEIGHT_CLASS_GIGANTIC)
multiplier = 1.35
if(status == FISH_DEAD)
multiplier -= 0.35 // huge nerf if dead
force *= multiplier
attack_speed *= multiplier
demolition_mod *= multiplier
block_chance *= multiplier
armour_penetration *= multiplier
wound_bonus *= multiplier
bare_wound_bonus *= multiplier
/obj/item/fish/dolphish/do_fish_process(seconds_per_tick)
. = ..()
var/patience_reduction = 1
var/turf/onturf = get_turf(loc)
//gas check
var/datum/gas_mixture/turf_gasmix = onturf.return_air()
// likes water, gets sleepy, gets very sleepy
if(turf_gasmix.gases[/datum/gas/water_vapor] && turf_gasmix.gases[/datum/gas/water_vapor][MOLES] >= 5)
patience_reduction *= 0.5
if(turf_gasmix.gases[/datum/gas/nitrous_oxide] && turf_gasmix.gases[/datum/gas/nitrous_oxide][MOLES] >= 5)
patience_reduction *= 0.25
if(turf_gasmix.gases[/datum/gas/healium] && turf_gasmix.gases[/datum/gas/healium][MOLES] >= 5)
patience_reduction *= 0.1
if(!ismob(loc))
// dividing by the multiplier nets us an increasing value. happy dolphish gain patience quicker
var/patience_bonus = (1 / patience_reduction)
patience = clamp(patience + patience_bonus * seconds_per_tick, 0, max_patience)
return
var/mob/living/moc = loc
if(moc.mob_biotypes & MOB_AQUATIC)
patience_reduction *= 0.6
if(HAS_TRAIT(moc, TRAIT_IS_WET))
patience_reduction *= 0.6
patience = clamp(patience - (patience_reduction * seconds_per_tick), 0, max_patience)
switch(patience)
if(0)
// No check, we always want sharky to bite jerky on 0
moc.visible_message(span_bolddanger("[src] bites directly into [moc] and squirms away from [moc.p_their()] grasp!"), span_userdanger("[src] sinks its fangs into you!!"))
moc.apply_damage(force, BRUTE, moc.get_active_hand(), wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness, attacking_item = src)
forceMove(moc.drop_location())
moc.painful_scream()
patience = max_patience
playsound(src, hitsound, 45)
if(1 to 10)
// No check, final warning as they struggle, also funny.
visible_message(span_bolddanger("[src] thrashes against [moc]'s grasp!"))
moc.shake_up_animation()
if(10 to 15)
if(last_effect == PATIENCE_FLINCH)
return
visible_message(span_danger("[src] flinches away from [moc]!"))
moc.shake_up_animation()
last_effect = PATIENCE_FLINCH
if(15 to 20)
if(last_effect == PATIENCE_UNCOMFY)
return
visible_message(span_notice("[src] seems uncomfortable in [moc]'s grasp."))
last_effect = PATIENCE_UNCOMFY
return
#undef PATIENCE_FLINCH
#undef PATIENCE_UNCOMFY
/obj/item/fish/flumpulus
name = "flumpulus"
fish_id = "flumpulus"
desc = "You can hardly even guess as to how this possibly counts as a fish. Inexplicably, you get the feeling that it could serve as a fantastic way to cushion a fall."
icon = 'icons/obj/aquarium/rift.dmi'
dedicated_in_aquarium_icon = 'icons/obj/aquarium/rift.dmi'
icon_state = "flumpulus"
lefthand_file = 'icons/mob/inhands/fish_lefthand.dmi'
righthand_file = 'icons/mob/inhands/fish_righthand.dmi'
attack_verb_continuous = list("splats", "splorts")
attack_verb_simple = list("splat", "splort")
sprite_width = 10
sprite_height = 9
required_fluid_type = AQUARIUM_FLUID_AIR
required_temperature_min = 0
required_temperature_max = INFINITY
food = /datum/reagent/consumable/nutriment/fat
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
fillet_type = /obj/item/food/meat/slab/human/mutant/slime
num_fillets = 2
stable_population = 2
fish_traits = list()
fish_movement_type = /datum/fish_movement/slow
fishing_difficulty_modifier = 22
favorite_bait = list()
disliked_bait = list()
// twice as big, half as heavy
average_size = 100
average_weight = 500
material_weight_mult = 1
weight_size_deviation = 0.6
safe_air_limits = list(
/datum/gas/nitrogen,
)
min_pressure = 0
max_pressure = HAZARD_HIGH_PRESSURE
beauty = FISH_BEAUTY_UGLY
/obj/item/fish/flumpulus/suicide_act(mob/living/user)
visible_message(span_suicide("[user] swallows [src] whole! It looks like they're trying to commit suicide!"))
forceMove(user)
. = MANUAL_SUICIDE
for(var/i in 1 to rand(5, 15))
addtimer(CALLBACK(src, PROC_REF(flump_attack), user), 0.4 SECONDS * i)
/obj/item/fish/flumpulus/proc/flump_attack(mob/living/user)
var/obj/item/organ/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES)
var/obj/item/organ/eyes/new_eyes = pick(list(/obj/item/organ/eyes/snail, /obj/item/organ/eyes/night_vision/mushroom))
new_eyes = new new_eyes(user)
new_eyes.Insert(user)
playsound(user, 'sound/effects/cartoon_sfx/cartoon_pop.ogg', 50, TRUE)
user.visible_message("[user]'s [eyes ? eyes : "eye holes"] suddenly sprout stalks and turn into [new_eyes]!")
ASYNC
user.emote("scream")
sleep(5 SECONDS)
if(!QDELETED(eyes))
eyes.visible_message(span_danger("[eyes] rapidly turn to dust."))
eyes.dust()
/obj/item/fish/flumpulus/get_base_edible_reagents_to_add()
var/list/return_list = ..()
//return_list[/datum/reagent/flumpulus_extract] = 10
return_list[/datum/reagent/medicine/oculine/flumpuline] = 10
return return_list
/obj/item/fish/flumpulus/intercept_zImpact(list/falling_movables, levels)
. = ..()
if(status == FISH_DEAD)
return .
for(var/mob/living/fallen_mob in falling_movables)
visible_message(span_danger("[src] flattens like a pancake as [fallen_mob] lands on top of it!"))
adjust_health(initial(health) * 0.1) // very durable
AddElement(/datum/element/squish, 15 SECONDS)
fallen_mob.Paralyze(0.5 SECONDS)
playsound(src, 'sound/effects/cartoon_sfx/cartoon_splat.ogg', 75)
return FALL_INTERCEPTED | FALL_NO_MESSAGE
/obj/item/fish/gullion
name = "gullion"
fish_id = "gullion"
desc = "This crystalline fish is actually one of only two known silicon-based lifeforms.\
It avoids death via oxygen-silicate reactions by organically shielding its exterior, allowing the thick scales to calcify into quartz and diamond, at the cost of rendering the fish functionally blind. \
How xenomorphs manage is a complete mystery bordering on bullshit."
icon = 'icons/obj/aquarium/rift.dmi'
dedicated_in_aquarium_icon = 'icons/obj/aquarium/rift.dmi'
icon_state = "gullion"
lefthand_file = 'icons/mob/inhands/fish_lefthand.dmi'
righthand_file = 'icons/mob/inhands/fish_righthand.dmi'
attack_verb_continuous = list("stabs", "jabs")
attack_verb_simple = list("stab", "jab")
hitsound = SFX_DEFAULT_FISH_SLAP
pickup_sound = 'sound/items/handling/materials/glass_pick_up.ogg'
drop_sound = 'sound/items/handling/materials/glass_drop.ogg'
sprite_width = 7
sprite_height = 5
food = /datum/reagent/silicon
feeding_frequency = 30 SECONDS
health = 160
death_text = "%SRC calcifies."
random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS
fillet_type = /obj/item/stack/sheet/mineral/diamond
num_fillets = 2
stable_population = 3
fish_traits = list(/datum/fish_trait/heavy, /datum/fish_trait/parthenogenesis) // this thing is a diamond farm
beauty = FISH_BEAUTY_EXCELLENT
fish_movement_type = /datum/fish_movement/slow
favorite_bait = list(/obj/item/stack/sheet/mineral/diamond)
fishing_difficulty_modifier = 22
average_size = 30
average_weight = 2000
weight_size_deviation = 0.3
safe_air_limits = list(
/datum/gas/oxygen = list(0, 2), // does NOT like oxygen
/datum/gas/water_vapor,
)
required_fluid_type = AQUARIUM_FLUID_SULPHWATEVER
required_temperature_min = 0
required_temperature_max = BODYTEMP_HEAT_DAMAGE_LIMIT
min_pressure = HAZARD_LOW_PRESSURE
max_pressure = WARNING_HIGH_PRESSURE
/obj/item/fish/gullion/suicide_act(mob/living/user)
visible_message(span_suicide("[user] swallows [src] whole! It looks like they're trying to commit suicide!"))
forceMove(user)
var/datum/gas_mixture/environment = user.loc.return_air()
var/oxygen_in_air = check_gases(environment.gases, list(/datum/gas/oxygen))
if(!oxygen_in_air || (status == FISH_DEAD))
visible_message(span_suicide("[user] chokes and dies! (Wait, from the fish or from lack of air?)"))
return OXYLOSS
user.petrify(statue_timer = INFINITY)
visible_message(span_suicide("[user]'s skin turns into quartz upon contact with the oxygen in the air!'"))
qdel(src)
return MANUAL_SUICIDE
+7
View File
@@ -132,6 +132,13 @@
. += "" //add a new line
. += span_notice("Thanks to your fishing skills, you can examine it again for more in-depth information.")
return
if(HAS_TRAIT(src, TRAIT_ROD_MANSUS_INFUSED))
if(IS_HERETIC(user))
. += span_purple("This rod has been <b>infused</b> by a heretic, improving its ability to catch glimpses of the Mansus. And fish.")
else
. += span_purple("It's glowing an eerie purple...")
else if(IS_HERETIC(user))
. += span_purple("As a Heretic, you can infuse this fishing rod with your <b>Mansus Grasp</b> by activating the spell while wielding it, to enhance its fishing power.")
/obj/item/fishing_rod/examine_more(mob/user)
. = ..()
@@ -504,6 +504,8 @@ GLOBAL_LIST_INIT(specific_fish_icons, generate_specific_fish_icons())
/datum/fish_source/proc/spawn_reward_from_explosion(atom/location, severity)
SIGNAL_HANDLER
if(fish_source_flags & FISH_SOURCE_FLAG_EXPLOSIVE_NONE)
return
var/multiplier = 1
if(fish_source_flags & FISH_SOURCE_FLAG_EXPLOSIVE_MALUS)
if(explosive_fishing_score <= 0)
+79 -10
View File
@@ -159,6 +159,7 @@
radial_name = "Chasm"
overlay_state = "portal_chasm"
radial_state = "ground_hole"
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_NONE
/datum/fish_source/portal/ocean
fish_table = list(
@@ -295,7 +296,7 @@
mover.long_jump_velocity_limit += rand(-100, 100)
///Cherry on top, fish caught from the randomizer portal also have (almost completely) random traits
/datum/fish_source/portal/random/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
/datum/fish_source/portal/random/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot, obj/item/fishing_rod/used_rod)
if(!ispath(reward_path, /obj/item/fish))
return ..()
@@ -342,9 +343,6 @@
return rod.hook.chasm_detritus_type
/datum/fish_source/chasm/spawn_reward_from_explosion(atom/location, severity)
return //Spawned content would immediately fall back into the chasm, so it wouldn't matter.
/datum/fish_source/lavaland
catalog_description = "Lava vents"
background = "background_lavaland"
@@ -582,7 +580,7 @@
return
return ..()
/datum/fish_source/hydro_tray/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
/datum/fish_source/hydro_tray/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot, obj/item/fishing_rod/used_rod)
if(reward_path != FISHING_RANDOM_SEED)
var/mob/living/created_reward = ..()
if(istype(created_reward))
@@ -662,7 +660,7 @@
//The range for waiting is also a bit narrower, so it cannot take as few as 3 seconds or as many as 25 to snatch an organ.
wait_time_range = list(6 SECONDS, 12 SECONDS)
/datum/fish_source/surgery/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
/datum/fish_source/surgery/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot, obj/item/fishing_rod/used_rod)
if(istype(fishing_spot, /obj/machinery/fishing_portal_generator))
var/obj/machinery/fishing_portal_generator/portal = fishing_spot
fishing_spot = portal.current_linked_atom
@@ -707,7 +705,7 @@
fish_table = list(
FISHING_DUD = 10,
)
fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD|FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG
fish_source_flags = FISH_SOURCE_FLAG_NO_BLUESPACE_ROD|FISH_SOURCE_FLAG_IGNORE_HIDDEN_ON_CATALOG|FISH_SOURCE_FLAG_EXPLOSIVE_NONE
fishing_difficulty = FISHING_EASY_DIFFICULTY + 5
#undef RANDOM_AQUARIUM_FISH
@@ -725,9 +723,6 @@
return fish_table
return table
/datum/fish_source/aquarium/spawn_reward_from_explosion(atom/location, severity)
return //If the aquarium breaks, all fish are released anyway.
/datum/fish_source/aquarium/generate_wiki_contents(datum/autowiki/fish_sources/wiki)
var/list/data = list()
@@ -775,3 +770,77 @@
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 20
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_MALUS
/datum/fish_source/dimensional_rift
catalog_description = null //it's a secret (sorta, I know you're reading this)
radial_state = "cursed" // placeholder
overlay_state = "portal_rift_2" // yeah good luck adaptin the rift sprite to this template. recolored randomizer's the best you're getting
fish_table = list(
FISHING_INFLUENCE = 6,
/obj/item/fish/starfish/chrystarfish = 7,
/obj/item/fish/dolphish = 7,
/obj/item/fish/flumpulus = 7,
/obj/item/fish/gullion = 7,
/mob/living/basic/heretic_summon/fire_shark/wild = 3,
/obj/item/eldritch_potion/crucible_soul = 1,
/obj/item/eldritch_potion/duskndawn = 1,
/obj/item/eldritch_potion/wounded = 1,
/obj/item/reagent_containers/cup/beaker/eldritch = 2,
)
fish_counts = list(
/mob/living/basic/heretic_summon/fire_shark/wild = 3,
/obj/item/eldritch_potion/crucible_soul = 1,
/obj/item/eldritch_potion/duskndawn = 1,
/obj/item/eldritch_potion/wounded = 1,
/obj/item/reagent_containers/cup/beaker/eldritch = 2,
)
fish_count_regen = list(
/mob/living/basic/heretic_summon/fire_shark/wild = 3 MINUTES,
/obj/item/eldritch_potion/crucible_soul = 5 MINUTES,
/obj/item/eldritch_potion/duskndawn = 5 MINUTES,
/obj/item/eldritch_potion/wounded = 5 MINUTES,
/obj/item/reagent_containers/cup/beaker/eldritch = 2.5 MINUTES,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 35
fish_source_flags = FISH_SOURCE_FLAG_EXPLOSIVE_NONE
/datum/fish_source/dimensional_rift/on_challenge_completed(mob/user, datum/fishing_challenge/challenge, success)
. = ..()
if(challenge.reward_path != FISHING_INFLUENCE)
return
var/mob/living/carbon/human/human_user
if(ishuman(user))
human_user = user
user.visible_message(span_danger("[user] reels [user.p_their()] [challenge.used_rod] in, catching.. nothing?"), span_notice("You catch.. a glimpse into the workings of the Mansus itself!"))
// Heretics that fish in the rift gain knowledge.
if(IS_HERETIC(user))
human_user?.add_mood_event("rift fishing", /datum/mood_event/rift_fishing)
var/obj/effect/heretic_influence/fishfluence = challenge.location
// But only if it's an open rift
if(!istype(fishfluence))
to_chat(user, span_notice("You glimpse something fairly uninteresting."))
return
fishfluence.after_drain(user)
var/datum/antagonist/heretic/heretic_datum = GET_HERETIC(user)
if(heretic_datum)
heretic_datum.knowledge_points++
to_chat(user, "[span_hear("You hear a whisper...")] [span_hypnophrase("THE HIGHER I RISE, THE MORE I FISH.")]")
// They can also gain an extra influence point if they infused their rod.
if(HAS_TRAIT(challenge.used_rod, TRAIT_ROD_MANSUS_INFUSED))
heretic_datum.knowledge_points++
to_chat(user, span_boldnotice("Your infused rod improves your knowledge gain!"))
return
// Non-heretics instead go crazy
human_user?.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 190)
human_user?.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus)
// Hand fires at them from the location
fire_curse_hand(user, get_turf(challenge.location))
// Handled above
/datum/fish_source/dimensional_rift/spawn_reward(reward_path, atom/spawn_location, atom/fishing_spot)
if(reward_path != FISHING_INFLUENCE)
return ..()
return
@@ -21,6 +21,7 @@
mob_size = MOB_SIZE_TINY
speak_emote = list("screams")
basic_mob_flags = DEL_ON_DEATH
ai_controller = /datum/ai_controller/basic_controller/simple_hostile_obstacles
/mob/living/basic/heretic_summon/fire_shark/Initialize(mapload)
. = ..()
@@ -32,3 +33,6 @@
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_FREE_HYPERSPACE_MOVEMENT, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
/mob/living/basic/heretic_summon/fire_shark/wild
faction = list(FACTION_HOSTILE)
@@ -78,6 +78,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/organ/heart/mutantheart = /obj/item/organ/heart
///Replaces default lungs with a different organ
var/obj/item/organ/lungs/mutantlungs = /obj/item/organ/lungs
/// Smoker lungs for the quirk, overriden by certain species
var/obj/item/organ/lungs/smoker_lungs = /obj/item/organ/lungs/smoker_lungs
///Replaces default eyes with a different organ
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
///Replaces default ears with a different organ
@@ -3,6 +3,7 @@
id = SPECIES_ETHEREAL
meat = /obj/item/food/meat/slab/human/mutant/ethereal
mutantlungs = /obj/item/organ/lungs/ethereal
smoker_lungs = /obj/item/organ/lungs/ethereal/ethereal_smoker
mutantstomach = /obj/item/organ/stomach/ethereal
mutanttongue = /obj/item/organ/tongue/ethereal
mutantheart = /obj/item/organ/heart/ethereal
@@ -19,6 +19,7 @@
inherent_biotypes = MOB_HUMANOID|MOB_MINERAL
inherent_respiration_type = RESPIRATION_PLASMA
mutantlungs = /obj/item/organ/lungs/plasmaman
smoker_lungs = /obj/item/organ/lungs/plasmaman/plasmaman_smoker
mutanttongue = /obj/item/organ/tongue/bone/plasmaman
mutantliver = /obj/item/organ/liver/bone/plasmaman
mutantstomach = /obj/item/organ/stomach/bone/plasmaman
+10 -5
View File
@@ -73,15 +73,22 @@
#define DUST_ANIMATION_TIME 1.3 SECONDS
/**
* This is the proc for turning a mob into ash.
* This is the proc for turning an atom into ash.
* Dusting robots does not eject the MMI, so it's a bit more powerful than gib()
*
* Arguments:
* Arguments: (Only used for mobs)
* * just_ash - If TRUE, ash will spawn where the mob was, as opposed to remains
* * drop_items - Should the mob drop their items before dusting?
* * force - Should this mob be FORCABLY dusted?
*/
/mob/living/proc/dust(just_ash, drop_items, force)
/atom/movable/proc/dust(just_ash, drop_items, force)
dust_animation()
// since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play.
// Looks much nicer and doesn't cause multiple runtimes.
QDEL_IN(src, DUST_ANIMATION_TIME)
/mob/living/dust(just_ash, drop_items, force)
..()
if(body_position == STANDING_UP)
// keep us upright so the animation fits.
ADD_TRAIT(src, TRAIT_FORCED_STANDING, TRAIT_GENERIC)
@@ -93,10 +100,8 @@
if(buckled)
buckled.unbuckle_mob(src, force = TRUE)
dust_animation()
addtimer(CALLBACK(src, PROC_REF(spawn_dust), just_ash), DUST_ANIMATION_TIME - 0.3 SECONDS)
ghostize()
QDEL_IN(src, DUST_ANIMATION_TIME) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes.
/// Animates turning into dust.
/// Does not delete src afterwards, BUT it will become invisible (and grey), so ensure you handle that yourself
+5
View File
@@ -3008,3 +3008,8 @@ GLOBAL_LIST_EMPTY(fire_appearances)
/mob/living/proc/check_hit_limb_zone_name(hit_zone)
if(has_limbs)
return hit_zone
/mob/living/proc/painful_scream(force = FALSE)
if(HAS_TRAIT(src, TRAIT_ANALGESIA) && !force)
return
INVOKE_ASYNC(src, PROC_REF(emote), "scream")
@@ -759,6 +759,63 @@
if(affected_mob.adjustOrganLoss(ORGAN_SLOT_EYES, 1.5 * REM * seconds_per_tick, required_organ_flag = affected_organ_flags))
. = UPDATE_MOB_HEALTH
/datum/reagent/medicine/oculine/flumpuline
name = "Flumpuline"
description = "Often confused for, or sold as, Oculine or a variation thereof. Slowly transmogrifies the eyes of the patient into grotesque stalks - but you'll never need glasses again."
color = "#6c596d"
metabolization_rate = 0.1 * REAGENTS_METABOLISM
overdose_threshold = 5
taste_description = "fungus"
purity = 1
ph = 0.01
chemical_flags = REAGENT_DEAD_PROCESS|REAGENT_IGNORE_STASIS|REAGENT_NO_RANDOM_RECIPE|REAGENT_CAN_BE_SYNTHESIZED
inverse_chem = /datum/reagent/inverse
inverse_chem_val = 0
var/static/list/eye_types = list(/obj/item/organ/eyes/snail, /obj/item/organ/eyes/night_vision/mushroom)
/datum/reagent/medicine/oculine/flumpuline/improve_eyesight(mob/living/carbon/affected_mob, obj/item/organ/eyes/eyes)
delta_light = 200 //2x better than pure oculine
eyes.lighting_cutoff += delta_light
affected_mob.update_sight()
/datum/reagent/medicine/oculine/flumpuline/restore_eyesight(mob/living/carbon/affected_mob, obj/item/organ/eyes/eyes)
eyes.lighting_cutoff -= delta_light
affected_mob.update_sight()
/datum/reagent/medicine/oculine/flumpuline/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
. = ..()
var/obj/item/organ/eyes/eyes = affected_mob.get_organ_slot(ORGAN_SLOT_EYES)
// if no eyes or inorganic do nothing. we let already changed eyes go because funny
if(!eyes || !IS_ORGANIC_ORGAN(eyes))
return .
if(!prob(2))
return .
flump_eyes(affected_mob, eyes)
// Overdose causes constant eye popping
/datum/reagent/medicine/oculine/flumpuline/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired)
. = ..()
if(!prob(25))
return
var/obj/item/organ/eyes/eyes = affected_mob.get_organ_slot(ORGAN_SLOT_EYES)
flump_eyes(affected_mob, eyes)
/datum/reagent/medicine/oculine/flumpuline/proc/flump_eyes(mob/affected_mob, obj/eyes)
var/obj/item/organ/eyes/new_eyes = pick(eye_types)
new_eyes = new new_eyes(affected_mob)
new_eyes.Insert(affected_mob)
playsound(affected_mob, 'sound/effects/cartoon_sfx/cartoon_pop.ogg', 50, TRUE)
affected_mob.visible_message("[affected_mob]'s [eyes ? eyes : "eye holes"] suddenly sprout stalks and turn into [new_eyes]!")
ASYNC
affected_mob.emote("scream")
sleep(5 SECONDS)
if(!QDELETED(eyes))
eyes.visible_message(span_danger("[eyes] rapidly turn to dust."))
eyes.dust()
/datum/reagent/medicine/inacusiate
name = "Inacusiate"
description = "Rapidly repairs damage to the patient's ears to cure deafness, assuming the source of said deafness isn't from genetic mutations, chronic deafness, or a total defecit of ears." //by "chronic" deafness, we mean people with the "deaf" quirk
@@ -153,9 +153,9 @@
return ..() | SPELL_NO_FEEDBACK | SPELL_NO_IMMEDIATE_COOLDOWN
/datum/action/cooldown/spell/touch/cast(mob/living/carbon/cast_on)
if(SEND_SIGNAL(cast_on, COMSIG_TOUCH_HANDLESS_CAST) & COMPONENT_CAST_HANDLESS)
if(SEND_SIGNAL(cast_on, COMSIG_TOUCH_HANDLESS_CAST, src) & COMPONENT_CAST_HANDLESS)
StartCooldown()
return ..()
return
if(!QDELETED(attached_hand) && (attached_hand in cast_on.held_items))
remove_hand(cast_on, reset_cooldown_after = TRUE)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 29 KiB

+1
View File
@@ -4234,6 +4234,7 @@
#include "code\modules\fishing\fish\types\freshwater.dm"
#include "code\modules\fishing\fish\types\holographic.dm"
#include "code\modules\fishing\fish\types\mining.dm"
#include "code\modules\fishing\fish\types\rift.dm"
#include "code\modules\fishing\fish\types\ruins.dm"
#include "code\modules\fishing\fish\types\saltwater.dm"
#include "code\modules\fishing\fish\types\station.dm"