mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-20 00:56:33 +01:00
371 lines
12 KiB
Plaintext
371 lines
12 KiB
Plaintext
#define ATMOS_CATEGORY 0
|
|
#define DISPOSALS_CATEGORY 1
|
|
#define TRANSIT_CATEGORY 2
|
|
|
|
#define BUILD_MODE (1<<0)
|
|
#define WRENCH_MODE (1<<1)
|
|
#define DESTROY_MODE (1<<2)
|
|
#define PAINT_MODE (1<<3)
|
|
|
|
/obj/item/pipe_dispenser
|
|
name = "Rapid Piping Device (RPD)"
|
|
desc = "A device used to rapidly pipe things."
|
|
icon = 'icons/obj/tools_vr.dmi'
|
|
icon_state = "rpd"
|
|
item_state = "rpd"
|
|
item_icons = list(
|
|
SLOT_ID_LEFT_HAND = 'icons/mob/items/lefthand.dmi',
|
|
SLOT_ID_RIGHT_HAND = 'icons/mob/items/righthand.dmi',
|
|
)
|
|
item_flags = ITEM_NO_BLUDGEON | ITEM_ENCUMBERS_WHILE_HELD
|
|
damage_force = 10
|
|
throw_force = 10
|
|
throw_speed = 1
|
|
throw_range = 5
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
slot_flags = SLOT_BELT
|
|
materials_base = list(MAT_STEEL = 20000, MAT_GLASS = 10000)
|
|
suit_storage_class = SUIT_STORAGE_CLASS_SOFTWEAR | SUIT_STORAGE_CLASS_HARDWEAR
|
|
///Sparks system used when changing device in the UI
|
|
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread
|
|
///Direction of the device we are going to spawn, set up in the UI
|
|
var/p_dir = NORTH
|
|
///Initial direction of the smart pipe we are going to spawn, set up in the UI
|
|
var/p_init_dir = ALL_CARDINALS
|
|
///Is the device of the flipped type?
|
|
var/p_flipped = FALSE
|
|
///Color of the device we are going to spawn
|
|
var/paint_color = "grey"
|
|
///Category currently active (Atmos, disposal, transit)
|
|
var/category = ATMOS_CATEGORY
|
|
///Piping layer we are going to spawn the atmos device in
|
|
var/piping_layer = PIPING_LAYER_DEFAULT
|
|
var/obj/item/tool/wrench/tool
|
|
///Stores the current device to spawn
|
|
var/datum/pipe_info/recipe
|
|
///Stores the first atmos device
|
|
var/static/datum/pipe_info/first_atmos
|
|
///Stores the first disposal device
|
|
var/static/datum/pipe_info/first_disposal
|
|
///Stores the first transit device
|
|
//var/static/datum/pipe_info/first_transit
|
|
///The modes that are allowed for the RPD
|
|
var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE //| REPROGRAM_MODE
|
|
var/static/list/pipe_layers = list(
|
|
"Regular" = PIPING_LAYER_REGULAR,
|
|
"Supply" = PIPING_LAYER_SUPPLY,
|
|
"Scrubber" = PIPING_LAYER_SCRUBBER,
|
|
"Fuel" = PIPING_LAYER_FUEL,
|
|
"Aux" = PIPING_LAYER_AUX
|
|
)
|
|
|
|
/obj/item/pipe_dispenser/Initialize(mapload)
|
|
. = ..()
|
|
spark_system.set_up(5, 0, src)
|
|
spark_system.attach(src)
|
|
tool = new /obj/item/tool/wrench/cyborg(src)
|
|
|
|
/obj/item/pipe_dispenser/proc/SetupPipes()
|
|
if(!first_atmos)
|
|
first_atmos = GLOB.atmos_pipe_recipes[GLOB.atmos_pipe_recipes[1]][1]
|
|
if(!first_disposal)
|
|
first_disposal = GLOB.disposal_pipe_recipes[GLOB.disposal_pipe_recipes[1]][1]
|
|
//if(!first_transit)
|
|
// first_transit = GLOB.transit_tube_recipes[GLOB.transit_tube_recipes[1]][1]
|
|
if(!recipe)
|
|
recipe = first_atmos
|
|
|
|
/obj/item/pipe_dispenser/Destroy()
|
|
QDEL_NULL(spark_system)
|
|
QDEL_NULL(tool)
|
|
return ..()
|
|
|
|
/obj/item/pipe_dispenser/examine(mob/user, dist)
|
|
. = ..()
|
|
. += "You can scroll your mouse wheel to change the piping layer."
|
|
|
|
/obj/item/pipe_dispenser/equipped(mob/user, slot, flags)
|
|
. = ..()
|
|
if(slot == SLOT_ID_HANDS)
|
|
RegisterSignal(user, COMSIG_MOUSE_SCROLL_ON, PROC_REF(mouse_wheeled))
|
|
else
|
|
UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON)
|
|
|
|
/obj/item/pipe_dispenser/unequipped(mob/user, slot, flags)
|
|
UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON)
|
|
return ..()
|
|
|
|
///obj/item/pipe_dispenser/cyborg_unequip(mob/user)
|
|
// UnregisterSignal(user, COMSIG_MOUSE_SCROLL_ON)
|
|
// return ..()
|
|
|
|
/obj/item/pipe_dispenser/attack_self(mob/user, datum/event_args/actor/actor)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
ui_interact(user)
|
|
|
|
/obj/item/pipe_dispenser/ui_asset_injection(datum/tgui/ui, list/immediate, list/deferred)
|
|
immediate += /datum/asset_pack/spritesheet/pipes
|
|
return ..()
|
|
|
|
/obj/item/pipe_dispenser/ui_state()
|
|
return GLOB.inventory_state
|
|
|
|
/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
|
|
SetupPipes()
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "RapidPipeDispenser", name)
|
|
ui.open()
|
|
|
|
/obj/item/pipe_dispenser/ui_static_data(mob/user, datum/tgui/ui)
|
|
var/list/data = list("paint_colors" = GLOB.pipe_paint_colors)
|
|
return data
|
|
|
|
/obj/item/pipe_dispenser/ui_data(mob/user, datum/tgui/ui)
|
|
var/list/data = list(
|
|
"category" = category,
|
|
"piping_layer" = piping_layer,
|
|
//"ducting_layer" = ducting_layer,
|
|
"preview_rows" = recipe.get_preview(p_dir),
|
|
"categories" = list(),
|
|
"selected_color" = paint_color,
|
|
"mode" = mode
|
|
)
|
|
|
|
var/list/recipes
|
|
switch(category)
|
|
if(ATMOS_CATEGORY)
|
|
recipes = GLOB.atmos_pipe_recipes
|
|
if(DISPOSALS_CATEGORY)
|
|
recipes = GLOB.disposal_pipe_recipes
|
|
//if(TRANSIT_CATEGORY)
|
|
// recipes = GLOB.transit_tube_recipes
|
|
for(var/c in recipes)
|
|
var/list/cat = recipes[c]
|
|
var/list/r = list()
|
|
for(var/i in 1 to cat.len)
|
|
var/datum/pipe_info/info = cat[i]
|
|
r += list(list("pipe_name" = info.name, "pipe_index" = i, "selected" = (info == recipe), "all_layers" = info.all_layers))
|
|
data["categories"] += list(list("cat_name" = c, "recipes" = r))
|
|
|
|
var/list/init_directions = list("north" = FALSE, "south" = FALSE, "east" = FALSE, "west" = FALSE)
|
|
for(var/direction in ALL_CARDINALS)
|
|
if(p_init_dir & direction)
|
|
init_directions[dir2text(direction)] = TRUE
|
|
data["init_directions"] = init_directions
|
|
return data
|
|
|
|
/obj/item/pipe_dispenser/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state, datum/event_args/actor/actor)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
if(!CHECK_MOBILITY(usr, MOBILITY_CAN_USE) || !in_range(loc, usr))
|
|
return TRUE
|
|
var/playeffect = TRUE
|
|
switch(action)
|
|
if("color")
|
|
paint_color = params["paint_color"]
|
|
if("category")
|
|
category = text2num(params["category"])
|
|
switch(category)
|
|
if(DISPOSALS_CATEGORY)
|
|
recipe = first_disposal
|
|
if(ATMOS_CATEGORY)
|
|
recipe = first_atmos
|
|
//if(TRANSIT_CATEGORY)
|
|
// recipe = first_transit
|
|
p_dir = NORTH
|
|
playeffect = FALSE
|
|
if("piping_layer")
|
|
piping_layer = text2num(params["piping_layer"])
|
|
playeffect = FALSE
|
|
//if("ducting_layer")
|
|
// ducting_layer = text2num(params["ducting_layer"])
|
|
// playeffect = FALSE
|
|
if("pipe_type")
|
|
var/static/list/recipes
|
|
if(!recipes)
|
|
recipes = GLOB.disposal_pipe_recipes + GLOB.atmos_pipe_recipes //+ GLOB.transit_tube_recipes
|
|
recipe = recipes[params["category"]][text2num(params["pipe_type"])]
|
|
p_dir = NORTH
|
|
if("setdir")
|
|
p_dir = text2dir(params["dir"])
|
|
p_flipped = text2num(params["flipped"])
|
|
playeffect = FALSE
|
|
if("mode")
|
|
var/n = text2num(params["mode"])
|
|
mode ^= n
|
|
if("init_dir_setting")
|
|
var/target_dir = p_init_dir ^ text2dir(params["dir_flag"])
|
|
// Refuse to create a smart pipe that can only connect in one direction (it would act weirdly and lack an icon)
|
|
if (ISNOTSTUB(target_dir))
|
|
p_init_dir = target_dir
|
|
else
|
|
to_chat(usr, SPAN_WARNING("\The [src]'s screen flashes a warning: Can't configure a pipe to only connect in one direction."))
|
|
playeffect = FALSE
|
|
if("init_reset")
|
|
p_init_dir = ALL_CARDINALS
|
|
if(playeffect)
|
|
spark_system.start()
|
|
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
|
|
return TRUE
|
|
|
|
/obj/item/pipe_dispenser/afterattack(atom/target, mob/user, clickchain_flags, list/params)
|
|
if(!user.IsAdvancedToolUser() || istype(target, /turf/space/transit) || !(clickchain_flags & CLICKCHAIN_HAS_PROXIMITY))
|
|
return ..()
|
|
|
|
//So that changing the menu settings doesn't affect the pipes already being built.
|
|
var/queued_piping_layer = piping_layer
|
|
var/queued_p_dir = p_dir
|
|
var/queued_p_flipped = p_flipped
|
|
|
|
//Make sure what we're clicking is valid for the current mode
|
|
var/static/list/make_pipe_whitelist
|
|
if(!make_pipe_whitelist)
|
|
make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe))
|
|
var/can_make_pipe = (isturf(target) || is_type_in_typecache(target, make_pipe_whitelist))
|
|
|
|
var/can_destroy_pipe = istype(target, /obj/item/pipe) || istype(target, /obj/item/pipe_meter) || istype(target, /obj/structure/disposalconstruct)
|
|
|
|
. = TRUE
|
|
if((mode & DESTROY_MODE) && can_destroy_pipe)
|
|
to_chat(user, SPAN_NOTICE("You start destroying a pipe..."))
|
|
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
|
if(do_after(user, 2, target = target))
|
|
activate()
|
|
animate_deletion(target)
|
|
return
|
|
|
|
//Painting pipes
|
|
if((mode & PAINT_MODE))
|
|
if(istype(target, /obj/machinery/atmospherics/pipe))
|
|
var/obj/machinery/atmospherics/pipe/P = target
|
|
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
|
P.change_color(pipe_colors[paint_color])
|
|
user.visible_message(SPAN_NOTICE("[user] paints \the [P] [paint_color]."), SPAN_NOTICE("You paint \the [P] [paint_color]."))
|
|
return
|
|
|
|
//Making pipes
|
|
if(mode & BUILD_MODE)
|
|
switch(category)
|
|
if(ATMOS_CATEGORY)
|
|
if(!can_make_pipe)
|
|
return ..()
|
|
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
|
if(istype(recipe, /datum/pipe_info/meter))
|
|
to_chat(user, SPAN_NOTICE("You start building a meter..."))
|
|
if(do_after(user, 2, target = target))
|
|
activate()
|
|
var/obj/item/pipe_meter/PM = new /obj/item/pipe_meter(get_turf(target))
|
|
PM.setAttachLayer(queued_piping_layer)
|
|
if(mode & WRENCH_MODE)
|
|
do_wrench(PM, user)
|
|
else if(istype(recipe, /datum/pipe_info/pipe))
|
|
if(recipe.all_layers == FALSE && (piping_layer == 1 || piping_layer == 5))
|
|
to_chat(user, SPAN_NOTICE("You can't build this object on the layer..."))
|
|
return ..()
|
|
else
|
|
var/datum/pipe_info/pipe/R = recipe
|
|
to_chat(user, SPAN_NOTICE("You start building a pipe..."))
|
|
if(do_after(user, 2, target = target))
|
|
if(recipe.all_layers == FALSE && (piping_layer == 1 || piping_layer == 5))//double check to stop cheaters (and to not waste time waiting for something that can't be placed)
|
|
to_chat(user, SPAN_NOTICE("You can't build this object on the layer..."))
|
|
return ..()
|
|
activate()
|
|
var/obj/machinery/atmospherics/path = R.pipe_type
|
|
var/pipe_item_type = initial(path.construction_type) || /obj/item/pipe
|
|
var/obj/item/pipe/P = new pipe_item_type(get_turf(target), path, queued_p_dir)
|
|
|
|
P.update()
|
|
P.add_fingerprint(usr)
|
|
if(R.paintable)
|
|
P.color = pipe_colors[paint_color]
|
|
P.setPipingLayer(queued_piping_layer)
|
|
if(queued_p_flipped)
|
|
P.do_a_flip()
|
|
if(mode & WRENCH_MODE)
|
|
do_wrench(P, user)
|
|
else
|
|
build_effect(P)
|
|
|
|
//Making disposals pipes
|
|
if(DISPOSALS_CATEGORY)
|
|
var/datum/pipe_info/disposal/R = recipe
|
|
if(!istype(R) || !can_make_pipe)
|
|
return ..()
|
|
target = get_turf(target)
|
|
if(istype(target, /turf/unsimulated))
|
|
to_chat(user, SPAN_WARNING("[src]'s error light flickers; there's something in the way!"))
|
|
return
|
|
to_chat(user, SPAN_NOTICE("You start building a disposals pipe..."))
|
|
playsound(src, 'sound/machines/click.ogg', 50, 1)
|
|
if(do_after(user, 4, target = target))
|
|
var/obj/structure/disposalconstruct/C = new(target, R.pipe_type, queued_p_dir, queued_p_flipped, R.subtype)
|
|
|
|
if(!C.can_place())
|
|
to_chat(user, SPAN_WARNING("There's not enough room to build that here!"))
|
|
qdel(C)
|
|
return
|
|
|
|
activate()
|
|
|
|
C.add_fingerprint(usr)
|
|
C.update_icon()
|
|
if(mode & WRENCH_MODE)
|
|
do_wrench(C, user)
|
|
else
|
|
build_effect(C)
|
|
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/pipe_dispenser/proc/build_effect(var/obj/P, var/time = 1.5)
|
|
set waitfor = FALSE
|
|
P.filters += filter(type = "angular_blur", size = 30)
|
|
animate(P.filters[P.filters.len], size = 0, time = time)
|
|
var/outline = filter(type = "outline", size = 1, color = "#22AAFF")
|
|
P.filters += outline
|
|
sleep(time)
|
|
P.filters -= outline
|
|
P.filters -= filter(type = "angular_blur", size = 0)
|
|
|
|
/obj/item/pipe_dispenser/proc/animate_deletion(var/obj/P, var/time = 1.5)
|
|
set waitfor = FALSE
|
|
P.filters += filter(type = "angular_blur", size = 0)
|
|
animate(P.filters[P.filters.len], size = 30, time = time)
|
|
sleep(time)
|
|
if(!QDELETED(P))
|
|
P.filters -= filter(type = "angular_blur", size = 30)
|
|
qdel(P)
|
|
|
|
/obj/item/pipe_dispenser/proc/activate()
|
|
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
|
|
/obj/item/pipe_dispenser/proc/do_wrench(var/atom/target, mob/user)
|
|
tool.lazy_melee_interaction_chain(target, user, CLICKCHAIN_HAS_PROXIMITY)
|
|
|
|
/obj/item/pipe_dispenser/proc/mouse_wheeled(mob/user, atom/A, delta_x, delta_y, params)
|
|
SIGNAL_HANDLER
|
|
if(user.incapacitated(INCAPACITATION_RESTRAINED))
|
|
return
|
|
|
|
if(delta_y < 0)
|
|
piping_layer = min(PIPING_LAYER_MAX, piping_layer + 1)
|
|
else if(delta_y > 0)
|
|
piping_layer = max(PIPING_LAYER_MIN, piping_layer - 1)
|
|
else
|
|
return
|
|
SStgui.update_uis(src)
|
|
to_chat(user, SPAN_NOTICE("You set the layer to [piping_layer]."))
|
|
|
|
#undef ATMOS_CATEGORY
|
|
#undef DISPOSALS_CATEGORY
|
|
#undef TRANSIT_CATEGORY
|
|
|
|
#undef BUILD_MODE
|
|
#undef WRENCH_MODE
|
|
#undef DESTROY_MODE
|
|
#undef PAINT_MODE
|