mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 17:14:47 +01:00
cc34f01082
## About The Pull Request UPDATE_ICON is needed rather than UPDATE_ICON_STATE to update the emissive blocker Closes #96076 ## Changelog 🆑 fix: Fixed plumbing ducts having weird shadows /🆑
348 lines
10 KiB
Plaintext
348 lines
10 KiB
Plaintext
/obj/machinery/duct
|
|
name = "fluid duct"
|
|
icon = 'icons/obj/pipes_n_cables/hydrochem/fluid_ducts.dmi'
|
|
icon_state = "nduct"
|
|
layer = PLUMBING_PIPE_VISIBILE_LAYER
|
|
use_power = NO_POWER_USE
|
|
|
|
///our ductnet, wich tracks what we're connected to
|
|
var/datum/ductnet/net
|
|
///the color of our duct
|
|
var/duct_color = ATMOS_COLOR_OMNI
|
|
///the layer of the duct
|
|
var/duct_layer = DUCT_LAYER_DEFAULT
|
|
///track machines we're connected to.
|
|
var/list/atom/movable/neighbours
|
|
|
|
/obj/machinery/duct/Initialize(mapload, color_of_duct, layer_of_duct)
|
|
if(GLOB.plumbing_layer_names["[layer_of_duct]"])
|
|
duct_layer = layer_of_duct
|
|
|
|
if(PERFORM_ALL_TESTS(maptest_log_mapping))
|
|
var/datum/overlap = ducting_layer_check(src, duct_layer)
|
|
if(!isnull(overlap))
|
|
var/message = GLOB.plumbing_layer_names["[duct_layer]"]
|
|
if(istype(overlap, /obj/machinery/duct))
|
|
message = "duct on [message]"
|
|
else
|
|
message = "machine on [message]"
|
|
log_mapping("Overlapping plumbing [message] detected at [AREACOORD(src)]")
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
. = ..()
|
|
|
|
if(GLOB.pipe_color_name[color_of_duct])
|
|
duct_color = color_of_duct
|
|
add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY)
|
|
|
|
var/offset
|
|
switch(duct_layer)
|
|
if(FIRST_DUCT_LAYER)
|
|
offset = -10
|
|
if(SECOND_DUCT_LAYER)
|
|
offset = -5
|
|
if(THIRD_DUCT_LAYER)
|
|
offset = 0
|
|
if(FOURTH_DUCT_LAYER)
|
|
offset = 5
|
|
if(FIFTH_DUCT_LAYER)
|
|
offset = 10
|
|
pixel_x = offset
|
|
pixel_y = offset
|
|
layer = initial(layer) + duct_layer * 0.0003
|
|
|
|
AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE)
|
|
|
|
register_context()
|
|
|
|
/obj/machinery/duct/post_machine_initialize()
|
|
. = ..()
|
|
|
|
//can be initialized already during map init by its neighbours
|
|
if(!net)
|
|
net = new (src)
|
|
|
|
LAZYINITLIST(neighbours)
|
|
for(var/direction in GLOB.cardinals)
|
|
//we have already connected. happens in circular connections
|
|
var/connected = FALSE
|
|
for(var/atom/movable/neighbour as anything in neighbours)
|
|
if(direction & neighbours[neighbour])
|
|
connected = TRUE
|
|
break
|
|
if(connected)
|
|
continue
|
|
|
|
for(var/atom/movable/plumbable in get_step(src, direction))
|
|
var/opposite_dir = REVERSE_DIR(direction)
|
|
|
|
if(istype(plumbable, /obj/machinery/duct))
|
|
var/obj/machinery/duct/other = plumbable
|
|
|
|
//must be same duct color
|
|
if((duct_color != other.duct_color) && !(duct_color == ATMOS_COLOR_OMNI || other.duct_color == ATMOS_COLOR_OMNI))
|
|
continue
|
|
//must be same duct layer
|
|
if(!(duct_layer & other.duct_layer))
|
|
continue
|
|
|
|
//connect ductnets
|
|
if(!other.net) //will be null only for map loaded ducts
|
|
net.ducts += other
|
|
other.net = net
|
|
else if(net != other.net) //merge the nets
|
|
var/datum/ductnet/othernet = other.net
|
|
//Take all its suppliers & demanders
|
|
net.suppliers |= othernet.suppliers
|
|
net.demanders |= othernet.demanders
|
|
for(var/datum/component/plumbing/component as anything in othernet.suppliers + othernet.demanders)
|
|
for(var/obj/machinery/duct/duct as anything in component.ducts)
|
|
if(component.ducts[duct] == othernet)
|
|
component.ducts[duct] = net
|
|
othernet.suppliers.Cut()
|
|
othernet.demanders.Cut()
|
|
|
|
//Take all its ducts
|
|
net.ducts |= othernet.ducts
|
|
for(var/obj/machinery/duct/duct as anything in othernet.ducts)
|
|
duct.net = net
|
|
|
|
//destory it
|
|
qdel(othernet)
|
|
|
|
//connecting us to duct
|
|
neighbours[other] = direction
|
|
//connecting duct to us
|
|
LAZYADDASSOC(other.neighbours, src, opposite_dir)
|
|
other.update_appearance(UPDATE_ICON)
|
|
|
|
continue
|
|
|
|
for(var/datum/component/plumbing/plumbing as anything in plumbable.GetComponents(/datum/component/plumbing))
|
|
//not anchored
|
|
if(!plumbing.active())
|
|
continue
|
|
|
|
//not on the same layer
|
|
if(!(duct_layer & plumbing.ducting_layer))
|
|
continue
|
|
|
|
//does the duct backend connect to either supplier or demander
|
|
if(!(opposite_dir & (plumbing.supply_connects | plumbing.demand_connects)))
|
|
continue
|
|
|
|
//connect duct to plumber
|
|
if(!net.add_plumber(plumbing, opposite_dir))
|
|
continue
|
|
|
|
//assign neighbour
|
|
neighbours[plumbing.parent] = direction
|
|
|
|
update_appearance(UPDATE_ICON)
|
|
|
|
///we disconnect ourself from our neighbours. we also destroy our ductnet and tell our neighbours to make a new one
|
|
/obj/machinery/duct/on_deconstruction()
|
|
var/obj/item/stack/ducts/duct_stack = new (drop_location())
|
|
duct_stack.duct_color = duct_color
|
|
duct_stack.duct_layer = duct_layer
|
|
duct_stack.add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY)
|
|
|
|
///Removes duct from ductnet
|
|
/obj/machinery/duct/proc/disconnect()
|
|
//remove ourself from the duct
|
|
net.ducts -= src
|
|
if(!net.ducts.len)
|
|
qdel(net) //destroy the pipeline. Suppliers aren't important if there aren't any ducts left
|
|
net = null
|
|
|
|
/obj/machinery/duct/Destroy()
|
|
//object was early deleted
|
|
if(!net)
|
|
return ..()
|
|
|
|
var/list/atom/movable/visited = list(src = TRUE)
|
|
while(neighbours.len)
|
|
var/atom/movable/neighbour = popleft(neighbours)
|
|
|
|
//disconnect ourself from our neighbours
|
|
var/obj/machinery/duct/pipe = neighbour
|
|
if(istype(pipe))
|
|
pipe.neighbours -= src
|
|
pipe.update_appearance(UPDATE_ICON)
|
|
|
|
//find every node that can be reached from our neighbour making sure to not revisit it again in circles
|
|
if(visited[neighbour])
|
|
continue
|
|
var/datum/ductnet/newnet
|
|
var/list/atom/movable/queue = list(neighbour)
|
|
while(queue.len)
|
|
var/atom/movable/node = popleft(queue)
|
|
if(visited[node])
|
|
continue
|
|
|
|
//visit all neighbours of this pipe as well
|
|
pipe = node
|
|
if(istype(pipe))
|
|
//assign to new pipenet
|
|
pipe.disconnect()
|
|
if(!newnet)
|
|
newnet = new
|
|
newnet.ducts += pipe
|
|
pipe.net = newnet
|
|
|
|
//go through its neighbours as well
|
|
for(var/atom/movable/subnode in pipe.neighbours)
|
|
queue += subnode
|
|
|
|
visited[node] = TRUE
|
|
continue
|
|
|
|
//assign machines to new network
|
|
for(var/datum/component/plumbing/plumbing as anything in node.GetComponents(/datum/component/plumbing))
|
|
//disconnect old net
|
|
for(var/dirtext in plumbing.ducts)
|
|
if(plumbing.ducts[dirtext] == net)
|
|
net.remove_plumber(plumbing)
|
|
//assign new net
|
|
if(newnet)
|
|
for(pipe as anything in newnet.ducts)
|
|
var/dir = pipe.neighbours[node]
|
|
if(dir)
|
|
newnet.add_plumber(plumbing, REVERSE_DIR(dir))
|
|
|
|
disconnect()
|
|
|
|
return ..()
|
|
|
|
/obj/machinery/duct/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
|
. = NONE
|
|
if(held_item?.tool_behaviour == TOOL_WRENCH)
|
|
context[SCREENTIP_CONTEXT_LMB] = "Destroy duct"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/machinery/duct/examine(mob/user)
|
|
. = ..()
|
|
. += span_notice("Its current color and layer are [GLOB.pipe_color_name[duct_color]] and [GLOB.plumbing_layer_names["[duct_layer]"]]. Use in-hand to change.")
|
|
. += span_notice("It can be [EXAMINE_HINT("wrenched")] apart.")
|
|
|
|
/obj/machinery/duct/update_icon_state()
|
|
var/temp_icon = initial(icon_state)
|
|
|
|
//compute connections
|
|
var/connects = NONE
|
|
for(var/neighbour in neighbours)
|
|
connects |= neighbours[neighbour]
|
|
|
|
for(var/direction in GLOB.cardinals)
|
|
switch(direction & connects)
|
|
if(NORTH)
|
|
temp_icon += "_n"
|
|
if(SOUTH)
|
|
temp_icon += "_s"
|
|
if(EAST)
|
|
temp_icon += "_e"
|
|
if(WEST)
|
|
temp_icon += "_w"
|
|
icon_state = temp_icon
|
|
return ..()
|
|
|
|
/obj/machinery/duct/wrench_act(mob/living/user, obj/item/wrench) //I can also be the RPD
|
|
wrench.play_tool_sound(src)
|
|
|
|
user.visible_message( \
|
|
"[user] ununfastens \the [src].", \
|
|
span_notice("You unfasten \the [src]."), \
|
|
span_hear("You hear ratcheting."))
|
|
|
|
deconstruct()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/stack/ducts
|
|
name = "stack of duct"
|
|
desc = "A stack of fluid ducts."
|
|
singular_name = "duct"
|
|
icon = 'icons/obj/pipes_n_cables/hydrochem/fluid_ducts.dmi'
|
|
icon_state = "ducts"
|
|
mats_per_unit = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*5)
|
|
w_class = WEIGHT_CLASS_TINY
|
|
novariants = FALSE
|
|
max_amount = 50
|
|
item_flags = NOBLUDGEON
|
|
merge_type = /obj/item/stack/ducts
|
|
matter_amount = 1
|
|
///Color of our duct
|
|
var/duct_color = ATMOS_COLOR_OMNI
|
|
///Default layer of our duct
|
|
var/duct_layer = THIRD_DUCT_LAYER
|
|
|
|
/obj/item/stack/ducts/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
|
. = ..()
|
|
|
|
//when wrench is over us
|
|
register_context()
|
|
|
|
//when we are over pipe
|
|
register_item_context()
|
|
|
|
/obj/item/stack/ducts/add_context(atom/source, list/context, obj/item/held_item, mob/user)
|
|
. = NONE
|
|
if(held_item?.tool_behaviour == TOOL_WRENCH && isopenturf(loc))
|
|
context[SCREENTIP_CONTEXT_LMB] = "Wrench duct"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/stack/ducts/add_item_context(obj/item/source, list/context, atom/target, mob/living/user)
|
|
. = NONE
|
|
if(istype(target, /obj/machinery/duct))
|
|
context[SCREENTIP_CONTEXT_LMB] = "Pick duct"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/obj/item/stack/ducts/examine(mob/user)
|
|
. = ..()
|
|
. += span_notice("Its current color and layer are [GLOB.pipe_color_name[duct_color]] and [GLOB.plumbing_layer_names["[duct_layer]"]]. Use in-hand to change.")
|
|
. += span_notice("Place on ground & [EXAMINE_HINT("wrench")] to create duct.")
|
|
|
|
/obj/item/stack/ducts/attack_self(mob/user)
|
|
var/new_layer = tgui_input_list(user, "Select a layer", "Layer", GLOB.plumbing_layers, GLOB.plumbing_layer_names["[duct_layer]"])
|
|
if(!user.is_holding(src))
|
|
return
|
|
if(new_layer)
|
|
duct_layer = GLOB.plumbing_layers[new_layer]
|
|
var/new_color = tgui_input_list(user, "Select a color", "Color", GLOB.pipe_paint_colors, GLOB.pipe_color_name[duct_color])
|
|
if(!user.is_holding(src))
|
|
return
|
|
if(new_color)
|
|
duct_color = GLOB.pipe_paint_colors[new_color]
|
|
add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY)
|
|
|
|
/obj/item/stack/ducts/wrench_act(mob/living/user, obj/item/tool)
|
|
return check_attach_turf(loc)
|
|
|
|
/obj/item/stack/ducts/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
// Turn into a duct stack and then merge to the in-hand stack.
|
|
if(istype(interacting_with, /obj/machinery/duct))
|
|
if(amount == max_amount)
|
|
balloon_alert(user, "stack full!")
|
|
return ITEM_INTERACT_FAILURE
|
|
qdel(interacting_with)
|
|
add(1)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
return check_attach_turf(interacting_with, user)
|
|
|
|
/obj/item/stack/ducts/proc/check_attach_turf(turf/open_turf, mob/user)
|
|
. = NONE
|
|
if(isopenturf(open_turf))
|
|
var/datum/overlap = ducting_layer_check(open_turf, duct_layer)
|
|
if(!isnull(overlap))
|
|
if(user)
|
|
open_turf.balloon_alert(user, "overlapping [istype(overlap, /obj/machinery/duct) ? "duct" : "machine"] detected!")
|
|
return ITEM_INTERACT_FAILURE
|
|
|
|
new /obj/machinery/duct(open_turf, duct_color, duct_layer)
|
|
playsound(open_turf, 'sound/machines/click.ogg', 50, TRUE)
|
|
use(1)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/stack/ducts/fifty
|
|
amount = 50
|