Files
Bubberstation/code/datums/materials/_material.dm
LemonInTheDark e9c87c0acb Starlight Polish (Space is blue!) (#72886)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

Adds support to underlays to realize_overlays
Ensures decals properly handle plane offsets
Fixes space lighting double applying if it's changeturf'd into. this
will be important later
Makes solar vis_contents block emissives as expected
Moves transit tube overlays to update_overlays, adds emissive blockers
to them

#### Adds render steps

An expansion on render_target based emissive blockers. 
They allow us to hijack an object's appearance and draw it somewhere
else, or even modify it, THEN draw it somewhere else.
They chain quite nicely

Fixes shuttles deleting z holder objects

#### Makes space emissive, makes walls and floors block emissives
The core idea here goes like this:
We make space glow, and give its overlays some color

This way, the tile and space parallax remain fullbright, along with
anything that doesn't block emissives, but anything that does block
emissives will instead get shaded the color of starlight

This requires a bit of extra work, see later

This is done automatically with render relays, which now support
specifiying layer and color (Need to make an editor for these one of
these days)

The emissive blocking floor stuff requires making a second render plate
to prevent double scaling

Also adds some new layering defines for lighting, and ensures all turf
lights have a layer. We'll get to this soon

#### Makes things in space blue

We color them the same as starlight, by taking advantage of space being
emissive
This means that things in space that block emissive will block it
correctly and be colored blue by the light overlay, but space itself
will remain fullbright

This does require redefining what always_lit means, but nothing but
cordons use that so it's fineee


#### Makes glass above space glow, and some other stuff

Glass tiles that sit above space will now shine light with matching
color to the glasses color. This includes mat tiles.

Glass tiles (not mat because they have no alpha) also only partially
block emissives.
Adds a new proc that uses render steps to acomplish this, essentially
we're cutting out bits below X alpha and drawing what remains as an
emissive.

#### Modifies partial space showing to support glow

Essentially, alongside displaying space as an underlay, we also display
a light overlay colored like starlight.
That starlight overlay gets masked to only be visible in bits that do
not contain any alpha.

We also mask the turf lighting to not go into bits that have no alpha,
to ensure we get the effect we want.
This is done with that lighting layer thing I mentioned earlier.

#### Makes appearance realization's list output ordered

I want it output in order of overlay, sub overlay suboverlay, next
overlay
Need to use insert for that

## Why It's Good For The Game

Pretty!
Also having space be emissive is a very very good way to test for fucked
emissive blockers (If it's broken why are we even drawing the overlay)
I know for a fact mob blockers on lizards and socks are kinda yorked, I
think there's more

<details>
<summary>
Old
</summary>


![image](https://user-images.githubusercontent.com/58055496/213916157-d4b38aa7-3ab6-42a4-989f-7bfba2dc2cba.png)

![image](https://user-images.githubusercontent.com/58055496/213916077-637fa288-bbee-477d-aded-730d9683477e.png)

![image](https://user-images.githubusercontent.com/58055496/213916088-0657a8a2-5627-48e2-8c4b-870c90ef2072.png)

</details>


<details>
<summary>
New
</summary>


![image](https://user-images.githubusercontent.com/58055496/213916107-2af74e64-1817-4a44-b528-180a9160cb9e.png)

![image](https://user-images.githubusercontent.com/58055496/213916115-5fa36fcc-b988-4ccf-850e-21c26ed463d0.png)

![image](https://user-images.githubusercontent.com/58055496/213916120-6833187d-b12e-42a7-ac4b-63c56deb71e5.png)

</details>

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
add: Space now makes things in it starlight faintly blue
fix: Glass floors that display space now properly let space shine
through them, rather then hiding it in the dark
add: Glass floors above space now glow faintly depending on their glass
type
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->

---------

Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
2023-01-31 09:52:27 +00:00

229 lines
8.6 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
var/starlight_color = COLOR_STARLIGHT
///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
/** 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/materials/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
O.clawfootstep = turf_sound_override
O.heavyfootstep = turf_sound_override
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, 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.