[MIRROR] Chasm Fishing [MDB IGNORE] (#15855)

* Chasm Fishing

* Update code/datums/components/chasm.dm

Co-authored-by: Jacquerel <hnevard@gmail.com>
Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-09-04 03:31:49 +01:00
committed by GitHub
co-authored by Jacquerel Tom
parent 0d0117f1d3
commit 3b088ec9e9
14 changed files with 267 additions and 53 deletions
+1
View File
@@ -35,6 +35,7 @@
#define FISHING_SPOT_PRESET_BEACH "beach"
#define FISHING_SPOT_PRESET_LAVALAND_LAVA "lavaland lava"
#define FISHING_SPOT_PRESET_CHASM "chasm"
#define FISHING_MINIGAME_RULE_HEAVY_FISH "heavy"
#define FISHING_MINIGAME_RULE_WEIGHTED_BAIT "weighted"
+133 -48
View File
@@ -1,6 +1,10 @@
/// List of weakrefs to containers for things which have fallen into chasms
GLOBAL_LIST_INIT(chasm_storage, list())
// Used by /turf/open/chasm and subtypes to implement the "dropping" mechanic
/datum/component/chasm
var/turf/target_turf
var/obj/effect/abstract/chasm_storage/storage
var/fall_message = "GAH! Ah... where are you?"
var/oblivion_message = "You stumble and stare into the abyss before you. It stares back, and you fall into the enveloping dark."
@@ -26,12 +30,33 @@
/obj/effect/dummy/phased_mob,
/obj/effect/mapping_helpers,
/obj/effect/wisp,
/obj/effect/ebeam,
/obj/effect/fishing_lure,
))
/datum/component/chasm/Initialize(turf/target)
RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/Entered)
target_turf = target
START_PROCESSING(SSobj, src) // process on create, in case stuff is still there
src.parent.AddElement(/datum/element/lazy_fishing_spot, FISHING_SPOT_PRESET_CHASM)
/datum/component/chasm/UnregisterFromParent()
STOP_PROCESSING(SSobj, src)
remove_storage()
/**
* Deletes the chasm storage object and removes empty weakrefs from global list
*/
/datum/component/chasm/proc/remove_storage()
if (!storage)
return
QDEL_NULL(storage)
var/list/chasm_storage = list()
for (var/datum/weakref/ref as anything in GLOB.chasm_storage)
if (!ref.resolve())
continue
chasm_storage += ref
GLOB.chasm_storage = chasm_storage
/datum/component/chasm/proc/Entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
@@ -54,35 +79,36 @@
LAZYREMOVE(found_safeties, S)
return LAZYLEN(found_safeties)
/datum/component/chasm/proc/drop_stuff(AM)
/datum/component/chasm/proc/drop_stuff(dropped_thing)
if (is_safe())
return FALSE
var/atom/parent = src.parent
var/to_check = AM ? list(AM) : parent.contents
var/to_check = dropped_thing ? list(dropped_thing) : parent.contents
for (var/thing in to_check)
if (droppable(thing))
. = TRUE
INVOKE_ASYNC(src, .proc/drop, thing)
/datum/component/chasm/proc/droppable(atom/movable/AM)
var/datum/weakref/falling_ref = WEAKREF(AM)
/datum/component/chasm/proc/droppable(atom/movable/dropped_thing)
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
// avoid an infinite loop, but allow falling a large distance
if(falling_atoms[falling_ref] && falling_atoms[falling_ref] > 30)
return FALSE
if(!isliving(AM) && !isobj(AM))
if(!isliving(dropped_thing) && !isobj(dropped_thing))
return FALSE
if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || (AM.movement_type & (FLOATING|FLYING)))
if(is_type_in_typecache(dropped_thing, forbidden_types) || dropped_thing.throwing || (dropped_thing.movement_type & (FLOATING|FLYING)))
return FALSE
//Flies right over the chasm
if(ismob(AM))
var/mob/M = AM
if(ismob(dropped_thing))
var/mob/M = dropped_thing
if(M.buckled) //middle statement to prevent infinite loops just in case!
var/mob/buckled_to = M.buckled
if((!ismob(M.buckled) || (buckled_to.buckled != M)) && !droppable(M.buckled))
return FALSE
if(ishuman(AM))
var/mob/living/carbon/human/victim = AM
if(ishuman(dropped_thing))
var/mob/living/carbon/human/victim = dropped_thing
if(istype(victim.belt, /obj/item/wormhole_jaunter))
var/obj/item/wormhole_jaunter/jaunter = victim.belt
var/turf/chasm = get_turf(victim)
@@ -92,59 +118,118 @@
return fall_into_chasm
return TRUE
/datum/component/chasm/proc/drop(atom/movable/AM)
var/datum/weakref/falling_ref = WEAKREF(AM)
/datum/component/chasm/proc/drop(atom/movable/dropped_thing)
var/datum/weakref/falling_ref = WEAKREF(dropped_thing)
//Make sure the item is still there after our sleep
if(!AM || !falling_ref?.resolve())
if(!dropped_thing || !falling_ref?.resolve())
falling_atoms -= falling_ref
return
falling_atoms[falling_ref] = (falling_atoms[falling_ref] || 0) + 1
var/turf/T = target_turf
var/atom/parent = src.parent
if(T)
// send to the turf below
AM.visible_message(span_boldwarning("[AM] falls into [parent]!"), span_userdanger("[fall_message]"))
T.visible_message(span_boldwarning("[AM] falls from above!"))
AM.forceMove(T)
if(isliving(AM))
var/mob/living/L = AM
dropped_thing.visible_message(span_boldwarning("[dropped_thing] falls into [parent]!"), span_userdanger("[fall_message]"))
T.visible_message(span_boldwarning("[dropped_thing] falls from above!"))
dropped_thing.forceMove(T)
if(isliving(dropped_thing))
var/mob/living/L = dropped_thing
L.Paralyze(100)
L.adjustBruteLoss(30)
falling_atoms -= falling_ref
return
else
// send to oblivion
AM.visible_message(span_boldwarning("[AM] falls into [parent]!"), span_userdanger("[oblivion_message]"))
if (isliving(AM))
var/mob/living/L = AM
L.notransform = TRUE
L.Paralyze(20 SECONDS)
// send to oblivion
dropped_thing.visible_message(span_boldwarning("[dropped_thing] falls into [parent]!"), span_userdanger("[oblivion_message]"))
if (isliving(dropped_thing))
var/mob/living/falling_mob = dropped_thing
falling_mob.notransform = TRUE
falling_mob.Paralyze(20 SECONDS)
var/oldtransform = AM.transform
var/oldcolor = AM.color
var/oldalpha = AM.alpha
animate(AM, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 10)
for(var/i in 1 to 5)
//Make sure the item is still there after our sleep
if(!AM || QDELETED(AM))
return
AM.pixel_y--
sleep(2)
var/oldtransform = dropped_thing.transform
var/oldcolor = dropped_thing.color
var/oldalpha = dropped_thing.alpha
animate(dropped_thing, transform = matrix() - matrix(), alpha = 0, color = rgb(0, 0, 0), time = 10)
for(var/i in 1 to 5)
//Make sure the item is still there after our sleep
if(!AM || QDELETED(AM))
if(!dropped_thing || QDELETED(dropped_thing))
return
dropped_thing.pixel_y--
sleep(2)
if(iscyborg(AM))
var/mob/living/silicon/robot/S = AM
qdel(S.mmi)
//Make sure the item is still there after our sleep
if(!dropped_thing || QDELETED(dropped_thing))
return
falling_atoms -= falling_ref
qdel(AM)
if(AM && !QDELETED(AM)) //It's indestructible
var/atom/parent = src.parent
parent.visible_message(span_boldwarning("[parent] spits out [AM]!"))
AM.alpha = oldalpha
AM.color = oldcolor
AM.transform = oldtransform
AM.throw_at(get_edge_target_turf(parent,pick(GLOB.alldirs)),rand(1, 10),rand(1, 10))
if (!storage)
storage = new(get_turf(parent))
RegisterSignal(storage, COMSIG_ATOM_EXITED, .proc/left_chasm)
GLOB.chasm_storage += WEAKREF(storage)
if (storage.contains(dropped_thing))
return
dropped_thing.alpha = oldalpha
dropped_thing.color = oldcolor
dropped_thing.transform = oldtransform
if (dropped_thing.forceMove(storage))
if (isliving(dropped_thing))
RegisterSignal(dropped_thing, COMSIG_LIVING_REVIVE, .proc/on_revive)
SEND_SIGNAL(dropped_thing, COMSIG_MOVABLE_SECLUDED_LOCATION)
else
parent.visible_message(span_boldwarning("[parent] spits out [dropped_thing]!"))
dropped_thing.throw_at(get_edge_target_turf(parent, pick(GLOB.alldirs)), rand(1, 10), rand(1, 10))
if (isliving(dropped_thing))
var/mob/living/fallen_mob = dropped_thing
if(fallen_mob.stat != DEAD)
fallen_mob.death(TRUE)
fallen_mob.notransform = FALSE
fallen_mob.apply_damage(300)
falling_atoms -= falling_ref
/**
* Called when something has left the chasm depths storage.
* Arguments
*
* * source - Chasm object holder.
* * gone - Item which has just left the chasm contents.
*/
/datum/component/chasm/proc/left_chasm(atom/source, atom/movable/gone)
SIGNAL_HANDLER
UnregisterSignal(gone, COMSIG_LIVING_REVIVE)
#define CHASM_TRAIT "chasm trait"
/**
* Called if something comes back to life inside the pit. Expected sources are badmins and changelings.
* Ethereals should take enough damage to be smashed and not revive.
*
* Arguments
* * escapee - Lucky guy who just came back to life at the bottom of a hole.
*/
/datum/component/chasm/proc/on_revive(mob/living/escapee)
SIGNAL_HANDLER
var/atom/parent = src.parent
parent.visible_message(span_boldwarning("After a long climb, [escapee] leaps out of [parent]!"))
ADD_TRAIT(escapee, TRAIT_MOVE_FLYING, CHASM_TRAIT) //Otherwise they instantly fall back in
escapee.forceMove(get_turf(parent))
escapee.throw_at(get_edge_target_turf(parent, pick(GLOB.alldirs)), rand(1, 10), rand(1, 10))
REMOVE_TRAIT(escapee, TRAIT_MOVE_FLYING, CHASM_TRAIT)
escapee.Paralyze(20 SECONDS, TRUE)
UnregisterSignal(escapee, COMSIG_LIVING_REVIVE)
#undef CHASM_TRAIT
/**
* An abstract object which is basically just a bag that the chasm puts people inside
*/
/obj/effect/abstract/chasm_storage
name = "chasm depths"
desc = "The bottom of a hole. You shouldn't be able to interact with this."
anchored = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+6 -1
View File
@@ -10,8 +10,10 @@
var/action_text
/// What should we tell other people what the user did? (Eg: "Guy digs up the turf.")
var/action_text_third_person
/// Percentage chance of receiving a bonus worm
var/worm_chance
/datum/element/diggable/Attach(datum/target, to_spawn, amount = 1, action_text = "dig up", action_text_third_person = "digs up")
/datum/element/diggable/Attach(datum/target, to_spawn, amount = 1, worm_chance = 30, action_text = "dig up", action_text_third_person = "digs up")
. = ..()
if(!isturf(target))
return ELEMENT_INCOMPATIBLE
@@ -21,6 +23,7 @@
src.to_spawn = to_spawn
src.amount = amount
src.worm_chance = worm_chance
src.action_text = action_text
src.action_text_third_person = action_text_third_person
@@ -36,6 +39,8 @@
for(var/i in 1 to amount)
new to_spawn(source)
if (prob(worm_chance))
new /obj/item/food/bait/worm(source)
user.visible_message(
span_notice("[user] [action_text_third_person] [source]."),
+7
View File
@@ -24,6 +24,8 @@
var/dug = FALSE
/// Icon state to use when broken
var/broken_state = "asteroid_dug"
/// Percentage chance of receiving a bonus worm
var/worm_chance = 30
/turf/open/misc/asteroid/break_tile()
icon_state = broken_state
@@ -39,6 +41,8 @@
/turf/open/misc/asteroid/proc/getDug()
dug = TRUE
new digResult(src, 5)
if (prob(worm_chance))
new /obj/item/food/bait/worm(src)
icon_state = "[base_icon_state]_dug"
/// If the user can dig the turf
@@ -124,6 +128,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
/turf/open/misc/asteroid/basalt/airless
initial_gas_mix = AIRLESS_ATMOS
worm_chance = 0
/turf/open/misc/asteroid/basalt/Initialize(mapload)
. = ..()
@@ -152,6 +157,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
initial_gas_mix = AIRLESS_ATMOS
baseturfs = /turf/open/misc/asteroid/airless
turf_type = /turf/open/misc/asteroid/airless
worm_chance = 0
/turf/open/misc/asteroid/snow
gender = PLURAL
@@ -217,6 +223,7 @@ GLOBAL_LIST_EMPTY(dug_up_basalt)
/turf/open/misc/asteroid/snow/airless
initial_gas_mix = AIRLESS_ATMOS
worm_chance = 0
/turf/open/misc/asteroid/snow/temperatre
initial_gas_mix = "o2=22;n2=82;TEMP=255.37"
+4 -3
View File
@@ -132,7 +132,8 @@
/turf/open/floor/grass/Initialize(mapload)
. = ..()
spawniconchange()
AddElement(/datum/element/diggable, /obj/item/stack/ore/glass, 2, "uproot", "uproots")
AddElement(/datum/element/diggable, /obj/item/stack/ore/glass, 2, worm_chance = 50, \
action_text = "uproot", action_text_third_person = "uproots")
/turf/open/floor/grass/proc/spawniconchange()
icon_state = "grass[rand(0,3)]"
@@ -170,7 +171,7 @@
/turf/open/floor/fake_snow/Initialize(mapload)
. = ..()
AddElement(/datum/element/diggable, /obj/item/stack/tile/mineral/snow, 2)
AddElement(/datum/element/diggable, /obj/item/stack/tile/mineral/snow, 2, worm_chance = 0)
/turf/open/floor/fake_snow/setup_broken_states()
return list("snow_dug")
@@ -197,7 +198,7 @@
/turf/open/floor/fakebasalt/Initialize(mapload)
. = ..()
AddElement(/datum/element/diggable, /obj/item/stack/ore/glass/basalt, 2)
AddElement(/datum/element/diggable, /obj/item/stack/ore/glass/basalt, 2, worm_chance = 0)
if(prob(15))
icon_state = "basalt[rand(0, 12)]"
set_basalt_light(src)
@@ -0,0 +1,46 @@
/// An object which should replace itself on initialisation with something which fell into a chasm.
/obj/item/chasm_detritus
name = "chasm detritus"
desc = "Abstract concept of an object which once fell into a deep hole."
icon_state = "skub"
/// Stuff which you can always fish up even if nothing fell into a hole.
var/static/list/default_contents = list(\
/obj/item/stack/ore/slag = 2, \
/obj/item/stack/sheet/bone = 3, \
/obj/effect/mob_spawn/corpse/human/skeleton = 1, \
/mob/living/simple_animal/hostile/asteroid/lobstrosity/lava = 1, \
)
/obj/item/chasm_detritus/Initialize(mapload)
. = ..()
if (prob(25))
create_default_object()
return
var/list/chasm_stuff = find_chasm_contents()
if (!chasm_stuff.len)
create_default_object()
return
var/atom/movable/detritus = pick(chasm_stuff)
detritus.forceMove(get_turf(src))
qdel(src)
/// Instantiates something from the default list.
/obj/item/chasm_detritus/proc/create_default_object()
var/contents_type = pick(default_contents)
new contents_type(get_turf(src))
qdel(src)
/// Returns a list of every object which is currently inside of a chasm.
/obj/item/chasm_detritus/proc/find_chasm_contents()
var/list/chasm_contents = list()
if (!GLOB.chasm_storage.len)
return chasm_contents
var/list/chasm_storage_resolved = recursive_list_resolve(GLOB.chasm_storage)
for (var/obj/storage as anything in chasm_storage_resolved)
for (var/thing as anything in storage.contents)
chasm_contents += thing
return chasm_contents
+15
View File
@@ -181,6 +181,21 @@
fillet_type = /obj/item/food/fishmeat/armorfish
fish_ai_type = FISH_AI_SLOW
//Chasm fish
/obj/item/fish/chasm_crab
name = "chasm chrab"
desc = "The young of the lobstrosity mature in pools below the earth, eating what falls in until large enough to clamber out. Those found near the station are well-fed."
icon_state = "chrab"
dedicated_in_aquarium_icon_state = "chrab_small"
sprite_height = 9
sprite_width = 8
source_height = 9
source_width = 8
stable_population = 4
feeding_frequency = 15 MINUTES
random_case_rarity = FISH_RARITY_RARE
fillet_type = /obj/item/food/meat/slab/rawcrab
/obj/item/storage/box/fish_debug
name = "box full of fish"
+25
View File
@@ -30,6 +30,20 @@
fishing_line_traits = FISHING_LINE_BOUNCY
line_color = "#99313f"
/obj/item/fishing_line/sinew
name = "fishing sinew"
desc = "an all-natural fishing line made of stretched out sinew"
icon = 'icons/obj/fishing.dmi'
icon_state = "reel_sinew"
line_color = "#d1cca3"
/datum/crafting_recipe/sinew_line
name = "Sinew Fishing Line Reel"
result = /obj/item/fishing_line/sinew
reqs = list(/obj/item/stack/sheet/sinew = 2)
time = 2 SECONDS
category = CAT_PRIMAL
// Hooks
/obj/item/fishing_hook
@@ -62,6 +76,17 @@
fishing_hook_traits = FISHING_HOOK_WEIGHTED
rod_overlay_icon_state = "hook_weighted_overlay"
/obj/item/fishing_hook/bone
name = "bone hook"
desc = "a simple hook carved from sharpened bone"
icon_state = "hook_bone"
/datum/crafting_recipe/bone_hook
name = "Goliath Bone Hook"
result = /obj/item/fishing_hook/bone
reqs = list(/obj/item/stack/sheet/bone = 1)
time = 2 SECONDS
category = CAT_PRIMAL
/obj/item/storage/toolbox/fishing
name = "fishing toolbox"
+14
View File
@@ -362,6 +362,20 @@
if(gone == hook)
hook = null
/obj/item/fishing_rod/bone
name = "bone fishing rod"
desc = "A humble rod, made with whatever happened to be on hand."
icon_state = "fishing_rod_bone"
/datum/crafting_recipe/bone_rod
name = "Bone Fishing Rod"
result = /obj/item/fishing_rod/bone
time = 5 SECONDS
reqs = list(/obj/item/stack/sheet/leather = 1,
/obj/item/stack/sheet/sinew = 2,
/obj/item/stack/sheet/bone = 2)
category = CAT_PRIMAL
/obj/item/fishing_rod/master
name = "master fishing rod"
desc = "The mythical rod of a lost fisher king. Said to be imbued with un-paralleled fishing power. There's writing on the back of the pole. \"中国航天制造\""
+4 -1
View File
@@ -11,6 +11,9 @@ GLOBAL_LIST_INIT(preset_fish_sources,init_fishing_configurations())
var/datum/fish_source/lavaland/lava_preset = new
.[FISHING_SPOT_PRESET_LAVALAND_LAVA] = lava_preset
var/datum/fish_source/chasm/chasm_preset = new
.[FISHING_SPOT_PRESET_CHASM] = chasm_preset
/// Where the fish actually come from - every fishing spot has one assigned but multiple fishing holes can share single source, ie single shared one for ocean/lavaland river
/datum/fish_source
/// Fish catch weight table - these are relative weights
@@ -87,7 +90,7 @@ GLOBAL_LIST_INIT(preset_fish_sources,init_fishing_configurations())
reward_path = FISHING_DUD //Ran out of these since rolling (multiple fishermen on same source most likely)
if(ispath(reward_path))
if(ispath(reward_path,/obj/item))
var/obj/item/reward = new reward_path
var/obj/item/reward = new reward_path(get_turf(fisherman))
if(ispath(reward_path,/obj/item/fish))
var/obj/item/fish/caught_fish = reward
caught_fish.randomize_weight_and_size()
@@ -21,6 +21,17 @@
)
catalog_description = "Fish dimension (Fishing portal generator)"
/datum/fish_source/chasm
catalog_description = "Chasm depths"
background = "fishing_background_lavaland"
fish_table = list(
FISHING_DUD = 5,
/obj/item/fish/chasm_crab = 15,
/obj/item/chasm_detritus = 30,
)
fishing_difficulty = FISHING_DEFAULT_DIFFICULTY + 5
/datum/fish_source/lavaland
catalog_description = "Lava vents"
background = "fishing_background_lavaland"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

+1
View File
@@ -3030,6 +3030,7 @@
#include "code\modules\fishing\aquarium\aquarium.dm"
#include "code\modules\fishing\aquarium\aquarium_kit.dm"
#include "code\modules\fishing\fish\_fish.dm"
#include "code\modules\fishing\fish\chasm_detritus.dm"
#include "code\modules\fishing\fish\fish_types.dm"
#include "code\modules\fishing\sources\_fish_source.dm"
#include "code\modules\fishing\sources\source_types.dm"