Shows assemblies some love. ♥

This commit is contained in:
ShizCalev
2018-05-06 08:05:37 -04:00
committed by CitadelStationBot
parent 11c1e8fbf7
commit 6415ecdbe9
21 changed files with 432 additions and 261 deletions

View File

@@ -58,6 +58,36 @@
attacher = user
return
//Attached device memes
/obj/item/transfer_valve/Move()
. = ..()
if(attached_device)
attached_device.holder_movement()
/obj/item/transfer_valve/dropped()
. = ..()
if(attached_device)
attached_device.dropped()
/obj/item/transfer_valve/on_found(mob/finder)
if(attached_device)
attached_device.on_found(finder)
/obj/item/transfer_valve/Crossed(atom/movable/AM as mob|obj)
. = ..()
if(attached_device)
attached_device.Crossed(AM)
/obj/item/transfer_valve/attack_hand()//Triggers mousetraps
. = ..()
if(.)
return
if(attached_device)
attached_device.attack_hand()
//These keep attached devices synced up, for example a TTV with a mouse trap being found in a bag so it's triggered, or moving the TTV with an infrared beam sensor to update the beam's direction.
/obj/item/transfer_valve/attack_self(mob/user)
user.set_machine(src)
var/dat = {"<B> Valve properties: </B>
@@ -91,8 +121,7 @@
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.forceMove(drop_location())
attached_device.holder = null
attached_device.on_detach()
attached_device = null
update_icon()
if(href_list["device"])
@@ -127,6 +156,10 @@
underlays += J
if(attached_device)
add_overlay("device")
if(istype(attached_device, /obj/item/assembly/infra))
var/obj/item/assembly/infra/sensor = attached_device
if(sensor.on && sensor.visible)
add_overlay("proxy_beam")
/obj/item/transfer_valve/proc/merge_gases()
tank_two.air_contents.volume += tank_one.air_contents.volume

View File

@@ -3,6 +3,7 @@
#define WIRE_PULSE_SPECIAL (1<<2)
#define WIRE_RADIO_RECEIVE (1<<3)
#define WIRE_RADIO_PULSE (1<<4)
#define ASSEMBLY_BEEP_VOLUME 5
/obj/item/assembly
name = "assembly"
@@ -16,6 +17,8 @@
throw_speed = 3
throw_range = 7
var/is_position_sensitive = FALSE //set to true if the device has different icons for each position.
//This will prevent things such as visible lasers from facing the incorrect direction when transformed by assembly_holder's update_icon()
var/secured = TRUE
var/list/attached_overlays = null
var/obj/item/assembly_holder/holder = null
@@ -30,14 +33,18 @@
/obj/item/assembly/proc/on_attach()
/obj/item/assembly/proc/on_detach()
/obj/item/assembly/proc/on_detach() //call this when detaching it from a device. handles any special functions that need to be updated ex post facto
if(!holder)
return FALSE
forceMove(holder.drop_location())
holder = null
return TRUE
/obj/item/assembly/proc/holder_movement() //Called when the holder is moved
return
/obj/item/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
return "The trigger assembly looks broken!"
if(!holder)
return FALSE
setDir(holder.dir)
return TRUE
/obj/item/assembly/proc/is_secured(mob/user)
if(!secured)
@@ -47,7 +54,7 @@
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/assembly/proc/pulsed(radio = 0)
/obj/item/assembly/proc/pulsed(radio = FALSE)
if(wire_type & WIRE_RECEIVE)
INVOKE_ASYNC(src, .proc/activate)
if(radio && (wire_type & WIRE_RADIO_RECEIVE))
@@ -56,7 +63,7 @@
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
/obj/item/assembly/proc/pulse(radio = 0)
/obj/item/assembly/proc/pulse(radio = FALSE)
if(connected && wire_type)
connected.pulse_assembly(src)
return TRUE
@@ -91,21 +98,19 @@
else
to_chat(user, "<span class='warning'>Both devices must be in attachable mode to be attached together.</span>")
return
if(istype(W, /obj/item/screwdriver))
if(toggle_secure())
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
else
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
return
..()
/obj/item/assembly/screwdriver_act(mob/living/user, obj/item/I)
if(toggle_secure())
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
else
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
add_fingerprint(user)
return TRUE
/obj/item/assembly/examine(mob/user)
..()
if(secured)
to_chat(user, "\The [src] is secured and ready to be used.")
else
to_chat(user, "\The [src] can be attached to other things.")
to_chat(user, "<span class='notice'>\The [src] [secured? "is secured and ready to be used!" : "can be attached to other things."]</span>")
/obj/item/assembly/attack_self(mob/user)

View File

@@ -13,11 +13,14 @@
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
/obj/item/onetankbomb/IsSpecialAssembly()
return TRUE
/obj/item/onetankbomb/examine(mob/user)
bombtank.examine(user)
/obj/item/onetankbomb/update_icon()
cut_overlays()
if(bombtank)
icon = bombtank.icon
icon_state = bombtank.icon_state
@@ -30,29 +33,37 @@
if(istype(W, /obj/item/analyzer))
bombtank.attackby(W, user)
return
if(istype(W, /obj/item/wrench) && !status) //This is basically bomb assembly code inverted. apparently it works.
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
add_fingerprint(user)
..()
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
if(bombassembly)
bombassembly.forceMove(drop_location())
bombassembly.master = null
bombassembly = null
if(bombtank)
bombtank.forceMove(drop_location())
bombtank.master = null
bombtank = null
qdel(src)
return TRUE
qdel(src)
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
. = FALSE
if(status)
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
return
var/obj/item/weldingtool/WT = W
if((istype(WT) && WT.welding))
if(!status)
status = TRUE
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
add_fingerprint(user)
..()
if(!I.tool_start_check(user, amount=0))
return
if(I.use_tool(src, user, 0, volume=40))
status = TRUE
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
add_fingerprint(user)
return TRUE
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
@@ -60,16 +71,20 @@
return
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
visible_message("[icon2html(src, viewers(src))] *beep* *beep*", "*beep* *beep*")
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
sleep(10)
if(!src)
if(QDELETED(src))
return
if(status)
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
else
bombtank.release()
//Assembly / attached device memes
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
. = ..()
if(bombassembly)
bombassembly.Crossed(AM)
@@ -77,6 +92,26 @@
if(bombassembly)
bombassembly.on_found(finder)
/obj/item/onetankbomb/attack_hand() //also for mousetraps
. = ..()
if(.)
return
if(bombassembly)
bombassembly.attack_hand()
/obj/item/onetankbomb/Move()
. = ..()
if(bombassembly)
bombassembly.setDir(dir)
bombassembly.Move()
/obj/item/onetankbomb/dropped()
. = ..()
if(bombassembly)
bombassembly.dropped()
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------

View File

@@ -2,10 +2,10 @@
name = "blast door controller"
desc = "A small electronic device able to control a blast door remotely."
icon_state = "control"
attachable = 1
attachable = TRUE
var/id = null
var/can_change_id = 0
var/cooldown = 0//Door cooldowns
var/cooldown = FALSE //Door cooldowns
/obj/item/assembly/control/examine(mob/user)
..()
@@ -13,15 +13,14 @@
to_chat(user, "<span class='notice'>Its channel ID is '[id]'.</span>")
/obj/item/assembly/control/activate()
cooldown = 1
cooldown = TRUE
var/openclose
for(var/obj/machinery/door/poddoor/M in GLOB.machines)
if(M.id == src.id)
if(openclose == null)
openclose = M.density
INVOKE_ASYNC(M, openclose ? /obj/machinery/door/poddoor.proc/open : /obj/machinery/door/poddoor.proc/close)
sleep(10)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/airlock
@@ -38,7 +37,7 @@
*/
/obj/item/assembly/control/airlock/activate()
cooldown = 1
cooldown = TRUE
var/doors_need_closing = FALSE
var/list/obj/machinery/door/airlock/open_or_close = list()
for(var/obj/machinery/door/airlock/D in GLOB.airlocks)
@@ -66,8 +65,7 @@
for(var/D in open_or_close)
INVOKE_ASYNC(D, doors_need_closing ? /obj/machinery/door/airlock.proc/close : /obj/machinery/door/airlock.proc/open)
sleep(10)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/massdriver
@@ -75,7 +73,7 @@
desc = "A small electronic device able to control a mass driver."
/obj/item/assembly/control/massdriver/activate()
cooldown = 1
cooldown = TRUE
for(var/obj/machinery/door/poddoor/M in GLOB.machines)
if (M.id == src.id)
INVOKE_ASYNC(M, /obj/machinery/door/poddoor.proc/open)
@@ -92,8 +90,7 @@
if (M.id == src.id)
INVOKE_ASYNC(M, /obj/machinery/door/poddoor.proc/close)
sleep(10)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
/obj/item/assembly/control/igniter
@@ -101,7 +98,7 @@
desc = "A remote controller for a mounted igniter."
/obj/item/assembly/control/igniter/activate()
cooldown = 1
cooldown = TRUE
for(var/obj/machinery/sparker/M in GLOB.machines)
if (M.id == src.id)
INVOKE_ASYNC(M, /obj/machinery/sparker.proc/ignite)
@@ -112,22 +109,19 @@
M.on = !M.on
M.icon_state = "igniter[M.on]"
sleep(30)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 30)
/obj/item/assembly/control/flasher
name = "flasher controller"
desc = "A remote controller for a mounted flasher."
/obj/item/assembly/control/flasher/activate()
cooldown = 1
cooldown = TRUE
for(var/obj/machinery/flasher/M in GLOB.machines)
if(M.id == src.id)
INVOKE_ASYNC(M, /obj/machinery/flasher.proc/flash)
sleep(50)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
/obj/item/assembly/control/crematorium
@@ -135,10 +129,9 @@
desc = "An evil-looking remote controller for a crematorium."
/obj/item/assembly/control/crematorium/activate()
cooldown = 1
cooldown = TRUE
for (var/obj/structure/bodycontainer/crematorium/C in GLOB.crematoriums)
if (C.id == id)
C.cremate(usr)
sleep(50)
cooldown = 0
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)

View File

@@ -93,7 +93,7 @@
if(crit_fail || (world.time < last_trigger + cooldown))
return FALSE
last_trigger = world.time
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
playsound(src, 'sound/weapons/flash.ogg', 100, TRUE)
times_used++
flash_recharge()
update_icon(TRUE)
@@ -195,6 +195,8 @@
/obj/item/assembly/flash/cyborg/attackby(obj/item/W, mob/user, params)
return
/obj/item/assembly/flash/cyborg/screwdriver_act(mob/living/user, obj/item/I)
return
/obj/item/assembly/flash/memorizer
name = "memorizer"
@@ -226,7 +228,7 @@
return FALSE
overheat = TRUE
addtimer(CALLBACK(src, .proc/cooldown), flashcd)
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
playsound(src, 'sound/weapons/flash.ogg', 100, TRUE)
update_icon(1)
return TRUE
@@ -272,7 +274,7 @@
return
crit_fail = FALSE
times_used = 0
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
update_icon()
flash.crit_fail = TRUE
flash.update_icon()

View File

@@ -3,10 +3,10 @@
desc = "Used for scanning and monitoring health."
icon_state = "health"
materials = list(MAT_METAL=800, MAT_GLASS=200)
attachable = 1
secured = 0
attachable = TRUE
secured = FALSE
var/scanning = 0
var/scanning = FALSE
var/health_scan
var/alarm_health = 0
@@ -16,31 +16,28 @@
/obj/item/assembly/health/activate()
if(!..())
return 0//Cooldown check
return FALSE//Cooldown check
toggle_scan()
return 0
return TRUE
/obj/item/assembly/health/toggle_secure()
secured = !secured
if(secured && scanning)
START_PROCESSING(SSobj, src)
else
scanning = 0
scanning = FALSE
STOP_PROCESSING(SSobj, src)
update_icon()
return secured
/obj/item/assembly/health/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W, /obj/item/multitool))
if(alarm_health == 0)
alarm_health = -90
user.show_message("You toggle [src] to \"detect death\" mode.")
else
alarm_health = 0
user.show_message("You toggle [src] to \"detect critical state\" mode.")
return
/obj/item/assembly/health/multitool_act(mob/living/user, obj/item/I)
if(alarm_health == 0)
alarm_health = -90
to_chat(user, "<span class='notice'>You toggle [src] to \"detect death\" mode.</span>")
else
return ..()
alarm_health = 0
to_chat(user, "<span class='notice'>You toggle [src] to \"detect critical state\" mode.</span>")
return TRUE
/obj/item/assembly/health/process()
if(!scanning || !secured)
@@ -58,7 +55,8 @@
health_scan = M.health
if(health_scan <= alarm_health)
pulse()
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", "*beep* *beep*")
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
toggle_scan()
return
return
@@ -77,8 +75,9 @@
. = ..()
if(!secured)
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
return 0
var/dat = "<TT><B>Health Sensor</B> <A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
return FALSE
var/dat = "<TT><B>Health Sensor</B></TT>"
dat += "<BR><A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
if(scanning && health_scan)
dat += "<BR>Health: [health_scan]"
user << browse(dat, "window=hscan")

View File

@@ -1,3 +1,4 @@
<<<<<<< HEAD
// See _DEFINES/is_helpers.dm for type helpers
/*
@@ -14,3 +15,21 @@ Desc: If true is an object that can hold an assemblyholder object
*/
/obj/proc/IsAssemblyHolder()
return 0
=======
// See _DEFINES/is_helpers.dm for type helpers
/*
Name: IsSpecialAssembly
Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door
*/
/obj/proc/IsSpecialAssembly()
return FALSE
/*
Name: IsAssemblyHolder
Desc: If true is an object that can hold an assemblyholder object
*/
/obj/proc/IsAssemblyHolder()
return FALSE
>>>>>>> b4d11c6... Shows assemblies some love. ♥ (#37632)

View File

@@ -15,7 +15,7 @@
var/obj/item/assembly/a_right = null
/obj/item/assembly_holder/IsAssemblyHolder()
return 1
return TRUE
/obj/item/assembly_holder/proc/assemble(obj/item/assembly/A, obj/item/assembly/A2, mob/user)
@@ -37,6 +37,7 @@
a_left = A
else
a_right = A
A.holder_movement()
/obj/item/assembly_holder/update_icon()
cut_overlays()
@@ -46,11 +47,16 @@
add_overlay("[O]_l")
if(a_right)
var/mutable_appearance/right = mutable_appearance(icon, "[a_right.icon_state]_left")
right.transform = matrix(-1, 0, 0, 0, 1, 0)
for(var/O in a_right.attached_overlays)
right.add_overlay("[O]_l")
add_overlay(right)
if(a_right.is_position_sensitive)
add_overlay("[a_right.icon_state]_right")
for(var/O in a_right.attached_overlays)
add_overlay("[O]_r")
else
var/mutable_appearance/right = mutable_appearance(icon, "[a_right.icon_state]_left")
right.transform = matrix(-1, 0, 0, 0, 1, 0)
for(var/O in a_right.attached_overlays)
right.add_overlay("[O]_l")
add_overlay(right)
if(master)
master.update_icon()
@@ -69,32 +75,37 @@
/obj/item/assembly_holder/Move()
. = ..()
if(a_left && a_right)
if(a_left)
a_left.holder_movement()
if(a_right)
a_right.holder_movement()
/obj/item/assembly_holder/dropped(mob/user)
. = ..()
if(a_left)
a_left.dropped()
if(a_right)
a_right.dropped()
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
. = ..()
if(.)
return
if(a_left && a_right)
a_left.holder_movement()
a_right.holder_movement()
if(a_left)
a_left.attack_hand()
if(a_right)
a_right.attack_hand()
/obj/item/assembly_holder/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
var/turf/T = get_turf(src)
if(!T)
return 0
if(a_left)
a_left.holder = null
a_left.forceMove(T)
if(a_right)
a_right.holder = null
a_right.forceMove(T)
qdel(src)
else
..()
/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool)
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
if(a_left)
a_left.on_detach()
a_left = null
if(a_right)
a_right.on_detach()
a_right = null
qdel(src)
return TRUE
/obj/item/assembly_holder/attack_self(mob/user)
src.add_fingerprint(user)
@@ -115,12 +126,12 @@
/obj/item/assembly_holder/proc/process_activation(obj/D, normal = 1, special = 1)
if(!D)
return 0
return FALSE
if((normal) && (a_right) && (a_left))
if(a_right != D)
a_right.pulsed(0)
a_right.pulsed(FALSE)
if(a_left != D)
a_left.pulsed(0)
a_left.pulsed(FALSE)
if(master)
master.receive_signal()
return 1
return TRUE

View File

@@ -23,12 +23,12 @@
/obj/item/assembly/igniter/activate()
if(!..())
return 0//Cooldown check
return FALSE//Cooldown check
var/turf/location = get_turf(loc)
if(location)
location.hotspot_expose(1000,1000)
sparks.start()
return 1
return TRUE
/obj/item/assembly/igniter/attack_self(mob/user)
activate()

View File

@@ -3,6 +3,7 @@
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
icon_state = "infrared"
materials = list(MAT_METAL=1000, MAT_GLASS=500)
is_position_sensitive = TRUE
var/on = FALSE
var/visible = FALSE
@@ -10,6 +11,7 @@
var/list/obj/effect/beam/i_beam/beams
var/olddir = 0
var/datum/component/redirect/listener
var/hearing_range = 3
/obj/item/assembly/infra/Initialize()
. = ..()
@@ -30,23 +32,27 @@
refreshBeam()
/obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_LIST(beams)
return ..()
. = ..()
/obj/item/assembly/infra/describe()
return "The infrared trigger is [on?"on":"off"]."
/obj/item/assembly/infra/examine(mob/user)
..()
to_chat(user, "<span class='notice'>The infrared trigger is [on?"on":"off"].</span>")
/obj/item/assembly/infra/activate()
if(!..())
return 0//Cooldown check
return FALSE//Cooldown check
on = !on
refreshBeam()
update_icon()
return 1
return TRUE
/obj/item/assembly/infra/toggle_secure()
secured = !secured
if(secured)
START_PROCESSING(SSobj, src)
refreshBeam()
else
QDEL_LIST(beams)
STOP_PROCESSING(SSobj, src)
@@ -59,13 +65,20 @@
if(on)
add_overlay("infrared_on")
attached_overlays += "infrared_on"
if(visible && secured)
add_overlay("infrared_visible")
attached_overlays += "infrared_visible"
if(holder)
holder.update_icon()
return
/obj/item/assembly/infra/dropped()
refreshBeam()
. = ..()
if(holder)
holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder
else
refreshBeam()
/obj/item/assembly/infra/process()
if(!on || !secured)
@@ -74,7 +87,15 @@
/obj/item/assembly/infra/proc/refreshBeam()
QDEL_LIST(beams)
if(throwing || !on || !secured || !(isturf(loc) || holder && isturf(holder.loc)))
if(throwing || !on || !secured)
return
if(holder)
if(holder.master) //incase the sensor is part of an assembly that's contained in another item, such as a single tank bomb
if(!holder.master.IsSpecialAssembly() || !isturf(holder.master.loc))
return
else if(!isturf(holder.loc)) //else just check where the holder is
return
else if(!isturf(loc)) //or just where the fuck we are in general
return
var/turf/T = get_turf(src)
var/_dir = dir
@@ -82,6 +103,11 @@
if(_T)
for(var/i in 1 to maxlength)
var/obj/effect/beam/i_beam/I = new(T)
if(istype(holder, /obj/item/assembly_holder))
var/obj/item/assembly_holder/assembly_holder = holder
I.icon_state = "[initial(I.icon_state)]_[(assembly_holder.a_left == src) ? "l":"r"]" //Sync the offset of the beam with the position of the sensor.
else if(istype(holder, /obj/item/transfer_valve))
I.icon_state = "[initial(I.icon_state)]_ttv"
I.density = TRUE
if(!I.Move(_T))
qdel(I)
@@ -96,6 +122,12 @@
_T = get_step(_T, _dir)
CHECK_TICK
/obj/item/assembly/infra/on_detach()
. = ..()
if(!.)
return
refreshBeam()
/obj/item/assembly/infra/attack_hand()
. = ..()
refreshBeam()
@@ -116,19 +148,17 @@
setDir(olddir)
olddir = null
/obj/item/assembly/infra/holder_movement()
if(!holder)
return 0
refreshBeam()
return 1
/obj/item/assembly/infra/proc/trigger_beam(atom/movable/AM, turf/location)
refreshBeam()
switchListener(location)
if(!secured || !on || next_activate > world.time)
return FALSE
pulse(0)
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
pulse(FALSE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
if(ismob(CHM))
var/mob/LM = CHM
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
@@ -144,7 +174,9 @@
. = ..()
if(is_secured(user))
user.set_machine(src)
var/dat = "<TT><B>Infrared Laser</B>\n<B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]<BR>\n<B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]<BR>\n</TT>"
var/dat = "<TT><B>Infrared Laser</B></TT>"
dat += "<BR><B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]"
dat += "<BR><B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
user << browse(dat, "window=infra")
@@ -163,6 +195,7 @@
refreshBeam()
if(href_list["visible"])
visible = !(visible)
update_icon()
refreshBeam()
if(href_list["close"])
usr << browse(null, "window=infra")

View File

@@ -2,17 +2,15 @@
name = "mousetrap"
desc = "A handy little spring-loaded trap for catching pesty rodents."
icon_state = "mousetrap"
item_state = "mousetrap"
materials = list(MAT_METAL=100)
attachable = 1
var/armed = 0
attachable = TRUE
var/armed = FALSE
/obj/item/assembly/mousetrap/examine(mob/user)
..()
if(armed)
to_chat(user, "The mousetrap is armed!")
else
to_chat(user, "The mousetrap is not armed.")
to_chat(user, "<span class='notice'>The pressure plate is [armed?"primed":"safe"].</span>")
/obj/item/assembly/mousetrap/activate()
if(..())
@@ -22,13 +20,9 @@
var/mob/living/carbon/human/user = usr
if((user.has_trait(TRAIT_DUMB) || user.has_trait(TRAIT_CLUMSY)) && prob(50))
to_chat(user, "<span class='warning'>Your hand slips, setting off the trigger!</span>")
pulse(0)
pulse(FALSE)
update_icon()
if(usr)
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
/obj/item/assembly/mousetrap/describe()
return "The pressure switch is [armed?"primed":"safe"]."
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
/obj/item/assembly/mousetrap/update_icon()
if(armed)
@@ -45,10 +39,10 @@
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.has_trait(TRAIT_PIERCEIMMUNE))
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
armed = FALSE
update_icon()
pulse(0)
pulse(FALSE)
return FALSE
switch(type)
if("feet")
@@ -66,10 +60,10 @@
var/mob/living/simple_animal/mouse/M = target
visible_message("<span class='boldannounce'>SPLAT!</span>")
M.splat()
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
armed = FALSE
update_icon()
pulse(0)
pulse(FALSE)
/obj/item/assembly/mousetrap/attack_self(mob/living/carbon/human/user)
@@ -87,7 +81,7 @@
to_chat(user, "<span class='notice'>You disarm [src].</span>")
armed = !armed
update_icon()
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
//ATTACK HAND IGNORING PARENT RETURN VALUE
@@ -145,4 +139,4 @@
/obj/item/assembly/mousetrap/armed
icon_state = "mousetraparmed"
armed = 1
armed = TRUE

View File

@@ -3,34 +3,36 @@
desc = "Used for scanning and alerting when someone enters a certain proximity."
icon_state = "prox"
materials = list(MAT_METAL=800, MAT_GLASS=200)
attachable = 1
attachable = TRUE
var/scanning = 0
var/timing = 0
var/scanning = FALSE
var/timing = FALSE
var/time = 10
var/sensitivity = 1
/obj/item/assembly/prox_sensor/proc/toggle_scan()
/obj/item/assembly/prox_sensor/proc/sense()
var/hearing_range = 3
/obj/item/assembly/prox_sensor/Initialize()
. = ..()
proximity_monitor = new(src, 0)
START_PROCESSING(SSobj, src)
/obj/item/assembly/prox_sensor/describe()
if(timing)
return "<span class='notice'>The proximity sensor is arming.</span>"
return "The proximity sensor is [scanning?"armed":"disarmed"]."
/obj/item/assembly/prox_sensor/Destroy()
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/assembly/prox_sensor/examine(mob/user)
..()
to_chat(user, "<span class='notice'>The proximity sensor is [timing ? "arming" : (scanning ? "armed" : "disarmed")].</span>")
/obj/item/assembly/prox_sensor/activate()
if(!..())
return 0//Cooldown check
timing = !timing
return FALSE//Cooldown check
if(!scanning)
timing = !timing
else
scanning = FALSE
update_icon()
return 1
return TRUE
/obj/item/assembly/prox_sensor/toggle_secure()
secured = !secured
@@ -38,8 +40,10 @@
if(scanning)
toggle_scan()
proximity_monitor.host = src
timing = 0
timing = FALSE
STOP_PROCESSING(SSobj, src)
else
START_PROCESSING(SSobj, src)
proximity_monitor.host = loc
update_icon()
return secured
@@ -51,25 +55,31 @@
sense()
/obj/item/assembly/prox_sensor/sense()
/obj/item/assembly/prox_sensor/proc/sense()
if(!scanning || !secured || next_activate > world.time)
return 0
pulse(0)
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
return FALSE
pulse(FALSE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
if(ismob(CHM))
var/mob/LM = CHM
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
next_activate = world.time + 30
return TRUE
/obj/item/assembly/prox_sensor/process()
if(timing)
time--
if(time <= 0)
timing = 0
toggle_scan(1)
time = initial(time)
if(!timing)
return
time--
if(time <= 0)
timing = FALSE
toggle_scan(TRUE)
time = initial(time)
/obj/item/assembly/prox_sensor/toggle_scan(scan)
/obj/item/assembly/prox_sensor/proc/toggle_scan(scan)
if(!secured)
return 0
return FALSE
scanning = scan
proximity_monitor.SetRange(scanning ? sensitivity : 0)
update_icon()
@@ -98,8 +108,11 @@
if(is_secured(user))
var/second = time % 60
var/minute = (time - second) / 60
var/dat = "<TT><B>Proximity Sensor</B>\n[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]\n<A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>\n</TT>"
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed"]</A> (Movement sensor active when armed!)"
var/dat = "<TT><B>Proximity Sensor</B></TT>"
if(!scanning)
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]"
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed (Movement sensor active when armed!)"]</A>"
dat += "<BR>Detection range: <A href='?src=[REF(src)];sense=down'>-</A> [sensitivity] <A href='?src=[REF(src)];sense=up'>+</A>"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"

View File

@@ -13,18 +13,18 @@
qdel(part2)
return ..()
/obj/item/assembly/shock_kit/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/wrench))
/obj/item/assembly/shock_kit/wrench_act(mob/living/user, obj/item/I)
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
if(part1)
part1.forceMove(drop_location())
part2.forceMove(drop_location())
part1.master = null
part2.master = null
part1 = null
if(part2)
part2.forceMove(drop_location())
part2.master = null
part2 = null
qdel(src)
return
add_fingerprint(user)
return
qdel(src)
return TRUE
/obj/item/assembly/shock_kit/attack_self(mob/user)
part1.attack_self(user)

View File

@@ -7,17 +7,18 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
materials = list(MAT_METAL=400, MAT_GLASS=120)
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
attachable = 1
attachable = TRUE
var/code = DEFAULT_SIGNALER_CODE
var/frequency = FREQ_SIGNALER
var/delay = 0
var/datum/radio_frequency/radio_connection
var/suicider = null
var/hearing_range = 1
/obj/item/assembly/signaler/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] eats \the [src]! If it is signaled, [user.p_they()] will die!</span>")
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
playsound(src, 'sound/items/eatfood.ogg', 50, TRUE)
user.transferItemToLoc(src, user, TRUE)
suicider = user
return MANUAL_SUICIDE
@@ -27,15 +28,14 @@
user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something.
user.death(0)
/obj/item/assembly/signaler/New()
..()
spawn(40)
set_frequency(frequency)
/obj/item/assembly/signaler/Initialize()
. = ..()
set_frequency(frequency)
/obj/item/assembly/signaler/Destroy()
SSradio.remove_object(src,frequency)
return ..()
. = ..()
/obj/item/assembly/signaler/activate()
if(!..())//cooldown processing
@@ -80,7 +80,7 @@ Code:
/obj/item/assembly/signaler/Topic(href, href_list)
..()
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
return
@@ -131,17 +131,22 @@ Code:
return
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
. = FALSE
if(!signal)
return 0
return
if(signal.data["code"] != code)
return 0
return
if(!(src.wires & WIRE_RADIO_RECEIVE))
return 0
return
if(suicider)
manual_suicide(suicider)
pulse(1)
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
return
pulse(TRUE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
if(ismob(CHM))
var/mob/LM = CHM
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
return TRUE
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
@@ -161,10 +166,11 @@ Code:
/obj/item/assembly/signaler/reciever/activate()
toggle_safety()
return 1
return TRUE
/obj/item/assembly/signaler/reciever/describe()
return "The radio receiver is [on?"on":"off"]."
/obj/item/assembly/signaler/reciever/examine(mob/user)
..()
to_chat(user, "<span class='notice'>The radio receiver is [on?"on":"off"].</span>")
/obj/item/assembly/signaler/reciever/receive_signal(datum/signal/signal)
if(!on)
@@ -183,11 +189,12 @@ Code:
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
if(!signal)
return 0
return FALSE
if(signal.data["code"] != code)
return 0
return FALSE
for(var/obj/effect/anomaly/A in get_turf(src))
A.anomalyNeutralize()
return TRUE
/obj/item/assembly/signaler/anomaly/attack_self()
return
@@ -196,3 +203,5 @@ Code:
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
return
/obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I)
return

View File

@@ -3,12 +3,13 @@
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
icon_state = "timer"
materials = list(MAT_METAL=500, MAT_GLASS=50)
attachable = 1
attachable = TRUE
var/timing = 0
var/timing = FALSE
var/time = 5
var/saved_time = 5
var/loop = 0
var/loop = FALSE
var/hearing_range = 3
/obj/item/assembly/timer/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] looks at the timer and decides [user.p_their()] fate! It looks like [user.p_theyre()] going to commit suicide!</span>")
@@ -21,22 +22,24 @@
user.adjustOxyLoss(200)
user.death(0)
/obj/item/assembly/timer/New()
..()
/obj/item/assembly/timer/Initialize()
. = ..()
START_PROCESSING(SSobj, src)
/obj/item/assembly/timer/describe()
if(timing)
return "The timer is counting down from [time]!"
return "The timer is set for [time] seconds."
/obj/item/assembly/timer/Destroy()
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/assembly/timer/examine(mob/user)
..()
to_chat(user, "<span class='notice'>The timer is [timing ? "counting down from [time]":"set for [time] seconds"].</span>")
/obj/item/assembly/timer/activate()
if(!..())
return 0//Cooldown check
return FALSE//Cooldown check
timing = !timing
update_icon()
return 1
return TRUE
/obj/item/assembly/timer/toggle_secure()
@@ -44,7 +47,7 @@
if(secured)
START_PROCESSING(SSobj, src)
else
timing = 0
timing = FALSE
STOP_PROCESSING(SSobj, src)
update_icon()
return secured
@@ -53,20 +56,25 @@
/obj/item/assembly/timer/proc/timer_end()
if(!secured || next_activate > world.time)
return FALSE
pulse(0)
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
pulse(FALSE)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
if(ismob(CHM))
var/mob/LM = CHM
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
if(loop)
timing = 1
timing = TRUE
update_icon()
/obj/item/assembly/timer/process()
if(timing)
time--
if(time <= 0)
timing = 0
timer_end()
time = saved_time
if(!timing)
return
time--
if(time <= 0)
timing = FALSE
timer_end()
time = saved_time
/obj/item/assembly/timer/update_icon()
@@ -84,7 +92,9 @@
if(is_secured(user))
var/second = time % 60
var/minute = (time - second) / 60
var/dat = "<TT><B>Timing Unit</B>\n[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]\n<A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>\n</TT>"
var/dat = "<TT><B>Timing Unit</B></TT>"
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]"
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
dat += "<BR><BR><A href='?src=[REF(src)];repeat=[(loop ? "0'>Stop repeating" : "1'>Set to repeat")]</A>"
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
@@ -95,7 +105,7 @@
/obj/item/assembly/timer/Topic(href, href_list)
..()
if(usr.incapacitated() || !in_range(loc, usr))
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=timer")
onclose(usr, "timer")
return

View File

@@ -1,14 +1,19 @@
#define INCLUSIVE_MODE 1
#define EXCLUSIVE_MODE 2
#define RECOGNIZER_MODE 3
#define VOICE_SENSOR_MODE 4
/obj/item/assembly/voice
name = "voice analyzer"
desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
icon_state = "voice"
materials = list(MAT_METAL=500, MAT_GLASS=50)
flags_1 = HEAR_1
attachable = 1
attachable = TRUE
verb_say = "beeps"
verb_ask = "beeps"
verb_exclaim = "beeps"
var/listening = 0
var/listening = FALSE
var/recorded = "" //the activation message
var/mode = 1
var/static/list/modes = list("inclusive",
@@ -32,60 +37,64 @@
/obj/item/assembly/voice/proc/record_speech(atom/movable/speaker, raw_message, datum/language/message_language)
switch(mode)
if(1)
if(INCLUSIVE_MODE)
recorded = raw_message
listening = 0
listening = FALSE
say("Activation message is '[recorded]'.", message_language)
if(2)
if(EXCLUSIVE_MODE)
recorded = raw_message
listening = 0
listening = FALSE
say("Activation message is '[recorded]'.", message_language)
if(3)
if(RECOGNIZER_MODE)
recorded = speaker.GetVoice()
listening = 0
listening = FALSE
say("Your voice pattern is saved.", message_language)
if(4)
if(VOICE_SENSOR_MODE)
if(length(raw_message))
addtimer(CALLBACK(src, .proc/pulse, 0), 10)
/obj/item/assembly/voice/proc/check_activation(atom/movable/speaker, raw_message)
. = 0
. = FALSE
switch(mode)
if(1)
if(INCLUSIVE_MODE)
if(findtext(raw_message, recorded))
. = 1
if(2)
. = TRUE
if(EXCLUSIVE_MODE)
if(raw_message == recorded)
. = 1
if(3)
. = TRUE
if(RECOGNIZER_MODE)
if(speaker.GetVoice() == recorded)
. = 1
if(4)
. = TRUE
if(VOICE_SENSOR_MODE)
if(length(raw_message))
. = 1
. = TRUE
/obj/item/assembly/voice/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/multitool))
mode %= modes.len
mode++
to_chat(user, "You set [src] into a [modes[mode]] mode.")
listening = 0
recorded = ""
else
return ..()
/obj/item/assembly/voice/multitool_act(mob/living/user, obj/item/I)
mode %= modes.len
mode++
to_chat(user, "<span class='notice'>You set [src] into [modes[mode]] mode.</span>")
listening = FALSE
recorded = ""
return TRUE
/obj/item/assembly/voice/activate()
if(secured)
if(!holder)
listening = !listening
say("[listening ? "Now" : "No longer"] recording input.")
if(!secured || holder)
return FALSE
listening = !listening
say("[listening ? "Now" : "No longer"] recording input.")
return TRUE
/obj/item/assembly/voice/attack_self(mob/user)
if(!user)
return 0
return FALSE
activate()
return 1
return TRUE
/obj/item/assembly/voice/toggle_secure()
. = ..()
listening = 0
listening = FALSE
#undef INCLUSIVE_MODE
#undef EXCLUSIVE_MODE
#undef RECOGNIZER_MODE
#undef VOICE_SENSOR_MODE

View File

@@ -637,6 +637,7 @@
var/frequency = FREQ_SIGNALER
var/code = DEFAULT_SIGNALER_CODE
var/datum/radio_frequency/radio_connection
var/hearing_range = 1
/obj/item/integrated_circuit/input/signaler/Initialize()
. = ..()
@@ -690,7 +691,11 @@
return 0
activate_pin(3)
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
for(var/CHM in get_hearers_in_view(hearing_range, src))
if(ismob(CHM))
var/mob/LM = CHM
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
/obj/item/integrated_circuit/input/ntnet_packet
name = "NTNet networking circuit"

View File

@@ -170,7 +170,8 @@
if(href_list["send"])
signaler.send_activation()
audible_message("[icon2html(src, world)] *beep* *beep*")
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
if(href_list["freq"])
var/new_frequency = (signaler.frequency + text2num(href_list["freq"]))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB