Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions code/__DEFINES/layers.dm
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@
/// The range unique planes can be in
#define PLANE_RANGE (HIGHEST_EVER_PLANE - LOWEST_EVER_PLANE)

// FLOOR_PLANE layer(s)
// We need to force this plane to render as if we were not using sidemap
// this allows larger then bound floors to layer as we'd expect
// ANYTHING on the floor plane needs TOPDOWN_LAYER, and nothing that isn't on the floor plane can have it

// NOTICE: we break from the pattern of increasing in steps of like 0.01 here
// Because TOPDOWN_LAYER is 10000 and that's enough to floating point our modifications away

/// Used to shift all topdown layer emissives to a the game plane equivalent layers, as otherwise they render above everything else due to being KEEP_APART
#define TOPDOWN_TO_EMISSIVE_LAYER(layer) LERP(FLOOR_EMISSIVE_START_LAYER, FLOOR_EMISSIVE_END_LAYER, (layer - (TOPDOWN_LAYER + 1)) / TOPDOWN_LAYER_COUNT)

// Must be equal to the offset of the highest topdown layer
#define TOPDOWN_LAYER_COUNT 18

#define SPACE_LAYER 1.8
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
#define MID_TURF_LAYER 2.02
Expand All @@ -58,6 +72,8 @@
#define CLOSED_TURF_LAYER 2.05
#define BULLET_HOLE_LAYER 2.06
#define ABOVE_NORMAL_TURF_LAYER 2.08
#define FLOOR_EMISSIVE_START_LAYER 2.09
#define FLOOR_EMISSIVE_END_LAYER 2.26
#define LATTICE_LAYER 2.2
#define DISPOSAL_PIPE_LAYER 2.3
#define GAS_PIPE_HIDDEN_LAYER 2.35
Expand Down
32 changes: 28 additions & 4 deletions code/__DEFINES/lighting.dm
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,38 @@
/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
#define EMISSIVE_BLOCK_UNIQUE 2

#define _EMISSIVE_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, val,0,0,0)
#define _EMISSIVE_COLOR_NO_BLOOM(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,val,0,0)
#define _SPECULAR_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,val,0)
/// The color matrix applied to all emissive overlays. Should be solely dependent on alpha and not have RGB overlap with [EM_BLOCK_COLOR].
#define EMISSIVE_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,1,0)
/// A globaly cached version of [EMISSIVE_COLOR] for quick access.
#define EMISSIVE_COLOR _EMISSIVE_COLOR(1)
#define EMISSIVE_COLOR_NO_BLOOM _EMISSIVE_COLOR_NO_BLOOM(1)
#define SPECULAR_COLOR _SPECULAR_COLOR(1)
/// A globally cached version of [EMISSIVE_COLOR] for quick access.
GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR)
GLOBAL_LIST_INIT(emissive_color_no_bloom, EMISSIVE_COLOR_NO_BLOOM)
GLOBAL_LIST_INIT(specular_color, SPECULAR_COLOR)

// Types of emissives
/// Emissive that will not have bloom applied to it, encoded into the green channel
#define EMISSIVE_NO_BLOOM 0
/// Emissive that will get bloom applied to it, encoded into the red channel
#define EMISSIVE_BLOOM 1
/// Mimics a highly reflective surface, will not have any glow by itself but will amplify any lighting applied to it, encoded into the blue channel
#define EMISSIVE_SPECULAR 2

/// Light cutoff of specular emissives, controls how sharp a light must be before it starts reflecting
#define SPECULAR_EMISSIVE_CUTOFF 0.3
/// Controls how bright specular emissives sourced from overlay lights are
/// Keep in mind that overlay lights are also affected by the specular cutoff, so the maximum light value achievable is (contrast - cutoff)
#define SPECULAR_EMISSIVE_OVERLAY_CONTRAST 1.4

#define _EM_BLOCK_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,val, 0,0,0,0)
/// The color matrix applied to all emissive blockers. Should be solely dependent on alpha and not have RGB overlap with [EMISSIVE_COLOR].
#define EM_BLOCK_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
/// A globaly cached version of [EM_BLOCK_COLOR] for quick access.
#define EM_BLOCK_COLOR _EM_BLOCK_COLOR(1)
/// A globally cached version of [EM_BLOCK_COLOR] for quick access.
GLOBAL_LIST_INIT(em_block_color, EM_BLOCK_COLOR)

/// A set of appearance flags applied to all emissive and emissive blocker overlays.
#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR)
/// The color matrix used to mask out emissive blockers on the emissive plane. Alpha should default to zero, be solely dependent on the RGB value of [EMISSIVE_COLOR], and be independant of the RGB value of [EM_BLOCK_COLOR].
Expand Down
2 changes: 1 addition & 1 deletion code/__HELPERS/icon_smoothing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ DEFINE_BITFIELD(smoothing_junction, list(
var/turf/neighbor_turf = get_step(src, turned_adjacency & (NORTH|SOUTH))
if(!neighbor_turf) //You can step out of map boundaries
return
var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, plane = FLOOR_PLANE)
var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, offset_spokesman = src, plane = FLOOR_PLANE)
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
neighbor_turf = get_step(src, turned_adjacency & (EAST|WEST))
if(!neighbor_turf) //You can step out of map boundaries
Expand Down
43 changes: 37 additions & 6 deletions code/__HELPERS/lighting.dm
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EMISSIVE_COLOR].
/proc/emissive_appearance(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
appearance.color = GLOB.emissive_color
/proc/emissive_appearance(icon, icon_state = "", atom/offset_spokesman, layer, alpha = 255, appearance_flags = NONE, offset_const, effect_type = EMISSIVE_BLOOM)
if((isnull(layer) || layer == FLOAT_LAYER) && IS_TOPDOWN_PLANE(offset_spokesman.plane))
layer = TOPDOWN_TO_EMISSIVE_LAYER(offset_spokesman.layer)
else if(isnull(layer))
layer = FLOAT_LAYER

var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, offset_spokesman, EMISSIVE_PLANE, 255, appearance_flags | EMISSIVE_APPEARANCE_FLAGS, offset_const)
if(alpha == 255)
switch(effect_type)
if(EMISSIVE_NO_BLOOM)
appearance.color = GLOB.emissive_color_no_bloom
if (EMISSIVE_BLOOM)
appearance.color = GLOB.emissive_color
if (EMISSIVE_SPECULAR)
appearance.color = GLOB.specular_color
else
var/alpha_ratio = alpha/255
switch(effect_type)
if(EMISSIVE_NO_BLOOM)
appearance.color = _EMISSIVE_COLOR_NO_BLOOM(alpha_ratio)
if (EMISSIVE_BLOOM)
appearance.color = _EMISSIVE_COLOR(alpha_ratio)
if (EMISSIVE_SPECULAR)
appearance.color = _SPECULAR_COLOR(alpha_ratio)

return appearance

/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EM_BLOCK_COLOR].
/proc/emissive_blocker(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
appearance.color = GLOB.em_block_color
/proc/emissive_blocker(icon, icon_state = "", atom/offset_spokesman, layer, alpha = 255, appearance_flags = NONE, offset_const)
if (isnull(layer))
if(IS_TOPDOWN_PLANE(offset_spokesman.plane))
layer = TOPDOWN_TO_EMISSIVE_LAYER(offset_spokesman.layer)
else
layer = FLOAT_LAYER
var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, offset_spokesman, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS, offset_const)
if(alpha == 255)
appearance.color = GLOB.em_block_color
else
var/alpha_ratio = alpha/255
appearance.color = _EM_BLOCK_COLOR(alpha_ratio)
return appearance
7 changes: 6 additions & 1 deletion code/_onclick/hud/radial.dm
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(choice_id == NEXT_PAGE_ID)
E.name = "Next Page"
E.next_page = TRUE
E.icon_state = "radial_slice" // Resets the bg icon state to the default for next page buttons.
E.add_overlay("radial_next")
else
if(istext(choices_values[choice_id]))
Expand Down Expand Up @@ -267,6 +268,7 @@ GLOBAL_LIST_EMPTY(radial_menus)

var/mutable_appearance/MA = new /mutable_appearance(to_extract_from)
if(MA)
SET_PLANE_EXPLICIT(MA, ABOVE_HUD_PLANE, anchor)
MA.layer = ABOVE_HUD_LAYER
MA.appearance_flags |= RESET_TRANSFORM
return MA
Expand All @@ -285,9 +287,12 @@ GLOBAL_LIST_EMPTY(radial_menus)
current_user = M.client
//Blank
menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = ABOVE_HUD_LAYER)
menu_holder.plane = ABOVE_HUD_PLANE

SET_PLANE_EXPLICIT(menu_holder, ABOVE_HUD_PLANE, M)
menu_holder.appearance_flags |= KEEP_APART
menu_holder.vis_contents += elements + close_button
if(!isnull(close_button))
menu_holder.vis_contents += close_button
current_user.images += menu_holder

/datum/radial_menu/proc/hide()
Expand Down
2 changes: 1 addition & 1 deletion code/datums/components/attachment.dm
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
overlay_layer = parent.render_layer
if(parent.render_plane)
overlay_layer = parent.render_plane
overlays += mutable_appearance(parent.icon, "[parent.icon_state]-attached",overlay_layer,overlay_plane)
overlays += mutable_appearance(parent.icon, "[parent.icon_state]-attached", plane = overlay_layer, alpha = overlay_plane)

/datum/component/attachment/proc/try_attach(obj/item/parent, obj/item/holder, mob/user, bypass_checks)
SIGNAL_HANDLER
Expand Down
2 changes: 1 addition & 1 deletion code/datums/elements/turf_transparency.dm
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
if(!ispath(path))
warning("Z-level [our_turf.z] has invalid baseturf '[our_turf.virtual_level_trait(ZTRAIT_BASETURF)]'")
path = /turf/open/space
var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER-0.02, plane = PLANE_SPACE)
var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = SPACE_LAYER + 0.1, offset_spokesman = our_turf, plane = PLANE_SPACE)
underlay_appearance.appearance_flags = RESET_ALPHA | RESET_COLOR
our_turf.underlays += underlay_appearance
return TRUE
40 changes: 28 additions & 12 deletions code/datums/mutable_appearance.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,34 @@

// Mutable appearances are children of images, just so you know.

/mutable_appearance/New()
// Mutable appearances erase template vars on new, because they accept an appearance to copy as an arg
// If we have nothin to copy, we set the float plane
/mutable_appearance/New(mutable_appearance/to_copy)
..()
plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
if(!to_copy)
plane = FLOAT_PLANE

// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
MA.plane = plane
MA.alpha = alpha
MA.appearance_flags |= appearance_flags
return MA
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, atom/offset_spokesman, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, offset_const)
var/mutable_appearance/appearance = new()
appearance.icon = icon
appearance.icon_state = icon_state
appearance.layer = layer
appearance.alpha = alpha
appearance.appearance_flags |= appearance_flags
if(plane != FLOAT_PLANE)
// You need to pass in some non null object to reference
if(isatom(offset_spokesman))
// Note, we are ok with null turfs, that's not an error condition we'll just default to 0, the error would be
// Not passing ANYTHING in, key difference
SET_PLANE_EXPLICIT(appearance, plane, offset_spokesman)
// That or I'll let you pass in a static offset. Don't be stupid now
else if(!isnull(offset_const))
SET_PLANE_W_SCALAR(appearance, plane, offset_const)
// otherwise if you're setting plane you better have the guts to back it up
else
stack_trace("No plane offset passed in as context for a non floating mutable appearance, things are gonna go to hell on multiz maps")
else if(!isnull(offset_spokesman) && !isatom(offset_spokesman))
stack_trace("Why did you pass in offset_spokesman as [offset_spokesman]? We need an atom to properly offset planes")

return appearance
4 changes: 2 additions & 2 deletions code/modules/atmospherics/machinery/airalarm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/airalarm, 27)
emissive_state = "alarm2"

. += mutable_appearance(icon, emissive_state)
. += mutable_appearance(icon, "light_emissive", layer, EMISSIVE_PLANE)
. += mutable_appearance(icon, "light_emissive", layer, src, plane = EMISSIVE_PLANE)

if(perc_danger_level) //When there's any danger level, light up the "AIR" sign too
. += mutable_appearance(icon, "alarm_sign")
. += mutable_appearance(icon, "alarm_sign", layer, EMISSIVE_PLANE)
. += mutable_appearance(icon, "alarm_sign", layer, src, plane = EMISSIVE_PLANE)

/obj/machinery/airalarm/process(seconds_per_tick)
if((machine_stat & (NOPOWER|BROKEN)) || shorted)
Expand Down
104 changes: 82 additions & 22 deletions code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
if(icon_state != icon_aggro)
icon_state = icon_aggro

/mob/living/simple_animal/hostile/asteroid/goliath/update_overlays()
. = ..()
if (stat != DEAD)
. += emissive_appearance(icon, "[icon_living]_e", src, effect_type = EMISSIVE_NO_BLOOM)

/mob/living/simple_animal/hostile/asteroid/goliath/pup
name = "goliath pup"
desc = "An immature goliath. Goliaths at this stage of life lack fully-developed tendrils, and are reliant on their parents to unearth and supply food."
Expand Down Expand Up @@ -291,35 +296,90 @@
//tentacles
/obj/effect/temp_visual/goliath_tentacle
name = "goliath tentacle"
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "Goliath_tentacle_wiggle"
icon = 'icons/mob/lavaland/lavaland_monsters2.dmi'
icon_state = "goliath_tentacle_spawn"
layer = BELOW_MOB_LAYER
var/mob/living/spawner
var/wiggle = "Goliath_tentacle_spawn"
var/retract = "Goliath_tentacle_retract"
var/wiggle = "goliath_tentacle_wiggle"
var/retract = "goliath_tentacle_retract"
var/difficulty = 3

/obj/effect/temp_visual/goliath_tentacle/Initialize(mapload, mob/living/new_spawner,recursive = FALSE)
/obj/effect/temp_visual/goliath_tentacle/update_overlays()
. = ..()
. += emissive_appearance('icons/mob/lavaland/lavaland_monsters2.dmi', "[icon_state]_e", src, effect_type = EMISSIVE_NO_BLOOM)
. += emissive_appearance('icons/mob/lavaland/lavaland_monsters2.dmi', "[icon_state]_e_bloom", src)

// Позже удалить, пока для примера останется тут.
/// A tentacle which grabs you if you don't get away from it
/obj/effect/goliath_tentacle
name = "goliath tentacle"
icon = 'icons/mob/lavaland/lavaland_monsters2.dmi'
icon_state = "goliath_tentacle_spawn"
layer = BELOW_MOB_LAYER
plane = GAME_PLANE
anchored = TRUE
/// Timer for our current action stage
var/action_timer
/// Time in which to grab people
var/grapple_time = 10 SECONDS

/obj/effect/goliath_tentacle/Initialize(mapload, mob/living/new_spawner,recursive = FALSE)
. = ..()
flick(wiggle,src)
for(var/obj/effect/temp_visual/goliath_tentacle/T in loc)
if(T != src)
if (ismineralturf(loc))
var/turf/closed/mineral/floor = loc
floor.gets_drilled()
if (!isopenturf(loc) || isspaceturf(loc))
return INITIALIZE_HINT_QDEL
for (var/obj/effect/temp_visual/goliath_tentacle/tentacle in loc)
if (tentacle != src)
return INITIALIZE_HINT_QDEL
if(!QDELETED(new_spawner))
spawner = new_spawner
if(ismineralturf(loc))
var/turf/closed/mineral/M = loc
M.gets_drilled()
deltimer(timerid)
timerid = addtimer(CALLBACK(src, PROC_REF(tripanim)), 7, TIMER_STOPPABLE)
if(!recursive)
deltimer(action_timer)
action_timer = addtimer(CALLBACK(src, PROC_REF(animate_grab)), 0.7 SECONDS, TIMER_STOPPABLE)
update_appearance(UPDATE_OVERLAYS)

/obj/effect/goliath_tentacle/Destroy()
deltimer(action_timer)
return ..()

/// Change to next icon state and set up grapple
/obj/effect/goliath_tentacle/proc/animate_grab()
icon_state = "goliath_tentacle_wiggle"
update_appearance(UPDATE_OVERLAYS)
deltimer(action_timer)
addtimer(CALLBACK(src, PROC_REF(grab)), 0.3 SECONDS, TIMER_STOPPABLE)

/// Grab everyone we share space with. If it's nobody, go home.
/obj/effect/goliath_tentacle/proc/grab()
for (var/mob/living/victim in loc)
if (victim.stat == DEAD) //if (victim.stat == DEAD || HAS_TRAIT(victim, TRAIT_TENTACLE_IMMUNE))
continue
balloon_alert(victim, "grabbed")
visible_message(span_danger("[src] grabs hold of [victim]!"))
victim.apply_damage(rand(10,20), BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG), wound_bonus = CANT_WOUND) //already dangerous, don't break legs too
if(iscarbon(victim))
var/obj/item/restraints/legcuffs/beartrap/goliath/B = new /obj/item/restraints/legcuffs/beartrap/goliath(get_turf(victim))
B.on_entered(src, victim)
if (!has_buckled_mobs())
retract()
return
var/list/directions = get_directions()
for(var/i in 1 to difficulty)
var/spawndir = pick_n_take(directions)
var/turf/T = get_step(src, spawndir)
if(T)
new type(T, spawner)
deltimer(action_timer)
action_timer = addtimer(CALLBACK(src, PROC_REF(retract)), grapple_time, TIMER_STOPPABLE)

/// Play exit animation.
/obj/effect/goliath_tentacle/proc/retract()
if (icon_state == "goliath_tentacle_retract")
return // Already retracting
//SEND_SIGNAL(src, COMSIG_GOLIATH_TENTACLE_RETRACTING)
unbuckle_all_mobs(force = TRUE)
icon_state = "goliath_tentacle_retract"
update_appearance(UPDATE_OVERLAYS)
deltimer(action_timer)
action_timer = QDEL_IN_STOPPABLE(src, 0.7 SECONDS)

/obj/effect/goliath_tentacle/update_overlays()
. = ..()
. += emissive_appearance(icon, "[icon_state]_e", src, effect_type = EMISSIVE_NO_BLOOM)
. += emissive_appearance(icon, "[icon_state]_e_bloom", src)

/obj/effect/temp_visual/goliath_tentacle/proc/get_directions()
return GLOB.cardinals.Copy()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/power/floodlight.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
/obj/machinery/power/floodlight
name = "floodlight"
desc = "A pole with powerful mounted lights on it. Due to its high power draw, it must be powered by a direct connection to a wire node."
icon = 'icons/obj/lighting.dmi'
icon = 'mod_celadon/_storage_icons/icons/structures/obj/lighting.dmi' //icon = 'icons/obj/lighting.dmi' // [CELADON-EDIT]
icon_state = "floodlight"
density = TRUE
max_integrity = 100
Expand Down
Loading