Files
Bubberstation/code/modules/shuttle/on_move.dm
SkyratBot 5f9f60713b [MIRROR] Starlight Polish (Space is blue!) [MDB IGNORE] (#19059)
* 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>

* update modular

* Update _decal.dm

* Update _decal.dm

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com>
Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
Co-authored-by: lessthanthree <83487515+lessthnthree@users.noreply.github.com>
2023-02-12 00:42:28 -08:00

401 lines
14 KiB
Plaintext

/*
All ShuttleMove procs go here
*/
/************************************Base procs************************************/
// Called on every turf in the shuttle region, returns a bitflag for allowed movements of that turf
// returns the new move_mode (based on the old)
/turf/proc/fromShuttleMove(turf/newT, move_mode)
if(!(move_mode & MOVE_AREA) || !isshuttleturf(src))
return move_mode
return move_mode | MOVE_TURF | MOVE_CONTENTS
// Called from the new turf before anything has been moved
// Only gets called if fromShuttleMove returns true first
// returns the new move_mode (based on the old)
/turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle)
. = move_mode
if(!(. & MOVE_TURF))
return
var/shuttle_dir = shuttle.dir
for(var/i in contents)
var/atom/movable/thing = i
if(ismob(thing))
if(isliving(thing))
var/mob/living/M = thing
if(M.buckled)
M.buckled.unbuckle_mob(M, 1)
if(M.pulledby)
M.pulledby.stop_pulling()
M.stop_pulling()
M.visible_message(span_warning("[shuttle] slams into [M]!"))
SSblackbox.record_feedback("tally", "shuttle_gib", 1, M.type)
log_shuttle("[key_name(M)] was shuttle gibbed by [shuttle].")
M.investigate_log("has been gibbed by [shuttle].", INVESTIGATE_DEATHS)
M.gib()
else //non-living mobs shouldn't be affected by shuttles, which is why this is an else
if(istype(thing, /obj/effect/abstract) || istype(thing, /obj/singularity) || istype(thing, /obj/energy_ball))
continue
if(!thing.anchored)
step(thing, shuttle_dir)
else
qdel(thing)
// Called on the old turf to move the turf data
/turf/proc/onShuttleMove(turf/newT, list/movement_force, move_dir)
if(newT == src) // In case of in place shuttle rotation shenanigans.
return
// Destination turf changes.
// Baseturfs is definitely a list or this proc wouldnt be called.
var/shuttle_depth = depth_to_find_baseturf(/turf/baseturf_skipover/shuttle)
if(!shuttle_depth)
CRASH("A turf queued to move via shuttle somehow had no skipover in baseturfs. [src]([type]):[loc]")
//SKYRAT EDIT ADDITION
if(newT.lgroup)
newT.lgroup.remove_from_group(newT)
if(newT.liquids)
if(newT.liquids.immutable)
newT.liquids.remove_turf(src)
else
qdel(newT.liquids, TRUE)
if(lgroup)
lgroup.remove_from_group(src)
if(liquids)
liquids.ChangeToNewTurf(newT)
newT.reasses_liquids()
//SKYRAT EDIT END
newT.CopyOnTop(src, 1, shuttle_depth, TRUE)
newT.blocks_air = TRUE
newT.air_update_turf(TRUE, FALSE)
blocks_air = TRUE
air_update_turf(TRUE, TRUE)
if(isopenturf(newT))
var/turf/open/new_open = newT
new_open.copy_air_with_tile(src)
SEND_SIGNAL(src, COMSIG_TURF_ON_SHUTTLE_MOVE, newT)
return TRUE
// Called on the new turf after everything has been moved
/turf/proc/afterShuttleMove(turf/oldT, rotation)
//Dealing with the turf we left behind
oldT.TransferComponents(src)
SSexplosions.wipe_turf(src)
var/shuttle_depth = depth_to_find_baseturf(/turf/baseturf_skipover/shuttle)
if(shuttle_depth)
oldT.ScrapeAway(shuttle_depth)
if(rotation)
shuttleRotate(rotation) //see shuttle_rotate.dm
return TRUE
/turf/proc/lateShuttleMove(turf/oldT)
blocks_air = initial(blocks_air)
air_update_turf(TRUE, blocks_air)
oldT.blocks_air = initial(oldT.blocks_air)
oldT.air_update_turf(TRUE, oldT.blocks_air)
/////////////////////////////////////////////////////////////////////////////////////
// Called on every atom in shuttle turf contents before anything has been moved
// returns the new move_mode (based on the old)
// WARNING: Do not leave turf contents in beforeShuttleMove or dock() will runtime
/atom/movable/proc/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
return move_mode
/// Called on atoms to move the atom to the new location
/atom/movable/proc/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
if(newT == oldT) // In case of in place shuttle rotation shenanigans.
return
if(loc != oldT) // This is for multi tile objects
return
abstract_move(newT)
return TRUE
// Called on atoms after everything has been moved
/atom/movable/proc/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
if(light)
update_light()
if(rotation)
shuttleRotate(rotation)
update_parallax_contents()
return TRUE
/atom/movable/proc/lateShuttleMove(turf/oldT, list/movement_force, move_dir)
if(!movement_force || anchored)
return
var/throw_force = movement_force["THROW"]
if(!throw_force)
return
var/turf/target = get_edge_target_turf(src, move_dir)
var/range = throw_force * 10
range = CEILING(rand(range-(range*0.1), range+(range*0.1)), 10)/10
var/speed = range/5
safe_throw_at(target, range, speed, force = MOVE_FORCE_EXTREMELY_STRONG)
/////////////////////////////////////////////////////////////////////////////////////
// Called on areas before anything has been moved
// returns the new move_mode (based on the old)
/area/proc/beforeShuttleMove(list/shuttle_areas)
if(!shuttle_areas[src])
return NONE
return MOVE_AREA
// Called on areas to move their turf between areas
/area/proc/onShuttleMove(turf/oldT, turf/newT, area/underlying_old_area)
if(newT == oldT) // In case of in place shuttle rotation shenanigans.
return TRUE
contents -= oldT
turfs_to_uncontain += oldT
underlying_old_area.contents += oldT
underlying_old_area.contained_turfs += oldT
oldT.transfer_area_lighting(src, underlying_old_area)
//The old turf has now been given back to the area that turf originaly belonged to
var/area/old_dest_area = newT.loc
parallax_movedir = old_dest_area.parallax_movedir
old_dest_area.contents -= newT
old_dest_area.turfs_to_uncontain += newT
contents += newT
contained_turfs += newT
newT.transfer_area_lighting(old_dest_area, src)
return TRUE
// Called on areas after everything has been moved
/area/proc/afterShuttleMove(new_parallax_dir)
parallax_movedir = new_parallax_dir
return TRUE
/area/proc/lateShuttleMove()
return
/************************************Turf move procs************************************/
/************************************Area move procs************************************/
/************************************Machinery move procs************************************/
/obj/machinery/door/airlock/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
for(var/obj/machinery/door/airlock/other_airlock in range(2, src)) // includes src, extended because some escape pods have 1 plating turf exposed to space
other_airlock.shuttledocked = FALSE
other_airlock.air_tight = TRUE
INVOKE_ASYNC(other_airlock, TYPE_PROC_REF(/obj/machinery/door/, close), FALSE, TRUE) // force crush
/obj/machinery/door/airlock/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
var/current_area = get_area(src)
for(var/obj/machinery/door/airlock/other_airlock in orange(2, src)) // does not include src, extended because some escape pods have 1 plating turf exposed to space
if(get_area(other_airlock) != current_area) // does not include double-wide airlocks unless actually docked
// Cycle linking is only disabled if we are actually adjacent to another airlock
shuttledocked = TRUE
other_airlock.shuttledocked = TRUE
/obj/machinery/camera/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(. & MOVE_AREA)
. |= MOVE_CONTENTS
GLOB.cameranet.removeCamera(src)
/obj/machinery/camera/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
GLOB.cameranet.addCamera(src)
/obj/machinery/mech_bay_recharge_port/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir)
. = ..()
recharging_turf = get_step(loc, dir)
/obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
if(pipe_vision_img)
pipe_vision_img.loc = loc
/obj/machinery/computer/auxiliary_base/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
if(is_mining_level(z)) //Avoids double logging and landing on other Z-levels due to badminnery
SSblackbox.record_feedback("associative", "colonies_dropped", 1, list("x" = x, "y" = y, "z" = z))
/obj/machinery/atmospherics/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
var/missing_nodes = FALSE
for(var/i in 1 to device_type)
if(nodes[i])
var/obj/machinery/atmospherics/node = nodes[i]
var/connected = FALSE
for(var/D in GLOB.cardinals)
if(node in get_step(src, D))
connected = TRUE
break
if(!connected)
nullify_node(i)
if(!nodes[i])
missing_nodes = TRUE
if(missing_nodes)
atmos_init()
for(var/obj/machinery/atmospherics/A in pipeline_expansion())
A.atmos_init()
if(A.return_pipenet())
A.add_member(src)
SSair.add_to_rebuild_queue(src)
else
// atmos_init() calls update_appearance(), so we don't need to call it
update_appearance()
/obj/machinery/navbeacon/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
GLOB.navbeacons["[z]"] -= src
GLOB.deliverybeacons -= src
/obj/machinery/navbeacon/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
if(codes["patrol"])
if(!GLOB.navbeacons["[z]"])
GLOB.navbeacons["[z]"] = list()
GLOB.navbeacons["[z]"] += src //Register with the patrol list!
if(codes["delivery"])
GLOB.deliverybeacons += src
GLOB.deliverybeacontags += location
/************************************Item move procs************************************/
/obj/item/storage/pod/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
// If the pod was launched, the storage will always open. The reserved_level check
// ignores the movement of the shuttle from the transit level to
// the station as it is loaded in.
if (oldT && !is_reserved_level(oldT.z))
unlocked = TRUE
update_appearance()
/************************************Mob move procs************************************/
/mob/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
if(!move_on_shuttle)
return
. = ..()
/mob/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
if(!move_on_shuttle)
return
. = ..()
if(client && movement_force)
var/shake_force = max(movement_force["THROW"], movement_force["KNOCKDOWN"])
if(buckled)
shake_force *= 0.25
shake_camera(src, shake_force, 1)
/mob/living/lateShuttleMove(turf/oldT, list/movement_force, move_dir)
if(buckled)
return
. = ..()
var/knockdown = movement_force["KNOCKDOWN"]
if(knockdown)
Paralyze(knockdown)
/mob/living/simple_animal/hostile/megafauna/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
. = ..()
message_admins("Megafauna [src] [ADMIN_FLW(src)] moved via shuttle from [ADMIN_COORDJMP(oldT)] to [ADMIN_COORDJMP(loc)]")
/************************************Structure move procs************************************/
/obj/structure/grille/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(. & MOVE_AREA)
. |= MOVE_CONTENTS
/obj/structure/lattice/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(. & MOVE_AREA)
. |= MOVE_CONTENTS
/obj/structure/cable/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
cut_cable_from_powernet(FALSE)
/obj/structure/cable/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
Connect_cable(TRUE)
propagate_if_no_network()
/obj/machinery/power/shuttle_engine/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(. & MOVE_AREA)
. |= MOVE_CONTENTS
/obj/structure/ladder/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if (!(resistance_flags & INDESTRUCTIBLE))
disconnect()
/obj/structure/ladder/afterShuttleMove(turf/oldT, list/movement_force, shuttle_dir, shuttle_preferred_direction, move_dir, rotation)
. = ..()
if (!(resistance_flags & INDESTRUCTIBLE))
LateInitialize()
/obj/structure/ladder/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
if (resistance_flags & INDESTRUCTIBLE)
// simply don't be moved
return FALSE
return ..()
/************************************Misc move procs************************************/
/obj/docking_port/mobile/beforeShuttleMove(turf/newT, rotation, move_mode, obj/docking_port/mobile/moving_dock)
. = ..()
if(moving_dock == src)
. |= MOVE_CONTENTS
// Never move the stationary docking port, otherwise things get WEIRD
/obj/docking_port/stationary/onShuttleMove()
return FALSE
// Holy shit go away
/obj/effect/abstract/z_holder/onShuttleMove()
return FALSE
// Special movable stationary port, for your mothership shenanigans
/obj/docking_port/stationary/movable/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
if(!moving_dock.can_move_docking_ports || old_dock == src)
return FALSE
if(newT == oldT) // In case of in place shuttle rotation shenanigans.
return
if(loc != oldT) // This is for multi tile objects
return
abstract_move(newT)
return TRUE
/obj/docking_port/stationary/public_mining_dock/onShuttleMove(turf/newT, turf/oldT, list/movement_force, move_dir, obj/docking_port/stationary/old_dock, obj/docking_port/mobile/moving_dock)
shuttle_id = "mining_public" //It will not move with the base, but will become enabled as a docking point.