[READY]integrated circuitry port+upgrade.

This commit is contained in:
arsserpentarium
2017-11-14 12:05:22 +03:00
committed by CitadelStationBot
parent 4afc4f5b39
commit d8847ea167
61 changed files with 6933 additions and 9 deletions
@@ -0,0 +1,103 @@
/obj/item/device/integrated_electronics/analyzer
name = "circuit analyzer"
desc = "This tool can scan an assembly and generate code necessary to recreate it in a circuit printer."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "analyzer"
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
var/list/circuit_list = list()
var/list/assembly_list = list(/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone)
/obj/item/device/integrated_electronics/analyzer/afterattack(var/atom/A, var/mob/living/user)
visible_message( "<span class='notice'>attempt to scan</span>")
if(ispath(A.type,/obj/item/device/electronic_assembly))
var/i = 0
var/j = 0
var/HTML ="start.assembly{{*}}" //1-st in chapters.1-st block is just to secure start of program from excess symbols.{{*}} is delimeter for chapters.
visible_message( "<span class='notice'>start of scan</span>")
for(var/ix in 1 to assembly_list.len)
var/obj/item/I = assembly_list[ix]
if( A.type == I )
HTML += initial(I.name) +"=-="+A.name //2-nd block.assembly type and name. Maybe in future there will also be color and accesories.
break
/*
If(I.name == "electronic implant")
var/obj/item/weapon/implant/integrated_circuit/PI = PA //now it can't recreate electronic implants.and devices maybe I'll fix it later.
var/obj/item/device/electronic_assembly/implant/PIC = PI.IC
A = PIC
*/
HTML += "{{*}}components" //3-rd block.components. First element is useless.delimeter for elements is ^%^.In element first circuit's default name.Second is user given name.delimiter is =-=
for(var/obj/item/integrated_circuit/IC in A.contents)
i =i + 1
HTML += "^%^"+IC.name+"=-="+IC.displayed_name
if(i == 0)
return
HTML += "{{*}}values" //4-th block.values. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second is data type.third is value.delimiter is :+:
i = 0
var/val
var/list/inp=list()
var/list/out=list()
var/list/act=list()
var/list/ioa=list()
for(var/obj/item/integrated_circuit/IC in A.contents)
i += 1
if(IC.inputs && IC.inputs.len)
for(j in 1 to IC.inputs.len)
var/datum/integrated_io/IN =IC.inputs[j]
inp[IN] = "[i]i[j]"
if(islist(IN.data))
val = list2params(IN.data)
HTML += "^%^"+"[i]i[j]:+:list:+:[val]"
else if(isnum(IN.data))
val= IN.data
HTML += "^%^"+"[i]i[j]:+:num:+:[val]"
else if(istext(IN.data))
val = IN.data
HTML += "^%^"+"[i]i[j]:+:text:+:[val]"
if(IC.outputs && IC.outputs.len)
for(j in 1 to IC.outputs.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = IC.outputs[j]
out[OUT] = "[i]o[j]"
if(IC.activators && IC.activators.len)
for(j in 1 to IC.activators.len)
var/datum/integrated_io/ACT = IC.activators[j]
act[ACT] = "[i]a[j]"
ioa.Add(inp)
ioa.Add(out)
ioa.Add(act)
HTML += "{{*}}wires"
if(inp && inp.len)
for(i in 1 to inp.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = inp[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+inp[P]+"=-="+ioa[C]
if(out && out.len)
for(i in 1 to out.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = out[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+out[P]+"=-="+ioa[C]
if(act && act.len)
for(i in 1 to act.len) //5-th block.wires. First element is useless.delimeter for elements is ^%^.In element first i/o id.Second too.delimiter is =-=
var/datum/integrated_io/P = act[i]
for(j in 1 to P.linked.len)
var/datum/integrated_io/C = P.linked[j]
HTML += "^%^"+act[P]+"=-="+ioa[C]
HTML += "{{*}}end" //6 block.like 1.
visible_message( "<span class='notice'>[A] has been scanned,</span>")
user << browse(jointext(HTML, null), "window=analyzer;size=[500]x[600];border=1;can_resize=1;can_close=1;can_minimize=1")
else
..()
@@ -0,0 +1,342 @@
#define IC_MAX_SIZE_BASE 25
#define IC_COMPLEXITY_BASE 75
/obj/item/device/electronic_assembly
name = "electronic assembly"
desc = "It's a case, for building small electronics with."
w_class = WEIGHT_CLASS_SMALL
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "setup_small"
flags_1 = NOBLUDGEON_1
var/max_components = IC_MAX_SIZE_BASE
var/max_complexity = IC_COMPLEXITY_BASE
var/opened = FALSE
var/obj/item/stock_parts/cell/battery // Internal cell which most circuits need to work.
var/cell_type = /obj/item/stock_parts/cell
var/can_charge = TRUE //Can it be charged in a recharger?
var/charge_sections = 4
var/charge_tick = FALSE
var/charge_delay = 4
var/use_cyborg_cell = TRUE
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
/obj/item/device/electronic_assembly/medium
name = "electronic mechanism"
icon_state = "setup_medium"
desc = "It's a case, for building medium-sized electronics with."
w_class = WEIGHT_CLASS_NORMAL
max_components = IC_MAX_SIZE_BASE * 2
max_complexity = IC_COMPLEXITY_BASE * 2
/obj/item/device/electronic_assembly/large
name = "electronic machine"
icon_state = "setup_large"
desc = "It's a case, for building large electronics with."
w_class = WEIGHT_CLASS_BULKY
max_components = IC_MAX_SIZE_BASE * 4
max_complexity = IC_COMPLEXITY_BASE * 4
anchored = FALSE
/obj/item/device/electronic_assembly/large/attackby(var/obj/item/O, var/mob/user)
if(default_unfasten_wrench(user, O, 20))
return
..()
/obj/item/device/electronic_assembly/large/attack_tk(mob/user)
if(anchored)
return
..()
/obj/item/device/electronic_assembly/large/attack_hand(mob/user)
if(anchored)
attack_self(user)
return
..()
/obj/item/device/electronic_assembly/drone
name = "electronic drone"
icon_state = "setup_drone"
desc = "It's a case, for building mobile electronics with."
w_class = WEIGHT_CLASS_SMALL
max_components = IC_MAX_SIZE_BASE * 3
max_complexity = IC_COMPLEXITY_BASE * 3
/obj/item/device/electronic_assembly/Initialize()
.=..()
START_PROCESSING(SScircuit, src)
/obj/item/device/electronic_assembly/Destroy()
STOP_PROCESSING(SScircuit, src)
return ..()
/obj/item/device/electronic_assembly/process()
handle_idle_power()
/obj/item/device/electronic_assembly/proc/handle_idle_power()
// First we generate power.
for(var/obj/item/integrated_circuit/passive/power/P in contents)
P.make_energy()
// Now spend it.
for(var/obj/item/integrated_circuit/IC in contents)
if(IC.power_draw_idle)
if(!draw_power(IC.power_draw_idle))
IC.power_fail()
/obj/item/device/electronic_assembly/interact(mob/user)
if(!check_interactivity(user))
return
var/total_part_size = return_total_size()
var/total_complexity = return_total_complexity()
var/HTML = list()
HTML += "<html><head><title>[name]</title></head><body>"
HTML += "<br><a href='?src=[REF(src)]'>\[Refresh\]</a> | "
HTML += "<a href='?src=[REF(src)];rename=1'>\[Rename\]</a><br>"
HTML += "[total_part_size]/[max_components] ([round((total_part_size / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=[REF(src)];remove_cell=1'>\[Remove\]</a>"
else
HTML += "<span class='danger'>No powercell detected!</span>"
HTML += "<br><br>"
HTML += "Components:<hr>"
HTML += "Built in:<br>"
//Put removable circuits in separate categories from non-removable
for(var/obj/item/integrated_circuit/circuit in contents)
if(!circuit.removable)
HTML += "<a href=?src=[REF(circuit)];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=[REF(circuit)];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=[REF(circuit)];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=[REF(circuit)];bottom=[REF(circuit)];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
HTML += "<hr>"
HTML += "Removable:<br>"
for(var/obj/item/integrated_circuit/circuit in contents)
if(circuit.removable)
HTML += "<a href=?src=[REF(circuit)];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=[REF(circuit)];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=[REF(circuit)];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=[REF(circuit)];remove=1;from_assembly=1>\[Remove\]</a> | "
HTML += "<a href=?src=[REF(circuit)];bottom=[REF(circuit)];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
HTML += "</body></html>"
user << browse(jointext(HTML,null), "window=assembly-\[REF(src)];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/electronic_assembly/Topic(href, href_list[])
if(..())
return 1
if(href_list["rename"])
rename(usr)
if(href_list["remove_cell"])
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
else
var/turf/T = get_turf(src)
battery.forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supplier.</span>")
battery = null
interact(usr) // To refresh the UI.
/obj/item/device/electronic_assembly/proc/rename()
var/mob/M = usr
if(!check_interactivity(M))
return
var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text,1)
if(!check_interactivity(M))
return
if(src && input)
to_chat(M, "<span class='notice'>The machine now has a label reading '[input]'.</span>")
name = input
/obj/item/device/electronic_assembly/proc/can_move()
return FALSE
/obj/item/device/electronic_assembly/drone/can_move()
return TRUE
/obj/item/device/electronic_assembly/update_icon()
if(opened)
icon_state = initial(icon_state) + "-open"
else
icon_state = initial(icon_state)
/obj/item/device/electronic_assembly/examine(mob/user)
..()
for(var/obj/item/integrated_circuit/IC in contents)
IC.external_examine(user)
if(istype(IC,/obj/item/integrated_circuit/output/screen))
var/obj/item/integrated_circuit/output/screen/S
if(S.stuff_to_display)
to_chat(user, "There's a little screen labeled '[S]', which displays '[S.stuff_to_display]'.")
if(opened)
interact(user)
/obj/item/device/electronic_assembly/proc/return_total_complexity()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.complexity
/obj/item/device/electronic_assembly/proc/return_total_size()
. = 0
for(var/obj/item/integrated_circuit/part in contents)
. += part.size
// Returns true if the circuit made it inside.
/obj/item/device/electronic_assembly/proc/add_circuit(var/obj/item/integrated_circuit/IC, var/mob/user)
if(!opened)
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(IC.w_class > w_class)
to_chat(user, "<span class='warning'>\The [IC] is way too big to fit into \the [src].</span>")
return FALSE
var/total_part_size = return_total_size()
var/total_complexity = return_total_complexity()
if((total_part_size + IC.size) > max_components)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC]', as there's insufficient space.</span>")
return FALSE
if((total_complexity + IC.complexity) > max_complexity)
to_chat(user, "<span class='warning'>You can't seem to add the '[IC]', since this setup's too complicated for the case.</span>")
return FALSE
if(!user.transferItemToLoc(IC, src))
return FALSE
IC.assembly = src
return TRUE
/obj/item/device/electronic_assembly/afterattack(atom/target, mob/user, proximity)
for(var/obj/item/integrated_circuit/input/sensor/S in contents)
if(!proximity)
if(istype(S,/obj/item/integrated_circuit/input/sensor/ranged)||(!user))
if(user.client)
if(!(target in view(user.client)))
continue
else
if(!(target in view(user)))
continue
else
continue
S.set_pin_data(IC_OUTPUT, 1, WEAKREF(target))
S.check_then_do_work()
S.scan(target)
visible_message("<span class='notice'> [user] waves [src] around [target].</span>")
/obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/integrated_circuit))
if(!user.canUnEquip(I))
return FALSE
if(add_circuit(I, user))
to_chat(user, "<span class='notice'>You slide [I] inside [src].</span>")
playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
return TRUE
else if(istype(I, /obj/item/crowbar))
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
opened = !opened
to_chat(user, "<span class='notice'>You [opened ? "opened" : "closed"] [src].</span>")
update_icon()
return TRUE
else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || istype(I, /obj/item/screwdriver))
if(opened)
interact(user)
else
to_chat(user, "<span class='warning'> [src] isn't opened, so you can't fiddle with the internal components. \
Try using a crowbar.</span>")
else if(istype(I, /obj/item/stock_parts/cell))
if(!opened)
to_chat(user, "<span class='warning'> [src] isn't opened, so you can't put anything inside. Try using a crowbar.</span>")
return FALSE
if(battery)
to_chat(user, "<span class='warning'> [src] already has \a [battery] inside. Remove it first if you want to replace it.</span>")
return FALSE
var/obj/item/stock_parts/cell = I
user.transferItemToLoc(I, loc)
cell.forceMove(src)
battery = cell
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)
return TRUE
else
return ..()
/obj/item/device/electronic_assembly/attack_self(mob/user)
if(!check_interactivity(user))
return
if(opened)
interact(user)
var/list/input_selection = list()
var/list/available_inputs = list()
for(var/obj/item/integrated_circuit/input/input in contents)
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)
i++
var/disp_name= "[input.displayed_name] \[[input]\]"
if(i)
disp_name += " ([i+1])"
input_selection.Add(disp_name)
var/obj/item/integrated_circuit/input/choice
if(available_inputs)
if(available_inputs.len ==1)
choice = available_inputs[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]
if(choice)
choice.ask_for_input(user)
/obj/item/device/electronic_assembly/emp_act(severity)
..()
for(var/i in 1 to contents.len)
var/atom/movable/AM = contents[i]
AM.emp_act(severity)
// Returns true if power was successfully drawn.
/obj/item/device/electronic_assembly/proc/draw_power(amount)
if(battery && battery.use(amount * GLOB.CELLRATE))
return TRUE
return FALSE
// Ditto for giving.
/obj/item/device/electronic_assembly/proc/give_power(amount)
if(battery && battery.give(amount * GLOB.CELLRATE))
return TRUE
return FALSE
/obj/item/device/electronic_assembly/Moved(oldLoc, dir)
for(var/obj/item/integrated_circuit/IC in contents)
IC.ext_moved(oldLoc, dir)
@@ -0,0 +1,64 @@
/obj/item/device/integrated_electronics/debugger
name = "circuit debugger"
desc = "This small tool allows one working with custom machinery to directly set data to a specific pin, useful for writing \
settings to specific circuits, or for debugging purposes. It can also pulse activation pins."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "debugger"
flags_1 = CONDUCT_1 | NOBLUDGEON_1
w_class = WEIGHT_CLASS_SMALL
var/data_to_write = null
var/accepting_refs = FALSE
/obj/item/device/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")
if(!user.IsAdvancedToolUser())
return
var/new_data = null
switch(type_to_use)
if("string")
accepting_refs = FALSE
new_data = input("Now type in a string.","[src] string writing") as null|text
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
new_data = input("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
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("null")
data_to_write = null
to_chat(user, "<span class='notice'>You set \the [src]'s memory to absolutely nothing.</span>")
/obj/item/device/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/device/integrated_electronics/debugger/proc/write_data(var/datum/integrated_io/io, mob/user)
if(io.io_type == DATA_CHANNEL)
io.write_data_to_pin(data_to_write)
var/data_to_show = data_to_write
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>")
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [io.holder]'s [io].</span>")
io.holder.interact(user) // This is to update the UI.
@@ -0,0 +1,136 @@
/obj/item/integrated_circuit/proc/setup_io(var/list/io_list, var/io_type, var/list/io_default_list)
var/list/io_list_copy = io_list.Copy()
io_list.Cut()
for(var/i in 1 to io_list_copy.len)
var/io_entry = io_list_copy[i]
var/default_data = null
var/io_type_override = null
// Override the default data.
if(io_default_list && io_default_list.len) // List containing special pin types that need to be added.
default_data = io_default_list["[i]"] // This is deliberately text because the index is a number in text form.
// Override the pin type.
if(io_list_copy[io_entry])
io_type_override = io_list_copy[io_entry]
if(io_type_override)
// world << "io_type_override is now [io_type_override] on [src]."
io_list.Add(new io_type_override(src, io_entry, default_data))
else
io_list.Add(new io_type(src, io_entry, default_data))
/obj/item/integrated_circuit/proc/set_pin_data(var/pin_type, var/pin_number, datum/new_data)
if (istype(new_data) && !isweakref(new_data))
new_data = WEAKREF(new_data)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.write_data_to_pin(new_data)
/obj/item/integrated_circuit/proc/get_pin_data(var/pin_type, var/pin_number)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.get_data()
/obj/item/integrated_circuit/proc/get_pin_data_as_type(var/pin_type, var/pin_number, var/as_type)
var/datum/integrated_io/pin = get_pin_ref(pin_type, pin_number)
return pin.data_as_type(as_type)
/obj/item/integrated_circuit/proc/activate_pin(var/pin_number)
var/datum/integrated_io/activate/A = activators[pin_number]
A.push_data()
/datum/integrated_io/proc/get_data()
if(isweakref(data))
return data.resolve()
return data
/obj/item/integrated_circuit/proc/get_pin_ref(var/pin_type, var/pin_number)
switch(pin_type)
if(IC_INPUT)
if(pin_number > inputs.len)
return
return inputs[pin_number]
if(IC_OUTPUT)
if(pin_number > outputs.len)
return
return outputs[pin_number]
if(IC_ACTIVATOR)
if(pin_number > activators.len)
return
return activators[pin_number]
return
/obj/item/integrated_circuit/proc/handle_wire(var/datum/integrated_io/pin, var/obj/item/device/integrated_electronics/tool)
if(istype(tool, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = tool
if(pin)
wirer.wire(pin, usr)
return TRUE
else if(istype(tool, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = tool
if(pin)
debugger.write_data(pin, usr)
return TRUE
return FALSE
/obj/item/integrated_circuit/proc/asc2b64(var/S)
var/static/list/b64 = list(
"A"=0,"B"=1,"C"=2,"D"=3,
"E"=4,"F"=5,"G"=6,"H"=7,
"I"=8,"J"=9,"K"=10,"L"=11,
"M"=12,"N"=13,"O"=14,"P"=15,
"Q"=16,"R"=17,"S"=18,"T"=19,
"U"=20,"V"=21,"W"=22,"X"=23,
"Y"=24,"Z"=25,"a"=26,"b"=27,
"c"=28,"d"=29,"e"=30,"f"=31,
"g"=32,"h"=33,"i"=34,"j"=35,
"k"=36,"l"=37,"m"=38,"n"=39,
"o"=40,"p"=41,"q"=42,"r"=43,
"s"=44,"t"=45,"u"=46,"v"=47,
"w"=48,"x"=49,"y"=50,"z"=51,
"0"=52,"1"=53,"2"=54,"3"=55,
"4"=56,"5"=57,"6"=58,"7"=59,
"8"=60,"9"=61,","=62,"."=63
)
var/ls = lentext(S)
var/c
var/i=1
while(i <= ls)
var/sb1=text2ascii(S,i)
var/sb2=text2ascii(S,i+1)
var/sb3=text2ascii(S,i+2)
var/cb1 = (sb1 & 252)>>2
var/cb2 = ((sb1 & 3)<<6 | (sb2 & 240)>>2)>>2
var/cb3 = (sb2 & 15)<<2 | (sb3 & 192)>>6
var/cb4 = (sb3 & 63)
c=c+b64[cb1+1]+b64[cb2+1]+b64[cb3+1]+b64[cb4+1]
i=i+3
return c
/obj/item/integrated_circuit/proc/b642asc(var/S)
var/static/list/b64 = list("A"=1,"B"=2,"C"=3,"D"=4,"E"=5,"F"=6,"G"=7,"H"=8,"I"=9,"J"=10,"K"=11,"L"=12,"M"=13,"N"=14,"O"=15,"P"=16,"Q"=17,"R"=18,
"S"=19,"T"=20,"U"=21,"V"=22,"W"=23,"X"=24,"Y"=25,"Z"=26,"a"=27,"b"=28,"c"=29,"d"=30,"e"=31,"f"=32,"g"=33,"h"=34,"i"=35,"j"=36,"k"=37,"l"=38,"m"=39,"n"=40,"o"=41,
"p"=42,"q"=43,"r"=44,"s"=45,"t"=46,"u"=47,"v"=48,"w"=49,"x"=50,"y"=51,"z"=52,"0"=53,"1"=54,"2"=55,"3"=56,"4"=57,"5"=58,"6"=59,"7"=60,"8"=61,"9"=62,","=63,"."=64)
var/ls = lentext(S)
var/c
var/i=1
while(i<=ls)
var/cb1=b64[copytext(S,i,i+1)]-1
var/cb2=b64[copytext(S,i+1,i+2)]-1
var/cb3=b64[copytext(S,i+2,i+3)]-1
var/cb4=b64[copytext(S,i+3,i+4)]-1
var/sb1=cb1<<2 | (cb2 & 48)>>4
var/sb2=(cb2 & 15) <<4 | (cb3 & 60)>>2
var/sb3=(cb3 & 3)<<6 | cb4
c=c+ascii2text(sb1)+ascii2text(sb2)+ascii2text(sb3)
i=i+4
return c
/proc/XorEncrypt(string,key)
if(!string || !key ||!istext(string)||!istext(key))
return
var/r
for(var/i = 1 to length(string))
r += ascii2text(text2ascii(string,i) ^ text2ascii(key,(i-1)%length(string)+1))
return r
@@ -0,0 +1,437 @@
/obj/item/integrated_circuit
name = "integrated circuit"
desc = "It's a tiny chip! This one doesn't seem to do much, however."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "template"
w_class = WEIGHT_CLASS_TINY
var/obj/item/device/electronic_assembly/assembly // Reference to the assembly holding this circuit, if any.
var/extended_desc
var/list/inputs = list()
var/list/inputs_default = list()// Assoc list which will fill a pin with data upon creation. e.g. "2" = 0 will set input pin 2 to equal 0 instead of null.
var/list/outputs = list()
var/list/outputs_default =list()// Ditto, for output.
var/list/activators = list()
var/next_use = 0 // Uses world.time
var/complexity = 1 // This acts as a limitation on building machines, more resource-intensive components cost more 'space'.
var/size = 1 // This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0
var/cooldown_per_use = 9 // Circuits are limited in how many times they can be work()'d by this variable.
var/power_draw_per_use = 0 // How much power is drawn when work()'d.
var/power_draw_idle = 0 // How much power is drawn when doing nothing.
var/spawn_flags // Used for world initializing, see the #defines above.
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/allow_multitool = TRUE // Allows additional multitool functionality
// Used as a global var, (Do not set manually in children).
/*
Integrated circuits are essentially modular machines. Each circuit has a specific function, and combining them inside Electronic Assemblies allows
a creative player the means to solve many problems. Circuits are held inside an electronic assembly, and are wired using special tools.
*/
/obj/item/integrated_circuit/examine(mob/user)
interact(user)
external_examine(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.")
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
if(I.linked.len)
to_chat(user, "The '[I]' is connected to [I.get_linked_to_desc()].")
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
if(O.linked.len)
to_chat(user, "The '[O]' is connected to [O.get_linked_to_desc()].")
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
if(A.linked.len)
to_chat(user, "The '[A]' is connected to [A.get_linked_to_desc()].")
any_examine(user)
interact(user)
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
/obj/item/integrated_circuit/proc/external_examine(mob/user)
any_examine(user)
/obj/item/integrated_circuit/proc/any_examine(mob/user)
return
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
else
return user.canUseTopic(src,be_close = TRUE)
/obj/item/integrated_circuit/Initialize()
displayed_name = name
setup_io(inputs, /datum/integrated_io, inputs_default)
setup_io(outputs, /datum/integrated_io, outputs_default)
setup_io(activators, /datum/integrated_io/activate)
..()
/obj/item/integrated_circuit/proc/on_data_written() //Override this for special behaviour when new data gets pushed to the circuit.
return
/obj/item/integrated_circuit/Destroy()
QDEL_LIST(inputs)
QDEL_LIST(outputs)
QDEL_LIST(activators)
. = ..()
/*
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = loc
return assembly.resolve_nano_host()
return ..()
*/
/obj/item/integrated_circuit/emp_act(severity)
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.scramble()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.scramble()
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
A.scramble()
/obj/item/integrated_circuit/verb/rename_component()
set name = "Rename Circuit"
set category = "Object"
set desc = "Rename your circuit, useful to stay organized."
var/mob/M = usr
if(!check_interactivity(M))
return
var/input = reject_bad_name(input("What do you want to name this?", "Rename", src.name) as null|text,1)
if(src && input && check_interactivity(M))
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
displayed_name = input
/obj/item/integrated_circuit/interact(mob/user)
if(!check_interactivity(user))
return
// if(!assembly)
// return
var/window_height = 350
var/window_width = 600
//var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px"
//var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px"
var/table_edge_width = "30%"
var/table_middle_width = "40%"
var/HTML = list()
HTML += "<html><head><title>[src.displayed_name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
HTML += "<br><a href='?src=[REF(src)];return=1'>\[Return to Assembly\]</a>"
HTML += "<br><a href='?src=[REF(src)];'>\[Refresh\]</a> | "
HTML += "<a href='?src=[REF(src)];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=[REF(src)];scan=1'>\[Scan with Device\]</a> | "
if(src.removable)
HTML += "<a href='?src=[REF(src)];remove=1'>\[Remove\]</a><br>"
HTML += "<colgroup>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]>[io.display_pin_type()] [io.name]</a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]>[linked]</a> \
@ <a href=?src=[REF(linked.holder)];examine=1;>[linked.holder.displayed_name]</a><br>"
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]>[io.display_pin_type()] [io.name]</a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]>[linked]</a> \
@ <a href=?src=[REF(linked.holder)];examine=1;>[linked.holder.displayed_name]</a><br>"
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
words += "<b><a href=?src=[REF(src)];pin_name=1;pin=[REF(io)]><font color='FF0000'>[io]</font></a> <a href=?src=[REF(src)];pin_data=1;pin=[REF(io)]><font color='FF0000'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</font></a></b><br>"
if(io.linked.len)
for(var/k in 1 to io.linked.len)
var/datum/integrated_io/linked = io.linked[k]
// words += "<a href=?src=[REF(linked.holder)];pin_name=1;pin=[REF(linked)];link=[REF(io)]>\[[linked]\]</a>
words += "<a href=?src=[REF(src)];pin_unwire=1;pin=[REF(io)];link=[REF(linked)]><font color='FF0000'>[linked]</font></a> \
@ <a href=?src=[REF(linked.holder)];examine=1;><font color='FF0000'>[linked.holder.displayed_name]</font></a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
// HTML += "<br><font color='33CC33'>Meta Variables;</font>" // If more meta vars get introduced, uncomment this.
// HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
if(power_draw_idle)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_idle] W (Idle)</font>"
if(power_draw_per_use)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_per_use] W (Active)</font>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></html>"
if(src.assembly)
user << browse(jointext(HTML, null), "window=assembly-[REF(src.assembly)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
else
user << browse(jointext(HTML, null), "window=circuit-[REF(src)];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "assembly-[REF(src.assembly)]")
/obj/item/integrated_circuit/Topic(href, href_list)
if(!check_interactivity(usr))
return
if(..())
return TRUE
var/update = TRUE
var/obj/item/device/electronic_assembly/A = src.assembly
var/update_to_assembly = FALSE
var/datum/integrated_io/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/datum/integrated_io/linked = null
if(href_list["link"])
linked = locate(href_list["link"]) in pin.linked
var/obj/held_item = usr.get_active_held_item()
if(href_list["rename"])
rename_component(usr)
if(href_list["from_assembly"])
update = FALSE
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
if(href_list["pin_name"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/obj/item/device/multitool/M = held_item
M.wire(pin,usr)
if(href_list["pin_data"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/datum/integrated_io/io = pin
io.ask_for_pin_data(usr) // The pins themselves will determine how to ask for data, and will validate the data.
/*
if(io.io_type == DATA_CHANNEL)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number", "null")
if(!check_interactivity(usr))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = input("Now type in a string.","[src] string writing") as null|text
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
//to_chat(user, "<span class='notice'>You write '[new_data]' to the '[io]' pin of \the [io.holder].</span>")
if("number")
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && check_interactivity(usr) )
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
if("null")
if(check_interactivity(usr))
to_chat(usr, "<span class='notice'>You clear the pin's memory.</span>")
io.write_data_to_pin(new_data)
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(usr, "<span class='notice'>You pulse \the [io.holder]'s [io] pin.</span>")
*/
if(href_list["pin_unwire"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = TRUE
else
var/obj/item/device/multitool/M = held_item
M.unwire(pin, linked, usr)
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(linked)
wirer.wire(linked, usr)
else if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
var/obj/item/integrated_circuit/examined
if(href_list["examined"])
examined = href_list["examined"]
else
examined = src
examined.interact(usr)
update = FALSE
if(href_list["bottom"])
var/obj/item/integrated_circuit/circuit = locate(href_list["bottom"]) in src.assembly.contents
var/assy = circuit.assembly
if(!circuit)
return
circuit.loc = null
circuit.loc = assy
. = TRUE
update_to_assembly = TRUE
if(href_list["scan"])
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
if(href_list["return"])
if(A)
update_to_assembly = TRUE
usr << browse(null, "window=circuit-[REF(src)];border=1;can_resize=1;can_close=1;can_minimize=1")
else
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
if(href_list["remove"])
if(!A)
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
return
if(!removable)
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
var/obj/item/device/electronic_assembly/ea = loc
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
if(istype(ea))
ea.interact(usr)
update = FALSE
return
if(update)
if(A && istype(A) && update_to_assembly)
A.interact(usr)
else
interact(usr) // To refresh the UI.
/obj/item/integrated_circuit/proc/push_data()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.push_data()
/obj/item/integrated_circuit/proc/pull_data()
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.push_data()
/obj/item/integrated_circuit/proc/draw_idle_power()
if(assembly)
return assembly.draw_power(power_draw_idle)
// Override this for special behaviour when there's no power left.
/obj/item/integrated_circuit/proc/power_fail()
return
// Returns true if there's enough power to work().
/obj/item/integrated_circuit/proc/check_power()
if(!assembly)
return FALSE // Not in an assembly, therefore no power.
if(assembly.draw_power(power_draw_per_use))
return TRUE // Battery has enough.
return FALSE // Not enough power.
/obj/item/integrated_circuit/proc/check_then_do_work(var/ignore_power = FALSE)
if(world.time < next_use) // All intergrated circuits have an internal cooldown, to protect from spam.
return
if(power_draw_per_use && !ignore_power)
if(!check_power())
power_fail()
return
next_use = world.time + cooldown_per_use
do_work()
/obj/item/integrated_circuit/proc/do_work()
return
/obj/item/integrated_circuit/proc/disconnect_all()
for(var/k in 1 to inputs.len)
var/datum/integrated_io/I = inputs[k]
I.disconnect()
for(var/k in 1 to outputs.len)
var/datum/integrated_io/O = outputs[k]
O.disconnect()
for(var/k in 1 to activators.len)
var/datum/integrated_io/activate/A = activators[k]
A.disconnect()
/obj/item/integrated_circuit/proc/ext_moved(oldLoc, dir)
return
@@ -0,0 +1,197 @@
/*
Pins both hold data for circuits, as well move data between them. Some also cause circuits to do their function. DATA_CHANNEL pins are the data holding/moving kind,
where as PULSE_CHANNEL causes circuits to work() when their pulse hits them.
A visualization of how pins work is below. Imagine the below image involves an addition circuit.
When the bottom pin, the activator, receives a pulse, all the numbers on the left (input) get added, and the answer goes on the right side (output).
Inputs Outputs
A [2]\ /[8] result
B [1]-\|++|/
C [4]-/|++|
D [1]/ ||
||
Activator
*/
/datum/integrated_io
var/name = "input/output"
var/obj/item/integrated_circuit/holder
var/datum/weakref/data // This is a weakref, to reduce typecasts. Note that oftentimes numbers and text may also occupy this.
var/list/linked = list()
var/io_type = DATA_CHANNEL
/datum/integrated_io/New(newloc, name1, new_data)
name = name1
if(new_data)
data = new_data
holder = newloc
if(!istype(holder))
message_admins("ERROR: An integrated_io ([name]) spawned without a valid holder! This is a bug.")
/datum/integrated_io/Destroy()
disconnect()
data = null
holder = null
return ..()
/*
/datum/integrated_io/nano_host()
return holder.nano_host()
*/
/datum/integrated_io/proc/data_as_type(var/as_type)
if(!isweakref(data))
return
var/datum/weakref/w = data
var/output = w.resolve()
return istype(output, as_type) ? output : null
/datum/integrated_io/proc/display_data(var/input)
if(isnull(input))
return "(null)" // Empty data means nothing to show.
if(istext(input))
return "(\"[input]\")" // Wraps the 'string' in escaped quotes, so that people know it's a 'string'.
/*
list[](
"A",
"B",
"C"
)
*/
if(islist(input))
var/list/my_list = input
var/result = "list\[[my_list.len]\]("
if(my_list.len)
result += "<br>"
var/pos = 0
for(var/line in my_list)
result += "[display_data(line)]"
pos++
if(pos != my_list.len)
result += ",<br>"
result += "<br>"
result += ")"
return result
if(isweakref(input))
var/datum/weakref/w = input
var/atom/A = w.resolve()
return A ? "([A.name] \[Ref\])" : "(null)" // For refs, we want just the name displayed.
//return A ? "([REF(A)] \[Ref\])" : "(null)"
return "([input])" // Nothing special needed for numbers or other stuff.
/datum/integrated_io/activate/display_data()
return "(\[pulse\])"
/datum/integrated_io/proc/display_pin_type()
return IC_FORMAT_ANY
/datum/integrated_io/activate/display_pin_type()
return IC_FORMAT_PULSE
/datum/integrated_io/proc/scramble()
if(isnull(data))
return
if(isnum(data))
write_data_to_pin(rand(-10000, 10000))
if(istext(data))
write_data_to_pin("ERROR")
push_data()
/datum/integrated_io/activate/scramble()
push_data()
/datum/integrated_io/proc/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data) || istext(new_data) || isweakref(new_data))
data = new_data
holder.on_data_written()
else if(islist(new_data))
var/list/new_list = new_data
data = new_list.Copy(1,min( IC_MAX_LIST_LENGTH+1, new_list.len ))
holder.on_data_written()
/datum/integrated_io/proc/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
io.write_data_to_pin(data)
/datum/integrated_io/activate/push_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
io.holder.check_then_do_work()
/datum/integrated_io/proc/pull_data()
for(var/k in 1 to linked.len)
var/datum/integrated_io/io = linked[k]
write_data_to_pin(io.data)
/datum/integrated_io/proc/get_linked_to_desc()
if(linked.len)
return "the [english_list(linked)]"
return "nothing"
/datum/integrated_io/proc/disconnect()
//First we iterate over everything we are linked to.
if(linked && linked.len)
for(var/i in 1 to linked.len)
var/datum/integrated_io/their_io = linked[i]
//While doing that, we iterate them as well, and disconnect ourselves from them.
if(their_io.linked.len && their_io.linked)
for(var/j in 1 to their_io.linked.len)
var/datum/integrated_io/their_linked_io = their_io.linked[j]
if(their_linked_io == src)
their_io.linked.Remove(src)
else
continue
//Now that we're removed from them, we gotta remove them from us.
linked.Remove(their_io)
/datum/integrated_io/proc/ask_for_data_type(mob/user, var/default, var/list/allowed_data_types = list("string","number","null"))
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in allowed_data_types
if(!holder.check_interactivity(user))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = input("Now type in a string.","[src] string writing", istext(default) ? default : null) as null|text
if(istext(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input "+new_data+" into the pin.</span>")
return new_data
if("number")
new_data = input("Now type in a number.","[src] number writing", isnum(default) ? default : null) as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
return new_data
if("null")
if(holder.check_interactivity(user))
to_chat(user, "<span class='notice'>You clear the pin's memory.</span>")
return new_data
// Basically a null check
/datum/integrated_io/proc/is_valid()
return !isnull(data)
// This proc asks for the data to write, then writes it.
/datum/integrated_io/proc/ask_for_pin_data(mob/user)
var/new_data = ask_for_data_type(user)
write_data_to_pin(new_data)
/datum/integrated_io/activate/ask_for_pin_data(mob/user) // This just pulses the pin.
holder.check_then_do_work(ignore_power = TRUE)
to_chat(user, "<span class='notice'>You pulse \the [holder]'s [src] pin.</span>")
/datum/integrated_io/activate
name = "activation pin"
io_type = PULSE_CHANNEL
/datum/integrated_io/activate/out // All this does is just make the UI say 'out' instead of 'in'
data = 1
@@ -0,0 +1,156 @@
/obj/item/device/integrated_electronics/prefab
var/debug = FALSE
name = "prefab"
desc = "new machine in package"
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "box_template"
w_class = WEIGHT_CLASS_BULKY
var/program="blank"
var/list/as_names = list()
/obj/item/device/integrated_electronics/prefab/attack_self(var/mob/user)
if(program && program != "blank")
assemble(program)
else
return ..()
/obj/item/device/integrated_electronics/prefab/Initialize()
. = ..()
var/list/assembly_list = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone,
)
for(var/k in 1 to assembly_list.len)
var/obj/item/I = assembly_list[k]
as_names[initial(I.name)] = I
addtimer(CALLBACK(src, .proc/attack_self), 2) //IDK, why it's need dely,but otherwise it doesn't work.
/obj/item/device/integrated_electronics/prefab/proc/assemble(var/program)
var/list/all_circuits = SScircuit.all_circuits //cached lists = free performance
var/list/chap = splittext( program ,"{{*}}")
var/list/elements = list()
var/list/elements_input = list()
var/list/element = list()
var/obj/item/AS
var/PA
var/i = 0
var/list/ioa = list()
var/datum/integrated_io/IO
var/datum/integrated_io/IO2
if(debug)
visible_message( "<span class='notice'>started successful</span>")
if(chap[2] != "")
if(debug)
visible_message( "<span class='notice'>assembly</span>")
element = splittext( chap[2] ,"=-=")
PA = as_names[element[1]]
AS = new PA(null)
AS.loc = src
AS.name = element[2]
else
return //what's the point if there is no assembly?
if(chap[3] != "components") //if there is only one word,there is no components.
elements_input = splittext( chap[3] ,"^%^")
if(debug)
visible_message( "<span class='notice'>components[elements_input.len]</span>")
i = 0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem) //I don't know,why Cut or copy don't works. If somebody can fix it, it should be fixed.
if(debug)
visible_message( "<span class='notice'>components[elements.len]</span>")
if(!length(elements_input))
return
if(debug)
visible_message( "<span class='notice'>inserting components[elements.len]</span>")
var/obj/item/integrated_circuit/comp
i=0
for(var/E in elements)
i=i+1
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
var/path_to_use = all_circuits[element[1]]
comp = new path_to_use(null)
comp.loc = AS
comp.displayed_name = element[2]
comp.assembly = AS
if(comp.inputs && comp.inputs.len)
for(var/j in 1 to comp.inputs.len)
var/datum/integrated_io/IN = comp.inputs[j]
ioa["[i]i[j]"] = IN
if(debug)
visible_message( "<span class='notice'>[i]i[j]</span>")
if(comp.outputs && comp.outputs.len)
for(var/j in 1 to comp.outputs.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = comp.outputs[j]
ioa["[i]o[j]"] = OUT
if(debug)
visible_message( "<span class='notice'>[i]o[j]</span>")
if(comp.activators && comp.activators.len)
for(var/j in 1 to comp.activators.len)
var/datum/integrated_io/ACT = comp.activators[j]
ioa["[i]a[j]"] = ACT
if(debug)
visible_message( "<span class='notice'>[i]a[j]</span>")
else
return
if(!AS.contents.len)
return
if(chap[4] != "values") //if there is only one word,there is no values
elements_input = splittext( chap[4] ,"^%^")
if(debug)
visible_message( "<span class='notice'>values[elements_input.len]</span>")
i=0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>values[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting values[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,":+:")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
if(element[2]=="text")
IO.write_data_to_pin(element[3])
else if(element[2]=="num")
IO.write_data_to_pin(text2num(element[3]))
else if(element[2]=="list")
IO.write_data_to_pin(params2list(element[3]))
if(chap[5] != "wires") //if there is only one word,there is no wires
elements_input = splittext( chap[5] ,"^%^")
i=0
elements = list()
if(debug)
visible_message( "<span class='notice'>wires[elements_input.len]</span>")
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>wires[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting wires[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
IO2 = ioa[element[2]]
IO.linked |= IO2
AS.forceMove(loc)
qdel(src)
@@ -0,0 +1,413 @@
/obj/item/device/integrated_circuit_printer
name = "integrated circuit printer"
desc = "A portable(ish) machine made to print tiny modular circuitry out of metal."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "circuit_printer"
w_class = WEIGHT_CLASS_BULKY
var/metal = 0
var/init_max_metal = 100
var/max_metal = 100
var/metal_per_sheet = 10 // One sheet equals this much metal.
var/debug = FALSE
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly.
var/static/list/recipe_list //category = list(paths in category)
var/current_category = null
var/as_printing = FALSE
var/as_needs = 0
var/program ="blank"
var/obj/item/device/integrated_electronics/prefab/PR = null
/obj/item/device/integrated_circuit_printer/proc/check_interactivity(mob/user)
return user.canUseTopic(src,be_close = TRUE)
/obj/item/device/integrated_circuit_printer/upgraded
upgraded = TRUE
can_clone = TRUE
/obj/item/device/integrated_circuit_printer/Initialize()
. = ..()
if(!recipe_list)
recipe_list = SScircuit.circuit_fabricator_recipe_list
/obj/item/device/integrated_circuit_printer/attackby(var/obj/item/O, var/mob/user)
if(istype(O,/obj/item/stack/sheet/metal))
var/obj/item/stack/sheet/metal/stack = O
var/num = min((max_metal - metal) / metal_per_sheet, stack.amount)
if(num < 1)
to_chat(user, "<span class='warning'>\The [src] is too full to add more metal.</span>")
return
if(stack.use(num))
to_chat(user, "<span class='notice'>You add [num] sheet\s to \the [src].</span>")
metal += num * metal_per_sheet
if(as_printing)
if(as_needs <= metal)
PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc))
PR.program = program
metal = metal - as_needs
to_chat(user, "<span class='notice'>Assembly has been printed.</span>")
as_printing = FALSE
as_needs = 0
max_metal = init_max_metal
else
to_chat(user, "<span class='notice'>Please insert [(as_needs-metal)/10] more metal!</span>")
interact(user)
return TRUE
if(istype(O,/obj/item/integrated_circuit))
to_chat(user, "<span class='notice'>You insert the circuit into \the [src]. </span>")
user.temporarilyRemoveItemFromInventory(O)
metal = min(metal + O.w_class, max_metal)
qdel(O)
interact(user)
return TRUE
if(istype(O,/obj/item/disk/integrated_circuit/upgrade/advanced))
if(upgraded)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
upgraded = TRUE
interact(user)
return TRUE
if(istype(O,/obj/item/disk/integrated_circuit/upgrade/clone))
if(can_clone)
to_chat(user, "<span class='warning'>\The [src] already has this upgrade. </span>")
return TRUE
to_chat(user, "<span class='notice'>You install \the [O] into \the [src]. </span>")
can_clone = TRUE
interact(user)
return TRUE
return ..()
/obj/item/device/integrated_circuit_printer/attack_self(var/mob/user)
interact(user)
/obj/item/device/integrated_circuit_printer/interact(mob/user)
var/window_height = 600
var/window_width = 500
if(isnull(current_category))
current_category = recipe_list[1]
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.<br>"
HTML += "Circuits available: [upgraded ? "Advanced":"Regular"]."
HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"]."
HTML += "Crossed out circuits mean that the printer is not sufficiently upgraded to create that circuit.<br>"
HTML += "<hr>"
if(can_clone)
HTML += "Here you can load script for your assembly.<br>"
if(as_printing)
HTML += " {Load Program} "
else
HTML += " <A href='?src=[REF(src)];print=load'>{Load Program}</a> "
if(program == "blank")
HTML += " {Check Program} "
else
HTML += " <A href='?src=[REF(src)];print=check'>{Check Program}</a> "
if((program == "blank")|as_printing)
HTML += " {Print assembly} "
else
HTML += " <A href='?src=[REF(src)];print=print'>{Print assembly}</a> "
if(as_printing)
HTML += "<br> printing in process. Please insert more metal. "
HTML += "<br><hr>"
HTML += "Categories:"
for(var/category in recipe_list)
if(category != current_category)
HTML += " <a href='?src=[REF(src)];category=[category]'>\[[category]\]</a> "
else // Bold the button if it's already selected.
HTML += " <b>\[[category]\]</b> "
HTML += "<hr>"
HTML += "<center><h4>[current_category]</h4></center>"
var/list/current_list = recipe_list[current_category]
for(var/k in 1 to current_list.len)
var/obj/O = current_list[k]
var/can_build = TRUE
if(istype(O, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = current_list[k]
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=[current_list[k]]'>\[[initial(O.name)]\]</A>: [initial(O.desc)]<br>"
else
HTML += "<s>\[[initial(O.name)]\]: [initial(O.desc)]</s><br>"
user << browse(jointext(HTML, null), "window=integrated_printer;size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/integrated_circuit_printer/Topic(href, href_list)
if(!check_interactivity(usr))
return
if(..())
return TRUE
var/sc = 0
add_fingerprint(usr)
if(href_list["category"])
current_category = href_list["category"]
if(href_list["build"])
var/build_type = text2path(href_list["build"])
if(!build_type || !ispath(build_type))
return TRUE
var/cost = 1
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
else if(ispath(build_type, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = build_type
cost = initial(IC.w_class)
if(metal - cost < 0)
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
return TRUE
metal -= cost
new build_type(get_turf(loc))
if(href_list["print"])
if(!CONFIG_GET(flag/ic_printing))
to_chat(usr, "<span class='warning'>CentCom has disabled printing of custom circuitry due to recent allegations of copyright infringement.</span>")
return
switch(href_list["print"])
if("load")
program = input("Put your code there:", "loading", null, null)
if("check")
sc = sanity_check(program,usr)
if(sc == 0)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else if(sc == -1)
to_chat(usr, "<span class='warning'>Unknown circuits found. Upgrades required to process this design.</span>")
else if(sc == null)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else
to_chat(usr, "<span class='notice'>Program is correct.You'll need [sc/10] sheets of metal</span>")
if("print")
sc = sanity_check(program,usr)
if(sc == 0 || sc == null)
to_chat(usr, "<span class='warning'>Invalid program.</span>")
else if(sc == -1)
to_chat(usr, "<span class='warning'>Unknown circuits found. Upgrades required to process this design.</span>")
else
as_printing = TRUE
if(sc <= metal)
PR = new/obj/item/device/integrated_electronics/prefab(get_turf(loc))
PR.program = program
metal = metal - sc
to_chat(usr, "<span class='notice'>Assembly has been printed.</span>")
as_printing = FALSE
as_needs = 0
max_metal=init_max_metal
else
max_metal = sc + metal_per_sheet
as_needs = sc
to_chat(usr, "<span class='notice'>Please insert [(as_needs-metal)/10] more metal!</span>")
interact(usr)
// FUKKEN UPGRADE DISKS
/obj/item/disk/integrated_circuit/upgrade
name = "integrated circuit printer upgrade disk"
desc = "Install this into your integrated circuit printer to enhance it."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "upgrade_disk"
item_state = "card-id"
w_class = WEIGHT_CLASS_SMALL
origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4)
/obj/item/disk/integrated_circuit/upgrade/advanced
name = "integrated circuit printer upgrade disk - advanced designs"
desc = "Install this into your integrated circuit printer to enhance it. This one adds new, advanced designs to the printer."
// To be implemented later.
/obj/item/disk/integrated_circuit/upgrade/clone
name = "integrated circuit printer upgrade disk - circuit cloner"
desc = "Install this into your integrated circuit printer to enhance it. This one allows the printer to duplicate assemblies."
icon_state = "upgrade_disk_clone"
origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5)
/obj/item/device/integrated_circuit_printer/proc/sanity_check(var/program,var/mob/user)
var/list/chap = splittext( program ,"{{*}}")
if(chap.len != 6)
return 0 //splitting incorrect
var/list/elements = list()
var/list/elements_input = list()
var/list/element = list()
var/obj/item/PA
var/obj/item/device/electronic_assembly/PF
var/datum/integrated_io/IO
var/datum/integrated_io/IO2
var/i = 0
var/obj/item/integrated_circuit/comp
var/list/ioa = list()
var/list/as_samp = list()
var/list/all_circuits = SScircuit.all_circuits // It's free. Performance. We're giving you cpu time. It's free. We're giving you time. It's performance, free. It's free cpu time for you jim!
var/list/assembly_list = list(
/obj/item/device/electronic_assembly,
/obj/item/device/electronic_assembly/medium,
/obj/item/device/electronic_assembly/large,
/obj/item/device/electronic_assembly/drone,
)
var/compl = 0
var/maxcomp = 0
var/cap = 0
var/maxcap = 0
var/metalcost = 0
for(var/k in 1 to assembly_list.len)
var/obj/item/I = assembly_list[k]
as_samp[initial(I.name)] = I
if(debug)
visible_message( "<span class='notice'>started successful</span>")
if(chap[2] != "")
if(debug)
visible_message( "<span class='notice'>assembly</span>")
element = splittext( chap[2] ,"=-=")
PA = as_samp[element[1]]
if(ispath(PA,/obj/item/device/electronic_assembly))
PF = PA
maxcap = initial(PF.max_components)
maxcomp = initial(PF.max_complexity)
metalcost = metalcost + round( (initial(PF.max_complexity) + initial(PF.max_components) ) / 4)
if(debug)
visible_message( "<span class='notice'>maxcap[maxcap]maxcomp[maxcomp]</span>")
else
return 0
to_chat(usr, "<span class='notice'>This is program for [element[2]]</span>")
/*
else if(istype(PA,/obj/item/weapon/implant/integrated_circuit))
var/obj/item/weapon/implant/integrated_circuit/PI = PA
var/obj/item/device/electronic_assembly/implant/PIC = PI.IC
maxcap = PIC.max_components
maxcomp = PIC.max_complexity
metalcost = metalcost + round( (initial(PIC.max_complexity) + initial(PIC.max_components) ) / 4)*/
else
return 0 //what's the point if there is no assembly?
if(chap[3] != "components") //if there is only one word,there is no components.
elements_input = splittext( chap[3] ,"^%^")
if(debug)
visible_message( "<span class='notice'>components[elements_input.len]</span>")
i = 0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>components[elements.len]</span>")
if(elements_input.len<1)
return 0
if(debug)
visible_message( "<span class='notice'>inserting components[elements.len]</span>")
i=0
for(var/E in elements)
i=i+1
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
comp = all_circuits[element[1]]
if(!comp)
break
if(!upgraded)
var/obj/item/integrated_circuit/IC = comp
if(!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT))
return -1
compl = compl + initial(comp.complexity)
cap = cap + initial(comp.size)
metalcost = metalcost + initial(initial(comp.w_class))
var/obj/item/integrated_circuit/circuit = new comp
var/list/ini = circuit.inputs
if(length(ini))
for(var/j in 1 to ini.len)
var/datum/integrated_io/IN = ini[j]
ioa["[i]i[j]"] = IN
if(debug)
visible_message( "<span class='notice'>[i]i[j]</span>")
ini = circuit.outputs
if(length(ini))
for(var/j in 1 to ini.len) //Also this block uses for setting all i/o id's
var/datum/integrated_io/OUT = ini[j]
ioa["[i]o[j]"] = OUT
if(debug)
visible_message( "<span class='notice'>[i]o[j]</span>")
ini = circuit.activators
if(length(ini))
for(var/j in 1 to ini.len)
var/datum/integrated_io/ACT = ini.[j]
ioa["[i]a[j]"] = ACT
if(debug)
visible_message( "<span class='notice'>[i]a[j]</span>")
if(i<elements.len)
return 0
else
return 0
if(debug)
visible_message( "<span class='notice'>cap[cap]compl[compl]maxcompl[maxcomp]maxcap[maxcap]</span>")
if(cap == 0)
return 0
if(cap>maxcap)
return 0
if(compl>maxcomp)
return 0
if(chap[4] != "values") //if there is only one word,there is no values
elements_input = splittext( chap[4] ,"^%^")
if(debug)
visible_message( "<span class='notice'>values[elements_input.len]</span>")
i=0
elements = list()
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>values[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting values[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,":+:")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
if(!ioa[element[1]])
return 0
if(element[2]=="text")
continue
else if(element[2]=="num")
continue
else if(element[2]=="list")
continue
else
return 0
if(chap[5] != "wires") //if there is only one word,there is no wires
elements_input = splittext( chap[5] ,"^%^")
i=0
elements = list()
if(debug)
visible_message( "<span class='notice'>wires[elements_input.len]</span>")
for(var/elem in elements_input)
i=i+1
if(i>1)
elements.Add(elem)
if(debug)
visible_message( "<span class='notice'>wires[elements.len]</span>")
if(elements.len>0)
if(debug)
visible_message( "<span class='notice'>setting wires[elements.len]</span>")
for(var/E in elements)
element = splittext( E ,"=-=")
if(debug)
visible_message( "<span class='notice'>[E]</span>")
IO = ioa[element[1]]
IO2 = ioa[element[2]]
if(!((element[2]+"=-="+element[1]) in elements))
return 0
if(!IO)
return 0
if(!IO2)
return 0
if(initial(IO.io_type) != initial(IO2.io_type))
return 0
return metalcost
@@ -0,0 +1,26 @@
// These pins only contain 0 or 1. Null is not allowed.
/datum/integrated_io/boolean
name = "boolean pin"
data = FALSE
/datum/integrated_io/boolean/ask_for_pin_data(mob/user) // 'Ask' is a bit misleading, acts more like a toggle.
var/new_data = !data
to_chat(user, "<span class='notice'>You switch the data bit to [data? "true" : "false"].</span>")
write_data_to_pin(new_data)
/datum/integrated_io/boolean/write_data_to_pin(var/new_data)
if(new_data == FALSE || new_data == TRUE)
data = new_data
holder.on_data_written()
/datum/integrated_io/boolean/scramble()
write_data_to_pin(rand(FALSE,TRUE))
push_data()
/datum/integrated_io/boolean/display_pin_type()
return IC_FORMAT_BOOLEAN
/datum/integrated_io/boolean/display_data(var/input)
if(data == TRUE)
return "(True)"
return "(False)"
@@ -0,0 +1,27 @@
// These pins can only contain a 1 character string or null.
/datum/integrated_io/char
name = "char pin"
/datum/integrated_io/char/ask_for_pin_data(mob/user)
var/new_data = input("Please type in one character.","[src] char writing") as null|text
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "new_data" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/char/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
if(length(new_data) > 1)
return
data = new_data
holder.on_data_written()
// This makes the text go from "A" to "%".
/datum/integrated_io/char/scramble()
if(!is_valid())
return
var/list/options = list("!","@","#","$","%","^","&","*","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
data = pick(options)
push_data()
/datum/integrated_io/char/display_pin_type()
return IC_FORMAT_CHAR
@@ -0,0 +1,49 @@
// These pins can only contain a color (in the form of #FFFFFF) or null.
/datum/integrated_io/color
name = "color pin"
/datum/integrated_io/color/ask_for_pin_data(mob/user)
var/new_data = input("Please select a color.","[src] color writing") as null|color
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input a <font color='[new_data]'>new color</font> into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/color/write_data_to_pin(var/new_data)
// Since this is storing the color as a string hex color code, we need to make sure it's actually one.
if(isnull(new_data) || istext(new_data))
if(istext(new_data))
new_data = uppertext(new_data)
if(length(new_data) != 7) // We can hex if we want to, we can leave your strings behind
return // Cause your strings don't hex and if they don't hex
var/friends = copytext(new_data, 2, 8) // Well they're are no strings of mine
// I say, we can go where we want to, a place where they will never find
var/safety_dance = 1
while(safety_dance >= 7) // And we can act like we come from out of this world.log
var/hex = copytext(friends, safety_dance, safety_dance+1)
if(!(hex in list("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")))
return // Leave the fake one far behind,
safety_dance++
data = new_data // And we can hex
holder.on_data_written()
// This randomizes the color.
/datum/integrated_io/color/scramble()
if(!is_valid())
return
var/new_data
for(var/i=1;i<=3;i++)
var/temp_col = "[num2hex(rand(0,255))]"
if(length(temp_col )<2)
temp_col = "0[temp_col]"
new_data += temp_col
data = new_data
push_data()
/datum/integrated_io/color/display_pin_type()
return IC_FORMAT_COLOR
/datum/integrated_io/color/display_data(var/input)
if(!isnull(data))
return "(<font color='[data]'>[data]</font>)"
return ..()
@@ -0,0 +1,31 @@
// These pins can only contain directions (1,2,4,8...) or null.
/datum/integrated_io/dir
name = "dir pin"
/datum/integrated_io/dir/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a valid dir number. \
Valid dirs are;\n\
North/Fore = [NORTH],\n\
South/Aft = [SOUTH],\n\
East/Starboard = [EAST],\n\
West/Port = [WEST],\n\
Northeast = [NORTHEAST],\n\
Northwest = [NORTHWEST],\n\
Southeast = [SOUTHEAST],\n\
Southwest = [SOUTHWEST]","[src] dir writing") as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/dir/write_data_to_pin(var/new_data)
if(isnull(new_data) || new_data in list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)/* + list(UP, DOWN)*/)
data = new_data
holder.on_data_written()
/datum/integrated_io/dir/display_pin_type()
return IC_FORMAT_DIR
/datum/integrated_io/dir/display_data(var/input)
if(!isnull(data))
return "([dir2text(data)])"
return ..()
@@ -0,0 +1,148 @@
// These pins contain a list. Null is not allowed.
/datum/integrated_io/lists
name = "list pin"
data = list()
/datum/integrated_io/lists/ask_for_pin_data(mob/user)
interact(user)
/datum/integrated_io/lists/proc/interact(mob/user)
var/list/my_list = data
var/t = "<h2>[src]</h2><br>"
t += "List length: [my_list.len]<br>"
t += "<a href='?src=[REF(src)]'>\[Refresh\]</a> | "
t += "<a href='?src=[REF(src)];add=1'>\[Add\]</a> | "
t += "<a href='?src=[REF(src)];swap=1'>\[Swap\]</a> | "
t += "<a href='?src=[REF(src)];clear=1'>\[Clear\]</a><br>"
t += "<hr>"
var/i = 0
for(var/line in my_list)
i++
t += "#[i] | [display_data(line)] | "
t += "<a href='?src=[REF(src)];edit=1;pos=[i]'>\[Edit\]</a> | "
t += "<a href='?src=[REF(src)];remove=1;pos=[i]'>\[Remove\]</a><br>"
user << browse(t, "window=list_pin_[REF(src)];size=500x400")
/datum/integrated_io/lists/proc/add_to_list(mob/user, var/new_entry)
if(!new_entry && user)
new_entry = ask_for_data_type(user)
if(is_valid(new_entry))
Add(new_entry)
/datum/integrated_io/lists/proc/Add(var/new_entry)
var/list/my_list = data
if(my_list.len > IC_MAX_LIST_LENGTH)
my_list.Cut(Start=1,End=2)
my_list.Add(new_entry)
/datum/integrated_io/lists/proc/remove_from_list_by_position(mob/user, var/position)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
return
if(!position)
return
var/target_entry = my_list.Find(position)
if(target_entry)
my_list.Remove(target_entry)
/datum/integrated_io/lists/proc/remove_from_list(mob/user, var/target_entry)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to remove.</span>")
return
if(!target_entry)
target_entry = input(user, "Which piece of data do you want to remove?", "Remove") as null|anything in my_list
if(holder.check_interactivity(user) && target_entry)
my_list.Remove(target_entry)
/datum/integrated_io/lists/proc/edit_in_list(mob/user, var/target_entry)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
return
if(!target_entry)
target_entry = input(user, "Which piece of data do you want to edit?", "Edit") as null|anything in my_list
if(holder.check_interactivity(user) && target_entry)
var/edited_entry = ask_for_data_type(user, target_entry)
if(edited_entry)
target_entry = edited_entry
/datum/integrated_io/lists/proc/edit_in_list_by_position(mob/user, var/position)
var/list/my_list = data
if(!my_list.len)
to_chat(user, "<span class='warning'>The list is empty, there's nothing to modify.</span>")
return
if(!position)
return
var/target_entry = my_list.Find(position)
if(target_entry)
var/edited_entry = ask_for_data_type(user, target_entry)
if(edited_entry)
target_entry = edited_entry
/datum/integrated_io/lists/proc/swap_inside_list(mob/user, var/first_target, var/second_target)
var/list/my_list = data
if(my_list.len <= 1)
to_chat(user, "<span class='warning'>The list is empty, or too small to do any meaningful swapping.</span>")
return
if(!first_target)
first_target = input(user, "Which piece of data do you want to swap? (1)", "Swap") as null|anything in my_list
if(holder.check_interactivity(user) && first_target)
if(!second_target)
second_target = input(user, "Which piece of data do you want to swap? (2)", "Swap") as null|anything in my_list - first_target
if(holder.check_interactivity(user) && second_target)
var/first_pos = my_list.Find(first_target)
var/second_pos = my_list.Find(second_target)
my_list.Swap(first_pos, second_pos)
/datum/integrated_io/lists/proc/clear_list(mob/user)
var/list/my_list = data
my_list.Cut()
/datum/integrated_io/lists/scramble()
var/list/my_list = data
my_list = shuffle(my_list)
push_data()
/datum/integrated_io/lists/write_data_to_pin(var/new_data)
if(islist(new_data))
var/list/new_list = new_data
data = new_list.Copy(1,min( IC_MAX_LIST_LENGTH+1, new_list.len ))
holder.on_data_written()
/datum/integrated_io/lists/display_pin_type()
return IC_FORMAT_LIST
/datum/integrated_io/lists/Topic(href, href_list)
if(!holder.check_interactivity(usr))
return
if(..())
return TRUE
if(href_list["add"])
add_to_list(usr)
if(href_list["swap"])
swap_inside_list(usr)
if(href_list["clear"])
clear_list(usr)
if(href_list["remove"])
if(href_list["pos"])
remove_from_list_by_position(usr, text2num(href_list["pos"]))
else
remove_from_list(usr)
if(href_list["edit"])
if(href_list["pos"])
edit_in_list_by_position(usr, text2num(href_list["pos"]))
else
edit_in_list(usr)
holder.interact(usr) // Refresh the main UI,
interact(usr) // and the list UI.
@@ -0,0 +1,18 @@
// These pins can only contain numbers (int and floating point) or null.
/datum/integrated_io/number
name = "number pin"
// data = 0
/datum/integrated_io/number/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a number.","[src] number writing") as null|num
if(isnum(new_data) && holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/number/write_data_to_pin(var/new_data)
if(isnull(new_data) || isnum(new_data))
data = new_data
holder.on_data_written()
/datum/integrated_io/number/display_pin_type()
return IC_FORMAT_NUMBER
@@ -0,0 +1,14 @@
// These pins only contain weakrefs or null.
/datum/integrated_io/ref
name = "ref pin"
/datum/integrated_io/ref/ask_for_pin_data(mob/user) // This clears the pin.
write_data_to_pin(null)
/datum/integrated_io/ref/write_data_to_pin(var/new_data)
if(isnull(new_data) || isweakref(new_data))
data = new_data
holder.on_data_written()
/datum/integrated_io/ref/display_pin_type()
return IC_FORMAT_REF
@@ -0,0 +1,27 @@
// These pins can only contain text and null.
/datum/integrated_io/string
name = "string pin"
/datum/integrated_io/string/ask_for_pin_data(mob/user)
var/new_data = input("Please type in a string.","[src] string writing") as null|text
if(holder.check_interactivity(user) )
to_chat(user, "<span class='notice'>You input [new_data ? "[new_data]" : "NULL"] into the pin.</span>")
write_data_to_pin(new_data)
/datum/integrated_io/string/write_data_to_pin(var/new_data)
if(isnull(new_data) || istext(new_data))
data = new_data
holder.on_data_written()
// This makes the text go "from this" to "#G&*!HD$%L"
/datum/integrated_io/string/scramble()
if(!is_valid())
return
var/list/options = list("!","@","#","$","%","^","&","*","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
var/new_data = ""
for(var/i in 1 to length(data))
new_data += pick(options)
push_data()
/datum/integrated_io/string/display_pin_type()
return IC_FORMAT_STRING
@@ -0,0 +1,102 @@
#define WIRE "wire"
#define WIRING "wiring"
#define UNWIRE "unwire"
#define UNWIRING "unwiring"
/obj/item/device/integrated_electronics/wirer
name = "circuit wirer"
desc = "It's a small wiring tool, with a wire roll, electric soldering iron, wire cutter, and more in one package. \
The wires used are generally useful for small electronics, such as circuitboards and breadboards, as opposed to larger wires \
used for power or data transmission."
icon = 'icons/obj/electronic_assemblies.dmi'
icon_state = "wirer-wire"
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_SMALL
var/datum/integrated_io/selected_io = null
var/mode = WIRE
/obj/item/device/integrated_electronics/wirer/update_icon()
icon_state = "wirer-[mode]"
/obj/item/device/integrated_electronics/wirer/proc/wire(var/datum/integrated_io/io, mob/user)
if(!io.holder.assembly)
to_chat(user, "<span class='warning'>\The [io.holder] needs to be secured inside an assembly first.</span>")
return
if(mode == WIRE)
selected_io = io
to_chat(user, "<span class='notice'>You attach a data wire to \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = WIRING
update_icon()
else if(mode == WIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.</span>")
return
if(io.io_type != selected_io.io_type)
to_chat(user, "<span class='warning'>Those two types of channels are incompatable. The first is a [selected_io.io_type], \
while the second is a [io.io_type].</span>")
return
if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly)
to_chat(user, "<span class='warning'>Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.</span>")
return
selected_io.linked |= io
io.linked |= selected_io
to_chat(user, "<span class='notice'>You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].</span>")
mode = WIRE
update_icon()
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
else if(mode == UNWIRE)
selected_io = io
if(!io.linked.len)
to_chat(user, "<span class='warning'>There is nothing connected to \the [selected_io] data channel.</span>")
selected_io = null
return
to_chat(user, "<span class='notice'>You prepare to detach a data wire from \the [selected_io.holder]'s [selected_io.name] data channel.</span>")
mode = UNWIRING
update_icon()
return
else if(mode == UNWIRING)
if(io == selected_io)
to_chat(user, "<span class='warning'>You can't wire a pin into each other, so unwiring \the [selected_io.holder] from \
the same pin is rather moot.</span>")
return
if(selected_io in io.linked)
io.linked.Remove(selected_io)
selected_io.linked.Remove(io)
to_chat(user, "<span class='notice'>You disconnect \the [selected_io.holder]'s [selected_io.name] from \
\the [io.holder]'s [io.name].</span>")
selected_io.holder.interact(user) // This is to update the UI.
selected_io = null
mode = UNWIRE
update_icon()
else
to_chat(user, "<span class='warning'>\The [selected_io.holder]'s [selected_io.name] and \the [io.holder]'s \
[io.name] are not connected.</span>")
return
/obj/item/device/integrated_electronics/wirer/attack_self(mob/user)
switch(mode)
if(WIRE)
mode = UNWIRE
if(WIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to wire the data channel.</span>")
selected_io = null
mode = WIRE
if(UNWIRE)
mode = WIRE
if(UNWIRING)
if(selected_io)
to_chat(user, "<span class='notice'>You decide not to disconnect the data channel.</span>")
selected_io = null
mode = UNWIRE
update_icon()
to_chat(user, "<span class='notice'>You set \the [src] to [mode].</span>")
#undef WIRE
#undef WIRING
#undef UNWIRE
#undef UNWIRING