Files
Bubberstation/code/datums/materials/_material.dm
Time-Green 42543ac141 NEW STATION TRAIT: Radioactive Nebula (#76825)
## About The Pull Request

Adds a new station trait: Radioactive Nebula!

The station is located inside a radioactive nebula. Space background and
lighting is different shades of green. Objects in space will also glow
green. (This is kinda lying, since the glowing stuff isn't radioactive,
you just get an element that slowly irradiates you, though people and
certain objects that get the 'IRRADIATED' status may still double-whammy
you)

Do not go into space without rad-protected gear, or you will get very
sick very fast. RAD-protection MODsuit modules spawn in robotics and are
also immediately researched.

The nebula does protect against external threats, like pirates, ninja's
and nukies. They can still get to the station pretty well, but they
can't stay in space for extended periods of time

To make it more livable, public rad protection gear will spawn in
lockers around the station. Everyone will also spawn with potassium
iodide pills in their emergency box. Dynamics threat is also reduced by
30, so there's a proclivity towards more lower threat rounds when the
radioactive nebula is present. Radioactive resonance virus cannot be
generated though, since it kinda obliterates any and all challenge and
threat


![image](https://github.com/tgstation/tgstation/assets/7501474/8eedcb85-1bb8-4e87-a794-d6781fee680d)

**Shielding**


![image](https://github.com/tgstation/tgstation/assets/7501474/ae1b25d7-6fbd-4a86-8c95-5947b1122632)

In order to protect the station from radiation, nebula shielding units
need to be constructed. Five spawn ready-to-built in engineering, and
more can be bought pretty cheap from cargo. (Normal radstorms are
disabled)

The gravity generator has 20 minutes of innate shielding, where every
nebula shielding unit adds another 20 minutes. 5 are needed to
completely block all radiation even when the gravity gen is down, but
constructing more is recommended in-case of sabotage/destructions/power
outtages.

Active nebula shielding will passively generate tritium. You can either
vent/ignore this, or use it for something. I'm not an atmos tech but I'm
sure you can do something with it

_What happens when no shielding units are constructed/they all fail?_
The station will suffer a 5 minute long radiation storm, with only
shuttles being excempt. The storm is nerfed strongly, and you can tank
the 5 minutes, but you'll be pretty sick. After the 5 minutes are over,
central command will send an emergency shielding unit which will block
the radiation for 10 minutes and warn the station to set up nebula
shielding.


## Why It's Good For The Game
The station being inside a radioactive nebula shakes up a pretty major
aspect of the game (that being the 'space' in space station 13). Hallway
decals are colored green, display screens will display radiation
markings, carps blend with the nebula, etc. Putting the station inside a
radioactive nebula shakes up the rules of the game and what people can
expect. Suddenly, you can no longer just go outside without taking meds
or getting proper radiation protection, encouraging people to stay cozy
and inside.


![image](https://github.com/tgstation/tgstation/assets/7501474/40112936-8514-47f7-b3e0-b1c782b6a0a6)

Inside, the crew gets the goal to set-up radiation shielding to defend
themselves against the nebula, rewarding a creative engineering
department with passive resource income and protecting the station
against massive radiation storms. I think it's nice to give engineering
something to set up. Even if they don't care, they can just plop it down
somewhere in a closed room and be done with it.

The radiation storm is pretty aggressive, but very survivable if you use
your potassium iodide pills, the extra radiation suits or whatever
chemistry has whipped up.

Most importantly, it gives the entire station a common enemy: the
nebula. Everyone is encouraged to prepare against the mechanics.
Chemistry can make meds, viro can make protective virusses, robotics
gets encouraged to make radprotected MODsuits, engineering gets to
set-up radiation shielding, assistants can look at space or whatever
assistants do.


<details>
  <summary>Cool images</summary>


![image](https://github.com/tgstation/tgstation/assets/7501474/387f2d75-8ba6-425b-8f0f-9423cf7aab19)


![image](https://github.com/tgstation/tgstation/assets/7501474/eb65de97-13ce-4ce9-8902-4144994d217f)


![image](https://github.com/tgstation/tgstation/assets/7501474/60b915a5-8549-4a3b-afe6-f0e823207883)


![image](https://github.com/tgstation/tgstation/assets/7501474/239ae614-8d26-4b77-936f-1d2baa38d32c)

  
</details>

## Changelog

🆑
add: Adds a new rare radioactive nebula station trait! Get ready and
PREPARE, before it gets in...
tweak: Nearstation space area lighting may look slightly different
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
Co-authored-by: Jacquerel <hnevard@gmail.com>
2023-07-21 16:51:15 +01:00

235 lines
8.9 KiB
Plaintext

/*! Material datum
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
*/
/datum/material
/// What the material is referred to as IC.
var/name = "material"
/// A short description of the material. Not used anywhere, yet...
var/desc = "its..stuff."
/// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material.
var/id
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
///Deprecated, use greyscale_color instead.
var/color
///Determines the color palette of the material. Formatted the same as atom/var/greyscale_colors
var/greyscale_colors
///Base alpha of the material, is used for greyscale icons.
var/alpha = 255
///Starlight color of the material
///This is the color of light it'll emit if its turf is transparent and over space. Defaults to COLOR_STARLIGHT if not set
var/starlight_color
///Bitflags that influence how SSmaterials handles this material.
var/init_flags = MATERIAL_INIT_MAPLOAD
///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for
var/list/categories = list()
///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets
var/sheet_type
///This is a modifier for force, and resembles the strength of the material
var/strength_modifier = 1
///This is a modifier for integrity, and resembles the strength of the material
var/integrity_modifier = 1
///This is the amount of value per 1 unit of the material
var/value_per_unit = 0
///Armor modifiers, multiplies an items normal armor vars by these amounts.
var/armor_modifiers = list(MELEE = 1, BULLET = 1, LASER = 1, ENERGY = 1, BOMB = 1, BIO = 1, FIRE = 1, ACID = 1)
///How beautiful is this material per unit.
var/beauty_modifier = 0
///Can be used to override the sound items make, lets add some SLOSHing.
var/item_sound_override
///Can be used to override the stepsound a turf makes. MORE SLOOOSH
var/turf_sound_override
///what texture icon state to overlay
var/texture_layer_icon_state
///a cached icon for the texture filter
var/cached_texture_filter_icon
///What type of shard the material will shatter to
var/obj/item/shard_type
///What type of debris the tile will leave behind when shattered.
var/obj/effect/decal/debris_type
/** Handles initializing the material.
*
* Arugments:
* - _id: The ID the material should use. Overrides the existing ID.
*/
/datum/material/proc/Initialize(_id, ...)
if(_id)
id = _id
else if(isnull(id))
id = type
if(texture_layer_icon_state)
cached_texture_filter_icon = icon('icons/turf/composite.dmi', texture_layer_icon_state)
return TRUE
///This proc is called when the material is added to an object.
/datum/material/proc/on_applied(atom/source, amount, material_flags)
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
if(color) //Do we have a custom color?
source.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
if(alpha)
source.alpha = alpha
if(texture_layer_icon_state)
ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
source.add_filter("material_texture_[name]",1,layering_filter(icon=cached_texture_filter_icon,blend_mode=BLEND_INSET_OVERLAY))
if(material_flags & MATERIAL_GREYSCALE)
var/config_path = get_greyscale_config_for(source.greyscale_config)
source.set_greyscale(greyscale_colors, config_path)
if(alpha < 255)
source.opacity = FALSE
if(material_flags & MATERIAL_ADD_PREFIX)
source.name = "[name] [source.name]"
if(beauty_modifier)
source.AddElement(/datum/element/beauty, beauty_modifier * amount)
if(isobj(source)) //objs
on_applied_obj(source, amount, material_flags)
else if(istype(source, /turf)) //turfs
on_applied_turf(source, amount, material_flags)
source.mat_update_desc(src)
///This proc is called when a material updates an object's description
/atom/proc/mat_update_desc(datum/material/mat)
return
///This proc is called when the material is added to an object specifically.
/datum/material/proc/on_applied_obj(obj/o, amount, material_flags)
if(material_flags & MATERIAL_AFFECT_STATISTICS)
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
o.modify_max_integrity(new_max_integrity)
o.force *= strength_modifier
o.throwforce *= strength_modifier
o.set_armor(o.get_armor().generate_new_with_multipliers(armor_modifiers))
if(!isitem(o))
return
var/obj/item/item = o
if(material_flags & MATERIAL_GREYSCALE)
var/worn_path = get_greyscale_config_for(item.greyscale_config_worn)
var/lefthand_path = get_greyscale_config_for(item.greyscale_config_inhand_left)
var/righthand_path = get_greyscale_config_for(item.greyscale_config_inhand_right)
item.set_greyscale(
new_worn_config = worn_path,
new_inhand_left = lefthand_path,
new_inhand_right = righthand_path
)
if(!item_sound_override)
return
item.hitsound = item_sound_override
item.usesound = item_sound_override
item.mob_throw_hit_sound = item_sound_override
item.equip_sound = item_sound_override
item.pickup_sound = item_sound_override
item.drop_sound = item_sound_override
/datum/material/proc/on_applied_turf(turf/T, amount, material_flags)
if(isopenturf(T))
if(turf_sound_override)
var/turf/open/O = T
O.footstep = turf_sound_override
O.barefootstep = turf_sound_override + "barefoot"
O.clawfootstep = turf_sound_override + "claw"
O.heavyfootstep = FOOTSTEP_GENERIC_HEAVY
if(alpha < 255)
T.AddElement(/datum/element/turf_z_transparency)
setup_glow(T)
return
/datum/material/proc/setup_glow(turf/on)
if(GET_TURF_PLANE_OFFSET(on) != GET_LOWEST_STACK_OFFSET(on.z)) // We ain't the bottom brother
return
// We assume no parallax means no space means no light
if(SSmapping.level_trait(on.z, ZTRAIT_NOPARALLAX))
return
on.set_light(2, 0.75, get_starlight_color())
///Gets the space color and possible changed color if space is different
/datum/material/proc/get_starlight_color()
return starlight_color || GLOB.starlight_color
/datum/material/proc/get_greyscale_config_for(datum/greyscale_config/config_path)
if(!config_path)
return
for(var/datum/greyscale_config/path as anything in subtypesof(config_path))
if(type != initial(path.material_skin))
continue
return path
///This proc is called when the material is removed from an object.
/datum/material/proc/on_removed(atom/source, amount, material_flags)
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
if(color)
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
if(texture_layer_icon_state)
source.remove_filter("material_texture_[name]")
REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
source.alpha = initial(source.alpha)
if(material_flags & MATERIAL_GREYSCALE)
source.set_greyscale(initial(source.greyscale_colors), initial(source.greyscale_config))
if(material_flags & MATERIAL_ADD_PREFIX)
source.name = initial(source.name)
if(beauty_modifier)
source.RemoveElement(/datum/element/beauty, beauty_modifier * amount)
if(isobj(source)) //objs
on_removed_obj(source, amount, material_flags)
if(istype(source, /turf)) //turfs
on_removed_turf(source, amount, material_flags)
///This proc is called when the material is removed from an object specifically.
/datum/material/proc/on_removed_obj(obj/o, amount, material_flags)
if(material_flags & MATERIAL_AFFECT_STATISTICS)
var/new_max_integrity = initial(o.max_integrity)
o.modify_max_integrity(new_max_integrity)
o.force = initial(o.force)
o.throwforce = initial(o.throwforce)
if(isitem(o) && (material_flags & MATERIAL_GREYSCALE))
var/obj/item/item = o
item.set_greyscale(
new_worn_config = initial(item.greyscale_config_worn),
new_inhand_left = initial(item.greyscale_config_inhand_left),
new_inhand_right = initial(item.greyscale_config_inhand_right)
)
/datum/material/proc/on_removed_turf(turf/T, amount, material_flags)
if(alpha < 255)
T.RemoveElement(/datum/element/turf_z_transparency)
/**
* This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption.
* Arguments
* * M - person consuming the mat
* * S - (optional) item the mat is contained in (NOT the item with the mat itself)
*/
/datum/material/proc/on_accidental_mat_consumption(mob/living/carbon/M, obj/item/S)
return FALSE
/** Returns the composition of this material.
*
* Mostly used for alloys when breaking down materials.
*
* Arguments:
* - amount: The amount of the material to break down.
* - breakdown_flags: Some flags dictating how exactly this material is being broken down.
*/
/datum/material/proc/return_composition(amount=1, breakdown_flags=NONE)
return list((src) = amount) // Yes we need the parenthesis, without them BYOND stringifies src into "src" and things break.