Fishing bluespace capsules (#87639)

## About The Pull Request
With this PR, I'm introducing fishing bluespace capsules to the game.
They can be found on the black market, but I'll get a couple more ways
to get them before it's ready.

Anyway, they're special bluespace capsules that spawn a fishing spot of
your choice. The fishing spot can be changed by alt-clicking the
capsule, and so far it has 5 choices, plus 2 locked behind emagging for
obvious reasons:
- Freshwater: pretty basic, you get freshwater fish from this.
- Saltwater: mainly saltwater fish.
- Tiziran: You get tiziran fish here, like the gunner jellyfish,
armorfish, needlefish, dwarves moonfish and the new, bigger zagoskian
moonfish. By the by, moonfish now periodically lay moonfish eggs, a
staple of lizardfolk cuisine.
- Ice fishing spot: A small ice turf with a hole dug in it; salmon,
arctic char, arctic chrabs and the bonemass (skeleton fish).
- Hot Spring: Somehow the new home to the ought-to-be-extinct
sacabambaspis. It also doubles as a better shower overall, with mild
healing on top of stamina recovery. Felinids still hate it though, and
won't benefit from the healing.
- Lava: A 2x2 square of pure lava. Requires an emag for obvious reasons.
- Plasma: Ditto, but it's plasma instead of lava.

As a sidenote, unlike standard shelter capsules, these require their
area to be clear of pipes and cables on top of the other requirements,
unless emagged. Obviously, I've done some changes to allow pipes and
cables to not be hidden by water turfs, though I'm still keeping these
reqs because I don't think these fishing spots would look great if
riddled with cables and pipes. I may remove this extra req later if it
proves to be a tad too tedious.

Also they don't knock you back when expanding.

Screenshot from a recent test (fixed the misplaced decal and tweaked a
few things since then):

![immagine](https://github.com/user-attachments/assets/6bbcddfb-ff1c-4e96-834a-2129cadbb31f)


## Why It's Good For The Game
The idea stems from how not all fishing spots aren't designed to be
accessible every round, which is fine, because we have the fish-porter
for that. However, even the fish-porter should have its limits in terms
of what it can provide by itself (linking is all fair and game), so I've
thought having something of a middle point would been neat, also as a
way to mess around with the station layout a bit, to empower the player
with a little extra "terraforming".

## Changelog

🆑
add: Added fishing bluespace capsules to the game, which can be used to
spawn a variety of fishing spots, from freshwater to tiziran sea to hot
springs, and also lava and plasma if emagged.
add: Added two new fish: the zagoskian moonfish and the sacabambaspis.
Moonfish will now periodically lay moonfish eggs.
map: The 'crashed pod' lavaland ruin now has a hot spring, and the
cursed hotspring on icemoon now has a plastic chair and a fishing
toolbox.
/🆑
This commit is contained in:
Ghom
2024-11-11 08:01:09 +13:00
committed by GitHub
parent 48beb20406
commit e5472d9be4
50 changed files with 1409 additions and 277 deletions
+25 -9
View File
@@ -15,9 +15,14 @@
icon_state = "capsule"
icon = 'icons/obj/mining.dmi'
w_class = WEIGHT_CLASS_TINY
///The id we use to fetch the template datum
var/template_id = "shelter_alpha"
///The template datum we use to load the shelter
var/datum/map_template/shelter/template
///If true, this capsule is active and will deploy the area if conditions are met.
var/used = FALSE
///Will this capsule yeet mobs back once the area is deployed?
var/yeet_back = TRUE
/obj/item/survivalcapsule/proc/get_template()
if(template)
@@ -37,7 +42,7 @@
. += "This capsule has the [template.name] stored."
. += template.description
/obj/item/survivalcapsule/interact(mob/user)
/obj/item/survivalcapsule/interact(mob/living/user)
. = ..()
if(.)
return .
@@ -50,6 +55,9 @@
loc.visible_message(span_warning("[src] begins to shake. Stand back!"))
used = TRUE
addtimer(CALLBACK(src, PROC_REF(expand), user), 5 SECONDS)
if(iscarbon(user))
var/mob/living/carbon/carbon = user
carbon.throw_mode_on(THROW_MODE_TOGGLE)
return TRUE
/// Expands the capsule into a full shelter, placing the template at the item's location (NOT triggerer's location)
@@ -58,24 +66,32 @@
return
var/turf/deploy_location = get_turf(src)
var/status = template.check_deploy(deploy_location)
switch(status)
if(SHELTER_DEPLOY_BAD_AREA)
loc.visible_message(span_warning("[src] will not function in this area."))
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP)
loc.visible_message(span_warning("[src] doesn't have room to deploy! You need to clear a [template.width]x[template.height] area!"))
var/status = template.check_deploy(deploy_location, src, get_ignore_flags())
if(status != SHELTER_DEPLOY_ALLOWED)
fail_feedback(status)
used = FALSE
return
yote_nearby(deploy_location)
if(yeet_back)
yote_nearby(deploy_location)
template.load(deploy_location, centered = TRUE)
trigger_admin_alert(triggerer, deploy_location)
playsound(src, 'sound/effects/phasein.ogg', 100, TRUE)
new /obj/effect/particle_effect/fluid/smoke(get_turf(src))
qdel(src)
/// Returns a bitfield used to ignore some checks in template.check_deploy()
/obj/item/survivalcapsule/proc/get_ignore_flags()
return NONE
///Returns a message including the reason why it couldn't be deployed
/obj/item/survivalcapsule/proc/fail_feedback(status)
switch(status)
if(SHELTER_DEPLOY_BAD_AREA)
loc.visible_message(span_warning("[src] will not function in this area."))
if(SHELTER_DEPLOY_BAD_TURFS, SHELTER_DEPLOY_ANCHORED_OBJECTS, SHELTER_DEPLOY_OUTSIDE_MAP, SHELTER_DEPLOY_BANNED_OBJECTS)
loc.visible_message(span_warning("[src] doesn't have room to deploy! You need to clear a [template.width]x[template.height] area!"))
/// Throws any mobs near the deployed location away from the item / shelter
/// Does some math to make closer mobs get thrown further
/obj/item/survivalcapsule/proc/yote_nearby(turf/deploy_location)
+95 -21
View File
@@ -1,36 +1,39 @@
///Map templates used for bluespace survival capsules.
/datum/map_template/shelter
var/shelter_id
var/description
var/list/blacklisted_turfs
var/list/whitelisted_turfs
var/list/banned_areas
var/list/banned_objects
has_ceiling = TRUE
ceiling_turf = /turf/open/floor/engine/hull
ceiling_baseturfs = list(/turf/open/floor/plating)
///The id of the shelter template in the relative list from the mapping subsystem
var/shelter_id
///The description of the shelter, shown when examining survival capsule.
var/description
///If turf in the affected turfs is in this list, the survival capsule cannot be deployed.
var/list/blacklisted_turfs
///Areas where the capsule cannot be deployed.
var/list/banned_areas
///If any object in this list is found in the affected turfs, the capsule cannot deploy.
var/list/banned_objects = list()
/datum/map_template/shelter/New()
. = ..()
blacklisted_turfs = typecacheof(/turf/closed)
whitelisted_turfs = list()
banned_areas = typecacheof(/area/shuttle)
banned_objects = list()
/datum/map_template/shelter/proc/check_deploy(turf/deploy_location)
/datum/map_template/shelter/proc/check_deploy(turf/deploy_location, obj/item/survivalcapsule/capsule, ignore_flags = NONE)
var/affected = get_affected_turfs(deploy_location, centered=TRUE)
for(var/turf/T in affected)
var/area/A = get_area(T)
if(is_type_in_typecache(A, banned_areas))
for(var/turf/turf in affected)
var/area/area = get_area(turf)
if(is_type_in_typecache(area, banned_areas))
return SHELTER_DEPLOY_BAD_AREA
var/banned = is_type_in_typecache(T, blacklisted_turfs)
var/permitted = is_type_in_typecache(T, whitelisted_turfs)
if(banned && !permitted)
if(is_type_in_typecache(turf, blacklisted_turfs))
return SHELTER_DEPLOY_BAD_TURFS
for(var/obj/O in T)
if((O.density && O.anchored) || is_type_in_typecache(O, banned_objects))
for(var/obj/object in turf)
if(!(ignore_flags & CAPSULE_IGNORE_ANCHORED_OBJECTS) && object.density && object.anchored)
return SHELTER_DEPLOY_ANCHORED_OBJECTS
if(!(ignore_flags & CAPSULE_IGNORE_BANNED_OBJECTS) && is_type_in_typecache(object, banned_objects))
return SHELTER_DEPLOY_BANNED_OBJECTS
// Check if the shelter sticks out of map borders
var/shelter_origin_x = deploy_location.x - round(width/2)
@@ -53,7 +56,7 @@
/datum/map_template/shelter/alpha/New()
. = ..()
whitelisted_turfs = typecacheof(/turf/closed/mineral)
blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/beta
@@ -68,7 +71,7 @@
/datum/map_template/shelter/beta/New()
. = ..()
whitelisted_turfs = typecacheof(/turf/closed/mineral)
blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/charlie
@@ -83,7 +86,7 @@
/datum/map_template/shelter/charlie/New()
. = ..()
whitelisted_turfs = typecacheof(/turf/closed/mineral)
blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
/datum/map_template/shelter/toilet
@@ -96,5 +99,76 @@
/datum/map_template/shelter/toilet/New()
. = ..()
whitelisted_turfs = typecacheof(/turf/closed/mineral)
blacklisted_turfs -= typesof(/turf/closed/mineral)
banned_objects = typecacheof(/obj/structure/stone_tile)
///Not exactly mining shelters, but they make use of survival capsules code.
/datum/map_template/shelter/fishing
name = "Freshwater Spring"
shelter_id = "fishing_default"
description = "A spring from which you can fish several freshwater fish, including goldfish, catfish and pikes."
mappath = "_maps/templates/fishing_freshwater.dmm"
has_ceiling = FALSE
///The icon shown in the radial menu
var/radial_icon = "river"
/**
* If FALSE, the capsule needs to be emagged for this template to be selectable.
* its usage will also be logged, and admins warned if used indoors.
*/
var/safe = TRUE
/datum/map_template/shelter/fishing/New()
. = ..()
blacklisted_turfs -= typesof(/turf/closed/mineral)
blacklisted_turfs += typecacheof(/turf/open/openspace)
// Stop the capsule from being used around pipes and cables (if not emagged) cuz it'd look bad and a bit disruptive.
banned_objects = typecacheof(list(
/obj/structure/disposalpipe,
/obj/machinery/atmospherics/pipe,
/obj/structure/cable,
/obj/structure/transit_tube,
))
/datum/map_template/shelter/fishing/beach
name = "Saltwater Spring"
shelter_id = "fishing_beach"
mappath = "_maps/templates/fishing_saltwater.dmm"
description = "A spring from which you can fish several saltwater fish, including clownfish, pufferfish and stingrays."
radial_icon = "seaboat"
/datum/map_template/shelter/fishing/tizira
name = "Tiziran Spring"
shelter_id = "fishing_tizira"
mappath = "_maps/templates/fishing_tizira.dmm"
description = "A spring from which you can fish several fish native to the lizardfolk's native planet, Tizira."
radial_icon = "planet"
/datum/map_template/shelter/fishing/hot_spring
name = "Hot Spring"
shelter_id = "fishing_hot_spring"
mappath = "_maps/templates/fishing_hot_spring.dmm"
description = "A hot spring. Its purposes as a fishing spot is limited, but at least you get to have a relaxing bath."
radial_icon = "onsen"
/datum/map_template/shelter/fishing/ice
name = "Ice Fishing Spot"
shelter_id = "fishing_ice"
mappath = "_maps/templates/fishing_ice.dmm"
description = "A small, already dug ice hole surrounded by snow. You can catch salmon and arctic char here."
radial_icon = "ice"
/datum/map_template/shelter/fishing/lava
name = "Lava Fishing Spot"
shelter_id = "fishing_lava"
mappath = "_maps/templates/fishing_lava.dmm"
description = "A small 2x2 puddle of not-safe-for-live lava. You can catch lava loops here, and maybe a chest."
radial_icon = "lava"
safe = FALSE
/datum/map_template/shelter/fishing/plasma
name = "Plasma Fishing Spot"
shelter_id = "fishing_plasma"
mappath = "_maps/templates/fishing_plasma.dmm"
description = "A small 2x2 puddle of not-safe-for-live plasma. You can catch lava loops and arctic chrabs here."
radial_icon = "plasma"
safe = FALSE