module things, jfc
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/integrated_electronics/analyzer/afterattack(var/atom/A, var/mob/living/user)
|
||||
. = ..()
|
||||
if(istype(A, /obj/item/electronic_assembly))
|
||||
var/saved = "[A.name] analyzed! On circuit printers with cloning enabled, you may use the code below to clone the circuit:<br><br><code>[SScircuit.save_electronic_assembly(A)]</code>"
|
||||
if(saved)
|
||||
@@ -14,5 +15,3 @@
|
||||
user << browse(saved, "window=circuit_scan;size=500x600;border=1;can_resize=1;can_close=1;can_minimize=1")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[A] is not complete enough to be encoded!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -59,6 +59,11 @@
|
||||
COLOR_ASSEMBLY_PURPLE
|
||||
)
|
||||
|
||||
/obj/item/electronic_assembly/New()
|
||||
..()
|
||||
src.max_components = round(max_components)
|
||||
src.max_complexity = round(max_complexity)
|
||||
|
||||
/obj/item/electronic_assembly/GenerateTag()
|
||||
tag = "assembly_[next_assembly_id++]"
|
||||
|
||||
@@ -70,12 +75,18 @@
|
||||
to_chat(user, "<span class='notice'>The maintenance panel [opened ? "can be" : "is"] <b>screwed</b> in place.</span>")
|
||||
|
||||
if((isobserver(user) && ckeys_allowed_to_scan[user.ckey]) || IsAdminGhost(user))
|
||||
to_chat(user, "You can <a href='?src=[REF(src)];ghostscan=1'>scan</a> this circuit.");
|
||||
to_chat(user, "You can <a href='?src=[REF(src)];ghostscan=1'>scan</a> this circuit.")
|
||||
|
||||
for(var/I in assembly_components)
|
||||
var/obj/item/integrated_circuit/IC = I
|
||||
IC.external_examine(user)
|
||||
if(opened)
|
||||
interact(user)
|
||||
|
||||
/obj/item/electronic_assembly/proc/check_interactivity(mob/user)
|
||||
return user.canUseTopic(src, BE_CLOSE)
|
||||
|
||||
/obj/item/electronic_assembly/Collide(atom/AM)
|
||||
/obj/item/electronic_assembly/Bump(atom/AM)
|
||||
collw = AM
|
||||
.=..()
|
||||
if((istype(collw, /obj/machinery/door/airlock) || istype(collw, /obj/machinery/door/window)) && (!isnull(access_card)))
|
||||
@@ -306,14 +317,6 @@
|
||||
detail_overlay.color = detail_color
|
||||
add_overlay(detail_overlay)
|
||||
|
||||
/obj/item/electronic_assembly/examine(mob/user)
|
||||
..()
|
||||
for(var/I in assembly_components)
|
||||
var/obj/item/integrated_circuit/IC = I
|
||||
IC.external_examine(user)
|
||||
if(opened)
|
||||
interact(user)
|
||||
|
||||
/obj/item/electronic_assembly/proc/return_total_complexity()
|
||||
. = 0
|
||||
var/obj/item/integrated_circuit/part
|
||||
@@ -420,12 +423,15 @@
|
||||
|
||||
|
||||
/obj/item/electronic_assembly/afterattack(atom/target, mob/user, proximity)
|
||||
. = ..()
|
||||
for(var/obj/item/integrated_circuit/input/S in assembly_components)
|
||||
if(S.sense(target,user,proximity))
|
||||
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
|
||||
|
||||
|
||||
/obj/item/electronic_assembly/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(..())
|
||||
return TRUE
|
||||
I.play_tool_sound(src)
|
||||
opened = !opened
|
||||
to_chat(user, "<span class='notice'>You [opened ? "open" : "close"] the maintenance hatch of [src].</span>")
|
||||
@@ -439,7 +445,6 @@
|
||||
if(!user.canUnEquip(I))
|
||||
return FALSE
|
||||
if(try_add_component(I, user))
|
||||
interact(user)
|
||||
return TRUE
|
||||
else
|
||||
for(var/obj/item/integrated_circuit/input/S in assembly_components)
|
||||
@@ -465,24 +470,50 @@
|
||||
for(var/obj/item/integrated_circuit/input/S in assembly_components)
|
||||
S.attackby_react(I,user,user.a_intent)
|
||||
return ..()
|
||||
var/obj/item/stock_parts/cell = I
|
||||
user.transferItemToLoc(I, loc)
|
||||
cell.forceMove(src)
|
||||
battery = cell
|
||||
I.forceMove(src)
|
||||
battery = I
|
||||
diag_hud_set_circuitstat() //update diagnostic hud
|
||||
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supplier.</span>")
|
||||
interact(user)
|
||||
to_chat(user, "<span class='notice'>You slot the [I] inside \the [src]'s power supplier.</span>")
|
||||
return TRUE
|
||||
else if(istype(I, /obj/item/integrated_electronics/detailer))
|
||||
var/obj/item/integrated_electronics/detailer/D = I
|
||||
detail_color = D.detail_color
|
||||
update_icon()
|
||||
else
|
||||
for(var/obj/item/integrated_circuit/input/S in assembly_components)
|
||||
S.attackby_react(I,user,user.a_intent)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..()
|
||||
var/list/input_selection = list()
|
||||
//Check all the components asking for an input
|
||||
for(var/obj/item/integrated_circuit/input in assembly_components)
|
||||
if((input.demands_object_input && opened) || (input.demands_object_input && input.can_input_object_when_closed))
|
||||
var/i = 0
|
||||
//Check if there is another component with the same name and append a number for identification
|
||||
for(var/s in input_selection)
|
||||
var/obj/item/integrated_circuit/s_circuit = input_selection[s]
|
||||
if(s_circuit.name == input.name && s_circuit.displayed_name == input.displayed_name && s_circuit != input)
|
||||
i++
|
||||
var/disp_name= "[input.displayed_name] \[[input]\]"
|
||||
if(i)
|
||||
disp_name += " ([i+1])"
|
||||
//Associative lists prevent me from needing another list and using a Find proc
|
||||
input_selection[disp_name] = input
|
||||
|
||||
var/obj/item/integrated_circuit/choice
|
||||
if(input_selection)
|
||||
if(input_selection.len == 1)
|
||||
choice = input_selection[input_selection[1]]
|
||||
else
|
||||
var/selection = input(user, "Where do you want to insert that item?", "Interaction") as null|anything in input_selection
|
||||
if(!check_interactivity(user))
|
||||
return ..()
|
||||
if(selection)
|
||||
choice = input_selection[selection]
|
||||
if(choice)
|
||||
choice.additem(I, user)
|
||||
for(var/obj/item/integrated_circuit/input/S in assembly_components)
|
||||
S.attackby_react(I,user,user.a_intent)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/electronic_assembly/attack_self(mob/user)
|
||||
@@ -492,30 +523,33 @@
|
||||
interact(user)
|
||||
|
||||
var/list/input_selection = list()
|
||||
var/list/available_inputs = list()
|
||||
//Check all the components asking for an input
|
||||
for(var/obj/item/integrated_circuit/input/input in assembly_components)
|
||||
if(input.can_be_asked_input)
|
||||
available_inputs.Add(input)
|
||||
var/i = 0
|
||||
for(var/obj/item/integrated_circuit/s in available_inputs)
|
||||
if(s.name == input.name && s.displayed_name == input.displayed_name && s != input)
|
||||
//Check if there is another component with the same name and append a number for identification
|
||||
for(var/s in input_selection)
|
||||
var/obj/item/integrated_circuit/s_circuit = input_selection[s]
|
||||
if(s_circuit.name == input.name && s_circuit.displayed_name == input.displayed_name && s_circuit != input)
|
||||
i++
|
||||
var/disp_name= "[input.displayed_name] \[[input]\]"
|
||||
if(i)
|
||||
disp_name += " ([i+1])"
|
||||
input_selection.Add(disp_name)
|
||||
//Associative lists prevent me from needing another list and using a Find proc
|
||||
input_selection[disp_name] = input
|
||||
|
||||
var/obj/item/integrated_circuit/input/choice
|
||||
if(available_inputs)
|
||||
if(available_inputs.len ==1)
|
||||
choice = available_inputs[1]
|
||||
|
||||
|
||||
if(input_selection)
|
||||
if(input_selection.len ==1)
|
||||
choice = input_selection[input_selection[1]]
|
||||
else
|
||||
var/selection = input(user, "What do you want to interact with?", "Interaction") as null|anything in input_selection
|
||||
if(!check_interactivity(user))
|
||||
return
|
||||
if(selection)
|
||||
var/index = input_selection.Find(selection)
|
||||
choice = available_inputs[index]
|
||||
choice = input_selection[selection]
|
||||
|
||||
if(choice)
|
||||
choice.ask_for_input(user)
|
||||
@@ -609,6 +643,37 @@
|
||||
icon_state = "setup_small_pda"
|
||||
desc = "It's a case, for building small electronics with. This one resembles a PDA."
|
||||
|
||||
/obj/item/electronic_assembly/small
|
||||
name = "electronic device"
|
||||
icon_state = "setup_device"
|
||||
desc = "It's a case, for building tiny-sized electronics with."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
max_components = IC_MAX_SIZE_BASE / 2
|
||||
max_complexity = IC_COMPLEXITY_BASE / 2
|
||||
|
||||
/obj/item/electronic_assembly/small/default
|
||||
name = "type-a electronic device"
|
||||
|
||||
/obj/item/electronic_assembly/small/cylinder
|
||||
name = "type-b electronic device"
|
||||
icon_state = "setup_device_cylinder"
|
||||
desc = "It's a case, for building tiny-sized electronics with. This one has a cylindrical design."
|
||||
|
||||
/obj/item/electronic_assembly/small/scanner
|
||||
name = "type-c electronic device"
|
||||
icon_state = "setup_device_scanner"
|
||||
desc = "It's a case, for building tiny-sized electronics with. This one has a scanner-like design."
|
||||
|
||||
/obj/item/electronic_assembly/small/hook
|
||||
name = "type-d electronic device"
|
||||
icon_state = "setup_device_hook"
|
||||
desc = "It's a case, for building tiny-sized electronics with. This one looks like it has a belt clip, but it's purely decorative."
|
||||
|
||||
/obj/item/electronic_assembly/small/box
|
||||
name = "type-e electronic device"
|
||||
icon_state = "setup_device_box"
|
||||
desc = "It's a case, for building tiny-sized electronics with. This one has a boxy design."
|
||||
|
||||
/obj/item/electronic_assembly/medium
|
||||
name = "electronic mechanism"
|
||||
icon_state = "setup_medium"
|
||||
@@ -750,6 +815,14 @@
|
||||
max_components = IC_MAX_SIZE_BASE
|
||||
max_complexity = IC_COMPLEXITY_BASE
|
||||
|
||||
/obj/item/electronic_assembly/wallmount/tiny
|
||||
name = "tiny wall-mounted electronic assembly"
|
||||
icon_state = "setup_wallmount_tiny"
|
||||
desc = "It's a case, for building tiny electronics with. It has a magnetized backing to allow it to stick to walls, but you'll still need to wrench the anchoring bolts in place to keep it on."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
max_components = IC_MAX_SIZE_BASE / 2
|
||||
max_complexity = IC_COMPLEXITY_BASE / 2
|
||||
|
||||
/obj/item/electronic_assembly/wallmount/proc/mount_assembly(turf/on_wall, mob/user) //Yeah, this is admittedly just an abridged and kitbashed version of the wallframe attach procs.
|
||||
if(get_dist(on_wall,user)>1)
|
||||
return
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/data_to_write = null
|
||||
var/accepting_refs = FALSE
|
||||
var/copy_values = FALSE
|
||||
|
||||
/obj/item/integrated_electronics/debugger/attack_self(mob/user)
|
||||
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref", "null")
|
||||
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number","ref","copy","null")
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return
|
||||
|
||||
@@ -19,43 +20,63 @@
|
||||
switch(type_to_use)
|
||||
if("string")
|
||||
accepting_refs = FALSE
|
||||
copy_values = FALSE
|
||||
new_data = stripped_input(user, "Now type in a string.","[src] string writing", no_trim = TRUE)
|
||||
if(istext(new_data) && user.IsAdvancedToolUser())
|
||||
data_to_write = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to \"[new_data]\".</span>")
|
||||
if("number")
|
||||
accepting_refs = FALSE
|
||||
copy_values = FALSE
|
||||
new_data = input(user, "Now type in a number.","[src] number writing") as null|num
|
||||
if(isnum(new_data) && user.IsAdvancedToolUser())
|
||||
data_to_write = new_data
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to [new_data].</span>")
|
||||
if("ref")
|
||||
accepting_refs = TRUE
|
||||
copy_values = FALSE
|
||||
to_chat(user, "<span class='notice'>You turn \the [src]'s ref scanner on. Slide it across \
|
||||
an object for a ref of that object to save it in memory.</span>")
|
||||
if("copy")
|
||||
accepting_refs = FALSE
|
||||
copy_values = TRUE
|
||||
to_chat(user, "<span class='notice'>You turn \the [src]'s value copier on. Use it on a pin \
|
||||
to save its current value in memory.</span>")
|
||||
if("null")
|
||||
data_to_write = null
|
||||
copy_values = FALSE
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
|
||||
|
||||
/obj/item/integrated_electronics/debugger/afterattack(atom/target, mob/living/user, proximity)
|
||||
. = ..()
|
||||
if(accepting_refs && proximity)
|
||||
data_to_write = WEAKREF(target)
|
||||
visible_message("<span class='notice'>[user] slides \a [src]'s over \the [target].</span>")
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to a reference to [target.name] \[Ref\]. The ref scanner is \
|
||||
now off.</span>")
|
||||
accepting_refs = FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
|
||||
//If the pin can take data:
|
||||
if(io.io_type == DATA_CHANNEL)
|
||||
//If the debugger is set to copy, copy the data in the pin onto it
|
||||
if(copy_values)
|
||||
data_to_write = io.data
|
||||
to_chat(user, "<span class='notice'>You let the debugger copy the data.</span>")
|
||||
copy_values = FALSE
|
||||
return
|
||||
|
||||
//Else, write the data to the pin
|
||||
io.write_data_to_pin(data_to_write)
|
||||
var/data_to_show = data_to_write
|
||||
//This is only to convert a weakref into a name for better output
|
||||
if(isweakref(data_to_write))
|
||||
var/datum/weakref/w = data_to_write
|
||||
var/atom/A = w.resolve()
|
||||
data_to_show = A.name
|
||||
to_chat(user, "<span class='notice'>You write '[data_to_write ? data_to_show : "NULL"]' to the '[io]' pin of \the [io.holder].</span>")
|
||||
|
||||
//If the pin can only be pulsed
|
||||
else if(io.io_type == PULSE_CHANNEL)
|
||||
io.holder.check_then_do_work(io.ord,ignore_power = TRUE)
|
||||
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s [io].</span>")
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places.
|
||||
var/removable = TRUE // Determines if a circuit is removable from the assembly.
|
||||
var/displayed_name = ""
|
||||
var/demands_object_input = FALSE
|
||||
var/can_input_object_when_closed = FALSE
|
||||
|
||||
|
||||
/*
|
||||
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
|
||||
@@ -35,6 +38,10 @@ a creative player the means to solve many problems. Circuits are held inside an
|
||||
external_examine(user)
|
||||
. = ..()
|
||||
|
||||
// Can be called via electronic_assembly/attackby()
|
||||
/obj/item/integrated_circuit/proc/additem(var/obj/item/I, var/mob/living/user)
|
||||
attackby(I, user)
|
||||
|
||||
// This should be used when someone is examining while the case is opened.
|
||||
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
|
||||
to_chat(user, "This board has [inputs.len] input pin\s, [outputs.len] output pin\s and [activators.len] activation pin\s.")
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
/obj/item/integrated_circuit_printer/proc/print_program(mob/user)
|
||||
if(!cloning)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>[src] has finished printing its assembly!</span>")
|
||||
playsound(src, 'sound/items/poster_being_created.ogg', 50, TRUE)
|
||||
var/obj/item/electronic_assembly/assembly = SScircuit.load_electronic_assembly(get_turf(src), program)
|
||||
@@ -52,7 +53,6 @@
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You install [O] into [src]. </span>")
|
||||
upgraded = TRUE
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/disk/integrated_circuit/upgrade/clone))
|
||||
@@ -61,7 +61,6 @@
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You install [O] into [src]. Circuit cloning will now be instant. </span>")
|
||||
fast_clone = TRUE
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/electronic_assembly))
|
||||
@@ -108,11 +107,17 @@
|
||||
interact(user)
|
||||
|
||||
/obj/item/integrated_circuit_printer/interact(mob/user)
|
||||
if(!(in_range(src, user) || issilicon(user)))
|
||||
return
|
||||
|
||||
if(isnull(current_category))
|
||||
current_category = SScircuit.circuit_fabricator_recipe_list[1]
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
|
||||
//Preparing the browser
|
||||
var/datum/browser/popup = new(user, "printernew", "Integrated Circuit Printer", 800, 630) // Set up the popup browser window
|
||||
|
||||
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
|
||||
if(debug)
|
||||
HTML += "<center><h3>DEBUG PRINTER -- Infinite materials. Cloning available.</h3></center>"
|
||||
@@ -132,13 +137,13 @@
|
||||
if(!cloning)
|
||||
HTML += " <A href='?src=[REF(src)];print=load'>{Load Program}</a> "
|
||||
else
|
||||
HTML += " {Load Program}"
|
||||
HTML += " Load Program"
|
||||
if(!program)
|
||||
HTML += " {[fast_clone ? "Print" : "Begin Printing"] Assembly}"
|
||||
HTML += " [fast_clone ? "Print" : "Begin Printing"] Assembly"
|
||||
else if(cloning)
|
||||
HTML += " <A href='?src=[REF(src)];print=cancel'>{Cancel Print}</a>"
|
||||
HTML += " <A href='?src=[REF(src)];print=cancel'>Cancel Print</a>"
|
||||
else
|
||||
HTML += " <A href='?src=[REF(src)];print=print'>{[fast_clone ? "Print" : "Begin Printing"] Assembly}</a>"
|
||||
HTML += " <A href='?src=[REF(src)];print=print'>[fast_clone ? "Print" : "Begin Printing"] Assembly</a>"
|
||||
|
||||
HTML += "<br><hr>"
|
||||
HTML += "Categories:"
|
||||
@@ -159,11 +164,12 @@
|
||||
if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded)
|
||||
can_build = FALSE
|
||||
if(can_build)
|
||||
HTML += "<A href='?src=[REF(src)];build=[path]'>\[[initial(O.name)]\]</A>: [initial(O.desc)]<br>"
|
||||
HTML += "<a href='?src=[REF(src)];build=[path]'>[initial(O.name)]</a>: [initial(O.desc)]<br>"
|
||||
else
|
||||
HTML += "<s>\[[initial(O.name)]\]</s>: [initial(O.desc)]<br>"
|
||||
HTML += "<s>[initial(O.name)]</s>: [initial(O.desc)]<br>"
|
||||
|
||||
user << browse(HTML, "window=integrated_printer;size=600x500;border=1;can_resize=1;can_close=1;can_minimize=1")
|
||||
popup.set_content(HTML)
|
||||
popup.open()
|
||||
|
||||
/obj/item/integrated_circuit_printer/Topic(href, href_list)
|
||||
if(!check_interactivity(usr))
|
||||
|
||||
@@ -11,4 +11,14 @@
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/ref/display_pin_type()
|
||||
return IC_FORMAT_REF
|
||||
return IC_FORMAT_REF
|
||||
|
||||
/datum/integrated_io/ref/connect_pin(datum/integrated_io/pin)
|
||||
..(pin)
|
||||
if(istype(pin,/datum/integrated_io/selfref))
|
||||
write_data_to_pin(pin.data)
|
||||
|
||||
/datum/integrated_io/ref/disconnect_pin(datum/integrated_io/pin)
|
||||
..(pin)
|
||||
if(istype(pin,/datum/integrated_io/selfref))
|
||||
write_data_to_pin(null)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// This pin only contains its own weakref and can't be changed
|
||||
/datum/integrated_io/selfref
|
||||
name = "selfref pin"
|
||||
|
||||
/datum/integrated_io/selfref/New()
|
||||
..()
|
||||
write_data_to_pin(src)
|
||||
|
||||
/datum/integrated_io/selfref/ask_for_pin_data(mob/user) // You can't clear it, it's self reference.
|
||||
|
||||
|
||||
/datum/integrated_io/selfref/write_data_to_pin(var/new_data) // You can't write anything else but itself onto it
|
||||
if(data)
|
||||
return
|
||||
data = WEAKREF(holder)
|
||||
holder.on_data_written()
|
||||
|
||||
/datum/integrated_io/selfref/display_pin_type()
|
||||
return IC_FORMAT_REF
|
||||
|
||||
/datum/integrated_io/selfref/connect_pin(datum/integrated_io/pin)
|
||||
pin.write_data_to_pin(data)
|
||||
..(pin)
|
||||
|
||||
/datum/integrated_io/selfref/disconnect_pin(datum/integrated_io/pin)
|
||||
..(pin)
|
||||
pin.write_data_to_pin(null)
|
||||
@@ -14,17 +14,13 @@
|
||||
"on read" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/input/card_reader/old
|
||||
name = "card reader"
|
||||
spawn_flags = 0
|
||||
|
||||
/obj/item/integrated_circuit/input/card_reader/attackby_react(obj/item/I, mob/living/user, intent)
|
||||
var/obj/item/card/id/card = I.GetID()
|
||||
var/list/access = I.GetAccess()
|
||||
var/passkey = strtohex(XorEncrypt(json_encode(access), SScircuit.cipherkey))
|
||||
|
||||
if(assembly)
|
||||
assembly.access_card.access = access
|
||||
assembly.access_card.access |= access
|
||||
|
||||
if(card) // An ID card.
|
||||
set_pin_data(IC_OUTPUT, 1, card.registered_name)
|
||||
|
||||
@@ -311,3 +311,33 @@
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// -Max- //
|
||||
/obj/item/integrated_circuit/arithmetic/max
|
||||
name = "max circuit"
|
||||
desc = "This circuit sends out the highest number."
|
||||
extended_desc = "The highest number is put out. Null is ignored."
|
||||
icon_state = "addition"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/min_comparision = FALSE
|
||||
|
||||
/obj/item/integrated_circuit/arithmetic/max/do_work()
|
||||
var/result
|
||||
for(var/k in 1 to inputs.len)
|
||||
var/I = get_pin_data(IC_INPUT, k)
|
||||
if(!isnum(I))
|
||||
continue
|
||||
if(!isnum(result) || (!min_comparision && I > result) || (min_comparision && I < result))
|
||||
result = I
|
||||
if(!isnum(result))
|
||||
result = 0
|
||||
set_pin_data(IC_OUTPUT, 1, result)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
// -Min- //
|
||||
/obj/item/integrated_circuit/arithmetic/max/min
|
||||
name = "min circuit"
|
||||
desc = "This circuit sends out the smallest number."
|
||||
extended_desc = "The smallest number is put out. Null is ignored. In case no number is found, 0 is given out."
|
||||
min_comparision = TRUE
|
||||
|
||||
@@ -357,6 +357,7 @@
|
||||
/obj/item/integrated_circuit/converter/abs_to_rel_coords
|
||||
name = "abs to rel coordinate converter"
|
||||
desc = "Easily convert absolute coordinates to relative coordinates with this."
|
||||
extended_desc = "Keep in mind that both sets of input coordinates should be absolute."
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"X1" = IC_PINTYPE_NUMBER,
|
||||
@@ -385,6 +386,71 @@
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/rel_to_abs_coords
|
||||
name = "rel to abs coordinate converter"
|
||||
desc = "Convert relative coordinates to absolute coordinates with this."
|
||||
extended_desc = "Keep in mind that only one set of input coordinates should be absolute, and the other relative. \
|
||||
The output coordinates will be the absolute form of the input relative coordinates."
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"X1" = IC_PINTYPE_NUMBER,
|
||||
"Y1" = IC_PINTYPE_NUMBER,
|
||||
"X2" = IC_PINTYPE_NUMBER,
|
||||
"Y2" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
outputs = list(
|
||||
"X" = IC_PINTYPE_NUMBER,
|
||||
"Y" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("compute abs coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
|
||||
var/x1 = get_pin_data(IC_INPUT, 1)
|
||||
var/y1 = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
var/x2 = get_pin_data(IC_INPUT, 3)
|
||||
var/y2 = get_pin_data(IC_INPUT, 4)
|
||||
|
||||
if(!isnull(x1) && !isnull(y1) && !isnull(x2) && !isnull(y2))
|
||||
set_pin_data(IC_OUTPUT, 1, x1 + x2)
|
||||
set_pin_data(IC_OUTPUT, 2, y1 + y2)
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/adv_rel_to_abs_coords
|
||||
name = "advanced rel to abs coordinate converter"
|
||||
desc = "Easily convert relative coordinates to absolute coordinates with this."
|
||||
extended_desc = "This circuit only requires a single set of relative inputs to output absolute coordinates."
|
||||
complexity = 2
|
||||
inputs = list(
|
||||
"X" = IC_PINTYPE_NUMBER,
|
||||
"Y" = IC_PINTYPE_NUMBER,
|
||||
)
|
||||
outputs = list(
|
||||
"X" = IC_PINTYPE_NUMBER,
|
||||
"Y" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("compute abs coordinates" = IC_PINTYPE_PULSE_IN, "on convert" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work()
|
||||
var/turf/T = get_turf(src)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
var/x1 = get_pin_data(IC_INPUT, 1)
|
||||
var/y1 = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
if(!isnull(x1) && !isnull(y1))
|
||||
set_pin_data(IC_OUTPUT, 1, T.x + x1)
|
||||
set_pin_data(IC_OUTPUT, 2, T.y + y1)
|
||||
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/hsv2hex
|
||||
name = "hsv to hexadecimal"
|
||||
desc = "This circuit can convert a HSV (Hue, Saturation, and Value) color to a Hexadecimal RGB color."
|
||||
|
||||
@@ -145,6 +145,55 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
number_of_pins = 16
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer
|
||||
name = "two pulse multiplexer"
|
||||
desc = "Pulse in pins to choose the pin value to be sent."
|
||||
extended_desc = "The input pulses are used to select which of the input pins has its data moved to the output."
|
||||
complexity = 2
|
||||
icon_state = "dmux2"
|
||||
inputs = list()
|
||||
outputs = list("output" = IC_PINTYPE_ANY)
|
||||
activators = list("on selected" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
var/number_of_pins = 2
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer/Initialize()
|
||||
for(var/i = 1 to number_of_pins)
|
||||
inputs["input [i]"] = IC_PINTYPE_ANY
|
||||
for(var/i = 1 to number_of_pins)
|
||||
activators["input [i]"] = IC_PINTYPE_PULSE_IN
|
||||
complexity = number_of_pins
|
||||
|
||||
. = ..()
|
||||
desc += " It has [number_of_pins] pulse in pins and [number_of_pins] output pins."
|
||||
extended_desc += " This pulse multiplexer has a range from 1 to [activators.len - 1]."
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer/do_work(ord)
|
||||
var/input_index = ord - 2
|
||||
|
||||
if(!isnull(input_index) && (input_index >= 0 && input_index < inputs.len))
|
||||
set_pin_data(IC_OUTPUT, 1,get_pin_data(IC_INPUT, input_index + 1))
|
||||
push_data()
|
||||
activate_pin(1)
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer/medium
|
||||
name = "four pulse multiplexer"
|
||||
icon_state = "dmux4"
|
||||
number_of_pins = 4
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer/large
|
||||
name = "eight pulse multiplexer"
|
||||
icon_state = "dmux8"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
number_of_pins = 8
|
||||
|
||||
/obj/item/integrated_circuit/transfer/pulsemultiplexer/huge
|
||||
name = "sixteen pulse multiplexer"
|
||||
icon_state = "dmux16"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
number_of_pins = 16
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wire_node
|
||||
name = "wire node"
|
||||
desc = "Just a wire node to make wiring easier. Transfers the pulse from in to out."
|
||||
@@ -156,4 +205,4 @@
|
||||
size = 0.1
|
||||
|
||||
/obj/item/integrated_circuit/transfer/wire_node/do_work()
|
||||
activate_pin(2)
|
||||
activate_pin(2)
|
||||
|
||||
@@ -162,11 +162,6 @@
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
//please delete at a later date after people stop using the old named circuit
|
||||
/obj/item/integrated_circuit/input/adv_med_scanner/old
|
||||
name = "integrated advanced medical analyser"
|
||||
spawn_flags = 0
|
||||
|
||||
/obj/item/integrated_circuit/input/slime_scanner
|
||||
name = "slime_scanner"
|
||||
desc = "A very small version of the xenobio analyser. This allows the machine to know every needed properties of slime. Output mutation list is non-associative."
|
||||
@@ -729,8 +724,7 @@
|
||||
inputs = list(
|
||||
"target NTNet addresses"= IC_PINTYPE_STRING,
|
||||
"data to send" = IC_PINTYPE_STRING,
|
||||
"secondary text" = IC_PINTYPE_STRING,
|
||||
"passkey" = IC_PINTYPE_STRING, //No this isn't a real passkey encryption scheme but that's why you keep your nodes secure so no one can find it out!
|
||||
"secondary text" = IC_PINTYPE_STRING
|
||||
)
|
||||
outputs = list(
|
||||
"address received" = IC_PINTYPE_STRING,
|
||||
@@ -756,11 +750,10 @@
|
||||
var/target_address = get_pin_data(IC_INPUT, 1)
|
||||
var/message = get_pin_data(IC_INPUT, 2)
|
||||
var/text = get_pin_data(IC_INPUT, 3)
|
||||
var/key = get_pin_data(IC_INPUT, 4)
|
||||
|
||||
var/datum/netdata/data = new
|
||||
data.recipient_ids = splittext(target_address, ";")
|
||||
data.standard_format_data(message, text, key)
|
||||
data.standard_format_data(message, text, assembly ? strtohex(XorEncrypt(json_encode(assembly.access_card.access), SScircuit.cipherkey)) : null)
|
||||
ntnet_send(data)
|
||||
|
||||
/obj/item/integrated_circuit/input/ntnet_receive(datum/netdata/data)
|
||||
@@ -777,9 +770,9 @@
|
||||
name = "Low level NTNet transreceiver"
|
||||
desc = "Enables the sending and receiving of messages over NTNet via packet data protocol. Allows advanced control of message contents and signalling. Must use associative lists. Outputs associative list. Has a slower transmission rate than normal NTNet circuits, due to increased data processing complexity."
|
||||
extended_desc = "Data can be sent or received using the second pin on each side, \
|
||||
with additonal data reserved for the third pin. When a message is received, the second activation pin \
|
||||
will pulse whatever is connected to it. Pulsing the first activation pin will send a message. Messages \
|
||||
can be sent to multiple recepients. Addresses must be separated with a semicolon, like this: Address1;Address2;Etc."
|
||||
When a message is received, the second activation pin will pulse whatever is connected to it. \
|
||||
Pulsing the first activation pin will send a message. Messages can be sent to multiple recepients. \
|
||||
Addresses must be separated with a semicolon, like this: Address1;Address2;Etc."
|
||||
icon_state = "signal"
|
||||
complexity = 4
|
||||
cooldown_per_use = 10
|
||||
@@ -809,6 +802,7 @@
|
||||
var/datum/netdata/data = new
|
||||
data.recipient_ids = splittext(target_address, ";")
|
||||
data.data = message
|
||||
data.passkey = assembly.access_card.access
|
||||
ntnet_send(data)
|
||||
|
||||
/obj/item/integrated_circuit/input/ntnet_advanced/ntnet_receive(datum/netdata/data)
|
||||
@@ -821,11 +815,11 @@
|
||||
/obj/item/integrated_circuit/input/gps
|
||||
name = "global positioning system"
|
||||
desc = "This allows you to easily know the position of a machine containing this device."
|
||||
extended_desc = "The coordinates that the GPS outputs are absolute, not relative."
|
||||
extended_desc = "The coordinates that the GPS outputs are absolute, not relative. The full coords output has the coords separated by commas and is in string format."
|
||||
icon_state = "gps"
|
||||
complexity = 4
|
||||
inputs = list()
|
||||
outputs = list("X"= IC_PINTYPE_NUMBER, "Y" = IC_PINTYPE_NUMBER, "Z" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("X"= IC_PINTYPE_NUMBER, "Y" = IC_PINTYPE_NUMBER, "Z" = IC_PINTYPE_NUMBER, "full coords" = IC_PINTYPE_STRING)
|
||||
activators = list("get coordinates" = IC_PINTYPE_PULSE_IN, "on get coordinates" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 30
|
||||
@@ -836,13 +830,14 @@
|
||||
set_pin_data(IC_OUTPUT, 1, null)
|
||||
set_pin_data(IC_OUTPUT, 2, null)
|
||||
set_pin_data(IC_OUTPUT, 3, null)
|
||||
set_pin_data(IC_OUTPUT, 4, null)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, T.x)
|
||||
set_pin_data(IC_OUTPUT, 2, T.y)
|
||||
set_pin_data(IC_OUTPUT, 3, T.z)
|
||||
|
||||
set_pin_data(IC_OUTPUT, 4, "[T.x],[T.y],[T.z]")
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
return A.data > B.data
|
||||
|
||||
/obj/item/integrated_circuit/logic/binary/greater_than_or_equal
|
||||
name = "greater_than or equal gate"
|
||||
name = "greater than or equal gate"
|
||||
desc = "This will output TRUE if the first input is greater than, or equal to the second input."
|
||||
icon_state = "greater_than_or_equal"
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
@@ -34,11 +34,13 @@
|
||||
var/lethal_projectile = null //lethal mode projectile type
|
||||
var/lethal_projectile_sound
|
||||
|
||||
demands_object_input = TRUE // You can put stuff in once the circuit is in assembly,passed down from additem and handled by attackby()
|
||||
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/Destroy()
|
||||
qdel(installed_gun)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/weapon_firing/attackby(var/obj/O, var/mob/user)
|
||||
if(istype(O, /obj/item/gun/energy))
|
||||
@@ -129,6 +131,7 @@
|
||||
//Shooting Code:
|
||||
A.preparePixelProjectile(target, src)
|
||||
A.fire()
|
||||
log_attack("[assembly] [REF(assembly)] has fired [installed_gun].")
|
||||
return A
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/locomotion
|
||||
@@ -184,6 +187,7 @@
|
||||
action_flags = IC_ACTION_COMBAT
|
||||
var/obj/item/grenade/attached_grenade
|
||||
var/pre_attached_grenade_type
|
||||
demands_object_input = TRUE // You can put stuff in once the circuit is in assembly,passed down from additem and handled by attackby()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grenade/Initialize()
|
||||
. = ..()
|
||||
@@ -350,7 +354,7 @@
|
||||
name = "grabber"
|
||||
desc = "A circuit with its own inventory for items. Used to grab and store things."
|
||||
icon_state = "grabber"
|
||||
extended_desc = "This circuit accepts a reference to an object to be grabbed, and can store up to 10 objects. Modes: 1 to grab, 0 to eject the first object, and -1 to eject all objects. If you throw something from a grabber's inventory with a thrower, the grabber will update its outputs accordingly."
|
||||
extended_desc = "This circuit accepts a reference to an object to be grabbed, and can store up to 10 objects. Modes: 1 to grab, 0 to eject the first object, -1 to eject all objects, and -2 to eject the target. If you throw something from a grabber's inventory with a thrower, the grabber will update its outputs accordingly."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
size = 3
|
||||
cooldown_per_use = 5
|
||||
@@ -359,37 +363,47 @@
|
||||
outputs = list("first" = IC_PINTYPE_REF, "last" = IC_PINTYPE_REF, "amount" = IC_PINTYPE_NUMBER,"contents" = IC_PINTYPE_LIST)
|
||||
activators = list("pulse in" = IC_PINTYPE_PULSE_IN,"pulse out" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
action_flags = IC_ACTION_COMBAT
|
||||
power_draw_per_use = 50
|
||||
var/max_items = 10
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/do_work()
|
||||
var/max_w_class = assembly.w_class
|
||||
var/atom/movable/acting_object = get_object()
|
||||
var/turf/T = get_turf(acting_object)
|
||||
var/obj/item/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
|
||||
if(!QDELETED(AM) && !istype(AM, /obj/item/electronic_assembly) && !istype(AM, /obj/item/transfer_valve) && !istype(AM, /obj/item/twohanded) && !istype(assembly.loc, /obj/item/implant/storage))
|
||||
var/mode = get_pin_data(IC_INPUT, 2)
|
||||
if(mode == 1)
|
||||
if(check_target(AM))
|
||||
var/weightcheck = FALSE
|
||||
if (AM.w_class <= max_w_class)
|
||||
weightcheck = TRUE
|
||||
else
|
||||
weightcheck = FALSE
|
||||
if((contents.len < max_items) && (weightcheck))
|
||||
AM.forceMove(src)
|
||||
if(mode == 0)
|
||||
if(contents.len)
|
||||
var/obj/item/U = contents[1]
|
||||
U.forceMove(T)
|
||||
if(mode == -1)
|
||||
if(contents.len)
|
||||
var/obj/item/U
|
||||
for(U in contents)
|
||||
U.forceMove(T)
|
||||
switch(mode)
|
||||
if(1)
|
||||
grab(AM)
|
||||
if(0)
|
||||
if(contents.len)
|
||||
drop(contents[1])
|
||||
if(-1)
|
||||
drop_all()
|
||||
if(-2)
|
||||
drop(AM)
|
||||
update_outputs()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/proc/grab(obj/item/AM)
|
||||
var/max_w_class = assembly.w_class
|
||||
if(check_target(AM))
|
||||
if(contents.len < max_items && AM.w_class <= max_w_class)
|
||||
var/atom/A = get_object()
|
||||
A.investigate_log("picked up ([AM]) with [src].", INVESTIGATE_CIRCUIT)
|
||||
AM.forceMove(src)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/proc/drop(obj/item/AM, turf/T = drop_location())
|
||||
var/atom/A = get_object()
|
||||
A.investigate_log("dropped ([AM]) from [src].", INVESTIGATE_CIRCUIT)
|
||||
AM.forceMove(T)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/proc/drop_all()
|
||||
if(contents.len)
|
||||
var/turf/T = drop_location()
|
||||
var/obj/item/U
|
||||
for(U in src)
|
||||
drop(U, T)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/proc/update_outputs()
|
||||
if(contents.len)
|
||||
set_pin_data(IC_OUTPUT, 1, WEAKREF(contents[1]))
|
||||
@@ -402,11 +416,7 @@
|
||||
push_data()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/grabber/attack_self(var/mob/user)
|
||||
if(contents.len)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/item/U
|
||||
for(U in contents)
|
||||
U.forceMove(T)
|
||||
drop_all()
|
||||
update_outputs()
|
||||
push_data()
|
||||
|
||||
@@ -436,6 +446,7 @@
|
||||
mode = CLAMP(mode, GRAB_PASSIVE, max_grab)
|
||||
if(AM)
|
||||
if(check_target(AM, exclude_contents = TRUE))
|
||||
acting_object.investigate_log("grabbed ([AM]) using [src].", INVESTIGATE_CIRCUIT)
|
||||
acting_object.start_pulling(AM,mode)
|
||||
if(acting_object.pulling)
|
||||
set_pin_data(IC_OUTPUT, 1, TRUE)
|
||||
@@ -528,16 +539,24 @@
|
||||
var/x_abs = CLAMP(T.x + target_x_rel, 0, world.maxx)
|
||||
var/y_abs = CLAMP(T.y + target_y_rel, 0, world.maxy)
|
||||
var/range = round(CLAMP(sqrt(target_x_rel*target_x_rel+target_y_rel*target_y_rel),0,8),1)
|
||||
|
||||
//remove damage
|
||||
A.throwforce = 0
|
||||
A.embedding = list("embed_chance" = 0)
|
||||
//throw it
|
||||
assembly.visible_message("<span class='danger'>[assembly] has thrown [A]!</span>")
|
||||
log_attack("[assembly] [REF(assembly)] has thrown [A].")
|
||||
A.forceMove(drop_location())
|
||||
A.throw_at(locate(x_abs, y_abs, T.z), range, 3)
|
||||
A.throw_at(locate(x_abs, y_abs, T.z), range, 3, , , , CALLBACK(src, .proc/post_throw, A))
|
||||
|
||||
// If the item came from a grabber now we can update the outputs since we've thrown it.
|
||||
if(G)
|
||||
if(istype(G))
|
||||
G.update_outputs()
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/thrower/proc/post_throw(obj/item/A)
|
||||
//return damage
|
||||
A.throwforce = initial(A.throwforce)
|
||||
A.embedding = initial(A.embedding)
|
||||
|
||||
/obj/item/integrated_circuit/manipulation/matman
|
||||
name = "material manager"
|
||||
desc = "This circuit is designed for automatic storage and distribution of materials."
|
||||
@@ -593,7 +612,7 @@
|
||||
/obj/item/integrated_circuit/manipulation/matman/Initialize()
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
|
||||
list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), 0,
|
||||
FALSE, list(/obj/item/stack), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
materials.max_amount =100000
|
||||
materials.precise_insertion = TRUE
|
||||
.=..()
|
||||
@@ -657,4 +676,4 @@
|
||||
/obj/item/integrated_circuit/manipulation/matman/Destroy()
|
||||
GET_COMPONENT(materials, /datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
.=..()
|
||||
.=..()
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
|
||||
|
||||
/obj/item/integrated_circuit/memory/constant/afterattack(atom/target, mob/living/user, proximity)
|
||||
. = ..()
|
||||
if(accepting_refs && proximity)
|
||||
var/datum/integrated_io/O = outputs[1]
|
||||
O.data = WEAKREF(target)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
category_text = "Output"
|
||||
|
||||
/obj/item/integrated_circuit/output/screen
|
||||
name = "small screen"
|
||||
name = "screen"
|
||||
extended_desc = " use <br> to start a new line"
|
||||
desc = "Takes any data type as an input, and displays it to the user upon examining."
|
||||
icon_state = "screen"
|
||||
@@ -34,14 +34,24 @@
|
||||
else
|
||||
stuff_to_display = replacetext("[I.data]", eol , "<br>")
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/medium
|
||||
name = "screen"
|
||||
desc = "Takes any data type as an input and displays it to the user upon examining, and to adjacent beings when pulsed."
|
||||
/obj/item/integrated_circuit/output/screen/large
|
||||
name = "large screen"
|
||||
desc = "Takes any data type as an input and displays it to anybody near the device when pulsed. \
|
||||
It can also be examined to see the last thing it displayed."
|
||||
icon_state = "screen_medium"
|
||||
power_draw_per_use = 20
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/medium/do_work()
|
||||
/obj/item/integrated_circuit/output/screen/large/do_work()
|
||||
..()
|
||||
|
||||
if(isliving(assembly.loc))//this whole block just returns if the assembly is neither in a mobs hands or on the ground
|
||||
var/mob/living/H = assembly.loc
|
||||
if(H.get_active_held_item() != assembly && H.get_inactive_held_item() != assembly)
|
||||
return
|
||||
else
|
||||
if(!isturf(assembly.loc))
|
||||
return
|
||||
|
||||
var/list/nearby_things = range(0, get_turf(src))
|
||||
for(var/mob/M in nearby_things)
|
||||
var/obj/O = assembly ? assembly : src
|
||||
@@ -51,22 +61,6 @@
|
||||
else
|
||||
investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT)
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/large
|
||||
name = "large screen"
|
||||
desc = "Takes any data type as an input and displays it to the user upon examining, and to all nearby beings when pulsed."
|
||||
icon_state = "screen_large"
|
||||
power_draw_per_use = 40
|
||||
cooldown_per_use = 10
|
||||
|
||||
/obj/item/integrated_circuit/output/screen/large/do_work()
|
||||
..()
|
||||
var/obj/O = assembly ? get_turf(assembly) : loc
|
||||
O.visible_message("<span class='notice'>[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]</span>")
|
||||
if(assembly)
|
||||
assembly.investigate_log("displayed \"[html_encode(stuff_to_display)]\" with [type].", INVESTIGATE_CIRCUIT)
|
||||
else
|
||||
investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT)
|
||||
|
||||
/obj/item/integrated_circuit/output/light
|
||||
name = "light"
|
||||
desc = "A basic light which can be toggled on/off when pulsed."
|
||||
@@ -88,7 +82,7 @@
|
||||
/obj/item/integrated_circuit/output/light/proc/update_lighting()
|
||||
if(light_toggled)
|
||||
if(assembly)
|
||||
assembly.set_light(l_range = light_brightness, l_power = light_brightness, l_color = light_rgb)
|
||||
assembly.set_light(l_range = light_brightness, l_power = 1, l_color = light_rgb)
|
||||
else
|
||||
if(assembly)
|
||||
assembly.set_light(0)
|
||||
@@ -118,7 +112,7 @@
|
||||
var/brightness = get_pin_data(IC_INPUT, 2)
|
||||
|
||||
if(new_color && isnum(brightness))
|
||||
brightness = CLAMP(brightness, 0, 6)
|
||||
brightness = CLAMP(brightness, 0, 4)
|
||||
light_rgb = new_color
|
||||
light_brightness = brightness
|
||||
|
||||
@@ -159,10 +153,8 @@
|
||||
return
|
||||
vol = CLAMP(vol ,0 , 100)
|
||||
playsound(get_turf(src), selected_sound, vol, freq, -1)
|
||||
if(assembly)
|
||||
assembly.investigate_log("played a sound ([selected_sound]) with [type].", INVESTIGATE_CIRCUIT)
|
||||
else
|
||||
investigate_log("played a sound ([selected_sound]) as [type].", INVESTIGATE_CIRCUIT)
|
||||
var/atom/A = get_object()
|
||||
A.investigate_log("played a sound ([selected_sound]) as [type].", INVESTIGATE_CIRCUIT)
|
||||
|
||||
/obj/item/integrated_circuit/output/sound/on_data_written()
|
||||
power_draw_per_use = get_pin_data(IC_INPUT, 2) * 15
|
||||
@@ -186,14 +178,14 @@
|
||||
name = "securitron sound circuit"
|
||||
desc = "Takes a sound name as an input, and will play said sound when pulsed. This circuit is similar to those used in Securitrons."
|
||||
sounds = list(
|
||||
"creep" = 'sound/voice/bcreep.ogg',
|
||||
"criminal" = 'sound/voice/bcriminal.ogg',
|
||||
"freeze" = 'sound/voice/bfreeze.ogg',
|
||||
"god" = 'sound/voice/bgod.ogg',
|
||||
"i am the law" = 'sound/voice/biamthelaw.ogg',
|
||||
"insult" = 'sound/voice/binsult.ogg',
|
||||
"radio" = 'sound/voice/bradio.ogg',
|
||||
"secure day" = 'sound/voice/bsecureday.ogg',
|
||||
"creep" = 'sound/voice/beepsky/creep.ogg',
|
||||
"criminal" = 'sound/voice/beepsky/criminal.ogg',
|
||||
"freeze" = 'sound/voice/beepsky/freeze.ogg',
|
||||
"god" = 'sound/voice/beepsky/god.ogg',
|
||||
"i am the law" = 'sound/voice/beepsky/iamthelaw.ogg',
|
||||
"insult" = 'sound/voice/beepsky/insult.ogg',
|
||||
"radio" = 'sound/voice/beepsky/radio.ogg',
|
||||
"secure day" = 'sound/voice/beepsky/secureday.ogg',
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
@@ -201,21 +193,21 @@
|
||||
name = "medbot sound circuit"
|
||||
desc = "Takes a sound name as an input, and will play said sound when pulsed. This circuit is often found in medical robots."
|
||||
sounds = list(
|
||||
"surgeon" = 'sound/voice/msurgeon.ogg',
|
||||
"radar" = 'sound/voice/mradar.ogg',
|
||||
"feel better" = 'sound/voice/mfeelbetter.ogg',
|
||||
"patched up" = 'sound/voice/mpatchedup.ogg',
|
||||
"injured" = 'sound/voice/minjured.ogg',
|
||||
"insult" = 'sound/voice/minsult.ogg',
|
||||
"coming" = 'sound/voice/mcoming.ogg',
|
||||
"help" = 'sound/voice/mhelp.ogg',
|
||||
"live" = 'sound/voice/mlive.ogg',
|
||||
"lost" = 'sound/voice/mlost.ogg',
|
||||
"flies" = 'sound/voice/mflies.ogg',
|
||||
"catch" = 'sound/voice/mcatch.ogg',
|
||||
"delicious" = 'sound/voice/mdelicious.ogg',
|
||||
"apple" = 'sound/voice/mapple.ogg',
|
||||
"no" = 'sound/voice/mno.ogg',
|
||||
"surgeon" = 'sound/voice/medbot/surgeon.ogg',
|
||||
"radar" = 'sound/voice/medbot/radar.ogg',
|
||||
"feel better" = 'sound/voice/medbot/feelbetter.ogg',
|
||||
"patched up" = 'sound/voice/medbot/patchedup.ogg',
|
||||
"injured" = 'sound/voice/medbot/injured.ogg',
|
||||
"insult" = 'sound/voice/medbot/insult.ogg',
|
||||
"coming" = 'sound/voice/medbot/coming.ogg',
|
||||
"help" = 'sound/voice/medbot/help.ogg',
|
||||
"live" = 'sound/voice/medbot/live.ogg',
|
||||
"lost" = 'sound/voice/medbot/lost.ogg',
|
||||
"flies" = 'sound/voice/medbot/flies.ogg',
|
||||
"catch" = 'sound/voice/medbot/catch.ogg',
|
||||
"delicious" = 'sound/voice/medbot/delicious.ogg',
|
||||
"apple" = 'sound/voice/medbot/apple.ogg',
|
||||
"no" = 'sound/voice/medbot/no.ogg',
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
|
||||
@@ -250,21 +242,22 @@
|
||||
A.say(sanitized_text)
|
||||
if (assembly)
|
||||
log_say("[assembly] [REF(assembly)] : [sanitized_text]")
|
||||
else
|
||||
else
|
||||
log_say("[name] ([type]) : [sanitized_text]")
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera
|
||||
name = "video camera circuit"
|
||||
desc = "Takes a string as a name and a boolean to determine whether it is on, and uses this to be a camera linked to the research network."
|
||||
extended_desc = "The camera is linked to the Research camera network."
|
||||
desc = "Takes a string as a name and a boolean to determine whether it is on, and uses this to be a camera linked to a list of networks you choose."
|
||||
extended_desc = "The camera is linked to a list of camera networks of your choosing. Common choices are 'rd' for the research network, 'ss13' for the main station network (visible to AI), 'mine' for the mining network, and 'thunder' for the thunderdome network (viewable from bar)."
|
||||
icon_state = "video_camera"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
complexity = 10
|
||||
inputs = list(
|
||||
"camera name" = IC_PINTYPE_STRING,
|
||||
"camera active" = IC_PINTYPE_BOOLEAN
|
||||
"camera active" = IC_PINTYPE_BOOLEAN,
|
||||
"camera network" = IC_PINTYPE_LIST
|
||||
)
|
||||
inputs_default = list("1" = "video camera circuit")
|
||||
inputs_default = list("1" = "video camera circuit", "3" = list("rd"))
|
||||
outputs = list()
|
||||
activators = list()
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
@@ -296,8 +289,11 @@
|
||||
if(camera)
|
||||
var/cam_name = get_pin_data(IC_INPUT, 1)
|
||||
var/cam_active = get_pin_data(IC_INPUT, 2)
|
||||
var/list/new_network = get_pin_data(IC_INPUT, 3)
|
||||
if(!isnull(cam_name))
|
||||
camera.c_tag = cam_name
|
||||
if(!isnull(new_network))
|
||||
camera.network = new_network
|
||||
set_camera_status(cam_active)
|
||||
|
||||
/obj/item/integrated_circuit/output/video_camera/power_fail()
|
||||
|
||||
@@ -16,59 +16,6 @@
|
||||
set_pin_data(IC_OUTPUT, 1, reagents.total_volume)
|
||||
push_data()
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke
|
||||
name = "smoke generator"
|
||||
desc = "Unlike most electronics, creating smoke is completely intentional."
|
||||
icon_state = "smoke"
|
||||
extended_desc = "This smoke generator creates clouds of smoke on command. It can also hold liquids inside, which will go \
|
||||
into the smoke clouds when activated. The reagents are consumed when the smoke is made."
|
||||
ext_cooldown = 1
|
||||
container_type = OPENCONTAINER
|
||||
volume = 100
|
||||
|
||||
complexity = 20
|
||||
cooldown_per_use = 1 SECONDS
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF
|
||||
)
|
||||
activators = list(
|
||||
"create smoke" = IC_PINTYPE_PULSE_IN,
|
||||
"on smoked" = IC_PINTYPE_PULSE_OUT,
|
||||
"push ref" = IC_PINTYPE_PULSE_IN
|
||||
)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 20
|
||||
var/smoke_radius = 5
|
||||
var/notified = FALSE
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke/on_reagent_change(changetype)
|
||||
//reset warning only if we have reagents now
|
||||
if(changetype == ADD_REAGENT)
|
||||
notified = FALSE
|
||||
push_vol()
|
||||
|
||||
/obj/item/integrated_circuit/reagent/smoke/do_work(ord)
|
||||
switch(ord)
|
||||
if(1)
|
||||
if(!reagents || (reagents.total_volume < IC_SMOKE_REAGENTS_MINIMUM_UNITS))
|
||||
return
|
||||
var/location = get_turf(src)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
S.attach(location)
|
||||
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
if(S)
|
||||
S.set_up(reagents, smoke_radius, location, notified)
|
||||
if(!notified)
|
||||
notified = TRUE
|
||||
S.start()
|
||||
reagents.clear_reagents()
|
||||
activate_pin(2)
|
||||
if(3)
|
||||
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
|
||||
push_data()
|
||||
|
||||
// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way.
|
||||
// This is a dirty hack to make injecting reagents into them work.
|
||||
// TODO: refactor that.
|
||||
@@ -118,7 +65,7 @@
|
||||
)
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list(
|
||||
"inject" = IC_PINTYPE_PULSE_IN,
|
||||
@@ -186,7 +133,7 @@
|
||||
|
||||
//Always log attemped injections for admins
|
||||
var/contained = reagents.log_list()
|
||||
add_logs(src, L, "attempted to inject", addition="which had [contained]")
|
||||
log_combat(src, L, "attempted to inject", addition="which had [contained]")
|
||||
L.visible_message("<span class='danger'>[acting_object] is trying to inject [L]!</span>", \
|
||||
"<span class='userdanger'>[acting_object] is trying to inject you!</span>")
|
||||
busy = TRUE
|
||||
@@ -194,7 +141,7 @@
|
||||
var/fraction = min(transfer_amount/reagents.total_volume, 1)
|
||||
reagents.reaction(L, INJECT, fraction)
|
||||
reagents.trans_to(L, transfer_amount)
|
||||
add_logs(src, L, "injected", addition="which had [contained]")
|
||||
log_combat(src, L, "injected", addition="which had [contained]")
|
||||
L.visible_message("<span class='danger'>[acting_object] injects [L] with its needle!</span>", \
|
||||
"<span class='userdanger'>[acting_object] injects you with its needle!</span>")
|
||||
else
|
||||
@@ -320,7 +267,7 @@
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list("push ref" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
@@ -367,7 +314,7 @@
|
||||
)
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list(
|
||||
"grind" = IC_PINTYPE_PULSE_IN,
|
||||
@@ -414,7 +361,7 @@
|
||||
)
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF
|
||||
"self reference" = IC_PINTYPE_SELFREF
|
||||
)
|
||||
activators = list(
|
||||
"juice" = IC_PINTYPE_PULSE_IN,
|
||||
@@ -459,7 +406,7 @@
|
||||
complexity = 8
|
||||
outputs = list(
|
||||
"volume used" = IC_PINTYPE_NUMBER,
|
||||
"self reference" = IC_PINTYPE_REF,
|
||||
"self reference" = IC_PINTYPE_SELFREF,
|
||||
"list of reagents" = IC_PINTYPE_LIST
|
||||
)
|
||||
activators = list(
|
||||
@@ -561,7 +508,7 @@
|
||||
"on" = IC_PINTYPE_BOOLEAN
|
||||
)
|
||||
inputs_default = list("1" = 300)
|
||||
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_REF,"temperature" = IC_PINTYPE_NUMBER)
|
||||
outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_SELFREF,"temperature" = IC_PINTYPE_NUMBER)
|
||||
spawn_flags = IC_SPAWN_RESEARCH
|
||||
var/heater_coefficient = 0.1
|
||||
|
||||
|
||||
@@ -95,12 +95,7 @@
|
||||
if(!assembly)
|
||||
activate_pin(3)
|
||||
return
|
||||
var/Ps = get_pin_data(IC_INPUT, 4)
|
||||
if(!Ps)
|
||||
return
|
||||
var/list/Pl = json_decode(XorEncrypt(hextostr(Ps, TRUE), SScircuit.cipherkey))
|
||||
if(Pl&&islist(Pl))
|
||||
idc.access = Pl
|
||||
idc.access = assembly.access_card.access
|
||||
var/turf/a_loc = get_turf(assembly)
|
||||
var/list/P = cir_get_path_to(assembly, locate(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2),a_loc.z), /turf/proc/Distance_cardinal, 0, 200, id=idc, exclude=get_turf(get_pin_data_as_type(IC_INPUT,3, /atom)), simulated_only = 0)
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/obj/item/integrated_circuit/text
|
||||
name = "text thingy"
|
||||
desc = "Does text-processing related things."
|
||||
category_text = "Text"
|
||||
complexity = 1
|
||||
|
||||
// - Text Replacer - //
|
||||
/obj/item/integrated_circuit/text/text_replacer
|
||||
name = "find-replace circuit"
|
||||
desc = "Replaces all of one bit of text with another"
|
||||
extended_desc = "Takes a string(haystack) and puts out the string while having a certain word(needle) replaced with another."
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
inputs = list(
|
||||
"haystack" = IC_PINTYPE_STRING,
|
||||
"needle" = IC_PINTYPE_STRING,
|
||||
"replacement" = IC_PINTYPE_STRING
|
||||
)
|
||||
activators = list(
|
||||
"replace" = IC_PINTYPE_PULSE_IN,
|
||||
"on replaced" = IC_PINTYPE_PULSE_OUT
|
||||
)
|
||||
outputs = list(
|
||||
"replaced string" = IC_PINTYPE_STRING
|
||||
)
|
||||
|
||||
/obj/item/integrated_circuit/text/text_replacer/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1,replacetext(get_pin_data(IC_INPUT, 1), get_pin_data(IC_INPUT, 2), get_pin_data(IC_INPUT, 3)))
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
@@ -142,25 +142,44 @@
|
||||
power_draw_per_use = 2
|
||||
|
||||
/obj/item/integrated_circuit/time/clock
|
||||
name = "integrated clock"
|
||||
desc = "Tells you what the local time is, specific to your station or planet."
|
||||
name = "integrated clock (NT Common Time)"
|
||||
desc = "Tells you what the time is, in Nanotrasen Common Time." //round time
|
||||
icon_state = "clock"
|
||||
inputs = list()
|
||||
outputs = list(
|
||||
"time" = IC_PINTYPE_STRING,
|
||||
"hours" = IC_PINTYPE_NUMBER,
|
||||
"minutes" = IC_PINTYPE_NUMBER,
|
||||
"seconds" = IC_PINTYPE_NUMBER
|
||||
"seconds" = IC_PINTYPE_NUMBER,
|
||||
"absolute decisecond elapsed time" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("get time" = IC_PINTYPE_PULSE_IN, "on time got" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
power_draw_per_use = 4
|
||||
power_draw_per_use = 2
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/proc/get_time()
|
||||
return world.time
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/do_work()
|
||||
var/wtime = world.time
|
||||
set_pin_data(IC_OUTPUT, 1, time2text(wtime, "hh:mm:ss") )
|
||||
set_pin_data(IC_OUTPUT, 2, text2num(time2text(wtime, "hh") ) )
|
||||
set_pin_data(IC_OUTPUT, 3, text2num(time2text(wtime, "mm") ) )
|
||||
set_pin_data(IC_OUTPUT, 4, text2num(time2text(wtime, "ss") ) )
|
||||
var/current_time = get_time()
|
||||
set_pin_data(IC_OUTPUT, 1, time2text(current_time, "hh:mm:ss") )
|
||||
set_pin_data(IC_OUTPUT, 2, text2num(time2text(current_time, "hh") ) )
|
||||
set_pin_data(IC_OUTPUT, 3, text2num(time2text(current_time, "mm") ) )
|
||||
set_pin_data(IC_OUTPUT, 4, text2num(time2text(current_time, "ss") ) )
|
||||
set_pin_data(IC_OUTPUT, 5, current_time)
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/station
|
||||
name = "integrated clock (Station Time)"
|
||||
desc = "Tells you what the time is, in terms and adjusted for your local station or planet"
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/station/get_time()
|
||||
return station_time()
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/bluespace
|
||||
name = "integrated clock (Bluespace Absolute Time)"
|
||||
desc = "Tells you what the time is, in Bluespace Absolute Time, unaffected by local time dilation or other phenomenon."
|
||||
|
||||
/obj/item/integrated_circuit/time/clock/bluespace/get_time()
|
||||
return REALTIMEOFDAY
|
||||
|
||||
Reference in New Issue
Block a user