mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
Adds Circuit variables (#60590)
Co-authored-by: Watermelon914 <3052169-Watermelon914@users.noreply.gitlab.com>
This commit is contained in:
co-authored by
Watermelon914
parent
63e8466f39
commit
05ede8dc30
@@ -211,7 +211,7 @@
|
||||
|
||||
/obj/item/circuit_component/module/ui_static_data(mob/user)
|
||||
. = list()
|
||||
.["global_port_types"] = GLOB.wiremod_types
|
||||
.["global_port_types"] = GLOB.wiremod_basic_types
|
||||
|
||||
/obj/item/circuit_component/module/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/circuit_component))
|
||||
@@ -280,7 +280,7 @@
|
||||
|
||||
if(action == "set_port_type")
|
||||
var/type = params["port_type"]
|
||||
if(!(type in GLOB.wiremod_types))
|
||||
if(!(type in GLOB.wiremod_basic_types))
|
||||
return
|
||||
component_port.set_datatype(type)
|
||||
internal_component_port.set_datatype(type)
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
|
||||
/obj/item/circuit_component/light/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
brightness.set_input(clamp(brightness.value || 0, 0, max_power))
|
||||
red.set_input(clamp(red.value, 0, 255))
|
||||
blue.set_input(clamp(blue.value, 0, 255))
|
||||
green.set_input(clamp(green.value, 0, 255))
|
||||
brightness.set_value(clamp(brightness.value || 0, 0, max_power))
|
||||
red.set_value(clamp(red.value, 0, 255))
|
||||
blue.set_value(clamp(blue.value, 0, 255))
|
||||
green.set_value(clamp(green.value, 0, 255))
|
||||
var/list/hsl = rgb2hsl(red.value || 0, green.value || 0, blue.value || 0)
|
||||
var/list/light_col = hsl2rgb(hsl[1], hsl[2], max(min_lightness, hsl[3]))
|
||||
shell_light_color = rgb(light_col[1], light_col[2], light_col[3])
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
/obj/item/circuit_component/radio/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
freq.set_input(sanitize_frequency(freq.value, TRUE))
|
||||
freq.set_value(sanitize_frequency(freq.value, TRUE))
|
||||
if(.)
|
||||
return
|
||||
var/frequency = freq.value
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
|
||||
/obj/item/circuit_component/soundemitter/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
volume.set_input(clamp(volume.value, 0, 100))
|
||||
frequency.set_input(clamp(frequency.value, -100, 100))
|
||||
volume.set_value(clamp(volume.value, 0, 100))
|
||||
frequency.set_value(clamp(frequency.value, -100, 100))
|
||||
if(.)
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* # Getter Component
|
||||
*
|
||||
* Gets the current value from a variable.
|
||||
*/
|
||||
/obj/item/circuit_component/getter
|
||||
display_name = "Variable Getter"
|
||||
desc = "A component that gets a variable globally on the circuit."
|
||||
|
||||
/// Variable name
|
||||
var/datum/port/input/option/variable_name
|
||||
|
||||
/// The value of the variable
|
||||
var/datum/port/output/value
|
||||
|
||||
var/datum/circuit_variable/current_variable
|
||||
|
||||
/obj/item/circuit_component/getter/populate_options()
|
||||
variable_name = add_option_port("Variable", null)
|
||||
|
||||
/obj/item/circuit_component/getter/add_to(obj/item/integrated_circuit/added_to)
|
||||
. = ..()
|
||||
variable_name.possible_options = added_to.circuit_variables
|
||||
|
||||
/obj/item/circuit_component/getter/removed_from(obj/item/integrated_circuit/removed_from)
|
||||
variable_name.possible_options = null
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/getter/Initialize()
|
||||
. = ..()
|
||||
value = add_output_port("Value", PORT_TYPE_ANY)
|
||||
|
||||
/obj/item/circuit_component/getter/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
// We don't care much about the parent's return value. We only care if the parent exists
|
||||
// since this should never really fail.
|
||||
if(!parent)
|
||||
return
|
||||
|
||||
var/variable_string = variable_name.value
|
||||
if(!variable_string)
|
||||
remove_current_variable()
|
||||
value.set_output(null)
|
||||
return
|
||||
|
||||
var/datum/circuit_variable/variable = parent.circuit_variables[variable_string]
|
||||
if(!variable)
|
||||
remove_current_variable()
|
||||
value.set_output(null)
|
||||
return
|
||||
|
||||
set_current_variable(variable)
|
||||
value.set_output(variable.value)
|
||||
|
||||
/obj/item/circuit_component/getter/proc/remove_current_variable()
|
||||
SIGNAL_HANDLER
|
||||
if(current_variable)
|
||||
current_variable.remove_listener(src)
|
||||
UnregisterSignal(current_variable, COMSIG_PARENT_QDELETING)
|
||||
current_variable = null
|
||||
|
||||
/obj/item/circuit_component/getter/proc/set_current_variable(datum/circuit_variable/variable)
|
||||
if(variable == current_variable)
|
||||
return
|
||||
|
||||
remove_current_variable()
|
||||
current_variable = variable
|
||||
current_variable.add_listener(src)
|
||||
RegisterSignal(current_variable, COMSIG_PARENT_QDELETING, .proc/remove_current_variable)
|
||||
value.set_datatype(variable.datatype)
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* # RAM Component
|
||||
*
|
||||
* Stores the current input when triggered.
|
||||
* Players will need to think logically when using the RAM component
|
||||
* as there can be race conditions due to the delays of transferring signals
|
||||
*/
|
||||
/obj/item/circuit_component/ram
|
||||
display_name = "RAM"
|
||||
desc = "A component that retains a variable."
|
||||
circuit_flags = CIRCUIT_FLAG_OUTPUT_SIGNAL
|
||||
|
||||
var/datum/port/input/option/ram_options
|
||||
|
||||
/// The input to store
|
||||
var/datum/port/input/input_port
|
||||
/// The trigger to store the current value of the input
|
||||
var/datum/port/input/trigger
|
||||
/// Clears the current input
|
||||
var/datum/port/input/clear
|
||||
|
||||
/// The current set value
|
||||
var/datum/port/output/output
|
||||
|
||||
var/current_type
|
||||
|
||||
/obj/item/circuit_component/ram/populate_options()
|
||||
var/static/component_options = list(
|
||||
PORT_TYPE_ANY,
|
||||
PORT_TYPE_STRING,
|
||||
PORT_TYPE_NUMBER,
|
||||
PORT_TYPE_LIST,
|
||||
PORT_TYPE_ATOM,
|
||||
PORT_TYPE_SIGNAL,
|
||||
)
|
||||
ram_options = add_option_port("RAM Options", component_options)
|
||||
|
||||
/obj/item/circuit_component/ram/Initialize()
|
||||
. = ..()
|
||||
input_port = add_input_port("Input", PORT_TYPE_ANY)
|
||||
trigger = add_input_port("Store", PORT_TYPE_SIGNAL)
|
||||
clear = add_input_port("Clear", PORT_TYPE_SIGNAL)
|
||||
|
||||
output = add_output_port("Stored Value", PORT_TYPE_ANY)
|
||||
|
||||
/obj/item/circuit_component/ram/Destroy()
|
||||
input_port = null
|
||||
trigger = null
|
||||
clear = null
|
||||
output = null
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/ram/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
if(current_type != ram_options.value)
|
||||
current_type = ram_options.value
|
||||
input_port.set_datatype(current_type)
|
||||
output.set_datatype(current_type)
|
||||
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(COMPONENT_TRIGGERED_BY(clear, port))
|
||||
output.set_output(null)
|
||||
return
|
||||
|
||||
if(!COMPONENT_TRIGGERED_BY(trigger, port))
|
||||
return TRUE
|
||||
|
||||
var/input_val = input_port.value
|
||||
|
||||
output.set_output(input_val)
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* # Setter Component
|
||||
*
|
||||
* Stores the current input when triggered into a variable.
|
||||
*/
|
||||
/obj/item/circuit_component/setter
|
||||
display_name = "Variable Setter"
|
||||
desc = "A component that sets a variable globally on the circuit."
|
||||
|
||||
circuit_flags = CIRCUIT_FLAG_OUTPUT_SIGNAL
|
||||
|
||||
/// Variable name
|
||||
var/datum/port/input/option/variable_name
|
||||
|
||||
/// The input to store
|
||||
var/datum/port/input/input_port
|
||||
/// The trigger to store the current value of the input
|
||||
var/datum/port/input/trigger
|
||||
|
||||
var/current_type
|
||||
|
||||
/obj/item/circuit_component/setter/populate_options()
|
||||
variable_name = add_option_port("Variable", null)
|
||||
|
||||
/obj/item/circuit_component/setter/add_to(obj/item/integrated_circuit/added_to)
|
||||
. = ..()
|
||||
variable_name.possible_options = added_to.circuit_variables
|
||||
|
||||
/obj/item/circuit_component/setter/removed_from(obj/item/integrated_circuit/removed_from)
|
||||
variable_name.possible_options = null
|
||||
return ..()
|
||||
|
||||
/obj/item/circuit_component/setter/Initialize()
|
||||
. = ..()
|
||||
input_port = add_input_port("Input", PORT_TYPE_ANY)
|
||||
trigger = add_input_port("Store", PORT_TYPE_SIGNAL)
|
||||
|
||||
/obj/item/circuit_component/setter/input_received(datum/port/input/port)
|
||||
. = ..()
|
||||
var/variable_string = variable_name.value
|
||||
if(!variable_string)
|
||||
return
|
||||
|
||||
var/datum/circuit_variable/variable = parent.circuit_variables[variable_string]
|
||||
if(!variable)
|
||||
return
|
||||
|
||||
if(variable.datatype != current_type)
|
||||
current_type = variable.datatype
|
||||
input_port.set_datatype(current_type)
|
||||
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(!COMPONENT_TRIGGERED_BY(trigger, port))
|
||||
return TRUE
|
||||
|
||||
variable.set_value(input_port.value)
|
||||
@@ -4,7 +4,7 @@
|
||||
/datum/port/input/option/New(obj/item/circuit_component/to_connect, name, datatype, trigger, default, possible_options)
|
||||
. = ..()
|
||||
src.possible_options = possible_options
|
||||
set_input(default, FALSE)
|
||||
set_value(default, force = TRUE)
|
||||
|
||||
/datum/circuit_datatype/option
|
||||
datatype = PORT_TYPE_OPTION
|
||||
|
||||
@@ -20,6 +20,11 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
|
||||
if(general_data["display_name"])
|
||||
set_display_name(general_data["display_name"])
|
||||
|
||||
var/list/variable_data = general_data["variables"]
|
||||
for(var/list/variable as anything in variable_data)
|
||||
var/variable_name = variable["name"]
|
||||
circuit_variables[variable_name] = new /datum/circuit_variable(variable_name, variable["datatype"])
|
||||
|
||||
admin_only = general_data["admin_only"]
|
||||
|
||||
var/list/circuit_data = general_data["components"]
|
||||
@@ -164,6 +169,15 @@ GLOBAL_LIST_INIT(circuit_dupe_whitelisted_types, list(
|
||||
general_data["display_name"] = display_name
|
||||
general_data["admin_only"] = admin_only
|
||||
|
||||
var/list/variables = list()
|
||||
for(var/variable_identifier in circuit_variables)
|
||||
var/list/new_data = list()
|
||||
var/datum/circuit_variable/variable = circuit_variables[variable_identifier]
|
||||
new_data["name"] = variable.name
|
||||
new_data["datatype"] = variable.datatype
|
||||
variables += list(new_data)
|
||||
general_data["variables"] = variables
|
||||
|
||||
return json_encode(general_data)
|
||||
|
||||
/obj/item/integrated_circuit/proc/load_component(type)
|
||||
|
||||
@@ -48,12 +48,27 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
/// Set by the shell. Holds the reference to the owner who inserted the component into the shell.
|
||||
var/datum/weakref/inserter_mind
|
||||
|
||||
/// Variables stored on this integrated circuit. with a `variable_name = value` structure
|
||||
var/list/datum/circuit_variable/circuit_variables = list()
|
||||
|
||||
/// The maximum amount of setters and getters a circuit can have
|
||||
var/max_setters_and_getters = 30
|
||||
|
||||
/// The current setter and getter count the circuit has.
|
||||
var/setter_and_getter_count = 0
|
||||
|
||||
/// X position of the examined_component
|
||||
var/examined_rel_x = 0
|
||||
|
||||
/// Y position of the examined component
|
||||
var/examined_rel_y = 0
|
||||
|
||||
/// The X position of the screen. Used for adding components
|
||||
var/screen_x = 0
|
||||
|
||||
/// The Y position of the screen. Used for adding components.
|
||||
var/screen_y = 0
|
||||
|
||||
/obj/item/integrated_circuit/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -69,6 +84,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
for(var/obj/item/circuit_component/to_delete in attached_components)
|
||||
remove_component(to_delete)
|
||||
qdel(to_delete)
|
||||
QDEL_LIST(circuit_variables)
|
||||
attached_components.Cut()
|
||||
shell = null
|
||||
examined_component = null
|
||||
@@ -182,8 +198,8 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
if(!success)
|
||||
return
|
||||
|
||||
to_add.rel_x = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS)
|
||||
to_add.rel_y = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS)
|
||||
to_add.rel_x = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS) - screen_x
|
||||
to_add.rel_y = rand(COMPONENT_MIN_RANDOM_POS, COMPONENT_MAX_RANDOM_POS) - screen_y
|
||||
to_add.parent = src
|
||||
attached_components += to_add
|
||||
RegisterSignal(to_add, COMSIG_MOVABLE_MOVED, .proc/component_move_handler)
|
||||
@@ -191,6 +207,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
|
||||
if(shell)
|
||||
to_add.register_shell(shell)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Adds a component to the circuitboard through a manual action.
|
||||
@@ -199,7 +216,7 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
if (SEND_SIGNAL(src, COMSIG_CIRCUIT_ADD_COMPONENT_MANUALLY, to_add, user) & COMPONENT_CANCEL_ADD_COMPONENT)
|
||||
return
|
||||
|
||||
add_component(to_add, user)
|
||||
return add_component(to_add, user)
|
||||
|
||||
/obj/item/integrated_circuit/proc/component_move_handler(obj/item/circuit_component/source)
|
||||
SIGNAL_HANDLER
|
||||
@@ -231,6 +248,12 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
get_asset_datum(/datum/asset/simple/circuit_assets)
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/ui_static_data(mob/user)
|
||||
. = list()
|
||||
.["global_basic_types"] = GLOB.wiremod_basic_types
|
||||
.["screen_x"] = screen_x
|
||||
.["screen_y"] = screen_y
|
||||
|
||||
/obj/item/integrated_circuit/ui_data(mob/user)
|
||||
. = list()
|
||||
.["components"] = list()
|
||||
@@ -272,6 +295,16 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
component_data["removable"] = component.removable
|
||||
.["components"] += list(component_data)
|
||||
|
||||
.["variables"] = list()
|
||||
for(var/variable_name in circuit_variables)
|
||||
var/datum/circuit_variable/variable = circuit_variables[variable_name]
|
||||
var/list/variable_data = list()
|
||||
variable_data["name"] = variable.name
|
||||
variable_data["datatype"] = variable.datatype
|
||||
variable_data["color"] = variable.color
|
||||
.["variables"] += list(variable_data)
|
||||
|
||||
|
||||
.["display_name"] = display_name
|
||||
|
||||
var/obj/item/circuit_component/examined
|
||||
@@ -479,6 +512,51 @@ GLOBAL_LIST_EMPTY_TYPED(integrated_circuits, /obj/item/integrated_circuit)
|
||||
. = TRUE
|
||||
if("save_circuit")
|
||||
return attempt_save_to(usr.client)
|
||||
if("add_variable")
|
||||
var/variable_identifier = trim(copytext(params["variable_name"], 1, PORT_MAX_NAME_LENGTH))
|
||||
if(variable_identifier in circuit_variables)
|
||||
return TRUE
|
||||
if(variable_identifier == "")
|
||||
return TRUE
|
||||
var/variable_datatype = params["variable_datatype"]
|
||||
if(!(variable_datatype in GLOB.wiremod_basic_types))
|
||||
return
|
||||
|
||||
circuit_variables[variable_identifier] = new /datum/circuit_variable(variable_identifier, variable_datatype)
|
||||
. = TRUE
|
||||
if("remove_variable")
|
||||
var/variable_identifier = params["variable_name"]
|
||||
if(!(variable_identifier in circuit_variables))
|
||||
return
|
||||
var/datum/circuit_variable/variable = circuit_variables[variable_identifier]
|
||||
if(!variable)
|
||||
return
|
||||
circuit_variables -= variable_identifier
|
||||
qdel(variable)
|
||||
. = TRUE
|
||||
if("add_setter_or_getter")
|
||||
if(setter_and_getter_count >= max_setters_and_getters)
|
||||
balloon_alert(usr, "setter and getter count at maximum capacity")
|
||||
return
|
||||
var/designated_type = /obj/item/circuit_component/getter
|
||||
if(params["is_setter"])
|
||||
designated_type = /obj/item/circuit_component/setter
|
||||
var/obj/item/circuit_component/component = new designated_type(src)
|
||||
if(!add_component(component, usr))
|
||||
qdel(component)
|
||||
return
|
||||
RegisterSignal(component, COMSIG_CIRCUIT_COMPONENT_REMOVED, .proc/clear_setter_or_getter)
|
||||
setter_and_getter_count++
|
||||
if("move_screen")
|
||||
screen_x = text2num(params["screen_x"])
|
||||
screen_y = text2num(params["screen_y"])
|
||||
|
||||
/obj/item/integrated_circuit/proc/clear_setter_or_getter(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
// This'll also be called in the Destroy() override of /obj/item/circuit_component
|
||||
if(!QDELING(source))
|
||||
qdel(source)
|
||||
setter_and_getter_count--
|
||||
|
||||
/obj/item/integrated_circuit/proc/on_atom_usb_cable_try_attach(datum/source, obj/item/usb_cable/usb_cable, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
* Sets the port's value to value.
|
||||
* Casts to the port's datatype (e.g. number -> string), and assumes this can be done.
|
||||
*/
|
||||
/datum/port/proc/set_value(value)
|
||||
if(src.value != value)
|
||||
/datum/port/proc/set_value(value, force = FALSE)
|
||||
if(src.value != value || force)
|
||||
if(isatom(value))
|
||||
UnregisterSignal(value, COMSIG_PARENT_QDELETING)
|
||||
src.value = datatype_handler.convert_value(src, value)
|
||||
@@ -156,7 +156,7 @@
|
||||
|
||||
/datum/port/input/New(obj/item/circuit_component/to_connect, name, datatype, trigger, default)
|
||||
. = ..()
|
||||
set_input(default)
|
||||
set_value(default)
|
||||
src.trigger = trigger
|
||||
src.connected_ports = list()
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* A circuit variable that holds the name, the datatype and the colour of the variable (taken from the datatype).
|
||||
*
|
||||
* Used in integrated circuits for setter and getter circuit components.
|
||||
*/
|
||||
/datum/circuit_variable
|
||||
/// The display name of the circuit variable
|
||||
var/name
|
||||
|
||||
/// The datatype of the circuit variable. Used by the setter and getter circuit components
|
||||
var/datatype
|
||||
|
||||
/// The colour that appears in the UI. The value is set to the datatype's matching colour
|
||||
var/color
|
||||
|
||||
/// The current value held by the variable.
|
||||
var/value
|
||||
|
||||
/// The components that are currently listening. Triggers them when the value is updated.
|
||||
var/list/obj/item/circuit_component/listeners
|
||||
|
||||
/datum/circuit_variable/New(name, datatype)
|
||||
. = ..()
|
||||
src.name = name
|
||||
src.datatype = datatype
|
||||
|
||||
var/datum/circuit_datatype/circuit_datatype = GLOB.circuit_datatypes[datatype]
|
||||
|
||||
src.listeners = list()
|
||||
src.color = circuit_datatype.color
|
||||
|
||||
|
||||
/datum/circuit_variable/Destroy(force, ...)
|
||||
listeners = null
|
||||
return ..()
|
||||
|
||||
/// Sets the value of the circuit component and triggers the appropriate listeners
|
||||
/datum/circuit_variable/proc/set_value(new_value)
|
||||
value = new_value
|
||||
for(var/obj/item/circuit_component/component as anything in listeners)
|
||||
TRIGGER_CIRCUIT_COMPONENT(component, null)
|
||||
|
||||
/// Adds a listener to receive inputs when the variable has a value that is set.
|
||||
/datum/circuit_variable/proc/add_listener(obj/item/circuit_component/to_add)
|
||||
listeners += to_add
|
||||
|
||||
/// Removes a listener to receive inputs when the variable has a value that is set. Listener will usually clean themselves up
|
||||
/datum/circuit_variable/proc/remove_listener(obj/item/circuit_component/to_remove)
|
||||
listeners -= to_remove
|
||||
Reference in New Issue
Block a user