Files
Citadel-Station-13-RP/code/game/objects/items/weapons/RCD.dm
Zandario 5a7f357b85 CitadelRP (#4108)
* dme and dmb

* Heeeere we gooo

* fasease

* Continued.

* AAAAAAAAAAAAAAAAAAAAAAAA

* Brain going numb

* agh

* The suffering will be worth it... right?

* Going blank...

* Am I done?

* AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

* Fixes

* Should be everything I care about right now.
2022-05-26 01:37:55 -07:00

490 lines
16 KiB
Plaintext

// Contains the rapid construction device.
/obj/item/rcd
name = "rapid construction device"
desc = "A device used to rapidly build and deconstruct. Reload with compressed matter cartridges."
icon = 'icons/obj/tools.dmi'
icon_state = "rcd"
item_state = "rcd"
drop_sound = 'sound/items/drop/gun.ogg'
pickup_sound = 'sound/items/pickup/gun.ogg'
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand.dmi',
slot_r_hand_str = 'icons/mob/items/righthand.dmi',
)
flags = NOBLUDGEON
force = 10
throwforce = 10
throw_speed = 1
throw_range = 5
w_class = ITEMSIZE_NORMAL
origin_tech = list(TECH_ENGINEERING = 4, TECH_MATERIAL = 2)
matter = list(MAT_STEEL = 50000)
preserve_item = TRUE // RCDs are pretty important.
var/datum/effect_system/spark_spread/spark_system
var/stored_matter = 0
var/max_stored_matter = RCD_MAX_CAPACITY
var/ranged = FALSE
var/busy = FALSE
var/allow_concurrent_building = FALSE // If true, allows for multiple RCD builds at the same time.
var/mode_index = 1
var/list/modes = list(RCD_FLOORWALL, RCD_AIRLOCK, RCD_WINDOWGRILLE, RCD_DECONSTRUCT)
var/can_remove_rwalls = FALSE
var/airlock_type = /obj/machinery/door/airlock
var/window_type = /obj/structure/window/reinforced/full
var/material_to_use = MAT_STEEL // So badmins can make RCDs that print diamond walls.
var/make_rwalls = FALSE // If true, when building walls, they will be reinforced.
var/ammostate
var/list/effects = list()
var/static/image/radial_image_airlock = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock")
var/static/image/radial_image_decon = image(icon= 'icons/mob/radial.dmi', icon_state = "delete")
var/static/image/radial_image_grillewind = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow")
var/static/image/radial_image_floorwall = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor")
/obj/item/rcd/Initialize(mapload)
src.spark_system = new /datum/effect_system/spark_spread
spark_system.set_up(5, 0, src)
spark_system.attach(src)
update_icon()
return ..()
/obj/item/rcd/Destroy()
QDEL_NULL(spark_system)
spark_system = null
return ..()
/obj/item/rcd/update_icon()
var/nearest_ten = round((stored_matter/max_stored_matter)*10, 1)
//Just to prevent updates every use
if(ammostate == nearest_ten)
return //No change
ammostate = nearest_ten
cut_overlays()
//Main sprite update
if(!nearest_ten)
icon_state = "[initial(icon_state)]_empty"
else
icon_state = "[initial(icon_state)]"
add_overlay("[initial(icon_state)]_charge[nearest_ten]")
/obj/item/rcd/examine(mob/user)
. = ..()
. += "It currently holds [stored_matter]/[max_stored_matter] matter-units."
// Used to add new cartridges.
/obj/item/rcd/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/rcd_ammo))
var/obj/item/rcd_ammo/cartridge = W
var/can_store = min(max_stored_matter - stored_matter, cartridge.remaining)
if(can_store <= 0)
to_chat(user, SPAN_WARNING( "There's either no space or \the [cartridge] is empty!"))
return FALSE
stored_matter += can_store
cartridge.remaining -= can_store
if(!cartridge.remaining)
to_chat(user, SPAN_WARNING( "\The [cartridge] dissolves as it empties of compressed matter."))
user.drop_from_inventory(W)
qdel(W)
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
to_chat(user, SPAN_NOTICE("The RCD now holds [stored_matter]/[max_stored_matter] matter-units."))
update_icon()
return TRUE
return ..()
/obj/item/rcd/proc/check_menu(mob/living/user)
if(!istype(user))
return FALSE
if(user.incapacitated() || !user.Adjacent(src))
return FALSE
return TRUE
// Changes which mode it is on.
/obj/item/rcd/attack_self(mob/living/user)
..()
var/list/choices = list(
"Airlock" = radial_image_airlock,
"Deconstruct" = radial_image_decon,
"Grilles & Windows" = radial_image_grillewind,
"Floors & Walls" = radial_image_floorwall
)
/* We don't have these features yet
if(upgrade & RCD_UPGRADE_FRAMES)
choices += list(
"Machine Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "machine"),
"Computer Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "computer_dir"),
)
if(upgrade & RCD_UPGRADE_SILO_LINK)
choices += list(
"Silo Link" = image(icon = 'icons/obj/mining.dmi', icon_state = "silo"),
)
if(mode == RCD_AIRLOCK)
choices += list(
"Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"),
"Change Airlock Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocktype")
)
else if(mode == RCD_WINDOWGRILLE)
choices += list(
"Change Window Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "windowtype")
)
*/
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
if(!check_menu(user))
return
switch(choice)
if("Floors & Walls")
mode_index = modes.Find(RCD_FLOORWALL)
if("Airlock")
mode_index = modes.Find(RCD_AIRLOCK)
if("Deconstruct")
mode_index = modes.Find(RCD_DECONSTRUCT)
if("Grilles & Windows")
mode_index = modes.Find(RCD_WINDOWGRILLE)
/* We don't have these features yet
if("Machine Frames")
mode = RCD_MACHINE
if("Computer Frames")
mode = RCD_COMPUTER
change_computer_dir(user)
return
if("Change Access")
change_airlock_access(user)
return
if("Change Airlock Type")
change_airlock_setting(user)
return
if("Change Window Type")
toggle_window_type(user)
return
if("Silo Link")
toggle_silo_link(user)
return
*/
else
return
playsound(src, 'sound/effects/pop.ogg', 50, FALSE)
to_chat(user, "<span class='notice'>You change RCD's mode to '[choice]'.</span>")
// Removes resources if the RCD can afford it.
/obj/item/rcd/proc/consume_resources(amount)
if(!can_afford(amount))
return FALSE
stored_matter -= amount
update_icon()
return TRUE
// Useful for testing before actually paying (e.g. before a do_after() ).
/obj/item/rcd/proc/can_afford(amount)
return stored_matter >= amount
/obj/item/rcd/afterattack(atom/A, mob/living/user, proximity)
if(!ranged && !proximity)
return FALSE
use_rcd(A, user)
// Used to call rcd_act() on the atom hit.
/obj/item/rcd/proc/use_rcd(atom/A, mob/living/user)
if(busy && !allow_concurrent_building)
to_chat(user, SPAN_WARNING( "\The [src] is busy finishing its current operation, be patient."))
return FALSE
var/list/rcd_results = A.rcd_values(user, src, modes[mode_index])
if(!rcd_results)
to_chat(user, SPAN_WARNING( "\The [src] blinks a red light as you point it towards \the [A], indicating \
that it won't work. Try changing the mode, or use it on something else."))
return FALSE
if(!can_afford(rcd_results[RCD_VALUE_COST]))
to_chat(user, SPAN_WARNING( "\The [src] lacks the required material to start."))
return FALSE
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
var/true_delay = rcd_results[RCD_VALUE_DELAY] * toolspeed
var/datum/beam/rcd_beam = null
if(ranged)
var/atom/movable/beam_origin = user // This is needed because mecha pilots are inside an object and the beam won't be made if it tries to attach to them..
if(!isturf(beam_origin.loc))
beam_origin = user.loc
rcd_beam = beam_origin.Beam(A, icon_state = "rped_upgrade", time = max(true_delay, 5))
busy = TRUE
perform_effect(A, true_delay)
if(do_after(user, true_delay, target = A))
busy = FALSE
// Doing another check in case we lost matter during the delay for whatever reason.
if(!can_afford(rcd_results[RCD_VALUE_COST]))
to_chat(user, SPAN_WARNING( "\The [src] lacks the required material to finish the operation."))
return FALSE
if(A.rcd_act(user, src, rcd_results[RCD_VALUE_MODE]))
consume_resources(rcd_results[RCD_VALUE_COST])
playsound(get_turf(A), 'sound/items/deconstruct.ogg', 50, 1)
return TRUE
// If they moved, kill the beam immediately.
qdel(rcd_beam)
busy = FALSE
return FALSE
// RCD variants.
// This one starts full.
/obj/item/rcd/loaded/Initialize(mapload)
stored_matter = max_stored_matter
return ..()
// This one makes cooler walls by using an alternative material.
/obj/item/rcd/shipwright
name = "shipwright's rapid construction device"
desc = "A device used to rapidly build and deconstruct. This version creates a stronger variant of wall, often \
used in the construction of hulls for starships. Reload with compressed matter cartridges."
icon_state = "swrcd"
item_state = "ircd"
material_to_use = MAT_STEELHULL
can_remove_rwalls = TRUE
make_rwalls = TRUE
/obj/item/rcd/shipwright/loaded/Initialize(mapload)
stored_matter = max_stored_matter
return ..()
/obj/item/rcd/advanced
name = "advanced rapid construction device"
desc = "A device used to rapidly build and deconstruct. This version works at a range, builds faster, and has a much larger capacity. \
Reload with compressed matter cartridges."
icon_state = "adv_rcd"
ranged = TRUE
toolspeed = 0.5 // Twice as fast.
max_stored_matter = RCD_MAX_CAPACITY * 3 // Three times capacity.
/obj/item/rcd/advanced/loaded/Initialize(mapload)
stored_matter = max_stored_matter
return ..()
// Electric RCDs.
// Currently just a base for the mounted RCDs.
// Currently there isn't a way to swap out the cells.
// One could be added if there is demand to do so.
/obj/item/rcd/electric
name = "electric rapid construction device"
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, no matter cartridges needed."
icon_state = "electric_rcd"
var/obj/item/cell/cell = null
var/make_cell = TRUE // If false, initialize() won't spawn a cell for this.
var/electric_cost_coefficent = 83.33 // Higher numbers make it less efficent. 86.3... means it should matche the standard RCD capacity on a 10k cell.
/obj/item/rcd/electric/Initialize(mapload)
if(make_cell)
cell = new /obj/item/cell/high(src)
return ..()
/obj/item/rcd/electric/Destroy()
if(cell)
QDEL_NULL(cell)
return ..()
/obj/item/rcd/electric/get_cell()
return cell
/obj/item/rcd/electric/can_afford(amount) // This makes it so borgs won't drain their last sliver of charge by mistake, as a bonus.
var/obj/item/cell/cell = get_cell()
if(cell)
return cell.check_charge(amount * electric_cost_coefficent)
return FALSE
/obj/item/rcd/electric/consume_resources(amount)
if(!can_afford(amount))
return FALSE
var/obj/item/cell/cell = get_cell()
return cell.checked_use(amount * electric_cost_coefficent)
/obj/item/rcd/electric/update_icon()
return
/obj/item/rcd/electric/proc/display_resources()
var/obj/item/cell/cell = get_cell()
if(cell)
return "The power source connected to \the [src] has a charge of [cell.percent()]%."
return "It lacks a source of power, and cannot function."
// 'Mounted' RCDs, used for borgs/RIGs/Mechas, all of which use their cells to drive the RCD.
/obj/item/rcd/electric/mounted
name = "mounted electric rapid construction device"
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity from an external power source."
make_cell = FALSE
/obj/item/rcd/electric/mounted/get_cell()
return get_external_power_supply()
/obj/item/rcd/electric/mounted/proc/get_external_power_supply()
if(isrobot(loc)) // In a borg.
var/mob/living/silicon/robot/R = loc
return R.cell
if(istype(loc, /obj/item/rig_module)) // In a RIG.
var/obj/item/rig_module/module = loc
if(module.holder) // Is it attached to a RIG?
return module.holder.cell
if(istype(loc, /obj/item/mecha_parts/mecha_equipment)) // In a mech.
var/obj/item/mecha_parts/mecha_equipment/ME = loc
if(ME.chassis) // Is the part attached to a mech?
return ME.chassis.cell
return null
// RCDs for borgs.
/obj/item/rcd/electric/mounted/borg
can_remove_rwalls = TRUE
desc = "A device used to rapidly build and deconstruct. It runs directly off of electricity, drawing directly from your cell."
electric_cost_coefficent = 41.66 // Twice as efficent, out of pity.
toolspeed = 0.5 // Twice as fast, since borg versions typically have this.
/obj/item/rcd/electric/mounted/borg/swarm
can_remove_rwalls = FALSE
name = "Rapid Assimilation Device"
ranged = TRUE
toolspeed = 0.7
material_to_use = MAT_STEELHULL
/obj/item/rcd/electric/mounted/borg/lesser
can_remove_rwalls = FALSE
// RCDs for RIGs.
/obj/item/rcd/electric/mounted/rig
// Old method for swapping modes as there is no way to bring up the radial.
/obj/item/rcd/electric/mounted/rig/attack_self(mob/living/user)
if(mode_index >= modes.len) // Shouldn't overflow unless someone messes with it in VV poorly but better safe than sorry.
mode_index = 1
else
mode_index++
to_chat(user, SPAN_NOTICE("Changed mode to '[modes[mode_index]]'."))
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
if(prob(20))
src.spark_system.start()
// RCDs for Mechs.
/obj/item/rcd/electric/mounted/mecha
ranged = TRUE
toolspeed = 0.5
// Infinite use RCD for debugging/adminbuse.
/obj/item/rcd/debug
name = "self-repleshing rapid construction device"
desc = "An RCD that appears to be plated with gold. For some reason it also seems to just \
be vastly superior to all other RCDs ever created, possibly due to it being colored gold."
icon_state = "debug_rcd"
ranged = TRUE
can_remove_rwalls = TRUE
allow_concurrent_building = TRUE
toolspeed = 0.25 // Four times as fast.
/obj/item/rcd/debug/can_afford(amount)
return TRUE
/obj/item/rcd/debug/consume_resources(amount)
return TRUE
/obj/item/rcd/debug/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/rcd_ammo))
to_chat(user, SPAN_NOTICE("\The [src] makes its own material, no need to add more."))
return FALSE
return ..()
// Ammo for the (non-electric) RCDs.
/obj/item/rcd_ammo
name = "compressed matter cartridge"
desc = "Highly compressed matter for the RCD."
icon = 'icons/obj/tools.dmi'
icon_state = "rcdammo"
item_state = "rcdammo"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand.dmi',
slot_r_hand_str = 'icons/mob/items/righthand.dmi',
)
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_MATERIAL = 2)
matter = list(MAT_STEEL = 30000, MAT_GLASS = 15000)
var/remaining = RCD_MAX_CAPACITY / 3
/obj/item/rcd_ammo/large
name = "high-capacity matter cartridge"
desc = "Do not ingest."
matter = list(MAT_STEEL = 45000, MAT_GLASS = 22500)
origin_tech = list(TECH_MATERIAL = 4)
remaining = RCD_MAX_CAPACITY
/obj/item/rcd_ammo/examine(mob/user)
. = ..()
. += "It currently holds [remaining]/[initial(remaining)] matter-units."
// RCD Construction Effects
/obj/item/rcd/proc/perform_effect(var/atom/A, var/time_taken)
effects[A] = new /obj/effect/constructing_effect(get_turf(A), time_taken, modes[mode_index])
/obj/item/rcd/use_rcd(atom/A, mob/living/user)
. = ..()
cleanup_effect(A)
/obj/item/rcd/proc/cleanup_effect(var/atom/A)
if(A in effects)
qdel(effects[A])
effects -= A
/obj/effect/constructing_effect
icon = 'icons/effects/effects_rcd.dmi'
icon_state = ""
plane = TURF_PLANE
layer = ABOVE_TURF_LAYER
anchored = TRUE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/status = 0
var/delay = 0
/obj/effect/constructing_effect/Initialize(mapload, rcd_delay, rcd_status)
. = ..()
status = rcd_status
delay = rcd_delay
if (status == RCD_DECONSTRUCT)
addtimer(CALLBACK(src, /atom/.proc/update_icon), 11)
delay -= 11
icon_state = "rcd_end_reverse"
else
update_icon()
/obj/effect/constructing_effect/update_icon()
icon_state = "rcd"
if (delay < 10)
icon_state += "_shortest"
else if (delay < 20)
icon_state += "_shorter"
else if (delay < 37)
icon_state += "_short"
if (status == RCD_DECONSTRUCT)
icon_state += "_reverse"
/obj/effect/constructing_effect/proc/end_animation()
if (status == RCD_DECONSTRUCT)
qdel(src)
else
icon_state = "rcd_end"
addtimer(CALLBACK(src, .proc/end), 15)
/obj/effect/constructing_effect/proc/end()
qdel(src)