From 14ad0d70e39b6aa5e704970b51dbef7a0f6dca79 Mon Sep 17 00:00:00 2001 From: LorenLuke Date: Sun, 16 Jul 2017 02:47:09 -0700 Subject: [PATCH] See changelog. --- code/game/machinery/cloning.dm | 1 + .../telecomms/machine_interactions.dm | 1 + code/modules/assembly/assembly.dm | 172 ++++----- code/modules/assembly/holder.dm | 356 +++++++++--------- code/modules/assembly/igniter.dm | 56 +-- code/modules/assembly/infrared.dm | 226 ++++++----- code/modules/assembly/mousetrap.dm | 180 ++++----- code/modules/assembly/proximity.dm | 243 ++++++------ code/modules/assembly/shock_kit.dm | 2 +- code/modules/assembly/signaler.dm | 270 ++++++------- code/modules/assembly/timer.dm | 169 ++++----- code/modules/examine/descriptions/devices.dm | 12 +- .../integrated_electronics/_defines.dm | 8 +- .../integrated_electronics/core/assemblies.dm | 83 +++- .../integrated_electronics/core/device.dm | 84 +++++ .../integrated_electronics/core/helpers.dm | 14 + .../core/integrated_circuit.dm | 220 ++++++++--- .../integrated_electronics/core/tools.dm | 124 +++++- .../subtypes/arithmetic.dm | 2 +- .../subtypes/built_in.dm | 28 ++ .../subtypes/converters.dm | 53 ++- .../subtypes/data_transfer.dm | 41 +- .../subtypes/input_output.dm | 34 +- .../integrated_electronics/subtypes/logic.dm | 8 +- .../subtypes/manipulation.dm | 165 ++++++-- .../integrated_electronics/subtypes/memory.dm | 8 +- .../integrated_electronics/subtypes/power.dm | 2 +- .../subtypes/reagents.dm | 6 +- .../integrated_electronics/subtypes/smart.dm | 2 +- .../integrated_electronics/subtypes/time.dm | 6 +- .../integrated_electronics/subtypes/trig.dm | 2 +- code/modules/research/designs.dm | 17 +- .../integrated_circuits/converter.dm | 6 +- html/changelogs/LorenLuke-IEC changes.yml | 50 +++ icons/obj/assemblies/new_assemblies.dmi | Bin 3535 -> 4159 bytes icons/obj/electronic_assemblies.dmi | Bin 32741 -> 33944 bytes polaris.dme | 2 + 37 files changed, 1604 insertions(+), 1049 deletions(-) create mode 100644 code/modules/integrated_electronics/core/device.dm create mode 100644 code/modules/integrated_electronics/subtypes/built_in.dm create mode 100644 html/changelogs/LorenLuke-IEC changes.yml diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 1a1bd9a463..6a055bdfc1 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -243,6 +243,7 @@ var/obj/item/device/multitool/M = W M.connecting = src user << "You load connection data from [src] to [M]." + M.update_icon() return else ..() diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 002da7bc53..1ab85f34b7 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -168,6 +168,7 @@ dat += "

MULTITOOL BUFFER: [P.buffer] ([P.buffer.id]) \[Link\] \[Flush\]" else dat += "

MULTITOOL BUFFER:
\[Add Machine\]" + P.update_icon() dat += "" temp = "" diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index 9587984177..747b0d442b 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -23,119 +23,119 @@ var/const/WIRE_RADIO_RECEIVE = 8 //Allows Pulsed(1) to call Activate() var/const/WIRE_RADIO_PULSE = 16 //Allows Pulse(1) to send a radio message - proc/activate() //What the device does when turned on - return +/obj/item/device/assembly/proc/activate() //What the device does when turned on + return - proc/pulsed(var/radio = 0) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs - return +/obj/item/device/assembly/proc/pulsed(var/radio = 0) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs + return - proc/pulse(var/radio = 0) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct - return +/obj/item/device/assembly/proc/pulse(var/radio = 0) //Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct + return - proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here - return +/obj/item/device/assembly/proc/toggle_secure() //Code that has to happen when the assembly is un\secured goes here + return - proc/attach_assembly(var/obj/A, var/mob/user) //Called when an assembly is attacked by another - return +/obj/item/device/assembly/proc/attach_assembly(var/obj/A, var/mob/user) //Called when an assembly is attacked by another + return - proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var - return +/obj/item/device/assembly/proc/process_cooldown() //Called via spawn(10) to have it count down the cooldown var + return - proc/holder_movement() //Called when the holder is moved - return +/obj/item/device/assembly/proc/holder_movement() //Called when the holder is moved + return - interact(mob/user as mob) //Called when attack_self is called - return +/obj/item/device/assembly/interact(mob/user as mob) //Called when attack_self is called + return - process_cooldown() - cooldown-- - if(cooldown <= 0) return 0 - spawn(10) - process_cooldown() - return 1 +/obj/item/device/assembly/process_cooldown() + cooldown-- + if(cooldown <= 0) return 0 + spawn(10) + process_cooldown() + return 1 - pulsed(var/radio = 0) - if(holder && (wires & WIRE_RECEIVE)) - activate() - if(radio && (wires & WIRE_RADIO_RECEIVE)) - activate() - return 1 +/obj/item/device/assembly/pulsed(var/radio = 0) + if(holder && (wires & WIRE_RECEIVE)) + activate() + if(radio && (wires & WIRE_RADIO_RECEIVE)) + activate() + return 1 - pulse(var/radio = 0) - if(holder && (wires & WIRE_PULSE)) - holder.process_activation(src, 1, 0) - if(holder && (wires & WIRE_PULSE_SPECIAL)) - holder.process_activation(src, 0, 1) +/obj/item/device/assembly/pulse(var/radio = 0) + if(holder && (wires & WIRE_PULSE)) + holder.process_activation(src, 1, 0) + if(holder && (wires & WIRE_PULSE_SPECIAL)) + holder.process_activation(src, 0, 1) // if(radio && (wires & WIRE_RADIO_PULSE)) - //Not sure what goes here quite yet send signal? + //Not sure what goes here quite yet send signal? + return 1 + + +/obj/item/device/assembly/activate() + if(!secured || (cooldown > 0)) return 0 + cooldown = 2 + spawn(10) + process_cooldown() + return 1 + + +/obj/item/device/assembly/toggle_secure() + secured = !secured + update_icon() + return secured + + +/obj/item/device/assembly/attach_assembly(var/obj/item/device/assembly/A, var/mob/user) + holder = new/obj/item/device/assembly_holder(get_turf(src)) + if(holder.attach(A,src,user)) + to_chat(user, "You attach \the [A] to \the [src]!") return 1 + return 0 - activate() - if(!secured || (cooldown > 0)) return 0 - cooldown = 2 - spawn(10) - process_cooldown() - return 1 - - - toggle_secure() - secured = !secured - update_icon() - return secured - - - attach_assembly(var/obj/item/device/assembly/A, var/mob/user) - holder = new/obj/item/device/assembly_holder(get_turf(src)) - if(holder.attach(A,src,user)) - user << "\blue You attach \the [A] to \the [src]!" - return 1 - return 0 - - - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isassembly(W)) - var/obj/item/device/assembly/A = W - if((!A.secured) && (!secured)) - attach_assembly(A,user) - return - if(isscrewdriver(W)) - if(toggle_secure()) - user << "\blue \The [src] is ready!" - else - user << "\blue \The [src] can now be attached!" +/obj/item/device/assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isassembly(W)) + var/obj/item/device/assembly/A = W + if((!A.secured) && (!secured)) + attach_assembly(A,user) return - ..() + if(isscrewdriver(W)) + if(toggle_secure()) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can now be attached!") return + ..() + return - process() - processing_objects.Remove(src) - return +/obj/item/device/assembly/process() + processing_objects.Remove(src) + return - examine(mob/user) - ..(user) - if((in_range(src, user) || loc == user)) - if(secured) - user << "\The [src] is ready!" - else - user << "\The [src] can be attached!" - return +/obj/item/device/assembly/examine(mob/user) + ..(user) + if((in_range(src, user) || loc == user)) + if(secured) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can be attached!") + return - attack_self(mob/user as mob) - if(!user) return 0 - user.set_machine(src) - interact(user) - return 1 +/obj/item/device/assembly/attack_self(mob/user as mob) + if(!user) return 0 + user.set_machine(src) + interact(user) + return 1 - interact(mob/user as mob) - return //HTML MENU FOR WIRES GOES HERE +/obj/item/device/assembly/interact(mob/user as mob) + return //HTML MENU FOR WIRES GOES HERE /obj/item/device/assembly/nano_host() if(istype(loc, /obj/item/device/assembly_holder)) diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index a614135f22..4986c2d7dc 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -14,201 +14,201 @@ var/obj/item/device/assembly/a_right = null var/obj/special_assembly = null - proc/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) - return +/obj/item/device/assembly_holder/proc/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) + return - proc/attach_special(var/obj/O, var/mob/user) - return +/obj/item/device/assembly_holder/proc/attach_special(var/obj/O, var/mob/user) + return - proc/process_activation(var/obj/item/device/D) - return +/obj/item/device/assembly_holder/proc/process_activation(var/obj/item/device/D) + return - proc/detached() - return +/obj/item/device/assembly_holder/proc/detached() + return - IsAssemblyHolder() - return 1 +/obj/item/device/assembly_holder/IsAssemblyHolder() + return 1 - attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) - if((!D)||(!D2)) return 0 - if((!isassembly(D))||(!isassembly(D2))) return 0 - if((D:secured)||(D2:secured)) return 0 - if(user) - user.remove_from_mob(D) - user.remove_from_mob(D2) - D:holder = src - D2:holder = src - D.loc = src - D2.loc = src - a_left = D - a_right = D2 - name = "[D.name]-[D2.name] assembly" - update_icon() - usr.put_in_hands(src) +/obj/item/device/assembly_holder/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) + if((!D)||(!D2)) return 0 + if((!isassembly(D))||(!isassembly(D2))) return 0 + if((D:secured)||(D2:secured)) return 0 + if(user) + user.remove_from_mob(D) + user.remove_from_mob(D2) + D:holder = src + D2:holder = src + D.loc = src + D2.loc = src + a_left = D + a_right = D2 + name = "[D.name]-[D2.name] assembly" + update_icon() + usr.put_in_hands(src) - return 1 + return 1 - attach_special(var/obj/O, var/mob/user) - if(!O) return - if(!O.IsSpecialAssembly()) return 0 +/obj/item/device/assembly_holder/attach_special(var/obj/O, var/mob/user) + if(!O) return + if(!O.IsSpecialAssembly()) return 0 /* if(O:Attach_Holder()) - special_assembly = O - update_icon() - src.name = "[a_left.name] [a_right.name] [special_assembly.name] assembly" + special_assembly = O + update_icon() + src.name = "[a_left.name] [a_right.name] [special_assembly.name] assembly" */ - return + return - update_icon() - overlays.Cut() - if(a_left) - overlays += "[a_left.icon_state]_left" - for(var/O in a_left.attached_overlays) - overlays += "[O]_l" - if(a_right) - src.overlays += "[a_right.icon_state]_right" - for(var/O in a_right.attached_overlays) - overlays += "[O]_r" - if(master) - master.update_icon() +/obj/item/device/assembly_holder/update_icon() + overlays.Cut() + if(a_left) + overlays += "[a_left.icon_state]_left" + for(var/O in a_left.attached_overlays) + overlays += "[O]_l" + if(a_right) + src.overlays += "[a_right.icon_state]_right" + for(var/O in a_right.attached_overlays) + overlays += "[O]_r" + if(master) + master.update_icon() /* if(special_assembly) - special_assembly.update_icon() - if(special_assembly:small_icon_state) - src.overlays += special_assembly:small_icon_state - for(var/O in special_assembly:small_icon_state_overlays) - src.overlays += O + special_assembly.update_icon() + if(special_assembly:small_icon_state) + src.overlays += special_assembly:small_icon_state + for(var/O in special_assembly:small_icon_state_overlays) + src.overlays += O */ - examine(mob/user) - ..(user) - if ((in_range(src, user) || src.loc == user)) - if (src.secured) - user << "\The [src] is ready!" - else - user << "\The [src] can be attached!" - return +/obj/item/device/assembly_holder/examine(mob/user) + ..(user) + if ((in_range(src, user) || src.loc == user)) + if (src.secured) + to_chat(user, "\The [src] is ready!") + else + to_chat(user, "\The [src] can be attached!") + return - HasProximity(atom/movable/AM as mob|obj) - if(a_left) - a_left.HasProximity(AM) - if(a_right) - a_right.HasProximity(AM) - if(special_assembly) - special_assembly.HasProximity(AM) +/obj/item/device/assembly_holder/HasProximity(atom/movable/AM as mob|obj) + if(a_left) + a_left.HasProximity(AM) + if(a_right) + a_right.HasProximity(AM) + if(special_assembly) + special_assembly.HasProximity(AM) - Crossed(atom/movable/AM as mob|obj) - if(a_left) - a_left.Crossed(AM) - if(a_right) - a_right.Crossed(AM) - if(special_assembly) - special_assembly.Crossed(AM) +/obj/item/device/assembly_holder/Crossed(atom/movable/AM as mob|obj) + if(a_left) + a_left.Crossed(AM) + if(a_right) + a_right.Crossed(AM) + if(special_assembly) + special_assembly.Crossed(AM) - on_found(mob/finder as mob) - if(a_left) - a_left.on_found(finder) - if(a_right) - a_right.on_found(finder) - if(special_assembly) - if(istype(special_assembly, /obj/item)) - var/obj/item/S = special_assembly - S.on_found(finder) +/obj/item/device/assembly_holder/on_found(mob/finder as mob) + if(a_left) + a_left.on_found(finder) + if(a_right) + a_right.on_found(finder) + if(special_assembly) + if(istype(special_assembly, /obj/item)) + var/obj/item/S = special_assembly + S.on_found(finder) - Move() - ..() - if(a_left && a_right) - a_left.holder_movement() - a_right.holder_movement() +/obj/item/device/assembly_holder/Move() + ..() + if(a_left && a_right) + a_left.holder_movement() + a_right.holder_movement() // if(special_assembly) // special_assembly:holder_movement() - return + return - attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess - if(a_left && a_right) - a_left.holder_movement() - a_right.holder_movement() +/obj/item/device/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess + if(a_left && a_right) + a_left.holder_movement() + a_right.holder_movement() // if(special_assembly) // special_assembly:Holder_Movement() - ..() - return + ..() + return - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isscrewdriver(W)) - if(!a_left || !a_right) - user << "\red BUG:Assembly part missing, please report this!" - return - a_left.toggle_secure() - a_right.toggle_secure() - secured = !secured - if(secured) - user << "\blue \The [src] is ready!" - else - user << "\blue \The [src] can now be taken apart!" - update_icon() +/obj/item/device/assembly_holder/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(isscrewdriver(W)) + if(!a_left || !a_right) + to_chat(user, " BUG:Assembly part missing, please report this!") return - else if(W.IsSpecialAssembly()) - attach_special(W, user) + a_left.toggle_secure() + a_right.toggle_secure() + secured = !secured + if(secured) + to_chat(user, "\The [src] is ready!") else - ..() + to_chat(user, "\The [src] can now be taken apart!") + update_icon() return + else if(W.IsSpecialAssembly()) + attach_special(W, user) + else + ..() + return - attack_self(mob/user as mob) - src.add_fingerprint(user) - if(src.secured) - if(!a_left || !a_right) - user << "\red Assembly part missing!" - return - if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code - switch(alert("Which side would you like to use?",,"Left","Right")) - if("Left") a_left.attack_self(user) - if("Right") a_right.attack_self(user) - return - else - if(!istype(a_left,/obj/item/device/assembly/igniter)) - a_left.attack_self(user) - if(!istype(a_right,/obj/item/device/assembly/igniter)) - a_right.attack_self(user) +/obj/item/device/assembly_holder/attack_self(mob/user as mob) + src.add_fingerprint(user) + if(src.secured) + if(!a_left || !a_right) + to_chat(user, " BUG:Assembly part missing, please report this!") + return + if(istype(a_left,a_right.type))//If they are the same type it causes issues due to window code + switch(alert("Which side would you like to use?",,"Left","Right")) + if("Left") a_left.attack_self(user) + if("Right") a_right.attack_self(user) + return else - var/turf/T = get_turf(src) - if(!T) return 0 - if(a_left) - a_left:holder = null - a_left.loc = T - if(a_right) - a_right:holder = null - a_right.loc = T - spawn(0) - qdel(src) - return + if(!istype(a_left,/obj/item/device/assembly/igniter)) + a_left.attack_self(user) + if(!istype(a_right,/obj/item/device/assembly/igniter)) + a_right.attack_self(user) + else + var/turf/T = get_turf(src) + if(!T) return 0 + if(a_left) + a_left:holder = null + a_left.loc = T + if(a_right) + a_right:holder = null + a_right.loc = T + spawn(0) + qdel(src) + return - process_activation(var/obj/D, var/normal = 1, var/special = 1) - if(!D) return 0 - if(!secured) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - if((normal) && (a_right) && (a_left)) - if(a_right != D) - a_right.pulsed(0) - if(a_left != D) - a_left.pulsed(0) - if(master) - master.receive_signal() +/obj/item/device/assembly_holder/process_activation(var/obj/D, var/normal = 1, var/special = 1) + if(!D) return 0 + if(!secured) + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + if((normal) && (a_right) && (a_left)) + if(a_right != D) + a_right.pulsed(0) + if(a_left != D) + a_left.pulsed(0) + if(master) + master.receive_signal() // if(special && special_assembly) // if(!special_assembly == D) // special_assembly.dothings() - return 1 + return 1 /obj/item/device/assembly_holder/hear_talk(mob/living/M as mob, msg, verb, datum/language/speaking) @@ -242,36 +242,36 @@ loc.verbs += /obj/item/device/assembly_holder/timer_igniter/verb/configure - detached() - loc.verbs -= /obj/item/device/assembly_holder/timer_igniter/verb/configure - ..() +/obj/item/device/assembly_holder/timer_igniterdetached() + loc.verbs -= /obj/item/device/assembly_holder/timer_igniter/verb/configure + ..() - verb/configure() - set name = "Set Timer" - set category = "Object" - set src in usr +/obj/item/device/assembly_holder/timer_igniterverb/configure() + set name = "Set Timer" + set category = "Object" + set src in usr - if ( !(usr.stat || usr.restrained()) ) - var/obj/item/device/assembly_holder/holder - if(istype(src,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/gren = src - holder=gren.detonator - var/obj/item/device/assembly/timer/tmr = holder.a_left - if(!istype(tmr,/obj/item/device/assembly/timer)) - tmr = holder.a_right - if(!istype(tmr,/obj/item/device/assembly/timer)) - usr << "This detonator has no timer." - return + if ( !(usr.stat || usr.restrained()) ) + var/obj/item/device/assembly_holder/holder + if(istype(src,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/gren = src + holder=gren.detonator + var/obj/item/device/assembly/timer/tmr = holder.a_left + if(!istype(tmr,/obj/item/device/assembly/timer)) + tmr = holder.a_right + if(!istype(tmr,/obj/item/device/assembly/timer)) + to_chat(usr, "This detonator has no timer.") + return - if(tmr.timing) - usr << "Clock is ticking already." - else - var/ntime = input("Enter desired time in seconds", "Time", "5") as num - if (ntime>0 && ntime<1000) - tmr.time = ntime - name = initial(name) + "([tmr.time] secs)" - usr << "Timer set to [tmr.time] seconds." - else - usr << "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"]." + if(tmr.timing) + to_chat(usr, "Clock is ticking already.") else - usr << "You cannot do this while [usr.stat?"unconscious/dead":"restrained"]." + var/ntime = input("Enter desired time in seconds", "Time", "5") as num + if (ntime>0 && ntime<1000) + tmr.time = ntime + name = initial(name) + "([tmr.time] secs)" + to_chat(usr, "Timer set to [tmr.time] seconds.") + else + to_chat(usr, "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"].") + else + to_chat(usr, "You cannot do this while [usr.stat?"unconscious/dead":"restrained"].") diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm index fc34669f3d..c7b0b619ba 100644 --- a/code/modules/assembly/igniter.dm +++ b/code/modules/assembly/igniter.dm @@ -2,36 +2,36 @@ name = "igniter" desc = "A small electronic device able to ignite combustable substances." icon_state = "igniter" - origin_tech = list(TECH_MAGNET = 1) - matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10) + origin_tech = list(TECH_MAGNET = 1) + matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10) secured = 1 wires = WIRE_RECEIVE +/obj/item/device/assembly/igniter/activate() + if(!..()) return 0//Cooldown check + + if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc + grenade.prime() + else + var/turf/location = get_turf(loc) + if(location) + location.hotspot_expose(1000,1000) + if (istype(src.loc,/obj/item/device/assembly_holder)) + if (istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) + var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc + if (tank && tank.modded) + tank.explode() + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(3, 1, src) + s.start() + + return 1 + + +/obj/item/device/assembly/igniter/attack_self(mob/user as mob) activate() - if(!..()) return 0//Cooldown check - - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.prime() - else - var/turf/location = get_turf(loc) - if(location) - location.hotspot_expose(1000,1000) - if (istype(src.loc,/obj/item/device/assembly_holder)) - if (istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) - var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc - if (tank && tank.modded) - tank.explode() - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - - return 1 - - - attack_self(mob/user as mob) - activate() - add_fingerprint(user) - return \ No newline at end of file + add_fingerprint(user) + return \ No newline at end of file diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index f448ce35a1..63c781452c 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -15,145 +15,141 @@ var/visible = 0 var/obj/effect/beam/i_beam/first = null - proc - trigger_beam() - - - activate() +/obj/item/device/assembly/infra/activate() if(!..()) return 0//Cooldown check on = !on update_icon() return 1 - toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - on = 0 - if(first) qdel(first) - processing_objects.Remove(src) - update_icon() - return secured - - +/obj/item/device/assembly/infra/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + on = 0 + if(first) qdel(first) + processing_objects.Remove(src) update_icon() - overlays.Cut() - attached_overlays = list() - if(on) - overlays += "infrared_on" - attached_overlays += "infrared_on" - - if(holder) - holder.update_icon() - return + return secured - process()//Old code - if(!on) - if(first) - qdel(first) - return +/obj/item/device/assembly/infra/update_icon() + overlays.Cut() + attached_overlays = list() + if(on) + overlays += "infrared_on" + attached_overlays += "infrared_on" - if((!(first) && (secured && (istype(loc, /turf) || (holder && istype(holder.loc, /turf)))))) - var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam((holder ? holder.loc : loc) ) - I.master = src - I.density = 1 - I.set_dir(dir) - step(I, I.dir) - if(I) - I.density = 0 - first = I - I.vis_spread(visible) - spawn(0) - if(I) - //world << "infra: setting limit" - I.limit = 8 - //world << "infra: processing beam \ref[I]" - I.process() - return - return + if(holder) + holder.update_icon() + return - attack_hand() - qdel(first) - ..() - return - - - Move() - var/t = dir - ..() - set_dir(t) - qdel(first) - return - - - holder_movement() - if(!holder) return 0 -// set_dir(holder.dir) - qdel(first) - return 1 - - - trigger_beam() - if((!secured)||(!on)||(cooldown > 0)) return 0 - pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return - - - interact(mob/user as mob)//TODO: change this this to the wire control panel - if(!secured) return - user.set_machine(src) - var/dat = text("Infrared Laser\nStatus: []
\nVisibility: []
\n
", (on ? text("On", src) : text("Off", src)), (src.visible ? text("Visible", src) : text("Invisible", src))) - dat += "

Refresh" - dat += "

Close" - user << browse(dat, "window=infra") - onclose(user, "infra") - return - - - Topic(href, href_list) - if(..()) return 1 - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=infra") - onclose(usr, "infra") +/obj/item/device/assembly/infra/process()//Old code + if(!on) + if(first) + qdel(first) return - if(href_list["state"]) - on = !(on) - update_icon() - - if(href_list["visible"]) - visible = !(visible) + if((!(first) && (secured && (istype(loc, /turf) || (holder && istype(holder.loc, /turf)))))) + var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam((holder ? holder.loc : loc) ) + I.master = src + I.density = 1 + I.set_dir(dir) + step(I, I.dir) + if(I) + I.density = 0 + first = I + I.vis_spread(visible) spawn(0) - if(first) - first.vis_spread(visible) + if(I) + //world << "infra: setting limit" + I.limit = 8 + //world << "infra: processing beam \ref[I]" + I.process() + return + return - if(href_list["close"]) - usr << browse(null, "window=infra") - return - if(usr) - attack_self(usr) +/obj/item/device/assembly/infra/attack_hand() + qdel(first) + ..() + return + +/obj/item/device/assembly/infra/Move() + var/t = dir + ..() + set_dir(t) + qdel(first) + return + + +/obj/item/device/assembly/infra/holder_movement() + if(!holder) return 0 +// set_dir(holder.dir) + qdel(first) + return 1 + + +/obj/item/device/assembly/infra/proc/trigger_beam() + if((!secured)||(!on)||(cooldown > 0)) return 0 + pulse(0) + if(!holder) + visible_message("\icon[src] *beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return + + +/obj/item/device/assembly/infra/interact(mob/user as mob)//TODO: change this this to the wire control panel + if(!secured) return + user.set_machine(src) + var/dat = text("Infrared Laser\nStatus: []
\nVisibility: []
\n
", (on ? text("On", src) : text("Off", src)), (src.visible ? text("Visible", src) : text("Invisible", src))) + dat += "

Refresh" + dat += "

Close" + user << browse(dat, "window=infra") + onclose(user, "infra") + return + + +/obj/item/device/assembly/infra/Topic(href, href_list, state = deep_inventory_state) + if(..()) return 1 + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=infra") + onclose(usr, "infra") return + if(href_list["state"]) + on = !(on) + update_icon() - verb/rotate()//This could likely be better - set name = "Rotate Infrared Laser" - set category = "Object" - set src in usr + if(href_list["visible"]) + visible = !(visible) + spawn(0) + if(first) + first.vis_spread(visible) - set_dir(turn(dir, 90)) + if(href_list["close"]) + usr << browse(null, "window=infra") return + if(usr) + attack_self(usr) + + return + + +/obj/item/device/assembly/infra/verb/rotate()//This could likely be better + set name = "Rotate Infrared Laser" + set category = "Object" + set src in usr + + set_dir(turn(dir, 90)) + return + /***************************IBeam*********************************/ diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index b731905e5f..9daceb384a 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -7,107 +7,107 @@ var/armed = 0 - examine(mob/user) - ..(user) - if(armed) - user << "It looks like it's armed." +/obj/item/device/assembly/mousetrap/examine(mob/user) + ..(user) + if(armed) + to_chat(user, "It looks like it's armed.") +/obj/item/device/assembly/mousetrap/update_icon() + if(armed) + icon_state = "mousetraparmed" + else + icon_state = "mousetrap" + if(holder) + holder.update_icon() + +/obj/item/device/assembly/mousetrap/proc/triggered(mob/target as mob, var/type = "feet") + if(!armed) + return + var/obj/item/organ/external/affecting = null + if(ishuman(target)) + var/mob/living/carbon/human/H = target + switch(type) + if("feet") + if(!H.shoes) + affecting = H.get_organ(pick("l_leg", "r_leg")) + H.Weaken(3) + if("l_hand", "r_hand") + if(!H.gloves) + affecting = H.get_organ(type) + H.Stun(3) + if(affecting) + if(affecting.take_damage(1, 0)) + H.UpdateDamageIcon() + H.updatehealth() + else if(ismouse(target)) + var/mob/living/simple_animal/mouse/M = target + visible_message("\red SPLAT!") + M.splat() + playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) + layer = MOB_LAYER - 0.2 + armed = 0 update_icon() - if(armed) - icon_state = "mousetraparmed" - else - icon_state = "mousetrap" - if(holder) - holder.update_icon() + pulse(0) - proc/triggered(mob/target as mob, var/type = "feet") - if(!armed) + +/obj/item/device/assembly/mousetrap/attack_self(mob/living/user as mob) + if(!armed) + user << "You arm [src]." + else + if((CLUMSY in user.mutations) && prob(50)) + var/which_hand = "l_hand" + if(!user.hand) + which_hand = "r_hand" + triggered(user, which_hand) + user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") return - var/obj/item/organ/external/affecting = null - if(ishuman(target)) - var/mob/living/carbon/human/H = target - switch(type) - if("feet") - if(!H.shoes) - affecting = H.get_organ(pick("l_leg", "r_leg")) - H.Weaken(3) - if("l_hand", "r_hand") - if(!H.gloves) - affecting = H.get_organ(type) - H.Stun(3) - if(affecting) - if(affecting.take_damage(1, 0)) - H.UpdateDamageIcon() - H.updatehealth() - else if(ismouse(target)) - var/mob/living/simple_animal/mouse/M = target - visible_message("\red SPLAT!") - M.splat() - playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) - layer = MOB_LAYER - 0.2 - armed = 0 - update_icon() - pulse(0) + to_chat(user, "You disarm [src].") + armed = !armed + update_icon() + playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3) - attack_self(mob/living/user as mob) - if(!armed) - user << "You arm [src]." - else - if((CLUMSY in user.mutations) && prob(50)) - var/which_hand = "l_hand" - if(!user.hand) - which_hand = "r_hand" - triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - return - user << "You disarm [src]." - armed = !armed - update_icon() - playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3) +/obj/item/device/assembly/mousetrap/attack_hand(mob/living/user as mob) + if(armed) + if((CLUMSY in user.mutations) && prob(50)) + var/which_hand = "l_hand" + if(!user.hand) + which_hand = "r_hand" + triggered(user, which_hand) + user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + return + ..() - attack_hand(mob/living/user as mob) - if(armed) - if((CLUMSY in user.mutations) && prob(50)) - var/which_hand = "l_hand" - if(!user.hand) - which_hand = "r_hand" - triggered(user, which_hand) - user.visible_message("[user] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - return - ..() +/obj/item/device/assembly/mousetrap/Crossed(AM as mob|obj) + if(armed) + if(ishuman(AM)) + var/mob/living/carbon/H = AM + if(H.m_intent == "run") + triggered(H) + H.visible_message("[H] accidentally steps on [src].", \ + "You accidentally step on [src]") + if(ismouse(AM)) + triggered(AM) + ..() - Crossed(AM as mob|obj) - if(armed) - if(ishuman(AM)) - var/mob/living/carbon/H = AM - if(H.m_intent == "run") - triggered(H) - H.visible_message("[H] accidentally steps on [src].", \ - "You accidentally step on [src]") - if(ismouse(AM)) - triggered(AM) - ..() +/obj/item/device/assembly/mousetrap/on_found(mob/living/finder as mob) + if(armed) + finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ + "You accidentally trigger [src]!") + triggered(finder, finder.hand ? "l_hand" : "r_hand") + return 1 //end the search! + return 0 - on_found(mob/living/finder as mob) - if(armed) - finder.visible_message("[finder] accidentally sets off [src], breaking their fingers.", \ - "You accidentally trigger [src]!") - triggered(finder, finder.hand ? "l_hand" : "r_hand") - return 1 //end the search! - return 0 - - - hitby(A as mob|obj) - if(!armed) - return ..() - visible_message("[src] is triggered by [A].") - triggered(null) +/obj/item/device/assembly/mousetrap/hitby(A as mob|obj) + if(!armed) + return ..() + visible_message("[src] is triggered by [A].") + triggered(null) /obj/item/device/assembly/mousetrap/armed @@ -124,4 +124,4 @@ return layer = TURF_LAYER+0.2 - usr << "You hide [src]." \ No newline at end of file + to_chat(usr, "You hide [src].") \ No newline at end of file diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index 2b71743416..0ce769bdc6 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -15,152 +15,147 @@ var/range = 2 - proc - toggle_scan() - sense() +/obj/item/device/assembly/prox_sensor/activate() + if(!..()) return 0//Cooldown check + timing = !timing + update_icon() + return 0 - activate() - if(!..()) return 0//Cooldown check - timing = !timing - update_icon() - return 0 +/obj/item/device/assembly/prox_sensor/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + scanning = 0 + timing = 0 + processing_objects.Remove(src) + update_icon() + return secured - toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - scanning = 0 - timing = 0 - processing_objects.Remove(src) - update_icon() - return secured - - - HasProximity(atom/movable/AM as mob|obj) - if(!istype(AM)) - log_debug("DEBUG: HasProximity called with [AM] on [src] ([usr]).") - return - if (istype(AM, /obj/effect/beam)) return - if (AM.move_speed < 12) sense() +/obj/item/device/assembly/prox_sensor/HasProximity(atom/movable/AM as mob|obj) + if(!istype(AM)) + log_debug("DEBUG: HasProximity called with [AM] on [src] ([usr]).") return + if (istype(AM, /obj/effect/beam)) return + if (AM.move_speed < 12) sense() + return - sense() - var/turf/mainloc = get_turf(src) +/obj/item/device/assembly/prox_sensor/proc/sense() + var/turf/mainloc = get_turf(src) // if(scanning && cooldown <= 0) // mainloc.visible_message("\icon[src] *boop* *boop*", "*boop* *boop*") - if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 - pulse(0) - if(!holder) - mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return + if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 + pulse(0) + if(!holder) + mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return - process() - if(scanning) - var/turf/mainloc = get_turf(src) - for(var/mob/living/A in range(range,mainloc)) - if (A.move_speed < 12) - sense() +/obj/item/device/assembly/prox_sensor/process() + if(scanning) + var/turf/mainloc = get_turf(src) + for(var/mob/living/A in range(range,mainloc)) + if (A.move_speed < 12) + sense() - if(timing && (time >= 0)) - time-- - if(timing && time <= 0) - timing = 0 - toggle_scan() - time = 10 - return + if(timing && (time >= 0)) + time-- + if(timing && time <= 0) + timing = 0 + toggle_scan() + time = 10 + return - dropped() - spawn(0) - sense() - return - return - - - toggle_scan() - if(!secured) return 0 - scanning = !scanning - update_icon() - return - - - update_icon() - overlays.Cut() - attached_overlays = list() - if(timing) - overlays += "prox_timing" - attached_overlays += "prox_timing" - if(scanning) - overlays += "prox_scanning" - attached_overlays += "prox_scanning" - if(holder) - holder.update_icon() - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.primed(scanning) - return - - - Move() - ..() +/obj/item/device/assembly/prox_sensor/dropped() + spawn(0) sense() return + return - interact(mob/user as mob)//TODO: Change this to the wires thingy - if(!secured) - user.show_message("\red The [name] is unsecured!") - return 0 - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("Proximity Sensor\n[] []:[]\n- - + +\n", (timing ? text("Arming", src) : text("Not Arming", src)), minute, second, src, src, src, src) - dat += text("
Range: - [] +", src, range, src) - dat += "
[scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" - dat += "

Refresh" - dat += "

Close" - user << browse(dat, "window=prox") - onclose(user, "prox") +/obj/item/device/assembly/prox_sensor/proc/toggle_scan() + if(!secured) return 0 + scanning = !scanning + update_icon() + return + + +/obj/item/device/assembly/prox_sensor/update_icon() + overlays.Cut() + attached_overlays = list() + if(timing) + overlays += "prox_timing" + attached_overlays += "prox_timing" + if(scanning) + overlays += "prox_scanning" + attached_overlays += "prox_scanning" + if(holder) + holder.update_icon() + if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) + var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc + grenade.primed(scanning) + return + + +/obj/item/device/assembly/prox_sensor/Move() + ..() + sense() + return + + +/obj/item/device/assembly/prox_sensor/interact(mob/user as mob)//TODO: Change this to the wires thingy + if(!secured) + user.show_message("\red The [name] is unsecured!") + return 0 + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("Proximity Sensor\n[] []:[]\n- - + +\n", (timing ? text("Arming", src) : text("Not Arming", src)), minute, second, src, src, src, src) + dat += text("
Range: - [] +", src, range, src) + dat += "
[scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" + dat += "

Refresh" + dat += "

Close" + user << browse(dat, "window=prox") + onclose(user, "prox") + return + + +/obj/item/device/assembly/prox_sensor/Topic(href, href_list, state = deep_inventory_state) + if(..()) return 1 + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=prox") + onclose(usr, "prox") return + if(href_list["scanning"]) + toggle_scan() - Topic(href, href_list) - if(..()) return 1 - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=prox") - onclose(usr, "prox") - return + if(href_list["time"]) + timing = text2num(href_list["time"]) + update_icon() - if(href_list["scanning"]) - toggle_scan() - - if(href_list["time"]) - timing = text2num(href_list["time"]) - update_icon() - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) - - if(href_list["range"]) - var/r = text2num(href_list["range"]) - range += r - range = min(max(range, 1), 5) - - if(href_list["close"]) - usr << browse(null, "window=prox") - return - - if(usr) - attack_self(usr) + if(href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 600) + if(href_list["range"]) + var/r = text2num(href_list["range"]) + range += r + range = min(max(range, 1), 5) + if(href_list["close"]) + usr << browse(null, "window=prox") return + + if(usr) + attack_self(usr) + + + return diff --git a/code/modules/assembly/shock_kit.dm b/code/modules/assembly/shock_kit.dm index edbe0e7491..2bfdbb53cd 100644 --- a/code/modules/assembly/shock_kit.dm +++ b/code/modules/assembly/shock_kit.dm @@ -29,7 +29,7 @@ return if(istype(W, /obj/item/weapon/screwdriver)) status = !status - user << "[src] is now [status ? "secured" : "unsecured"]!" + to_chat(user, "[src] is now [status ? "secured" : "unsecured"]!") add_fingerprint(user) return diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 1273b004a4..43f3c9560e 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -17,171 +17,171 @@ var/datum/radio_frequency/radio_connection var/deadman = 0 - New() - ..() - spawn(40) - set_frequency(frequency) - return +/obj/item/device/assembly/signaler/New() + ..() + spawn(40) + set_frequency(frequency) + return - activate() - if(cooldown > 0) return 0 - cooldown = 2 - spawn(10) - process_cooldown() +/obj/item/device/assembly/signaler/activate() + if(cooldown > 0) return 0 + cooldown = 2 + spawn(10) + process_cooldown() - signal() - return 1 + signal() + return 1 - update_icon() - if(holder) - holder.update_icon() - return +/obj/item/device/assembly/signaler/update_icon() + if(holder) + holder.update_icon() + return - interact(mob/user as mob, flag1) - var/t1 = "-------" +/obj/item/device/assembly/signaler/interact(mob/user as mob, flag1) + var/t1 = "-------" // if ((src.b_stat && !( flag1 ))) // t1 = text("-------
\nGreen Wire: []
\nRed Wire: []
\nBlue Wire: []
\n", (src.wires & 4 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 2 ? text("Cut Wire", src) : text("Mend Wire", src)), (src.wires & 1 ? text("Cut Wire", src) : text("Mend Wire", src))) // else // t1 = "-------" Speaker: [src.listening ? "Engaged" : "Disengaged"]
- var/dat = {" - + var/dat = {" + - Send Signal
- Frequency/Code for signaler:
- Frequency: - - - - - [format_frequency(src.frequency)] - + - +
+Send Signal
+Frequency/Code for signaler:
+Frequency: +- +- +[format_frequency(src.frequency)] ++ ++
- Code: - - - - - [src.code] - + - +
- [t1] -
"} - user << browse(dat, "window=radio") - onclose(user, "radio") +Code: +- +- +[src.code] ++ ++
+[t1] +
"} + user << browse(dat, "window=radio") + onclose(user, "radio") + return + + +/obj/item/device/assembly/signaler/Topic(href, href_list, state = deep_inventory_state) + if(..()) return 1 + + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=radio") + onclose(usr, "radio") return + if (href_list["freq"]) + var/new_frequency = (frequency + text2num(href_list["freq"])) + if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ) + new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) + set_frequency(new_frequency) - Topic(href, href_list) - if(..()) return 1 + if(href_list["code"]) + src.code += text2num(href_list["code"]) + src.code = round(src.code) + src.code = min(100, src.code) + src.code = max(1, src.code) - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=radio") - onclose(usr, "radio") - return + if(href_list["send"]) + spawn( 0 ) + signal() - if (href_list["freq"]) - var/new_frequency = (frequency + text2num(href_list["freq"])) - if(new_frequency < RADIO_LOW_FREQ || new_frequency > RADIO_HIGH_FREQ) - new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ) - set_frequency(new_frequency) + if(usr) + attack_self(usr) - if(href_list["code"]) - src.code += text2num(href_list["code"]) - src.code = round(src.code) - src.code = min(100, src.code) - src.code = max(1, src.code) + return - if(href_list["send"]) - spawn( 0 ) - signal() +/obj/item/device/assembly/signaler/attackby(obj/item/weapon/W, mob/user, params) + if(issignaler(W)) + var/obj/item/device/assembly/signaler/signaler2 = W + if(secured && signaler2.secured) + code = signaler2.code + frequency = signaler2.frequency + to_chat(user, "You transfer the frequency and code of [signaler2] to [src].") + else + ..() - if(usr) - attack_self(usr) +/obj/item/device/assembly/signaler/proc/signal() + if(!radio_connection) return - return - - attackby(obj/item/weapon/W, mob/user, params) - if(issignaler(W)) - var/obj/item/device/assembly/signaler/signaler2 = W - if(secured && signaler2.secured) - code = signaler2.code - frequency = signaler2.frequency - user << "You transfer the frequency and code of [signaler2] to [src]" - else - ..() - - proc/signal() - if(!radio_connection) return - - var/datum/signal/signal = new - signal.source = src - signal.encryption = code - signal.data["message"] = "ACTIVATE" - radio_connection.post_signal(src, signal) - return + var/datum/signal/signal = new + signal.source = src + signal.encryption = code + signal.data["message"] = "ACTIVATE" + radio_connection.post_signal(src, signal) + return /* - for(var/obj/item/device/assembly/signaler/S in world) - if(!S) continue - if(S == src) continue - if((S.frequency == src.frequency) && (S.code == src.code)) - spawn(0) - if(S) S.pulse(0) - return 0*/ + for(var/obj/item/device/assembly/signaler/S in world) + if(!S) continue + if(S == src) continue + if((S.frequency == src.frequency) && (S.code == src.code)) + spawn(0) + if(S) S.pulse(0) + return 0*/ - pulse(var/radio = 0) - if(src.connected && src.wires) - connected.Pulse(src) - else if(holder) - holder.process_activation(src, 1, 0) - else - ..(radio) - return 1 +/obj/item/device/assembly/signaler/pulse(var/radio = 0) + if(src.connected && src.wires) + connected.Pulse(src) + else if(holder) + holder.process_activation(src, 1, 0) + else + ..(radio) + return 1 - receive_signal(datum/signal/signal) - if(!signal) return 0 - if(signal.encryption != code) return 0 - if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 - pulse(1) +/obj/item/device/assembly/signaler/receive_signal(datum/signal/signal) + if(!signal) return 0 + if(signal.encryption != code) return 0 + if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 + pulse(1) - if(!holder) - for(var/mob/O in hearers(1, src.loc)) - O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) + if(!holder) + for(var/mob/O in hearers(1, src.loc)) + O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) + return + + +/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency) + if(!frequency) return - - - proc/set_frequency(new_frequency) - if(!frequency) - return - if(!radio_controller) - sleep(20) - if(!radio_controller) - return - radio_controller.remove_object(src, frequency) - frequency = new_frequency - radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + if(!radio_controller) + sleep(20) + if(!radio_controller) return + radio_controller.remove_object(src, frequency) + frequency = new_frequency + radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) + return - process() - if(!deadman) - processing_objects.Remove(src) - var/mob/M = src.loc - if(!M || !ismob(M)) - if(prob(5)) - signal() - deadman = 0 - processing_objects.Remove(src) - else if(prob(5)) - M.visible_message("[M]'s finger twitches a bit over [src]'s signal button!") - return +/obj/item/device/assembly/signaler/process() + if(!deadman) + processing_objects.Remove(src) + var/mob/M = src.loc + if(!M || !ismob(M)) + if(prob(5)) + signal() + deadman = 0 + processing_objects.Remove(src) + else if(prob(5)) + M.visible_message("[M]'s finger twitches a bit over [src]'s signal button!") + return - verb/deadman_it() - set src in usr - set name = "Threaten to push the button!" - set desc = "BOOOOM!" - deadman = 1 - processing_objects.Add(src) - log_and_message_admins("is threatening to trigger a signaler deadman's switch") - usr.visible_message("\red [usr] moves their finger over [src]'s signal button...") +/obj/item/device/assembly/signaler/verb/deadman_it() + set src in usr + set name = "Threaten to push the button!" + set desc = "BOOOOM!" + deadman = 1 + processing_objects.Add(src) + log_and_message_admins("is threatening to trigger a signaler deadman's switch") + usr.visible_message("\red [usr] moves their finger over [src]'s signal button...") /obj/item/device/assembly/signaler/Destroy() if(radio_controller) diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index cdd927afd6..810c5ec3b5 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -2,8 +2,8 @@ name = "timer" desc = "Used to time things. Works well with contraptions which has to count down. Tick tock." icon_state = "timer" - origin_tech = list(TECH_MAGNET = 1) - matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10) + origin_tech = list(TECH_MAGNET = 1) + matter = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 50, "waste" = 10) wires = WIRE_PULSE @@ -12,97 +12,94 @@ var/timing = 0 var/time = 10 - proc - timer_end() +/obj/item/device/assembly/timer/activate() + if(!..()) return 0//Cooldown check - activate() - if(!..()) return 0//Cooldown check - - timing = !timing - - update_icon() - return 0 - - - toggle_secure() - secured = !secured - if(secured) - processing_objects.Add(src) - else - timing = 0 - processing_objects.Remove(src) - update_icon() - return secured - - - timer_end() - if(!secured) return 0 - pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") - cooldown = 2 - spawn(10) - process_cooldown() - return - - - process() - if(timing && (time > 0)) - time-- - if(timing && time <= 0) - timing = 0 - timer_end() - time = 10 - return - + timing = !timing update_icon() - overlays.Cut() - attached_overlays = list() - if(timing) - overlays += "timer_timing" - attached_overlays += "timer_timing" - if(holder) - holder.update_icon() + return 0 + + +/obj/item/device/assembly/timer/toggle_secure() + secured = !secured + if(secured) + processing_objects.Add(src) + else + timing = 0 + processing_objects.Remove(src) + update_icon() + return secured + + +/obj/item/device/assembly/timer/proc/timer_end() + if(!secured) return 0 + pulse(0) + if(!holder) + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + cooldown = 2 + spawn(10) + process_cooldown() + return + + +/obj/item/device/assembly/timer/process() + if(timing && (time > 0)) + time-- + if(timing && time <= 0) + timing = 0 + timer_end() + time = 10 + return + + +/obj/item/device/assembly/timer/update_icon() + overlays.Cut() + attached_overlays = list() + if(timing) + overlays += "timer_timing" + attached_overlays += "timer_timing" + if(holder) + holder.update_icon() + return + + +/obj/item/device/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires + if(!secured) + user.show_message("\red The [name] is unsecured!") + return 0 + var/second = time % 60 + var/minute = (time - second) / 60 + var/dat = text("Timing Unit\n[] []:[]\n- - + +\n", (timing ? text("Timing", src) : text("Not Timing", src)), minute, second, src, src, src, src) + dat += "

Refresh" + dat += "

Close" + user << browse(dat, "window=timer") + onclose(user, "timer") + return + + +/obj/item/device/assembly/timer/Topic(href, href_list, state = deep_inventory_state) + if(..()) return 1 + if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) + usr << browse(null, "window=timer") + onclose(usr, "timer") return + if(href_list["time"]) + timing = text2num(href_list["time"]) + update_icon() - interact(mob/user as mob)//TODO: Have this use the wires - if(!secured) - user.show_message("\red The [name] is unsecured!") - return 0 - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = text("Timing Unit\n[] []:[]\n- - + +\n", (timing ? text("Timing", src) : text("Not Timing", src)), minute, second, src, src, src, src) - dat += "

Refresh" - dat += "

Close" - user << browse(dat, "window=timer") - onclose(user, "timer") + if(href_list["tp"]) + var/tp = text2num(href_list["tp"]) + time += tp + time = min(max(round(time), 0), 600) + + if(href_list["close"]) + usr << browse(null, "window=timer") return + if(usr) + attack_self(usr) - Topic(href, href_list) - if(..()) return 1 - if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr)) - usr << browse(null, "window=timer") - onclose(usr, "timer") - return - - if(href_list["time"]) - timing = text2num(href_list["time"]) - update_icon() - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) - - if(href_list["close"]) - usr << browse(null, "window=timer") - return - - if(usr) - attack_self(usr) - - return + return diff --git a/code/modules/examine/descriptions/devices.dm b/code/modules/examine/descriptions/devices.dm index 33954f6672..7b5c0019a4 100644 --- a/code/modules/examine/descriptions/devices.dm +++ b/code/modules/examine/descriptions/devices.dm @@ -19,4 +19,14 @@ up to 18,446,744,073,709,551,616 unique addresses, one of which is assigned to this device." description_antag = "Electromagnetic pulses will cause the device to disconnect all linked communicators. Turning off the Exonet node at the Telecomms \ - satellite will also accomplish this, but for all communicators on and near the station. This may be needed to allow for a quiet kill or capture." \ No newline at end of file + satellite will also accomplish this, but for all communicators on and near the station. This may be needed to allow for a quiet kill or capture." + +/obj/item/device/electronic_assembly/device + description_info = "This is the guts of a 'device' type electronic assembly, and can either be used in this form or can be used inside of the assembly to \ + allow it to interact with other assembly type devices (igniter, signaler, proximity sensor, etc). This device has unique inputs that allow it to either send \ + or receive pulsed signals from an attached items when inside an electronic assembly device frame (looks not unlike a signaler). Ensure the assembly is closed \ + before placing it inside the frame." + +/obj/item/device/assembly/electronic_assembly + description_info = "This is the casing for the 'device' type of electronic assembly. It behaves like any other 'assembly' type device such as an igniter or signaler \ + and can be attached to others in the same way. Use the 'toggle-open' verb (right click) or a crowbar to pop the electronic device open to add components and close when finished." \ No newline at end of file diff --git a/code/modules/integrated_electronics/_defines.dm b/code/modules/integrated_electronics/_defines.dm index 7089c19d51..47a5e40b22 100644 --- a/code/modules/integrated_electronics/_defines.dm +++ b/code/modules/integrated_electronics/_defines.dm @@ -31,9 +31,10 @@ var/list/all_integrated_circuits = list() var/extended_desc = null var/list/inputs = list() var/list/outputs = list() - var/list/activators = list() + var/list/activators = list() //associated_list, = 1 for inbound, = 0 for outbound 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 = null //This acts as a limitation on building machines, bigger components cost more 'space'. -1 for size 0 var/cooldown_per_use = 1 SECOND // 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. @@ -41,5 +42,6 @@ var/list/all_integrated_circuits = list() var/category_text = "NO CATEGORY THIS IS A BUG" // To show up on circuit printer, and perhaps other places. var/autopulse = -1 // When input is received, the circuit will pulse itself if set to 1. 0 means it won't. -1 means it is permanently off. var/removable = TRUE // Determines if a circuit is removable from the assembly. - - + var/displayed_name = "" + var/allow_multitool = 1 // Allows additional multitool functionality + // Used as a global var, (Do not set manually in children). diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index 5c49e1817c..a4d292488d 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -1,5 +1,5 @@ #define IC_COMPONENTS_BASE 20 -#define IC_COMPLEXITY_BASE 80 +#define IC_COMPLEXITY_BASE 60 /obj/item/device/electronic_assembly name = "electronic assembly" @@ -13,6 +13,7 @@ var/opened = 0 var/obj/item/weapon/cell/device/battery = null // Internal cell which most circuits need to work. + /obj/item/device/electronic_assembly/medium name = "electronic mechanism" icon_state = "setup_medium" @@ -38,8 +39,8 @@ name = "electronic implant" icon_state = "setup_implant" w_class = ITEMSIZE_TINY - max_components = IC_COMPONENTS_BASE / 2 - max_complexity = IC_COMPLEXITY_BASE / 2 + max_components = IC_COMPONENTS_BASE / 4 + max_complexity = IC_COMPLEXITY_BASE / 4 var/obj/item/weapon/implant/integrated_circuit/implant = null /obj/item/device/electronic_assembly/New() @@ -82,14 +83,19 @@ /obj/item/device/electronic_assembly/implant/resolve_nano_host() return implant -/obj/item/device/electronic_assembly/interact(mob/user) +/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user) if(!CanInteract(user, physical_state)) + return 0 + return 1 + +/obj/item/device/electronic_assembly/interact(mob/user) + if(!check_interactivity(user)) return var/total_parts = 0 var/total_complexity = 0 for(var/obj/item/integrated_circuit/part in contents) - total_parts++ + total_parts += part.size total_complexity = total_complexity + part.complexity var/HTML = list() @@ -103,14 +109,30 @@ else HTML += "No powercell detected!" HTML += "

" - HTML += "Components;
" + HTML += "Components:
" + HTML += "Built in:
" + + +//Put removable circuits in separate categories from non-removable + for(var/obj/item/integrated_circuit/circuit in contents) + if(!circuit.removable) + HTML += "[circuit.displayed_name] | " + HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " + HTML += "\[Move to Bottom\]" + HTML += "
" + + HTML += "
" + HTML += "Removable:
" + for(var/obj/item/integrated_circuit/circuit in contents) - HTML += "[circuit.name] | " - HTML += "\[Rename\] | " - HTML += "\[Scan with Debugger\] | " if(circuit.removable) - HTML += "\[Remove\]" - HTML += "
" + HTML += "[circuit.displayed_name] | " + HTML += "\[Rename\] | " + HTML += "\[Scan with Debugger\] | " + HTML += "\[Remove\] | " + HTML += "\[Move to Bottom\]" + HTML += "
" HTML += "" user << browse(jointext(HTML,null), "window=assembly-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1") @@ -140,11 +162,11 @@ set desc = "Rename your circuit, useful to stay organized." var/mob/M = usr - if(!CanInteract(M, physical_state)) + if(!check_interactivity(M)) return var/input = sanitizeSafe(input("What do you want to name this?", "Rename", src.name) as null|text, MAX_NAME_LEN) - if(src && input && CanInteract(M, physical_state)) + if(src && input) to_chat(M, "The machine now has a label reading '[input]'.") name = input @@ -191,7 +213,7 @@ /obj/item/device/electronic_assembly/proc/get_part_size() . = 0 for(var/obj/item/integrated_circuit/part in contents) - . += part.w_class + . += 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) @@ -206,7 +228,7 @@ var/total_part_size = get_part_size() var/total_complexity = get_part_complexity() - if((total_part_size + IC.w_class) > max_components) + if((total_part_size + IC.size) > max_components) to_chat(user, "You can't seem to add the '[IC.name]', as there's insufficient space.") return FALSE if((total_complexity + IC.complexity) > max_complexity) @@ -234,16 +256,18 @@ /obj/item/device/electronic_assembly/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/integrated_circuit)) if(!user.unEquip(I)) - return 0 + return FALSE if(add_circuit(I, user)) to_chat(user, "You slide \the [I] inside \the [src].") playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) interact(user) + return TRUE else if(istype(I, /obj/item/weapon/crowbar)) playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) opened = !opened to_chat(user, "You [opened ? "opened" : "closed"] \the [src].") 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/weapon/screwdriver)) if(opened) interact(user) @@ -264,20 +288,38 @@ playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1) to_chat(user, "You slot \the [cell] inside \the [src]'s power supplier.") 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/obj/item/integrated_circuit/input/choice = input(user, "What do you want to interact with?", "Interaction") as null|anything in available_inputs - if(choice && CanInteract(user, physical_state)) + 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.name]\]" + if(i) + disp_name += " ([i+1])" + input_selection.Add(disp_name) + + var/obj/item/integrated_circuit/input/choice + if(available_inputs) + var/selection = input(user, "What do you want to interact with?", "Interaction") as null|anything in input_selection + 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) @@ -295,4 +337,5 @@ /obj/item/device/electronic_assembly/proc/give_power(amount) if(battery && battery.give(amount * CELLRATE)) return TRUE - return FALSE \ No newline at end of file + return FALSE + diff --git a/code/modules/integrated_electronics/core/device.dm b/code/modules/integrated_electronics/core/device.dm new file mode 100644 index 0000000000..6b89a299a4 --- /dev/null +++ b/code/modules/integrated_electronics/core/device.dm @@ -0,0 +1,84 @@ +/obj/item/device/assembly/electronic_assembly + name = "electronic device" + desc = "It's a case for building electronics with. It can be attached to other small devices." + icon_state = "setup_device" + var/opened = 0 + + var/obj/item/device/electronic_assembly/device/EA + +/obj/item/device/assembly/electronic_assembly/New() + EA = new(src) + EA.holder = src + ..() + +/obj/item/device/assembly/electronic_assembly/attackby(obj/item/I as obj, mob/user as mob) + if (iscrowbar(I) ) + toggle_open(user) + else if (opened) + EA.attackby(I, user) + else + ..() + +/obj/item/device/assembly/electronic_assembly/proc/toggle_open(mob/user) + playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) + opened = !opened + EA.opened = opened + to_chat(user, "You [opened ? "opened" : "closed"] \the [src].") + secured = 1 + update_icon() + +/obj/item/device/assembly/electronic_assembly/update_icon() + if(EA) + icon_state = initial(icon_state) + else + icon_state = initial(icon_state)+"0" + if(opened) + icon_state = icon_state + "-open" + +/obj/item/device/assembly/electronic_assembly/attack_self(mob/user as mob) + if(EA) + EA.attack_self(user) + +/obj/item/device/assembly/electronic_assembly/pulsed(var/radio = 0) //Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs + if(EA) + for(var/obj/item/integrated_circuit/built_in/device_input/I in EA.contents) + I.do_work() + return + +/obj/item/device/assembly/electronic_assembly/examine(mob/user) + .=..(user, 1) + if(EA) + for(var/obj/item/integrated_circuit/IC in EA.contents) + IC.external_examine(user) + +/obj/item/device/assembly/electronic_assembly/verb/toggle() + set src in usr + set category = "Object" + set name = "Open/Close Device Assembly" + set desc = "Open or close device assembly!" + + toggle_open(usr) + + +/obj/item/device/electronic_assembly/device + name = "electronic device" + icon_state = "setup_device" + desc = "It's a tiny electronic device with specific use for attaching to other devices." + var/obj/item/device/assembly/electronic_assembly/holder + w_class = ITEMSIZE_TINY + max_components = IC_COMPONENTS_BASE * 3/4 + max_complexity = IC_COMPLEXITY_BASE * 3/4 + + +/obj/item/device/electronic_assembly/device/New() + ..() + var/obj/item/integrated_circuit/built_in/device_input/input = new(src) + var/obj/item/integrated_circuit/built_in/device_output/output = new(src) + input.assembly = src + output.assembly = src + +/obj/item/device/electronic_assembly/device/check_interactivity(mob/user) + if(!CanInteract(user, state = deep_inventory_state)) + return 0 + return 1 + diff --git a/code/modules/integrated_electronics/core/helpers.dm b/code/modules/integrated_electronics/core/helpers.dm index c98d74e79f..49779a4993 100644 --- a/code/modules/integrated_electronics/core/helpers.dm +++ b/code/modules/integrated_electronics/core/helpers.dm @@ -42,3 +42,17 @@ return null return activators[pin_number] return null + +/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 1 + + 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 1 + return 0 \ No newline at end of file diff --git a/code/modules/integrated_electronics/core/integrated_circuit.dm b/code/modules/integrated_electronics/core/integrated_circuit.dm index 1593297734..7c2a8100ea 100644 --- a/code/modules/integrated_electronics/core/integrated_circuit.dm +++ b/code/modules/integrated_electronics/core/integrated_circuit.dm @@ -4,9 +4,9 @@ a creative player the means to solve many problems. Circuits are held inside an */ /obj/item/integrated_circuit/examine(mob/user) - . = ..() - external_examine(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) @@ -31,6 +31,9 @@ a creative player the means to solve many problems. Circuits are held inside an return /obj/item/integrated_circuit/New() + displayed_name = name + if(!size) size = w_class + if(size == -1) size = 0 setup_io(inputs, /datum/integrated_io/input) setup_io(outputs, /datum/integrated_io/output) setup_io(activators, /datum/integrated_io/activate) @@ -58,22 +61,31 @@ a creative player the means to solve many problems. Circuits are held inside an for(var/datum/integrated_io/io in inputs + outputs + activators) io.scramble() +/obj/item/integrated_circuit/proc/check_interactivity(mob/user) + if(assembly) + return assembly.check_interactivity(user) + else if(!CanInteract(user, physical_state)) + return 0 + return 1 + /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(!CanInteract(M, physical_state)) + if(!check_interactivity(M)) return var/input = sanitizeSafe(input("What do you want to name the circuit?", "Rename", src.name) as null|text, MAX_NAME_LEN) - if(src && input && CanInteract(M, physical_state)) + if(src && input && assembly.check_interactivity(M)) to_chat(M, "The circuit '[src.name]' is now labeled '[input]'.") - name = input + displayed_name = input /obj/item/integrated_circuit/interact(mob/user) - if(!CanInteract(user, physical_state)) + if(!check_interactivity(user)) + return + if(!assembly) return var/window_height = 350 @@ -85,14 +97,17 @@ a creative player the means to solve many problems. Circuits are held inside an var/table_middle_width = "40%" var/HTML = list() - HTML += "[src.name]" + HTML += "[src.displayed_name]" HTML += "
" HTML += "" + HTML += "
\[Return to Assembly\]" + HTML += "
\[Refresh\] | " HTML += "\[Rename\] | " - HTML += "\[Scan with Debugger\] | " - HTML += "\[Remove\]
" + HTML += "\[Scan with Device\] | " + if(src.removable) + HTML += "\[Remove\]
" HTML += "" HTML += "" @@ -113,37 +128,31 @@ a creative player the means to solve many problems. Circuits are held inside an if(1) io = get_pin_ref(IC_INPUT, i) if(io) + words += "[io.name] [io.display_data()]
" if(io.linked.len) - words += "[io.name] [io.display_data()]
" for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" +// words += "\[[linked.name]\] + words += "[linked.name] \ + @ [linked.holder.displayed_name]
" + if(outputs.len > inputs.len) height = 1 if(2) if(i == 1) - words += "[src.name]

[src.desc]" + words += "[src.displayed_name]
([src.name])
[src.desc]" height = row_height else continue if(3) io = get_pin_ref(IC_OUTPUT, i) if(io) + words += "[io.name] [io.display_data()]
" if(io.linked.len) - words += "[io.name] [io.display_data()]
" for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name] [io.display_data()]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" +// words += "\[[linked.name]\] + words += "[linked.name] \ + @ [linked.holder.displayed_name]
" + if(inputs.len > outputs.len) height = 1 HTML += "" @@ -152,16 +161,14 @@ a creative player the means to solve many problems. Circuits are held inside an for(var/activator in activators) var/datum/integrated_io/io = activator var/words = list() + + words += "[io.name] [io.data?"\":"\"]
" if(io.linked.len) - words += "[io.name]
" for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" - else - words += "[io.name]
" - for(var/datum/integrated_io/linked in io.linked) - words += "\[[linked.name]\] \ - @ [linked.holder]
" +// words += "\[[linked.name]\] + words += "[linked.name] \ + @ [linked.holder.displayed_name]
" + HTML += "" HTML += "" HTML += "" @@ -182,20 +189,92 @@ a creative player the means to solve many problems. Circuits are held inside an HTML += "
[extended_desc]" HTML += "" - 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") + 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, "circuit-\ref[src]") + onclose(user, "assembly-\ref[src.assembly]") -/obj/item/integrated_circuit/Topic(href, href_list, state = physical_state) +/obj/item/integrated_circuit/Topic(href, href_list, state = interactive_state) + if(!check_interactivity(usr)) + return if(..()) return 1 - var/pin = locate(href_list["pin"]) in inputs + outputs + activators + + var/update = 1 + var/obj/item/device/electronic_assembly/A = src.assembly + var/update_to_assembly = 0 + 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_hand() + + if(href_list["rename"]) + rename_component(usr) + if(href_list["from_assembly"]) + update = 0 + 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"] = 1 + 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"] = 1 + + else + var/datum/integrated_io/io = pin + 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, "You input [new_data] into the pin.") + //to_chat(user, "You write '[new_data]' to the '[io]' pin of \the [io.holder].") + 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, "You input [new_data] into the pin.") + if("null") + if(check_interactivity(usr)) + to_chat(usr, "You clear the pin's memory.") + + 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, "You pulse \the [io.holder]'s [io] pin.") + + + if(href_list["pin_unwire"]) + if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool) + href_list["wire"] = 1 + 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(pin) + if(linked) + wirer.wire(linked, usr) + else if(pin) wirer.wire(pin, usr) else if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) @@ -206,10 +285,23 @@ a creative player the means to solve many problems. Circuits are held inside an to_chat(usr, "You can't do a whole lot without the proper tools.") if(href_list["examine"]) - examine(usr) + var/obj/item/integrated_circuit/examined + if(href_list["examined"]) + examined = href_list["examined"] + else + examined = src + examined.interact(usr) + update = 0 - if(href_list["rename"]) - rename_component(usr) + 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 + . = 1 + update_to_assembly = 1 if(href_list["scan"]) if(istype(held_item, /obj/item/device/integrated_electronics/debugger)) @@ -219,31 +311,47 @@ a creative player the means to solve many problems. Circuits are held inside an else to_chat(usr, "The Debugger's 'ref scanner' needs to be on.") else - to_chat(usr, "You need a Debugger set to 'ref' mode to do that.") + to_chat(usr, "You need a multitool/debugger set to 'ref' mode to do that.") if(href_list["autopulse"]) if(autopulse != -1) autopulse = !autopulse - if(href_list["remove"]) - if(istype(held_item, /obj/item/weapon/screwdriver)) - if(!removable) - to_chat(usr, "\The [src] seems to be permanently attached to the case.") - return - disconnect_all() - var/turf/T = get_turf(src) - forceMove(T) - assembly = null - playsound(T, 'sound/items/Crowbar.ogg', 50, 1) - to_chat(usr, "You pop \the [src] out of the case, and slide it out.") + if(href_list["return"]) + if(A) + update_to_assembly = 1 + usr << browse(null, "window=circuit-\ref[src];border=1;can_resize=1;can_close=1;can_minimize=1") else - to_chat(usr, "You need a screwdriver to remove components.") + to_chat(usr, "This circuit is not in an assembly!") + + + if(href_list["remove"]) + if(!A) + to_chat(usr, "This circuit is not in an assembly!") + return + if(!removable) + to_chat(usr, "\The [src] seems to be permanently attached to the case.") + 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, "You pop \the [src] out of the case, and slide it out.") + if(istype(ea)) ea.interact(usr) + update = 0 return - interact(usr) // To refresh the UI. + 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/datum/integrated_io/output/O in outputs) diff --git a/code/modules/integrated_electronics/core/tools.dm b/code/modules/integrated_electronics/core/tools.dm index a875917441..08765b94e5 100644 --- a/code/modules/integrated_electronics/core/tools.dm +++ b/code/modules/integrated_electronics/core/tools.dm @@ -165,6 +165,89 @@ io.holder.interact(user) // This is to update the UI. + + + +/obj/item/device/multitool + var/datum/integrated_io/selected_io = null + var/mode = 0 + +/obj/item/device/multitool/attack_self(mob/user) + if(selected_io) + selected_io = null + to_chat(user, "You clear the wired connection from the multitool.") + else + ..() + update_icon() + +/obj/item/device/multitool/update_icon() + if(selected_io) + if(buffer || connecting || connectable) + icon_state = "multitool_tracking" + else + icon_state = "multitool_red" + else + if(buffer || connecting || connectable) + icon_state = "multitool_tracking_fail" + else + icon_state = "multitool" + +/obj/item/device/multitool/proc/wire(var/datum/integrated_io/io, mob/user) + if(!io.holder.assembly) + to_chat(user, "\The [io.holder] needs to be secured inside an assembly first.") + return + + if(selected_io) + if(io == selected_io) + to_chat(user, "Wiring \the [selected_io.holder]'s [selected_io.name] into itself is rather pointless.") + return + if(io.io_type != selected_io.io_type) + to_chat(user, "Those two types of channels are incompatable. The first is a [selected_io.io_type], \ + while the second is a [io.io_type].") + return + if(io.holder.assembly && io.holder.assembly != selected_io.holder.assembly) + to_chat(user, "Both \the [io.holder] and \the [selected_io.holder] need to be inside the same assembly.") + return + selected_io.linked |= io + io.linked |= selected_io + + to_chat(user, "You connect \the [selected_io.holder]'s [selected_io.name] to \the [io.holder]'s [io.name].") + selected_io.holder.interact(user) // This is to update the UI. + selected_io = null + + else + selected_io = io + to_chat(user, "You link \the multitool to \the [selected_io.holder]'s [selected_io.name] data channel.") + + update_icon() + + +/obj/item/device/multitool/proc/unwire(var/datum/integrated_io/io1, var/datum/integrated_io/io2, mob/user) + if(!io1.linked.len || !io2.linked.len) + to_chat(user, "There is nothing connected to the data channel.") + return + + if(!(io1 in io2.linked) || !(io2 in io1.linked) ) + to_chat(user, "These data pins aren't connected!") + return + else + io1.linked.Remove(io2) + io2.linked.Remove(io1) + to_chat(user, "You clip the data connection between the [io1.holder.displayed_name]'s \ + [io1.name] and the [io2.holder.displayed_name]'s [io2.name].") + io1.holder.interact(user) // This is to update the UI. + update_icon() + + + + + + + + + + + /obj/item/weapon/storage/bag/circuits name = "circuit kit" desc = "This kit's essential for any circuitry projects." @@ -178,7 +261,8 @@ /obj/item/device/electronic_assembly, /obj/item/device/integrated_electronics, /obj/item/weapon/crowbar, - /obj/item/weapon/screwdriver + /obj/item/weapon/screwdriver, + /obj/item/device/multitool ) /obj/item/weapon/storage/bag/circuits/basic/New() @@ -186,7 +270,7 @@ spawn(2 SECONDS) // So the list has time to initialize. // for(var/obj/item/integrated_circuit/IC in all_integrated_circuits) // if(IC.spawn_flags & IC_SPAWN_DEFAULT) -// for(var/i = 1 to 3) +// for(var/i = 1 to 4) // new IC.type(src) new /obj/item/weapon/storage/bag/circuits/mini/arithmetic(src) new /obj/item/weapon/storage/bag/circuits/mini/trig(src) @@ -201,10 +285,11 @@ new /obj/item/weapon/storage/bag/circuits/mini/power(src) new /obj/item/device/electronic_assembly(src) - new /obj/item/device/integrated_electronics/wirer(src) - new /obj/item/device/integrated_electronics/debugger(src) - new /obj/item/weapon/crowbar(src) + new /obj/item/device/assembly/electronic_assembly(src) + new /obj/item/device/assembly/electronic_assembly(src) + new /obj/item/device/multitool(src) new /obj/item/weapon/screwdriver(src) + new /obj/item/weapon/crowbar(src) make_exact_fit() /obj/item/weapon/storage/bag/circuits/all/New() @@ -231,7 +316,6 @@ new /obj/item/device/integrated_electronics/wirer(src) new /obj/item/device/integrated_electronics/debugger(src) new /obj/item/weapon/crowbar(src) - new /obj/item/weapon/screwdriver(src) make_exact_fit() /obj/item/weapon/storage/bag/circuits/mini/ @@ -254,7 +338,7 @@ ..() for(var/obj/item/integrated_circuit/arithmetic/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -271,7 +355,7 @@ ..() for(var/obj/item/integrated_circuit/trig/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -288,7 +372,7 @@ ..() for(var/obj/item/integrated_circuit/input/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -305,7 +389,7 @@ ..() for(var/obj/item/integrated_circuit/output/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -322,7 +406,7 @@ ..() for(var/obj/item/integrated_circuit/memory/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -339,7 +423,7 @@ ..() for(var/obj/item/integrated_circuit/logic/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -356,7 +440,7 @@ ..() for(var/obj/item/integrated_circuit/time/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -373,7 +457,7 @@ ..() for(var/obj/item/integrated_circuit/reagent/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -390,7 +474,7 @@ ..() for(var/obj/item/integrated_circuit/transfer/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -407,7 +491,7 @@ ..() for(var/obj/item/integrated_circuit/converter/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -423,7 +507,7 @@ ..() for(var/obj/item/integrated_circuit/smart/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -439,7 +523,7 @@ ..() for(var/obj/item/integrated_circuit/manipulation/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() @@ -456,10 +540,10 @@ ..() for(var/obj/item/integrated_circuit/passive/power/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) for(var/obj/item/integrated_circuit/power/IC in all_integrated_circuits) if(IC.spawn_flags & spawn_flags_to_use) - for(var/i = 1 to 3) + for(var/i = 1 to 4) new IC.type(src) make_exact_fit() \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/arithmetic.dm b/code/modules/integrated_electronics/subtypes/arithmetic.dm index 059c699e50..48ad90928a 100644 --- a/code/modules/integrated_electronics/subtypes/arithmetic.dm +++ b/code/modules/integrated_electronics/subtypes/arithmetic.dm @@ -12,7 +12,7 @@ "\ H" ) outputs = list("\ result") - activators = list("\ compute", "\ on computed") + activators = list("compute" = 1, "on computed" = 0) category_text = "Arithmetic" autopulse = 1 power_draw_per_use = 5 // Math is pretty cheap. diff --git a/code/modules/integrated_electronics/subtypes/built_in.dm b/code/modules/integrated_electronics/subtypes/built_in.dm new file mode 100644 index 0000000000..e4a6d8e1b4 --- /dev/null +++ b/code/modules/integrated_electronics/subtypes/built_in.dm @@ -0,0 +1,28 @@ +/obj/item/integrated_circuit/built_in + 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" + size = -1 + w_class = ITEMSIZE_TINY + removable = FALSE // Determines if a circuit is removable from the assembly. + +/obj/item/integrated_circuit/built_in/device_input + name = "assembly input" + desc = "A built in chip for handling pulses from attached assembly items." + complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. + activators = list("on pulsed" = 0) + +/obj/item/integrated_circuit/built_in/device_input/do_work() + activate_pin(1) + +/obj/item/integrated_circuit/built_in/device_output + name = "assembly out" + desc = "A built in chip for pulsing attached assembly items." + complexity = 0 //This acts as a limitation on building machines, more resource-intensive components cost more 'space'. + activators = list("pulse attached" = 1) + +/obj/item/integrated_circuit/built_in/device_output/do_work() + if(istype(assembly, /obj/item/device/electronic_assembly/device)) + var/obj/item/device/electronic_assembly/device/device = assembly + device.holder.pulse() \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/converters.dm b/code/modules/integrated_electronics/subtypes/converters.dm index 431faa241f..498b20a7a0 100644 --- a/code/modules/integrated_electronics/subtypes/converters.dm +++ b/code/modules/integrated_electronics/subtypes/converters.dm @@ -3,7 +3,7 @@ complexity = 2 inputs = list("input") outputs = list("output") - activators = list("\ convert", "\ on convert") + activators = list("convert" = 1, "on convert" = 0) category_text = "Converter" autopulse = 1 power_draw_per_use = 10 @@ -15,6 +15,7 @@ /obj/item/integrated_circuit/converter/num2text name = "number to string" desc = "This circuit can convert a number variable into a string." + extended_desc = "Because of game limitations null/false variables will output a '0' string." icon_state = "num-string" inputs = list("\ input") outputs = list("\ output") @@ -26,6 +27,8 @@ var/incoming = get_pin_data(IC_INPUT, 1) if(incoming && isnum(incoming)) result = num2text(incoming) + else if(!incoming) + result = "0" set_pin_data(IC_OUTPUT, 1, result) push_data() @@ -107,8 +110,8 @@ push_data() activate_pin(2) -/obj/item/integrated_circuit/converter/concatenatior - name = "concatenatior" +/obj/item/integrated_circuit/converter/concatenator + name = "concatenator" desc = "This joins many strings or numbers together to get one big string." complexity = 4 inputs = list( @@ -122,10 +125,10 @@ "\ H" ) outputs = list("\ result") - activators = list("\ concatenate", "\ on concatenated") + activators = list("concatenate" = 1, "on concatenated" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH -/obj/item/integrated_circuit/converter/concatenatior/do_work() +/obj/item/integrated_circuit/converter/concatenator/do_work() var/result = null for(var/datum/integrated_io/input/I in inputs) I.pull_data() @@ -139,6 +142,44 @@ outgoing.push_data() activate_pin(2) +/obj/item/integrated_circuit/converter/separator + name = "separator" + desc = "This splits as single string into two at the relative split point." + extended_desc = "This circuits splits a given string into two, based on the string, and the index value. \ + The index splits the string after the given index, including spaces. So 'a person' with an index of '3' \ + will split into 'a p' and 'erson'." + complexity = 4 + inputs = list( + "\ string", + "\ index", + ) + outputs = list( + "\ before split", + "\ after split" + ) + activators = list("separate" = 1, "on separated" = 0) + spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH + + +/obj/item/integrated_circuit/converter/separator/do_work() + var/text = get_pin_data(IC_INPUT, 1) + var/index = get_pin_data(IC_INPUT, 2) + + var/split = min(index+1, length(text)) + + var/before_text = copytext(text, 1, split) + var/after_text = copytext(text, split, 0) + + var/datum/integrated_io/outgoing1 = outputs[1] + var/datum/integrated_io/outgoing2 = outputs[2] + outgoing1.data = before_text + outgoing2.data = after_text + outgoing1.push_data() + outgoing2.push_data() + + activate_pin(2) + + /obj/item/integrated_circuit/converter/radians2degrees name = "radians to degrees converter" desc = "Converts radians to degrees." @@ -182,7 +223,7 @@ complexity = 4 inputs = list("\ X1", "\ Y1", "\ X2", "\ Y2") outputs = list("\ X", "\ Y") - activators = list("\ compute rel coordinates", "\ on convert") + activators = list("compute rel coordinates" = 1, "on convert" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/converter/abs_to_rel_coords/do_work() diff --git a/code/modules/integrated_electronics/subtypes/data_transfer.dm b/code/modules/integrated_electronics/subtypes/data_transfer.dm index c5fe9741be..92a807906f 100644 --- a/code/modules/integrated_electronics/subtypes/data_transfer.dm +++ b/code/modules/integrated_electronics/subtypes/data_transfer.dm @@ -44,9 +44,9 @@ icon_state = "splitter" complexity = 3 activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B" + "pulse" = 1, + "pulse A" = 0, + "pulse B" = 0 ) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 @@ -64,11 +64,11 @@ icon_state = "splitter4" complexity = 5 activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B", - "outgoing pulse C", - "outgoing pulse D" + "pulse" = 1, + "pulse A" = 0, + "pulse B" = 0, + "pulse C" = 0, + "pulse D" = 0 ) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -79,15 +79,15 @@ w_class = ITEMSIZE_SMALL complexity = 9 activators = list( - "incoming pulse", - "outgoing pulse A", - "outgoing pulse B", - "outgoing pulse C", - "outgoing pulse D", - "outgoing pulse E", - "outgoing pulse F", - "outgoing pulse G", - "outgoing pulse H" + "incoming pulse" = 1, + "outgoing pulse A" = 0, + "outgoing pulse B" = 0, + "outgoing pulse C" = 0, + "outgoing pulse D" = 0, + "outgoing pulse E" = 0, + "outgoing pulse F" = 0, + "outgoing pulse G" = 0, + "outgoing pulse H" = 0 ) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 8 @@ -101,7 +101,7 @@ icon_state = "mux2" inputs = list("input selection") outputs = list("output") - activators = list("select") + activators = list("select" = 1, "on select" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 var/number_of_inputs = 2 @@ -120,7 +120,10 @@ if(isnum(input_index) && (input_index >= 1 && input_index < inputs.len)) output = get_pin_data(IC_INPUT, input_index + 1) + set_pin_data(IC_OUTPUT, 1, output) + push_data() + activate_pin(2) /obj/item/integrated_circuit/transfer/multiplexer/medium name = "four multiplexer" @@ -147,7 +150,7 @@ icon_state = "dmux2" inputs = list("output selection","input") outputs = list() - activators = list("select") + activators = list("select" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 var/number_of_outputs = 2 diff --git a/code/modules/integrated_electronics/subtypes/input_output.dm b/code/modules/integrated_electronics/subtypes/input_output.dm index 1a4fdb7c45..9b666267a4 100644 --- a/code/modules/integrated_electronics/subtypes/input_output.dm +++ b/code/modules/integrated_electronics/subtypes/input_output.dm @@ -14,7 +14,7 @@ can_be_asked_input = 1 inputs = list() outputs = list() - activators = list("\ on pressed") + activators = list("on pressed" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/button/ask_for_input(mob/user) //Bit misleading name for this specific use. @@ -29,7 +29,7 @@ can_be_asked_input = 1 inputs = list() outputs = list("\ on" = 0) - activators = list("\ on toggle") + activators = list("on toggle" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH /obj/item/integrated_circuit/input/toggle_button/ask_for_input(mob/user) // Ditto. @@ -46,7 +46,7 @@ can_be_asked_input = 1 inputs = list() outputs = list("\ number entered") - activators = list("\ on entered") + activators = list("on entered" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -65,7 +65,7 @@ can_be_asked_input = 1 inputs = list() outputs = list("\ string entered") - activators = list("\ on entered") + activators = list("on entered" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -83,7 +83,7 @@ complexity = 4 inputs = list("\ target") outputs = list("\ total health %", "\ total missing health") - activators = list("\ scan", "\ on scanned") + activators = list("scan" = 1, "on scanned" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) power_draw_per_use = 40 @@ -118,7 +118,7 @@ "\ oxy damage", "\ clone damage" ) - activators = list("\ scan", "\ on scanned") + activators = list("scan" = 1, "on scanned" = 0) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 4) power_draw_per_use = 80 @@ -148,7 +148,7 @@ that is holding the machine containing it." inputs = list() outputs = list("located ref") - activators = list("locate") + activators = list("locate" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 20 @@ -170,7 +170,7 @@ random." inputs = list("desired type ref") outputs = list("located ref") - activators = list("locate") + activators = list("locate" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 @@ -206,7 +206,7 @@ complexity = 4 inputs = list("\ frequency","\ code") outputs = list() - activators = list("\ send signal","\ on signal sent", "\ on signal received") + activators = list("send signal" = 1,"on signal sent" = 0, "on signal received" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2) power_draw_idle = 5 @@ -288,7 +288,7 @@ complexity = 4 inputs = list("\ target EPv2 address", "\ data to send", "\ secondary text") outputs = list("\ address received", "\ data received", "\ secondary text received") - activators = list("\ send data", "\ on data received") + activators = list("send data" = 1, "on data received" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2) power_draw_per_use = 50 @@ -332,7 +332,7 @@ complexity = 4 inputs = list() outputs = list("\ X", "\ Y") - activators = list("\ get coordinates", "\ on get coordinates") + activators = list("get coordinates" = 1, "on get coordinates" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 30 @@ -361,7 +361,7 @@ complexity = 8 inputs = list() outputs = list("\ speaker", "\ message") - activators = list("\ on message received", "\ on translation") + activators = list("on message received" = 1, "on translation" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 15 @@ -399,7 +399,7 @@ complexity = 12 inputs = list("\ ignore storage" = 1) outputs = list("\ scanned") - activators = list("\ on scanned") + activators = list("on scanned" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 120 @@ -423,7 +423,7 @@ icon_state = "screen" inputs = list("\ displayed data") outputs = list() - activators = list("\ load data") + activators = list("load data" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 10 autopulse = 1 @@ -477,7 +477,7 @@ complexity = 4 inputs = list() outputs = list() - activators = list("\ toggle light") + activators = list("toggle light" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH var/light_toggled = 0 var/light_brightness = 3 @@ -545,7 +545,7 @@ "\ frequency" ) outputs = list() - activators = list("play sound") + activators = list("play sound" = 1) power_draw_per_use = 20 var/list/sounds = list() @@ -558,7 +558,7 @@ cooldown_per_use = 4 SECONDS inputs = list("text") outputs = list() - activators = list("to speech") + activators = list("to speech" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 60 diff --git a/code/modules/integrated_electronics/subtypes/logic.dm b/code/modules/integrated_electronics/subtypes/logic.dm index ee5a36785b..849c4e37a7 100644 --- a/code/modules/integrated_electronics/subtypes/logic.dm +++ b/code/modules/integrated_electronics/subtypes/logic.dm @@ -4,7 +4,7 @@ extended_desc = "Logic circuits will treat a null, 0, and a \"\" string value as FALSE and anything else as TRUE." complexity = 3 outputs = list("result") - activators = list("\ compare") + activators = list("compare" = 1) category_text = "Logic" autopulse = 1 power_draw_per_use = 1 @@ -18,7 +18,7 @@ /obj/item/integrated_circuit/logic/binary inputs = list("\ A","\ B") - activators = list("\ compare", "\ on true result", "\ on false result") + activators = list("compare" = 1, "on true result" = 0, "on false result" = 0) /obj/item/integrated_circuit/logic/binary/do_work() pull_data() @@ -38,7 +38,7 @@ /obj/item/integrated_circuit/logic/unary inputs = list("\ A") - activators = list("\ compare", "\ on compare") + activators = list("compare" = 1, "on compare" = 0) /obj/item/integrated_circuit/logic/unary/do_work() pull_data() @@ -128,7 +128,7 @@ desc = "This gate inverts what's fed into it." icon_state = "not" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH - activators = list("\ invert", "\ on inverted") + activators = list("invert" = 1, "on inverted" = 0) /obj/item/integrated_circuit/logic/unary/not/do_check(var/datum/integrated_io/A) return !A.data diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index 4ee5145179..9b779ee39b 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -10,13 +10,14 @@ normal limitations to firearms, such as ammunition requirements and firing delays, still hold true if fired by the mechanism." complexity = 20 w_class = ITEMSIZE_NORMAL + size = 3 inputs = list( "\ target X rel", "\ target Y rel" ) outputs = list() activators = list( - "\ fire" + "fire" = 1 ) var/obj/item/weapon/gun/installed_gun = null spawn_flags = IC_SPAWN_RESEARCH @@ -35,6 +36,7 @@ return user.drop_from_inventory(gun) installed_gun = gun + size += gun.w_class gun.forceMove(src) user << "You slide \the [gun] into the firing mechanism." playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) @@ -45,52 +47,58 @@ if(installed_gun) installed_gun.forceMove(get_turf(src)) user << "You slide \the [installed_gun] out of the firing mechanism." + size = initial(size) playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1) installed_gun = null else user << "There's no weapon to remove from the mechanism." /obj/item/integrated_circuit/manipulation/weapon_firing/do_work() - if(..()) - if(!installed_gun) + if(!installed_gun) + return + + var/datum/integrated_io/target_x = inputs[1] + var/datum/integrated_io/target_y = inputs[2] + + if(src.assembly) + if(isnum(target_x.data)) + target_x.data = round(target_x.data) + if(isnum(target_y.data)) + target_y.data = round(target_y.data) + + var/turf/T = get_turf(src.assembly) + + if(target_x.data == 0 && target_y.data == 0) // Don't shoot ourselves. return - var/datum/integrated_io/target_x = inputs[1] - var/datum/integrated_io/target_y = inputs[2] + // We need to do this in order to enable relative coordinates, as locate() only works for absolute coordinates. + var/i + if(target_x.data > 0) + i = abs(target_x.data) + while(i > 0) + T = get_step(T, EAST) + i-- + else + i = abs(target_x.data) + while(i > 0) + T = get_step(T, WEST) + i-- - if(target_x.data && target_y.data && isnum(target_x.data) && isnum(target_y.data)) - var/turf/T = get_turf(src) + i = 0 + if(target_y.data > 0) + i = abs(target_y.data) + while(i > 0) + T = get_step(T, NORTH) + i-- + else if(target_y.data < 0) + i = abs(target_y.data) + while(i > 0) + T = get_step(T, SOUTH) + i-- - if(target_x.data == 0 && target_y.data == 0) // Don't shoot ourselves. - return - - // We need to do this in order to enable relative coordinates, as locate() only works for absolute coordinates. - var/i - if(target_x.data > 0) - i = abs(target_x.data) - while(i) - T = get_step(T, EAST) - i-- - else if(target_x.data < 0) - i = abs(target_x.data) - while(i) - T = get_step(T, WEST) - i-- - - if(target_y.data > 0) - i = abs(target_y.data) - while(i) - T = get_step(T, NORTH) - i-- - else if(target_y.data < 0) - i = abs(target_y.data) - while(i) - T = get_step(T, SOUTH) - i-- - - if(!T) - return - installed_gun.Fire_userless(T) + if(!T) + return + installed_gun.Fire_userless(T) /obj/item/integrated_circuit/manipulation/locomotion name = "locomotion circuit" @@ -110,9 +118,10 @@ being held, or anchored in some way. It should be noted that the ability to move is dependant on the type of assembly that this circuit inhabits." w_class = ITEMSIZE_NORMAL complexity = 20 +// size = 5 inputs = list("dir num") outputs = list() - activators = list("step towards dir") + activators = list("step towards dir" = 1) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 100 @@ -125,4 +134,82 @@ if(assembly.loc == T) // Check if we're held by someone. If the loc is the floor, we're not held. var/datum/integrated_io/wanted_dir = inputs[1] if(isnum(wanted_dir.data)) - step(assembly, wanted_dir.data) \ No newline at end of file + step(assembly, wanted_dir.data) + + +/obj/item/integrated_circuit/manipulation/grenade + name = "grenade primer" + desc = "This circuit comes with the ability to attach most types of grenades at prime them at will." + extended_desc = "Time between priming and detonation is limited to between 1 to 12 seconds but is optional. \ + If unset, not a number, or a number less than 1 then the grenade's built-in timing will be used. \ + Beware: Once primed there is no aborting the process!" + icon_state = "grenade" + complexity = 30 + size = 2 + inputs = list("\ detonation time") + outputs = list() + activators = list("prime grenade" = 1) + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 4) + var/obj/item/weapon/grenade/attached_grenade + var/pre_attached_grenade_type + +/obj/item/integrated_circuit/manipulation/grenade/New() + ..() + if(pre_attached_grenade_type) + var/grenade = new pre_attached_grenade_type(src) + attach_grenade(grenade) + +/obj/item/integrated_circuit/manipulation/grenade/Destroy() + if(attached_grenade && !attached_grenade.active) + attached_grenade.dropInto(loc) + detach_grenade() + . =..() + +/obj/item/integrated_circuit/manipulation/grenade/attackby(var/obj/item/weapon/grenade/G, var/mob/user) + if(istype(G)) + if(attached_grenade) + to_chat(user, "There is already a grenade attached!") + else if(user.unEquip(G, force=1)) + user.visible_message("\The [user] attaches \a [G] to \the [src]!", "You attach \the [G] to \the [src].") + attach_grenade(G) + G.forceMove(src) + else + ..() + +/obj/item/integrated_circuit/manipulation/grenade/attack_self(var/mob/user) + if(attached_grenade) + user.visible_message("\The [user] removes \an [attached_grenade] from \the [src]!", "You remove \the [attached_grenade] from \the [src].") + user.put_in_any_hand_if_possible(attached_grenade) || attached_grenade.dropInto(loc) + detach_grenade() + else + ..() + +/obj/item/integrated_circuit/manipulation/grenade/do_work() + if(attached_grenade && !attached_grenade.active) + var/datum/integrated_io/detonation_time = inputs[1] + if(isnum(detonation_time.data) && detonation_time.data > 0) + attached_grenade.det_time = between(1, detonation_time.data, 12) SECONDS + attached_grenade.activate() + var/atom/holder = loc + log_and_message_admins("activated a grenade assembly. Last touches: Assembly: [holder.fingerprintslast] Circuit: [fingerprintslast] Grenade: [attached_grenade.fingerprintslast]") + +// These procs do not relocate the grenade, that's the callers responsibility +/obj/item/integrated_circuit/manipulation/grenade/proc/attach_grenade(var/obj/item/weapon/grenade/G) + attached_grenade = G + destroyed_event.register(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade) + size += G.w_class + desc += " \An [attached_grenade] is attached to it!" + +/obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade() + if(!attached_grenade) + return + destroyed_event.unregister(attached_grenade, src, /obj/item/integrated_circuit/manipulation/grenade/proc/detach_grenade) + attached_grenade = null + size = initial(size) + desc = initial(desc) + +/obj/item/integrated_circuit/manipulation/grenade/frag + pre_attached_grenade_type = /obj/item/weapon/grenade/explosive + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_COMBAT = 10) + spawn_flags = null // Used for world initializing, see the #defines above. \ No newline at end of file diff --git a/code/modules/integrated_electronics/subtypes/memory.dm b/code/modules/integrated_electronics/subtypes/memory.dm index 49a049a982..91fe45e04b 100644 --- a/code/modules/integrated_electronics/subtypes/memory.dm +++ b/code/modules/integrated_electronics/subtypes/memory.dm @@ -5,7 +5,7 @@ complexity = 1 inputs = list("input pin 1") outputs = list("output pin 1") - activators = list("set") + activators = list("set" = 1, "on set") category_text = "Memory" spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 1 @@ -29,12 +29,13 @@ var/datum/integrated_io/I = inputs[i] var/datum/integrated_io/O = outputs[i] O.data = I.data + O.push_data() + activate_pin(2) /obj/item/integrated_circuit/memory/medium name = "memory circuit" desc = "This circuit can store four pieces of data." icon_state = "memory4" - w_class = ITEMSIZE_SMALL complexity = 4 inputs = list("input pin 1","input pin 2","input pin 3","input pin 4") outputs = list("output pin 1","output pin 2","output pin 3","output pin 4") @@ -45,7 +46,6 @@ name = "large memory circuit" desc = "This big circuit can hold eight pieces of data." icon_state = "memory8" - w_class = ITEMSIZE_SMALL complexity = 8 inputs = list( "input pin 1", @@ -121,7 +121,7 @@ complexity = 1 inputs = list() outputs = list("output pin") - activators = list("push data") + activators = list("push data" = 0) var/accepting_refs = 0 spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH diff --git a/code/modules/integrated_electronics/subtypes/power.dm b/code/modules/integrated_electronics/subtypes/power.dm index 3480a83a4a..215c1ff856 100644 --- a/code/modules/integrated_electronics/subtypes/power.dm +++ b/code/modules/integrated_electronics/subtypes/power.dm @@ -13,7 +13,7 @@ complexity = 16 inputs = list("\ target") outputs = list("\ target cell charge", "\ target cell max charge", "\ target cell percentage") - activators = list("\ transmit") + activators = list("transmit" = 1) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 4, TECH_POWER = 4, TECH_MAGNET = 3) power_draw_per_use = 500 // Inefficency has to come from somewhere. diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index e3b69d31cd..d67feb1c08 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -19,7 +19,7 @@ cooldown_per_use = 30 SECONDS inputs = list() outputs = list() - activators = list("create smoke") + activators = list("create smoke" = 1) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 3, TECH_BIO = 3) volume = 100 @@ -45,7 +45,7 @@ cooldown_per_use = 6 SECONDS inputs = list("\ target", "\ injection amount" = 5) outputs = list() - activators = list("\ inject") + activators = list("inject" = 1) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH volume = 30 power_draw_per_use = 15 @@ -90,7 +90,7 @@ complexity = 8 inputs = list("\ source", "\ target", "\ injection amount" = 10) outputs = list() - activators = list("\ transfer reagents", "\ on transfer") + activators = list("transfer reagents" = 1, "on transfer" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 2, TECH_DATA = 2, TECH_BIO = 2) var/transfer_amount = 10 diff --git a/code/modules/integrated_electronics/subtypes/smart.dm b/code/modules/integrated_electronics/subtypes/smart.dm index a90a3f57a3..7570734197 100644 --- a/code/modules/integrated_electronics/subtypes/smart.dm +++ b/code/modules/integrated_electronics/subtypes/smart.dm @@ -10,7 +10,7 @@ complexity = 25 inputs = list("\ target") outputs = list("\ dir") - activators = list("\ calculate dir", "\ on calculated") + activators = list("calculate dir" = 1, "on calculated" = 0) spawn_flags = IC_SPAWN_RESEARCH origin_tech = list(TECH_ENGINEERING = 4, TECH_DATA = 5) power_draw_per_use = 40 diff --git a/code/modules/integrated_electronics/subtypes/time.dm b/code/modules/integrated_electronics/subtypes/time.dm index 322ee2f9e0..64855d2a56 100644 --- a/code/modules/integrated_electronics/subtypes/time.dm +++ b/code/modules/integrated_electronics/subtypes/time.dm @@ -12,7 +12,7 @@ This circuit is set to send a pulse after a delay of two seconds." icon_state = "delay-20" var/delay = 2 SECONDS - activators = list("\ incoming","\ outgoing") + activators = list("incoming"= 1,"outgoing" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 2 @@ -79,7 +79,7 @@ var/ticks_completed = 0 var/is_running = FALSE inputs = list("\ enable ticking" = 0) - activators = list("\ outgoing pulse") + activators = list("outgoing pulse" = 0) spawn_flags = IC_SPAWN_RESEARCH power_draw_per_use = 4 @@ -132,7 +132,7 @@ icon_state = "clock" inputs = list() outputs = list("\ time", "\ hours", "\ minutes", "\ seconds") - activators = list("\ get time","\ on time got") + activators = list("get time" = 1,"on time got" = 0) spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_per_use = 4 diff --git a/code/modules/integrated_electronics/subtypes/trig.dm b/code/modules/integrated_electronics/subtypes/trig.dm index 72d779b621..ec773a160b 100644 --- a/code/modules/integrated_electronics/subtypes/trig.dm +++ b/code/modules/integrated_electronics/subtypes/trig.dm @@ -12,7 +12,7 @@ "\ H" ) outputs = list("\ result") - activators = list("\ compute", "\ on computed") + activators = list("compute" = 1, "on computed" = 0) category_text = "Trig" extended_desc = "Input and output are in degrees." autopulse = 1 diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index 6f1add522a..fb5d81ee9f 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1543,7 +1543,7 @@ CIRCUITS BELOW /datum/design/item/custom_circuit_assembly name = "Small custom assembly" - desc = "An customizable assembly for simple, small devices." + desc = "A customizable assembly for simple, small devices." id = "assembly-small" req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 2, TECH_POWER = 2) materials = list(DEFAULT_WALL_MATERIAL = 10000) @@ -1552,7 +1552,7 @@ CIRCUITS BELOW /datum/design/item/custom_circuit_assembly/medium name = "Medium custom assembly" - desc = "An customizable assembly suited for more ambitious mechanisms." + desc = "A customizable assembly suited for more ambitious mechanisms." id = "assembly-medium" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 3) materials = list(DEFAULT_WALL_MATERIAL = 20000) @@ -1561,7 +1561,7 @@ CIRCUITS BELOW /datum/design/item/custom_circuit_assembly/drone name = "Drone custom assembly" - desc = "An customizable assembly optimized for autonomous devices." + desc = "A customizable assembly optimized for autonomous devices." id = "assembly-drone" req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(DEFAULT_WALL_MATERIAL = 30000) @@ -1570,7 +1570,7 @@ CIRCUITS BELOW /datum/design/item/custom_circuit_assembly/large name = "Large custom assembly" - desc = "An customizable assembly for large machines." + desc = "A customizable assembly for large machines." id = "assembly-large" req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4) materials = list(DEFAULT_WALL_MATERIAL = 40000) @@ -1586,6 +1586,15 @@ CIRCUITS BELOW build_path = /obj/item/weapon/implant/integrated_circuit sort_string = "VCAAE" +/datum/design/item/custom_circuit_assembly/device + name = "Device custom assembly" + desc = "An customizable assembly designed to interface with other devices." + id = "assembly-implant" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000) + build_path = /obj/item/weapon/implant/integrated_circuit + sort_string = "VCAAF" + /datum/design/item/translator name = "handheld translator" id = "translator" diff --git a/code/unit_tests/integrated_circuits/converter.dm b/code/unit_tests/integrated_circuits/converter.dm index b2a414f4d8..b64f3f7e58 100644 --- a/code/unit_tests/integrated_circuits/converter.dm +++ b/code/unit_tests/integrated_circuits/converter.dm @@ -30,9 +30,9 @@ -/datum/unit_test/integrated_circuits/concatenatior - name = "Converter Circuits: Concatenatior" - circuit_type = /obj/item/integrated_circuit/converter/concatenatior +/datum/unit_test/integrated_circuits/concatenator + name = "Converter Circuits: concatenator" + circuit_type = /obj/item/integrated_circuit/converter/concatenator inputs_to_give = list("Lorem", " ", "ipsum", "...") expected_outputs = list("Lorem ipsum...") diff --git a/html/changelogs/LorenLuke-IEC changes.yml b/html/changelogs/LorenLuke-IEC changes.yml new file mode 100644 index 0000000000..8f0f370075 --- /dev/null +++ b/html/changelogs/LorenLuke-IEC changes.yml @@ -0,0 +1,50 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: LorenLuke + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - experiment: "Gives IECs some TLC (see below)." + - rscadd: "Adds 'Separator' circuit, allowing the player to now divide strings." + - rscadd: "Adds 'grenade' circuit, allowing the player to detonate a stored grenade in an assembly." + - rscadd: "Adds 'device' electronic assembly, allowing an 'assembly'-type (signaler/igniter) circuit to be used to interact with others." + - tweak: "Modifies some storage and complexity constants." + - tweak: "Adds 'size' variable for manual setting." + - tweak: "No longer requires screwdriver to remove components." + - tweak: "Enables multitool to wire/debug circuits with lesser functionality (can disable via variable)." + - tweak: "IECs no longer drown the player in windows, each assembly always uses only one window." + - tweak: "Added functionality to UI to help with user experience of above point." + - rscadd: "Adds 'on set' output pulses to multiplexer and memory circuits." + - bugfix: "Fixes multiplexer and memory circuits not pushing data to attached circuits." + - bugfix: "Number to string converts null inputs as '0' due to engine limitations (at least they work)." + - bugfix: "Gun manipulator circuit now functions properly (and can read '0' value inputs)." + - wip: "Phase 1/2 for wiring rework." \ No newline at end of file diff --git a/icons/obj/assemblies/new_assemblies.dmi b/icons/obj/assemblies/new_assemblies.dmi index 96b36bbf369e0eb9accc74a2d2c794964b3e18f9..0f9d337dc52207ce016a846ad1e1f2c09137cf45 100644 GIT binary patch delta 4006 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 C$V|@w diff --git a/icons/obj/electronic_assemblies.dmi b/icons/obj/electronic_assemblies.dmi index 81aa71eac773dda32062093e11546a517e6dc041..e81053bc3642547884e36f3ed5b3c436f0083567 100644 GIT binary patch delta 10844 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 Vsff@}E>shCNyp$qk(N!^e*iq<@^b(H delta 9640 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
[jointext(words, null)]
[jointext(words, null)]