Merge branch 'master' into instrument-tgui-n-optimization

This commit is contained in:
mochi
2020-09-14 20:04:48 +02:00
566 changed files with 13581 additions and 11293 deletions
+1 -1
View File
@@ -42,7 +42,7 @@
if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover))
return
if((H.flying) || H.buckled)
if(H.flying || H.floating || H.buckled)
return
var/damage = rand(min_damage, max_damage)
+1 -1
View File
@@ -51,6 +51,6 @@
Additionally calls the parent's `after_slip()` proc on the `victim`.
*/
/datum/component/slippery/proc/Slip(datum/source, mob/living/carbon/human/victim)
if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb))
if(istype(victim) && !victim.flying && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, slip_always, slip_verb))
var/atom/movable/owner = parent
owner.after_slip(victim)
+8
View File
@@ -67,6 +67,14 @@
var/obj/item/projectile/P = AM
if(P.original != parent)
return
if(ismob(AM))
var/mob/M = AM
if(M.flying)
return
if(isliving(AM))
var/mob/living/L = M
if(L.floating)
return
var/atom/current_parent = parent
if(isturf(current_parent.loc))
play_squeak()
+3
View File
@@ -57,6 +57,9 @@
W.plane = initial(W.plane)
W.loc = affected_mob.loc
W.dropped(affected_mob)
if(isobj(affected_mob.loc))
var/obj/O = affected_mob.loc
O.force_eject_occupant()
var/mob/living/new_mob = new new_form(affected_mob.loc)
if(istype(new_mob))
new_mob.a_intent = "harm"
+32 -13
View File
@@ -3,32 +3,51 @@
var/raw_time // When did this happen?
var/what // What happened
var/who // Who did it
var/target // Who/what was targeted (can be a string)
var/turf/where // Where did it happen
var/target // Who/what was targeted
var/where // Where did it happen
/datum/log_record/New(_log_type, _who, _what, _target, _where, _raw_time)
log_type = _log_type
who = get_subject_text(_who)
who = get_subject_text(_who, _log_type)
what = _what
target = get_subject_text(_target)
if(!_where)
target = get_subject_text(_target, _log_type)
if(!istext(_where) && !isturf(_where))
_where = get_turf(_who)
where = _where
if(isturf(_where))
var/turf/T = _where
where = ADMIN_COORDJMP(T)
else
where = _where
if(!_raw_time)
_raw_time = world.time
raw_time = _raw_time
/datum/log_record/proc/get_subject_text(subject)
/datum/log_record/proc/get_subject_text(subject, log_type)
if(ismob(subject) || isclient(subject) || istype(subject, /datum/mind))
return key_name_admin(subject)
if(isatom(subject))
. = key_name_admin(subject)
if(should_log_health(log_type) && isliving(subject))
. += get_health_string(subject)
else if(isatom(subject))
var/atom/A = subject
return A.name
if(istype(subject, /datum))
. = A.name
else if(istype(subject, /datum))
var/datum/D = subject
return D.type
return subject
else
. = subject
/datum/log_record/proc/get_health_string(var/mob/living/L)
var/OX = L.getOxyLoss() > 50 ? "<b>[L.getOxyLoss()]</b>" : L.getOxyLoss()
var/TX = L.getToxLoss() > 50 ? "<b>[L.getToxLoss()]</b>" : L.getToxLoss()
var/BU = L.getFireLoss() > 50 ? "<b>[L.getFireLoss()]</b>" : L.getFireLoss()
var/BR = L.getBruteLoss() > 50 ? "<b>[L.getBruteLoss()]</b>" : L.getBruteLoss()
return " ([L.health]: <font color='deepskyblue'>[OX]</font> - <font color='green'>[TX]</font> - <font color='#FFA500'>[BU]</font> - <font color='red'>[BR]</font>)"
/datum/log_record/proc/should_log_health(log_type)
if(log_type == ATTACK_LOG || log_type == DEFENSE_LOG)
return TRUE
return FALSE
/proc/compare_log_record(datum/log_record/A, datum/log_record/B)
var/time_diff = A.raw_time - B.raw_time
+108 -24
View File
@@ -1,31 +1,45 @@
#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG)
#define UPDATE_CKEY_MOB(__ckey) var/mob/result = selected_ckeys_mobs[__ckey];\
if(!result || result.ckey != __ckey){\
result = get_mob_by_ckey(__ckey);\
selected_ckeys_mobs[__ckey] = result;\
}
#define RECORD_WARN_LIMIT 1000
#define RECORD_HARD_LIMIT 2500
/datum/log_viewer
var/time_from = 0
var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up
var/list/selected_mobs = list() // The mobs in question
var/list/selected_log_types = list() // The log types being searched for
var/list/selected_mobs = list() // The mobs in question.
var/list/selected_ckeys = list() // The ckeys selected to search for. Will show all mobs the ckey is attached to
var/list/mob/selected_ckeys_mobs = list()
var/list/selected_log_types = ALL_LOGS // The log types being searched for
var/list/log_records = list() // Found and sorted records
/datum/log_viewer/proc/clear_all()
selected_mobs.Cut()
selected_log_types.Cut()
selected_log_types = ALL_LOGS
selected_ckeys.Cut()
selected_ckeys_mobs.Cut()
time_from = initial(time_from)
time_to = initial(time_to)
log_records.Cut()
return
/datum/log_viewer/proc/search()
/datum/log_viewer/proc/search(user)
log_records.Cut() // Empty the old results
var/list/invalid_mobs = list()
var/list/ckeys = selected_ckeys.Copy()
for(var/i in selected_mobs)
var/mob/M = i
if(!M || QDELETED(M))
if(!M || QDELETED(M) || !M.last_known_ckey)
invalid_mobs |= M
continue
ckeys |= M.last_known_ckey
for(var/ckey in ckeys)
for(var/log_type in selected_log_types)
var/list/logs = M.logs[log_type]
var/list/logs = GLOB.logging.get_logs_by_type(ckey, log_type)
var/len_logs = length(logs)
if(len_logs)
var/start_index = get_earliest_log_index(logs)
@@ -36,8 +50,8 @@
continue
log_records.Add(logs.Copy(start_index, end_index + 1))
if(invalid_mobs.len)
to_chat(usr, "<span class='warning'>The search criteria contained invalid mobs. They have been removed from the criteria.</span>")
if(length(invalid_mobs))
to_chat(user, "<span class='warning'>The search criteria contained invalid mobs. They have been removed from the criteria.</span>")
for(var/i in invalid_mobs)
selected_mobs -= i // Cleanup
@@ -91,9 +105,23 @@
return start
return 0
/datum/log_viewer/proc/add_mob(mob/user, mob/M)
/datum/log_viewer/proc/add_mobs(list/mob/mobs)
if(!length(mobs))
return
for(var/i in mobs)
add_mob(usr, i, FALSE)
/datum/log_viewer/proc/add_ckey(mob/user, ckey)
if(!user || !ckey)
return
selected_ckeys |= ckey
UPDATE_CKEY_MOB(ckey)
show_ui(user)
/datum/log_viewer/proc/add_mob(mob/user, mob/M, show_the_ui = TRUE)
if(!M || !user)
return
selected_mobs |= M
show_ui(user)
@@ -102,9 +130,9 @@
var/all_log_types = ALL_LOGS
var/trStyleTop = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;"
var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;"
var/dat
dat += "<head><style>.adminticket{border:2px solid} td{border:1px solid grey;} th{border:1px solid grey;} span{float:left;width:150px;}</style></head>"
dat += "<div style='height:15vh'>"
var/list/dat = list()
dat += "<head><meta http-equiv='X-UA-Compatible' content='IE=edge'><style>.adminticket{border:2px solid} td{border:1px solid grey;} th{border:1px solid grey;} span{float:left;width:150px;}</style></head>"
dat += "<div style='min-height:100px'>"
dat += "<span>Time Search Range:</span> <a href='?src=[UID()];start_time=1'>[gameTimestamp(wtime = time_from)]</a>"
dat += " To: <a href='?src=[UID()];end_time=1'>[gameTimestamp(wtime = time_to)]</a>"
dat += "<BR>"
@@ -115,20 +143,26 @@
if(QDELETED(M))
selected_mobs -= i
continue
dat += "<a href='?src=[UID()];remove_mob=\ref[M]'>[M.name]</a>"
dat += "<a href='?src=[UID()];remove_mob=\ref[M]'>[get_display_name(M)]</a>"
dat += "<a href='?src=[UID()];add_mob=1'>Add Mob</a>"
dat += "<a href='?src=[UID()];clear_mobs=1'>Clear All Mobs</a>"
dat += "<BR>"
dat += "<span>Ckeys being used:</span>"
for(var/ckey in selected_ckeys)
dat += "<a href='?src=[UID()];remove_ckey=[ckey]'>[get_ckey_name(ckey)]</a>"
dat += "<a href='?src=[UID()];add_ckey=1'>Add ckey</a>"
dat += "<a href='?src=[UID()];clear_ckeys=1'>Clear All ckeys</a>"
dat += "<BR>"
dat += "<span>Log Types:</span>"
for(var/i in all_log_types)
var/log_type = i
for(var/log_type in all_log_types)
var/enabled = (log_type in selected_log_types)
var/text
var/style
if(enabled)
text = "<b>[log_type]</b>"
style = "background: [get_logtype_color(i)]"
style = "background: [get_logtype_color(log_type)]"
else
text = log_type
@@ -142,9 +176,9 @@
// Search results
var/tdStyleTime = "width:80px; text-align:center;"
var/tdStyleType = "width:80px; text-align:center;"
var/tdStyleWho = "width:300px; text-align:center;"
var/tdStyleWho = "width:400px; text-align:center;"
var/tdStyleWhere = "width:150px; text-align:center;"
dat += "<div style='overflow-y: auto; max-height:76vh;'>"
dat += "<div style='overflow-y: auto; max-height:calc(100vh - 150px);'>"
dat += "<table style='width:100%; border: 1px solid;'>"
dat += "<tr style='[trStyleTop]'><th style='[tdStyleTime]'>When</th><th style='[tdStyleType]'>Type</th><th style='[tdStyleWho]'>Who</th><th>What</th><th>Target</th><th style='[tdStyleWhere]'>Where</th></tr>"
for(var/i in log_records)
@@ -153,13 +187,12 @@
dat +="<tr style='[trStyle]'><td style='[tdStyleTime]'>[time]</td><td style='[tdStyleType]background: [get_logtype_color(L.log_type)]'>[L.log_type]</td>\
<td style='[tdStyleWho]'>[L.who]</td><td style='background: [get_logtype_color(L.log_type)];'>[L.what]</td>\
<td style='[tdStyleWho]'>[L.target]</td><td style='[tdStyleWhere]'>[ADMIN_COORDJMP(L.where)]</td></tr>"
<td style='[tdStyleWho]'>[L.target]</td><td style='[tdStyleWhere]'>[L.where]</td></tr>"
dat += "</table>"
dat += "</div>"
var/datum/browser/popup = new(user, "Log viewer", "Log viewer", 1400, 600)
popup.set_content(dat)
var/datum/browser/popup = new(user, "Log Viewer", "Log Viewer", 1500, 600)
popup.set_content(dat.Join())
popup.open()
/datum/log_viewer/Topic(href, href_list)
@@ -188,6 +221,19 @@
return
if(href_list["search"])
search(usr)
var/records_len = length(log_records)
if(records_len > RECORD_WARN_LIMIT)
var/datum/log_record/last_record = log_records[RECORD_WARN_LIMIT]
var/last_time = gameTimestamp(wtime = last_record.raw_time - 9.99)
var/answer = alert(usr, "More than [RECORD_WARN_LIMIT] records were found. continuing will take a long time. This won't cause much lag for the server. Time at the [RECORD_WARN_LIMIT]th record '[last_time]'", "Warning", "Continue", "Limit to [RECORD_WARN_LIMIT]", "Cancel")
if(answer == "Limit to [RECORD_WARN_LIMIT]")
log_records.Cut(RECORD_WARN_LIMIT)
else if(answer == "Cancel")
log_records.Cut()
else
if(records_len > RECORD_HARD_LIMIT)
to_chat(usr, "<span class='warning'>Record limit reached. Limiting to [RECORD_HARD_LIMIT].</span>")
log_records.Cut(RECORD_HARD_LIMIT)
show_ui(usr)
return
if(href_list["clear_all"])
@@ -198,17 +244,31 @@
selected_mobs.Cut()
show_ui(usr)
return
if(href_list["clear_ckeys"])
selected_ckeys.Cut()
selected_ckeys_mobs.Cut()
show_ui(usr)
return
if(href_list["add_mob"])
var/list/mobs = getpois(TRUE, TRUE)
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
A.on_close(CALLBACK(src, .proc/add_mob, usr))
return
if(href_list["add_ckey"])
var/list/ckeys = GLOB.logging.get_ckeys_logged()
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a ckey: ", ckeys)
A.on_close(CALLBACK(src, .proc/add_ckey, usr))
return
if(href_list["remove_mob"])
var/mob/M = locate(href_list["remove_mob"])
if(M)
selected_mobs -= M
show_ui(usr)
return
if(href_list["remove_ckey"])
selected_ckeys -= href_list["remove_ckey"]
show_ui(usr)
return
if(href_list["toggle_log_type"])
var/log_type = href_list["toggle_log_type"]
if(log_type in selected_log_types)
@@ -232,4 +292,28 @@
return "deepskyblue"
if(MISC_LOG)
return "gray"
if(DEADCHAT_LOG)
return "#cc00c6"
if(OOC_LOG)
return "#002eb8"
if(LOOC_LOG)
return "#6699CC"
return "slategray"
/datum/log_viewer/proc/get_display_name(mob/M)
var/name = M.name
if(M.name != M.real_name)
name = "[name] ([M.real_name])"
if(isobserver(M))
name = "[name] (DEAD)"
return "\[[M.last_known_ckey]\] [name]"
/datum/log_viewer/proc/get_ckey_name(ckey)
UPDATE_CKEY_MOB(ckey)
var/mob/M = selected_ckeys_mobs[ckey]
return get_display_name(M)
#undef UPDATE_CKEY_MOB
#undef RECORD_WARN_LIMIT
#undef RECORD_HARD_LIMIT
+47
View File
@@ -0,0 +1,47 @@
/datum/logging
var/list/datum/log_record/logs = list() // Assoc list of assoc lists (ckey, (log_type, list/logs))
/datum/logging/proc/add_log(ckey, datum/log_record/log)
if(!ckey)
log_debug("GLOB.logging.add_log called with an invalid ckey")
return
if(!logs[ckey])
logs[ckey] = list()
var/list/log_types_list = logs[ckey]
if(!log_types_list[log.log_type])
log_types_list[log.log_type] = list()
var/list/datum/log_record/log_records = log_types_list[log.log_type]
log_records.Add(log)
/datum/logging/proc/get_ckeys_logged()
var/list/ckeys = list()
for(var/ckey in logs)
ckeys.Add(ckey)
return ckeys
/* Returns the logs of a given ckey and log_type
* If no logs exist it will return an empty list
*/
/datum/logging/proc/get_logs_by_type(ckey, log_type)
if(!ckey)
log_debug("GLOB.logging.get_logs_by_type called with an invalid ckey")
return
if(!log_type || !(log_type in ALL_LOGS))
log_debug("GLOB.logging.get_logs_by_type called with an invalid log_type '[log_type]'")
return
var/list/log_types_list = logs[ckey]
// Check if logs exist for the ckey
if(!length(log_types_list))
return list()
var/list/datum/log_record/log_records = log_types_list[log_type]
// Check if logs exist for this type
if(!log_records)
return list()
return log_records
+4 -11
View File
@@ -100,14 +100,6 @@
current.mind = null
leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
for(var/log_type in current.logs) // Copy the old logs
var/list/logs = current.logs[log_type]
if(new_character.logs[log_type])
new_character.logs[log_type] += logs.Copy() // Append the old ones
new_character.logs[log_type] = sortTim(new_character.logs[log_type], /proc/compare_log_record) // Sort them on time
else
new_character.logs[log_type] = logs.Copy() // Just copy them
SSnanoui.user_transferred(current, new_character)
if(new_character.mind) //remove any mind currently in our new body's mind variable
@@ -1419,9 +1411,10 @@
return A
/datum/mind/proc/announce_objectives()
to_chat(current, "<span class='notice'>Your current objectives:</span>")
for(var/line in splittext(gen_objective_text(), "<br>"))
to_chat(current, line)
if(current)
to_chat(current, "<span class='notice'>Your current objectives:</span>")
for(var/line in splittext(gen_objective_text(), "<br>"))
to_chat(current, line)
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
+2 -2
View File
@@ -222,10 +222,10 @@
name = "NT Undercover Operative"
// Disguised NT special forces, sent to quietly eliminate or keep tabs on people in high positions (e.g: captain)
uniform = /obj/item/clothing/under/color/black
uniform = /obj/item/clothing/under/color/random
back = /obj/item/storage/backpack
belt = /obj/item/storage/belt/utility/full/multitool
gloves = /obj/item/clothing/gloves/combat
gloves = /obj/item/clothing/gloves/color/yellow
shoes = /obj/item/clothing/shoes/chameleon/noslip
l_ear = /obj/item/radio/headset/centcom
id = /obj/item/card/id
+26
View File
@@ -248,3 +248,29 @@
allow_duplicates = FALSE // I dont even want to think about what happens if you have 2 shuttles with the same ID. Likely scary stuff.
always_place = TRUE // Its designed to make exploring other space ruins more accessible
cost = 0 // Force spawned so shouldnt have a cost
/datum/map_template/ruin/space/syndiecakesfactory
id = "Syndiecakes Factory"
suffix = "syndiecakesfactory.dmm"
name = "Syndicakes Factory"
description = "Syndicate used to get funds selling corgi cakes produced here. Was it hit by meteors or by a Nanotrasen comando?"
allow_duplicates = FALSE
cost = 2 //telecomms + multiple mobs
/datum/map_template/ruin/space/debris1
id = "debris1"
suffix = "debris1.dmm"
name = "Debris field 1"
description = "A bunch of metal chunks, wires and space waste"
/datum/map_template/ruin/space/debris2
id = "debris2"
suffix = "debris2.dmm"
name = "Debris field 2"
description = "A bunch of metal chunks, wires and space waste that used to be some kind of secure storage facility"
/datum/map_template/ruin/space/debris3
id = "debris3"
suffix = "debris3.dmm"
name = "Debris field 3"
description = "A bunch of metal chunks, wires and space waste. It used to be an arcade."
+8 -2
View File
@@ -9,8 +9,9 @@
var/admin_notes
/datum/map_template/shuttle/New()
shuttle_id = "[port_id]_[suffix]"
mappath = "[prefix][shuttle_id].dmm"
if(port_id && suffix)
shuttle_id = "[port_id]_[suffix]"
mappath = "[prefix][shuttle_id].dmm"
. = ..()
/datum/map_template/shuttle/emergency
@@ -132,3 +133,8 @@
suffix = "admin"
name = "NTV Argos"
description = "Default Admin ship. An older ship used for special operations."
/datum/map_template/shuttle/admin/armory
suffix = "armory"
name = "NRV Sparta"
description = "Armory Shuttle, with plenty of guns to hand out and some general supplies."
+5
View File
@@ -444,6 +444,11 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
return
// Normally, AoE spells will generate an attack log for every turf they loop over, while searching for targets.
// With this override, all /aoe_turf type spells will only generate 1 log, saying that the user has cast the spell.
/obj/effect/proc_holder/spell/aoe_turf/perform(list/targets, recharge, mob/user, make_attack_logs)
add_attack_logs(user, null, "Cast the AoE spell [name]", ATKLOG_ALL)
return ..(targets, recharge, user, FALSE)
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
//Checks for obstacles from A to B
-5
View File
@@ -13,11 +13,6 @@
action_icon_state = "knock"
sound = 'sound/magic/knock.ogg'
// Knock doesn't need to generate an attack log for every turf, set `make_attack_logs` to FALSE and just create a custom one.
/obj/effect/proc_holder/spell/aoe_turf/knock/perform(list/targets, recharge, mob/user)
add_attack_logs(user, user, "cast the spell [name]", ATKLOG_ALL)
return ..(targets, recharge, user, make_attack_logs = FALSE)
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets, mob/user = usr)
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
+4 -6
View File
@@ -633,7 +633,6 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
contains = list(/obj/machinery/power/emitter,
/obj/machinery/power/emitter)
cost = 10
containertype = /obj/structure/closet/crate/secure
containername = "emitter crate"
access = ACCESS_CE
containertype = /obj/structure/closet/crate/secure/engineering
@@ -717,7 +716,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
name = "Supermatter Shard Crate"
contains = list(/obj/machinery/power/supermatter_shard)
cost = 50 //So cargo thinks twice before killing themselves with it
containertype = /obj/structure/closet/crate/secure
containertype = /obj/structure/closet/crate/secure/engineering
containername = "supermatter shard crate"
access = ACCESS_CE
@@ -728,7 +727,7 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
/obj/item/pipe/circulator,
/obj/item/pipe/circulator)
cost = 25
containertype = /obj/structure/closet/crate/secure
containertype = /obj/structure/closet/crate/secure/engineering
containername = "thermo-electric generator crate"
access = ACCESS_CE
announce_beacons = list("Engineering" = list("Chief Engineer's Desk", "Atmospherics"))
@@ -1174,11 +1173,10 @@ GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY
containername = "fox crate"
/datum/supply_packs/organic/butterfly
name = "Butterflies Crate"
name = "Butterfly Crate"
cost = 50
containertype = /obj/structure/closet/critter/butterfly
containername = "butterflies crate"
contraband = 1
containername = "butterfly crate"
/datum/supply_packs/organic/deer
name = "Deer Crate"
+2 -2
View File
@@ -1725,8 +1725,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
U.purchase_log += "<BIG>[bicon(C)]</BIG>"
for(var/item in bought_items)
new item(C)
U.purchase_log += "<BIG>[bicon(item)]</BIG>"
var/obj/purchased = new item(C)
U.purchase_log += "<BIG>[bicon(purchased)]</BIG>"
log_game("[key_name(usr)] purchased a surplus crate with [jointext(itemlog, ", ")]")
/datum/uplink_item/bundles_TC/telecrystal
@@ -35,6 +35,8 @@
return
if(!L.client) //Only sentient people are going along with it!
return
if(L.flying)
return
L.adjustFireLoss(3)
/datum/weather/floor_is_lava/fake
+62 -106
View File
@@ -1,67 +1,29 @@
// Wires for airlocks
/datum/wires/airlock/secure
random = 1
randomize = TRUE
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
wire_count = 12
window_x = 410
window_y = 570
wire_count = 12 // 10 actual, 2 duds.
proper_name = "Airlock"
window_x = 400
window_y = 101
#define AIRLOCK_WIRE_IDSCAN 1
#define AIRLOCK_WIRE_MAIN_POWER1 2
#define AIRLOCK_WIRE_DOOR_BOLTS 4
#define AIRLOCK_WIRE_BACKUP_POWER1 8
#define AIRLOCK_WIRE_OPEN_DOOR 16
#define AIRLOCK_WIRE_AI_CONTROL 32
#define AIRLOCK_WIRE_ELECTRIFY 64
#define AIRLOCK_WIRE_SAFETY 128
#define AIRLOCK_WIRE_SPEED 256
#define AIRLOCK_WIRE_LIGHT 512
/datum/wires/airlock/New(atom/_holder)
wires = list(
WIRE_IDSCAN, WIRE_MAIN_POWER1, WIRE_DOOR_BOLTS, WIRE_BACKUP_POWER1, WIRE_OPEN_DOOR,
WIRE_AI_CONTROL, WIRE_ELECTRIFY, WIRE_SAFETY, WIRE_SPEED, WIRE_BOLT_LIGHT
)
return ..()
/datum/wires/airlock/GetWireName(index)
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
return "ID Scan"
if(AIRLOCK_WIRE_MAIN_POWER1)
return "Primary Power"
if(AIRLOCK_WIRE_DOOR_BOLTS)
return "Door Bolts"
if(AIRLOCK_WIRE_BACKUP_POWER1)
return "Primary Backup Power"
if(AIRLOCK_WIRE_OPEN_DOOR)
return "Door State"
if(AIRLOCK_WIRE_AI_CONTROL)
return "AI Control"
if(AIRLOCK_WIRE_ELECTRIFY)
return "Electrification"
if(AIRLOCK_WIRE_ELECTRIFY)
return "Door Safeties"
if(AIRLOCK_WIRE_ELECTRIFY)
return "Door Timing"
if(AIRLOCK_WIRE_ELECTRIFY)
return "Bolt Lights"
/datum/wires/airlock/CanUse(mob/living/L)
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(iscarbon(L))
if(A.Adjacent(L))
if(A.isElectrified())
if(A.shock(L, 100))
return 0
if(iscarbon(user) && A.Adjacent(user) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/airlock/get_status()
. = ..()
@@ -70,21 +32,20 @@
. += "The door bolts [A.locked ? "have fallen!" : "look up."]"
. += "The door bolt lights are [(A.lights && haspower) ? "on." : "off!"]"
. += "The test light is [haspower ? "on." : "off!"]"
. += "The test light is [haspower ? "on." : "off!"]"
. += "The 'AI control allowed' light is [(A.aiControlDisabled == 0 && !A.emagged && haspower) ? "on" : "off"]."
. += "The 'Check Wiring' light is [(A.safe == 0 && haspower) ? "on" : "off"]."
. += "The 'Check Timing Mechanism' light is [(A.normalspeed == 0 && haspower) ? "on" : "off"]."
. += "The emergency lights are [(A.emergency && haspower) ? "on" : "off"]."
/datum/wires/airlock/UpdateCut(index, mended)
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
A.aiDisabledIdScanner = !mended
if(AIRLOCK_WIRE_MAIN_POWER1)
switch(wire)
if(WIRE_IDSCAN)
A.aiDisabledIdScanner = !mend
if(WIRE_MAIN_POWER1)
if(!mended)
if(!mend)
//Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be crowbarred open, but bolts-raising will not work. Cutting these wires may electocute the user.
A.loseMainPower()
A.shock(usr, 50)
@@ -92,9 +53,9 @@
A.regainMainPower()
A.shock(usr, 50)
if(AIRLOCK_WIRE_BACKUP_POWER1)
if(WIRE_BACKUP_POWER1)
if(!mended)
if(!mend)
//Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user.
A.loseBackupPower()
A.shock(usr, 50)
@@ -102,16 +63,16 @@
A.regainBackupPower()
A.shock(usr, 50)
if(AIRLOCK_WIRE_DOOR_BOLTS)
if(WIRE_DOOR_BOLTS)
if(!mended)
if(!mend)
//Cutting this wire also drops the door bolts, and mending it does not raise them. (This is what happens now, except there are a lot more wires going to door bolts at present)
A.lock(1)
A.update_icon()
if(AIRLOCK_WIRE_AI_CONTROL)
if(WIRE_AI_CONTROL)
if(!mended)
if(!mend)
//one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
//aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
if(A.aiControlDisabled == 0)
@@ -124,44 +85,44 @@
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(AIRLOCK_WIRE_ELECTRIFY)
if(!mended)
if(WIRE_ELECTRIFY)
if(!mend)
//Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted.
A.electrify(-1)
else
A.electrify(0)
return // Don't update the dialog.
if(AIRLOCK_WIRE_SAFETY)
A.safe = mended
if(WIRE_SAFETY)
A.safe = mend
if(AIRLOCK_WIRE_SPEED)
A.autoclose = mended
if(mended)
if(WIRE_SPEED)
A.autoclose = mend
if(mend)
if(!A.density)
spawn(0)
A.close()
INVOKE_ASYNC(A, /obj/machinery/door/airlock/.proc/close)
if(AIRLOCK_WIRE_LIGHT)
A.lights = mended
if(WIRE_BOLT_LIGHT)
A.lights = mend
A.update_icon()
..()
/datum/wires/airlock/UpdatePulsed(index)
/datum/wires/airlock/on_pulse(wire)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
switch(wire)
if(WIRE_IDSCAN)
//Sending a pulse through flashes the red light on the door (if the door has power).
if(A.arePowerSystemsOn() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = 0
A.update_icon()
if(AIRLOCK_WIRE_MAIN_POWER1)
if(WIRE_MAIN_POWER1)
//Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter).
A.loseMainPower()
if(AIRLOCK_WIRE_DOOR_BOLTS)
if(WIRE_DOOR_BOLTS)
//one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not),
//raises them if they are down (only if power's on)
if(!A.locked)
@@ -170,45 +131,40 @@
else if(A.unlock())
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", hearing_distance = 1)
if(AIRLOCK_WIRE_BACKUP_POWER1)
if(WIRE_BACKUP_POWER1)
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
A.loseBackupPower()
if(AIRLOCK_WIRE_AI_CONTROL)
if(WIRE_AI_CONTROL)
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
addtimer(CALLBACK(A, /obj/machinery/door/airlock/.proc/ai_control_callback), 1 SECONDS)
spawn(10)
if(A)
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(AIRLOCK_WIRE_ELECTRIFY)
if(WIRE_ELECTRIFY)
//one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds.
A.electrify(30)
if(AIRLOCK_WIRE_OPEN_DOOR)
if(WIRE_OPEN_DOOR)
//tries to open the door without ID
//will succeed only if the ID wire is cut or the door requires no access and it's not emagged
if(A.emagged) return
if(!A.requiresID() || A.check_access(null))
spawn(0)
if(A.density)
A.open()
else
A.close()
if(AIRLOCK_WIRE_SAFETY)
if(A.density)
INVOKE_ASYNC(A, /obj/machinery/door/airlock/.proc/open)
else
INVOKE_ASYNC(A, /obj/machinery/door/airlock/.proc/close)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
spawn(0)
A.close()
INVOKE_ASYNC(A, /obj/machinery/door/airlock/.proc/close)
if(AIRLOCK_WIRE_SPEED)
if(WIRE_SPEED)
A.normalspeed = !A.normalspeed
if(AIRLOCK_WIRE_LIGHT)
if(WIRE_BOLT_LIGHT)
A.lights = !A.lights
A.update_icon()
+41 -69
View File
@@ -2,35 +2,22 @@
/datum/wires/alarm
holder_type = /obj/machinery/alarm
wire_count = 5
window_x = 385
window_y = 90
proper_name = "Air alarm"
#define AALARM_WIRE_IDSCAN 1
#define AALARM_WIRE_POWER 2
#define AALARM_WIRE_SYPHON 4
#define AALARM_WIRE_AI_CONTROL 8
#define AALARM_WIRE_AALARM 16
/datum/wires/alarm/New(atom/_holder)
wires = list(
WIRE_IDSCAN , WIRE_MAIN_POWER1 , WIRE_SYPHON,
WIRE_AI_CONTROL, WIRE_AALARM
)
return ..()
/datum/wires/alarm/GetWireName(index)
switch(index)
if(AALARM_WIRE_IDSCAN)
return "ID Scan"
if(AALARM_WIRE_POWER)
return "Power"
if(AALARM_WIRE_SYPHON)
return "Syphon"
if(AALARM_WIRE_AI_CONTROL)
return "AI Control"
if(AALARM_WIRE_AALARM)
return "Atmospherics Alarm"
/datum/wires/alarm/CanUse(mob/living/L)
/datum/wires/alarm/interactable(mob/user)
var/obj/machinery/alarm/A = holder
if(A.wiresexposed)
return 1
return 0
return TRUE
return FALSE
/datum/wires/alarm/get_status()
. = ..()
@@ -39,75 +26,60 @@
. += "The Air Alarm is [(A.shorted || (A.stat & (NOPOWER|BROKEN))) ? "offline." : "working properly!"]"
. += "The 'AI control allowed' light is [A.aidisabled ? "off" : "on"]."
/datum/wires/alarm/UpdateCut(index, mended)
/datum/wires/alarm/on_cut(wire, mend)
var/obj/machinery/alarm/A = holder
switch(index)
if(AALARM_WIRE_IDSCAN)
if(!mended)
switch(wire)
if(WIRE_IDSCAN)
if(!mend)
A.locked = 1
// to_chat(world, "Idscan wire cut")
if(AALARM_WIRE_POWER)
if(WIRE_MAIN_POWER1)
A.shock(usr, 50)
A.shorted = !mended
A.shorted = !mend
A.update_icon()
// to_chat(world, "Power wire cut")
if(AALARM_WIRE_AI_CONTROL)
A.aidisabled = !mended
// to_chat(world, "AI Control Wire Cut")
if(WIRE_AI_CONTROL)
A.aidisabled = !mend
if(AALARM_WIRE_SYPHON)
if(!mended)
if(WIRE_SYPHON)
if(!mend)
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
// to_chat(world, "Syphon Wire Cut")
if(AALARM_WIRE_AALARM)
if(A.alarm_area.atmosalert(2, A))
A.post_alert(2)
if(WIRE_AALARM)
if(A.alarm_area.atmosalert(ATMOS_ALARM_DANGER, A))
A.post_alert(ATMOS_ALARM_DANGER)
A.update_icon()
..()
/datum/wires/alarm/UpdatePulsed(index)
/datum/wires/alarm/on_pulse(wire)
var/obj/machinery/alarm/A = holder
switch(index)
if(AALARM_WIRE_IDSCAN)
switch(wire)
if(WIRE_IDSCAN)
A.locked = !A.locked
// to_chat(world, "Idscan wire pulsed")
if(AALARM_WIRE_POWER)
// to_chat(world, "Power wire pulsed")
if(A.shorted == 0)
A.shorted = 1
if(WIRE_MAIN_POWER1)
if(!A.shorted)
A.shorted = TRUE
A.update_icon()
addtimer(CALLBACK(A, /obj/machinery/alarm/.proc/unshort_callback), 120 SECONDS)
spawn(12000)
if(A.shorted == 1)
A.shorted = 0
A.update_icon()
if(AALARM_WIRE_AI_CONTROL)
// to_chat(world, "AI Control wire pulsed")
if(A.aidisabled == 0)
A.aidisabled = 1
if(WIRE_AI_CONTROL)
if(!A.aidisabled)
A.aidisabled = TRUE
A.updateDialog()
spawn(100)
if(A.aidisabled == 1)
A.aidisabled = 0
addtimer(CALLBACK(A, /obj/machinery/alarm/.proc/enable_ai_control_callback), 10 SECONDS)
if(AALARM_WIRE_SYPHON)
// to_chat(world, "Syphon wire pulsed")
if(WIRE_SYPHON)
if(A.mode == 1) // AALARM_MODE_SCRUB
A.mode = 3 // AALARM_MODE_PANIC
else
A.mode = 1 // AALARM_MODE_SCRUB
A.apply_mode()
if(AALARM_WIRE_AALARM)
// to_chat(world, "Aalarm wire pulsed")
if(A.alarm_area.atmosalert(0, A))
A.post_alert(0)
if(WIRE_AALARM)
if(A.alarm_area.atmosalert(ATMOS_ALARM_NONE, A))
A.post_alert(ATMOS_ALARM_NONE)
A.update_icon()
..()
+33 -58
View File
@@ -1,25 +1,13 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
wire_count = 4
proper_name = "APC"
window_x = 355
window_y = 97
#define APC_WIRE_IDSCAN 1
#define APC_WIRE_MAIN_POWER1 2
#define APC_WIRE_MAIN_POWER2 4
#define APC_WIRE_AI_CONTROL 8
/datum/wires/apc/GetWireName(index)
switch(index)
if(APC_WIRE_IDSCAN)
return "ID Scan"
if(APC_WIRE_MAIN_POWER1)
return "Primary Power"
if(APC_WIRE_MAIN_POWER2)
return "Secondary Power"
if(APC_WIRE_AI_CONTROL)
return "AI Control"
/datum/wires/apc/New(atom/_holder)
wires = list(WIRE_IDSCAN, WIRE_MAIN_POWER1, WIRE_MAIN_POWER2, WIRE_AI_CONTROL)
return ..()
/datum/wires/apc/get_status()
. = ..()
@@ -29,66 +17,53 @@
. += "The 'AI control allowed' light is [A.aidisabled ? "off" : "on"]."
/datum/wires/apc/CanUse(mob/living/L)
/datum/wires/apc/interactable(mob/user)
var/obj/machinery/power/apc/A = holder
if(A.panel_open && !A.opened)
return TRUE
return FALSE
/datum/wires/apc/UpdatePulsed(index)
/datum/wires/apc/on_pulse(wire)
var/obj/machinery/power/apc/A = holder
switch(index)
switch(wire)
if(WIRE_IDSCAN)
A.locked = FALSE
addtimer(CALLBACK(A, /obj/machinery/power/apc/.proc/relock_callback), 30 SECONDS)
if(APC_WIRE_IDSCAN)
A.locked = 0
spawn(300)
if(A)
A.locked = 1
A.updateDialog()
if(WIRE_MAIN_POWER1, WIRE_MAIN_POWER2)
if(!A.shorted)
A.shorted = TRUE
addtimer(CALLBACK(A, /obj/machinery/power/apc/.proc/check_main_power_callback), 120 SECONDS)
if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(A.shorted == 0)
A.shorted = 1
spawn(1200)
if(A && !IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
A.updateDialog()
if(APC_WIRE_AI_CONTROL)
if(A.aidisabled == 0)
A.aidisabled = 1
spawn(10)
if(A && !IsIndexCut(APC_WIRE_AI_CONTROL))
A.aidisabled = 0
A.updateDialog()
if(WIRE_AI_CONTROL)
if(!A.aidisabled)
A.aidisabled = TRUE
addtimer(CALLBACK(A, /obj/machinery/power/apc/.proc/check_ai_control_callback), 1 SECONDS)
..()
/datum/wires/apc/UpdateCut(index, mended)
/datum/wires/apc/on_cut(wire, mend)
var/obj/machinery/power/apc/A = holder
switch(index)
if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(!mended)
switch(wire)
if(WIRE_MAIN_POWER1, WIRE_MAIN_POWER2)
if(!mend)
A.shock(usr, 50)
A.shorted = 1
A.shorted = TRUE
else if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
else if(!is_cut(WIRE_MAIN_POWER1) && !is_cut(WIRE_MAIN_POWER2))
A.shorted = FALSE
A.shock(usr, 50)
if(APC_WIRE_AI_CONTROL)
if(!mended)
if(A.aidisabled == 0)
A.aidisabled = 1
if(WIRE_AI_CONTROL)
if(!mend)
if(!A.aidisabled)
A.aidisabled = TRUE
else
if(A.aidisabled == 1)
A.aidisabled = 0
if(A.aidisabled)
A.aidisabled = FALSE
..()
+31 -52
View File
@@ -1,21 +1,13 @@
/datum/wires/autolathe
holder_type = /obj/machinery/autolathe
wire_count = 10
proper_name = "Autolathe"
window_x = 340
window_y = 55
#define AUTOLATHE_HACK_WIRE 1
#define AUTOLATHE_SHOCK_WIRE 2
#define AUTOLATHE_DISABLE_WIRE 4
/datum/wires/autolathe/GetWireName(index)
switch(index)
if(AUTOLATHE_HACK_WIRE)
return "Hack"
if(AUTOLATHE_SHOCK_WIRE)
return "Shock"
if(AUTOLATHE_DISABLE_WIRE)
return "Disable"
/datum/wires/autolathe/New(atom/_holder)
wires = list(WIRE_AUTOLATHE_HACK, WIRE_ELECTRIFY, WIRE_AUTOLATHE_DISABLE)
return ..()
/datum/wires/autolathe/get_status()
. = ..()
@@ -24,51 +16,38 @@
. += "The green light is [A.shocked ? "off" : "on"]."
. += "The blue light is [A.hacked ? "off" : "on"]."
/datum/wires/autolathe/CanUse()
/datum/wires/autolathe/interactable(mob/user)
var/obj/machinery/autolathe/A = holder
if(iscarbon(user) && A.Adjacent(user) && A.shocked && A.shock(user, 100))
return FALSE
if(A.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/autolathe/UpdateCut(index, mended)
/datum/wires/autolathe/on_cut(wire, mend)
var/obj/machinery/autolathe/A = holder
switch(index)
if(AUTOLATHE_HACK_WIRE)
A.adjust_hacked(!mended)
if(AUTOLATHE_SHOCK_WIRE)
A.shocked = !mended
if(AUTOLATHE_DISABLE_WIRE)
A.disabled = !mended
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.adjust_hacked(!mend)
if(WIRE_ELECTRIFY)
A.shocked = !mend
if(WIRE_AUTOLATHE_DISABLE)
A.disabled = !mend
..()
/datum/wires/autolathe/UpdatePulsed(index)
if(IsIndexCut(index))
/datum/wires/autolathe/on_pulse(wire)
if(is_cut(wire))
return
var/obj/machinery/autolathe/A = holder
switch(index)
if(AUTOLATHE_HACK_WIRE)
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.adjust_hacked(!A.hacked)
updateUIs()
spawn(50)
if(A && !IsIndexCut(index))
A.adjust_hacked(0)
updateUIs()
if(AUTOLATHE_SHOCK_WIRE)
A.shocked = !A.shocked
updateUIs()
spawn(50)
if(A && !IsIndexCut(index))
A.shocked = 0
updateUIs()
if(AUTOLATHE_DISABLE_WIRE)
A.disabled = !A.disabled
updateUIs()
spawn(50)
if(A && !IsIndexCut(index))
A.disabled = 0
updateUIs()
addtimer(CALLBACK(A, /obj/machinery/autolathe/.proc/check_hacked_callback), 5 SECONDS)
/datum/wires/autolathe/proc/updateUIs()
SSnanoui.update_uis(src)
if(holder)
SSnanoui.update_uis(holder)
if(WIRE_ELECTRIFY)
A.shocked = !A.shocked
addtimer(CALLBACK(A, /obj/machinery/autolathe/.proc/check_electrified_callback), 5 SECONDS)
if(WIRE_AUTOLATHE_DISABLE)
A.disabled = !A.disabled
addtimer(CALLBACK(A, /obj/machinery/autolathe/.proc/check_disabled_callback), 5 SECONDS)
+20 -25
View File
@@ -1,9 +1,15 @@
// Wires for cameras.
/datum/wires/camera
random = 0
holder_type = /obj/machinery/camera
wire_count = 2
proper_name = "Camera"
window_x = 350
window_y = 95
/datum/wires/camera/New(atom/_holder)
wires = list(WIRE_FOCUS, WIRE_MAIN_POWER1)
return ..()
/datum/wires/camera/get_status()
. = ..()
@@ -11,51 +17,40 @@
. += "The focus light is [(C.view_range == initial(C.view_range)) ? "on" : "off"]."
. += "The power link light is [C.can_use() ? "on" : "off"]."
/datum/wires/camera/CanUse(mob/living/L)
/datum/wires/camera/interactable(mob/user)
var/obj/machinery/camera/C = holder
if(!C.panel_open)
return FALSE
return TRUE
#define CAMERA_WIRE_FOCUS 1
#define CAMERA_WIRE_POWER 2
/datum/wires/camera/GetWireName(index)
switch(index)
if(CAMERA_WIRE_FOCUS)
return "Focus"
if(CAMERA_WIRE_POWER)
return "Power"
/datum/wires/camera/UpdateCut(index, mended)
/datum/wires/camera/on_cut(wire, mend)
var/obj/machinery/camera/C = holder
switch(index)
if(CAMERA_WIRE_FOCUS)
var/range = (mended ? initial(C.view_range) : C.short_range)
switch(wire)
if(WIRE_FOCUS)
var/range = (mend ? initial(C.view_range) : C.short_range)
C.setViewRange(range)
if(CAMERA_WIRE_POWER)
if(C.status && !mended || !C.status && mended)
if(WIRE_MAIN_POWER1)
if(C.status && !mend || !C.status && mend)
C.toggle_cam(usr, TRUE)
C.obj_integrity = C.max_integrity //this is a pretty simplistic way to heal the camera, but there's no reason for this to be complex.
..()
/datum/wires/camera/UpdatePulsed(index)
/datum/wires/camera/on_pulse(wire)
var/obj/machinery/camera/C = holder
if(IsIndexCut(index))
if(is_cut(wire))
return
switch(index)
if(CAMERA_WIRE_FOCUS)
switch(wire)
if(WIRE_FOCUS)
var/new_range = (C.view_range == initial(C.view_range) ? C.short_range : initial(C.view_range))
C.setViewRange(new_range)
if(CAMERA_WIRE_POWER)
if(WIRE_MAIN_POWER1)
C.toggle_cam(null) // Deactivate the camera
..()
/datum/wires/camera/proc/CanDeconstruct()
if(IsIndexCut(CAMERA_WIRE_POWER) && IsIndexCut(CAMERA_WIRE_FOCUS))
if(is_cut(WIRE_MAIN_POWER1) && is_cut(WIRE_FOCUS))
return TRUE
else
return FALSE
+14 -14
View File
@@ -1,36 +1,36 @@
/datum/wires/explosive
wire_count = 1
proper_name = "Explosive"
window_x = 320
window_y = 50
#define WIRE_EXPLODE 1
/datum/wires/explosive/GetWireName(index)
switch(index)
if(WIRE_EXPLODE)
return "Explode"
/datum/wires/explosive/New(atom/_holder)
wires = list(WIRE_EXPLODE)
return ..()
/datum/wires/explosive/proc/explode()
return
/datum/wires/explosive/UpdatePulsed(index)
switch(index)
/datum/wires/explosive/on_pulse(wire)
switch(wire)
if(WIRE_EXPLODE)
explode()
..()
/datum/wires/explosive/UpdateCut(index, mended)
switch(index)
/datum/wires/explosive/on_cut(wire, mend)
switch(wire)
if(WIRE_EXPLODE)
if(!mended)
if(!mend)
explode()
..()
/datum/wires/explosive/gibtonite
holder_type = /obj/item/twohanded/required/gibtonite
/datum/wires/explosive/gibtonite/CanUse(mob/L)
return 1
/datum/wires/explosive/gibtonite/interactable(mob/user)
return TRUE
/datum/wires/explosive/gibtonite/UpdateCut(index, mended)
/datum/wires/explosive/gibtonite/on_cut(wire, mend)
return
/datum/wires/explosive/gibtonite/explode()
+20 -75
View File
@@ -1,90 +1,35 @@
/datum/wires/mulebot
random = 1
randomize = TRUE
holder_type = /mob/living/simple_animal/bot/mulebot
wire_count = 10
window_x = 410
proper_name = "Mulebot"
window_x = 370
window_y = -12
#define MULEBOT_WIRE_POWER1 1 // power connections
#define MULEBOT_WIRE_POWER2 2
#define MULEBOT_WIRE_AVOIDANCE 4 // mob avoidance
#define MULEBOT_WIRE_LOADCHECK 8 // load checking (non-crate)
#define MULEBOT_WIRE_MOTOR1 16 // motor wires
#define MULEBOT_WIRE_MOTOR2 32 //
#define MULEBOT_WIRE_REMOTE_RX 64 // remote recv functions
#define MULEBOT_WIRE_REMOTE_TX 128 // remote trans status
#define MULEBOT_WIRE_BEACON_RX 256 // beacon ping recv
/datum/wires/mulebot/New(atom/_holder)
wires = list(
WIRE_MAIN_POWER1, WIRE_MAIN_POWER2, WIRE_MOB_AVOIDANCE,
WIRE_LOADCHECK, WIRE_MOTOR1, WIRE_MOTOR2,
WIRE_REMOTE_RX, WIRE_REMOTE_TX, WIRE_BEACON_RX
)
return ..()
/datum/wires/mulebot/GetWireName(index)
switch(index)
if(MULEBOT_WIRE_POWER1)
return "Primary Power"
if(MULEBOT_WIRE_POWER2)
return "Secondary Power"
if(MULEBOT_WIRE_AVOIDANCE)
return "Mob Avoidance"
if(MULEBOT_WIRE_LOADCHECK)
return "Load Checking"
if(MULEBOT_WIRE_MOTOR1)
return "Primary Motor"
if(MULEBOT_WIRE_MOTOR2)
return "Secondary Motor"
if(MULEBOT_WIRE_REMOTE_RX)
return "Remote Signal Receiver"
if(MULEBOT_WIRE_REMOTE_TX)
return "Remote Signal Sender"
if(MULEBOT_WIRE_BEACON_RX)
return "Navigation Beacon Receiver"
/datum/wires/mulebot/CanUse(mob/living/L)
/datum/wires/mulebot/interactable(mob/user)
var/mob/living/simple_animal/bot/mulebot/M = holder
if(M.open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/mulebot/UpdatePulsed(index)
switch(index)
if(MULEBOT_WIRE_POWER1, MULEBOT_WIRE_POWER2)
/datum/wires/mulebot/on_pulse(wire)
switch(wire)
if(WIRE_MAIN_POWER1, WIRE_MAIN_POWER2)
holder.visible_message("<span class='notice'>[bicon(holder)] The charge light flickers.</span>")
if(MULEBOT_WIRE_AVOIDANCE)
if(WIRE_MOB_AVOIDANCE)
holder.visible_message("<span class='notice'>[bicon(holder)] The external warning lights flash briefly.</span>")
if(MULEBOT_WIRE_LOADCHECK)
if(WIRE_LOADCHECK)
holder.visible_message("<span class='notice'>[bicon(holder)] The load platform clunks.</span>")
if(MULEBOT_WIRE_MOTOR1, MULEBOT_WIRE_MOTOR2)
if(WIRE_MOTOR1, WIRE_MOTOR2)
holder.visible_message("<span class='notice'>[bicon(holder)] The drive motor whines briefly.</span>")
else
holder.visible_message("<span class='notice'>[bicon(holder)] You hear a radio crackle.</span>")
..()
// HELPER PROCS
/datum/wires/mulebot/proc/Motor1()
return !(wires_status & MULEBOT_WIRE_MOTOR1)
/datum/wires/mulebot/proc/Motor2()
return !(wires_status & MULEBOT_WIRE_MOTOR2)
/datum/wires/mulebot/proc/HasPower()
return !(wires_status & MULEBOT_WIRE_POWER1) && !(wires_status & MULEBOT_WIRE_POWER2)
/datum/wires/mulebot/proc/LoadCheck()
return !(wires_status & MULEBOT_WIRE_LOADCHECK)
/datum/wires/mulebot/proc/MobAvoid()
return !(wires_status & MULEBOT_WIRE_AVOIDANCE)
/datum/wires/mulebot/proc/RemoteTX()
return !(wires_status & MULEBOT_WIRE_REMOTE_TX)
/datum/wires/mulebot/proc/RemoteRX()
return !(wires_status & MULEBOT_WIRE_REMOTE_RX)
/datum/wires/mulebot/proc/BeaconRX()
return !(wires_status & MULEBOT_WIRE_BEACON_RX)
+29 -53
View File
@@ -1,28 +1,20 @@
/datum/wires/nuclearbomb
holder_type = /obj/machinery/nuclearbomb
random = 1
wire_count = 7
randomize = TRUE
wire_count = 7 // 3 actual, 4 duds.
proper_name = "Nuclear bomb"
window_x = 345
window_y = 75
#define NUCLEARBOMB_WIRE_LIGHT 1
#define NUCLEARBOMB_WIRE_TIMING 2
#define NUCLEARBOMB_WIRE_SAFETY 4
/datum/wires/nuclearbomb/New(atom/_holder)
wires = list(WIRE_BOMB_LIGHT, WIRE_BOMB_TIMING, WIRE_BOMB_SAFETY)
return ..()
/datum/wires/nuclearbomb/GetWireName(index)
switch(index)
if(NUCLEARBOMB_WIRE_LIGHT)
return "Bomb Light"
if(NUCLEARBOMB_WIRE_TIMING)
return "Bomb Timing"
if(NUCLEARBOMB_WIRE_SAFETY)
return "Bomb Safety"
/datum/wires/nuclearbomb/CanUse(mob/living/L)
/datum/wires/nuclearbomb/interactable(mob/user)
var/obj/machinery/nuclearbomb/N = holder
if(N.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/nuclearbomb/get_status()
. = ..()
@@ -31,52 +23,36 @@
. += "The device is is [N.safety ? "quiet" : "whirring"]."
. += "The lights are [N.lighthack ? "static" : "functional"]."
/datum/wires/nuclearbomb/UpdatePulsed(index)
/datum/wires/nuclearbomb/on_pulse(wire)
var/obj/machinery/nuclearbomb/N = holder
switch(index)
if(NUCLEARBOMB_WIRE_LIGHT)
switch(wire)
if(WIRE_BOMB_LIGHT)
N.lighthack = !N.lighthack
updateUIs()
spawn(100)
N.lighthack = !N.lighthack
updateUIs()
if(NUCLEARBOMB_WIRE_TIMING)
addtimer(CALLBACK(N, /obj/machinery/nuclearbomb/.proc/reset_lighthack_callback), 10 SECONDS)
if(WIRE_BOMB_TIMING)
if(N.timing)
message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonation wire, causing it to explode (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
N.explode()
if(NUCLEARBOMB_WIRE_SAFETY)
N.safety = !N.safety
updateUIs()
spawn(100)
N.safety = !N.safety
if(N.safety == 1)
if(!N.is_syndicate)
set_security_level(N.previous_level)
N.visible_message("<span class='notice'>The [N] quiets down.</span>")
if(!N.lighthack)
if(N.icon_state == "nuclearbomb2")
N.icon_state = "nuclearbomb1"
else
N.visible_message("<span class='notice'>The [N] emits a quiet whirling noise!</span>")
updateUIs()
/datum/wires/nuclearbomb/UpdateCut(index, mended)
if(WIRE_BOMB_SAFETY)
N.safety = !N.safety
addtimer(CALLBACK(N, /obj/machinery/nuclearbomb/.proc/reset_safety_callback), 10 SECONDS)
/datum/wires/nuclearbomb/on_cut(wire, mend)
var/obj/machinery/nuclearbomb/N = holder
switch(index)
if(NUCLEARBOMB_WIRE_SAFETY)
switch(wire)
if(WIRE_BOMB_SAFETY)
if(N.timing)
message_admins("[key_name_admin(usr)] cut a nuclear bomb's timing wire, causing it to explode (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[holder.x];Y=[holder.y];Z=[holder.z]'>JMP</a>)")
N.explode()
if(NUCLEARBOMB_WIRE_TIMING)
if(WIRE_BOMB_TIMING)
if(!N.lighthack)
if(N.icon_state == "nuclearbomb2")
N.icon_state = "nuclearbomb1"
N.timing = 0
GLOB.bomb_set = 0
if(NUCLEARBOMB_WIRE_LIGHT)
N.lighthack = !N.lighthack
GLOB.bomb_set = FALSE
/datum/wires/nuclearbomb/proc/updateUIs()
SSnanoui.update_uis(src)
if(holder)
SSnanoui.update_uis(holder)
if(WIRE_BOMB_LIGHT)
N.lighthack = !N.lighthack
+25 -40
View File
@@ -1,67 +1,52 @@
/datum/wires/particle_acc/control_box
wire_count = 5
holder_type = /obj/machinery/particle_accelerator/control_box
proper_name = "Particle accelerator control"
window_x = 361
window_y = 22
#define PARTICLE_TOGGLE_WIRE 1 // Toggles whether the PA is on or not.
#define PARTICLE_STRENGTH_WIRE 2 // Determines the strength of the PA.
#define PARTICLE_INTERFACE_WIRE 4 // Determines the interface showing up.
#define PARTICLE_LIMIT_POWER_WIRE 8 // Determines how strong the PA can be.
/datum/wires/particle_acc/control_box/New(atom/_holder)
wires = list(WIRE_PARTICLE_POWER, WIRE_PARTICLE_STRENGTH, WIRE_PARTICLE_INTERFACE, WIRE_PARTICLE_POWER_LIMIT)
return ..()
/datum/wires/particle_acc/control_box/GetWireName(index)
switch(index)
if(PARTICLE_TOGGLE_WIRE)
return "Power Toggle"
if(PARTICLE_STRENGTH_WIRE)
return "Strength"
if(PARTICLE_INTERFACE_WIRE)
return "Interface"
if(PARTICLE_LIMIT_POWER_WIRE)
return "Maximum Power"
/datum/wires/particle_acc/control_box/CanUse(mob/living/L)
/datum/wires/particle_acc/control_box/interactable(mob/user)
var/obj/machinery/particle_accelerator/control_box/C = holder
if(C.construction_state == 2)
return 1
return 0
return TRUE
return FALSE
/datum/wires/particle_acc/control_box/UpdatePulsed(index)
/datum/wires/particle_acc/control_box/on_pulse(wire)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(index)
if(PARTICLE_TOGGLE_WIRE)
switch(wire)
if(WIRE_PARTICLE_POWER)
C.toggle_power()
if(PARTICLE_STRENGTH_WIRE)
if(WIRE_PARTICLE_STRENGTH)
C.add_strength()
if(PARTICLE_INTERFACE_WIRE)
if(WIRE_PARTICLE_INTERFACE)
C.interface_control = !C.interface_control
if(PARTICLE_LIMIT_POWER_WIRE)
if(WIRE_PARTICLE_POWER_LIMIT)
C.visible_message("[bicon(C)]<b>[C]</b> makes a large whirring noise.")
..()
/datum/wires/particle_acc/control_box/UpdateCut(index, mended)
/datum/wires/particle_acc/control_box/on_cut(wire, mend)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(index)
if(PARTICLE_TOGGLE_WIRE)
if(C.active == !mended)
switch(wire)
if(WIRE_PARTICLE_POWER)
if(C.active == !mend)
C.toggle_power()
if(PARTICLE_STRENGTH_WIRE)
for(var/i = 1; i < 3; i++)
if(WIRE_PARTICLE_STRENGTH)
for(var/i in 1 to 2)
C.remove_strength()
if(PARTICLE_INTERFACE_WIRE)
C.interface_control = mended
if(WIRE_PARTICLE_INTERFACE)
C.interface_control = mend
if(PARTICLE_LIMIT_POWER_WIRE)
C.strength_upper_limit = (mended ? 2 : 3)
if(WIRE_PARTICLE_POWER_LIMIT)
C.strength_upper_limit = (mend ? 2 : 3)
if(C.strength_upper_limit < C.strength)
C.remove_strength()
..()
+27 -35
View File
@@ -1,52 +1,44 @@
/datum/wires/radio
holder_type = /obj/item/radio
wire_count = 3
proper_name = "Radio"
window_x = 330
window_y = 37
#define RADIO_WIRE_SIGNAL 1
#define RADIO_WIRE_RECEIVE 2
#define RADIO_WIRE_TRANSMIT 4
/datum/wires/radio/New(atom/_holder)
wires = list(WIRE_RADIO_SIGNAL, WIRE_RADIO_RECEIVER, WIRE_RADIO_TRANSMIT)
return ..()
/datum/wires/radio/GetWireName(index)
switch(index)
if(RADIO_WIRE_SIGNAL)
return "Signal"
if(RADIO_WIRE_RECEIVE)
return "Receiver"
if(RADIO_WIRE_TRANSMIT)
return "Transmitter"
/datum/wires/radio/CanUse(mob/living/L)
/datum/wires/radio/interactable(mob/user)
var/obj/item/radio/R = holder
if(R.b_stat)
return 1
return 0
return TRUE
return FALSE
/datum/wires/radio/UpdatePulsed(index)
/datum/wires/radio/on_pulse(wire)
var/obj/item/radio/R = holder
switch(index)
if(RADIO_WIRE_SIGNAL)
R.listening = !R.listening && !IsIndexCut(RADIO_WIRE_RECEIVE)
R.broadcasting = R.listening && !IsIndexCut(RADIO_WIRE_TRANSMIT)
switch(wire)
if(WIRE_RADIO_SIGNAL)
R.listening = !R.listening && !is_cut(WIRE_RADIO_RECEIVER)
R.broadcasting = R.listening && !is_cut(WIRE_RADIO_TRANSMIT)
if(RADIO_WIRE_RECEIVE)
R.listening = !R.listening && !IsIndexCut(RADIO_WIRE_SIGNAL)
if(WIRE_RADIO_RECEIVER)
R.listening = !R.listening && !is_cut(WIRE_RADIO_SIGNAL)
if(RADIO_WIRE_TRANSMIT)
R.broadcasting = !R.broadcasting && !IsIndexCut(RADIO_WIRE_SIGNAL)
if(WIRE_RADIO_TRANSMIT)
R.broadcasting = !R.broadcasting && !is_cut(WIRE_RADIO_SIGNAL)
..()
/datum/wires/radio/UpdateCut(index, mended)
/datum/wires/radio/on_cut(wire, mend)
var/obj/item/radio/R = holder
switch(index)
if(RADIO_WIRE_SIGNAL)
R.listening = mended && !IsIndexCut(RADIO_WIRE_RECEIVE)
R.broadcasting = mended && !IsIndexCut(RADIO_WIRE_TRANSMIT)
switch(wire)
if(WIRE_RADIO_SIGNAL)
R.listening = mend && !is_cut(WIRE_RADIO_RECEIVER)
R.broadcasting = mend && !is_cut(WIRE_RADIO_TRANSMIT)
if(RADIO_WIRE_RECEIVE)
R.listening = mended && !IsIndexCut(RADIO_WIRE_SIGNAL)
if(WIRE_RADIO_RECEIVER)
R.listening = mend && !is_cut(WIRE_RADIO_SIGNAL)
if(RADIO_WIRE_TRANSMIT)
R.broadcasting = mended && !IsIndexCut(RADIO_WIRE_SIGNAL)
if(WIRE_RADIO_TRANSMIT)
R.broadcasting = mend && !is_cut(WIRE_RADIO_SIGNAL)
..()
+29 -64
View File
@@ -1,32 +1,14 @@
/datum/wires/robot
random = 1
randomize = TRUE
holder_type = /mob/living/silicon/robot
wire_count = 5
window_x = 340
window_y = 106
proper_name = "Cyborg"
// /vg/ ordering
#define BORG_WIRE_MAIN_POWER 1 // The power wires do nothing whyyyyyyyyyyyyy
#define BORG_WIRE_LOCKED_DOWN 2
#define BORG_WIRE_CAMERA 4
#define BORG_WIRE_AI_CONTROL 8 // Not used on MoMMIs
#define BORG_WIRE_LAWCHECK 16 // Not used on MoMMIs
/datum/wires/robot/GetWireName(index)
switch(index)
if(BORG_WIRE_MAIN_POWER)
return "Main Power"
if(BORG_WIRE_LOCKED_DOWN)
return "Lockdown"
if(BORG_WIRE_CAMERA)
return "Camera"
if(BORG_WIRE_AI_CONTROL)
return "AI Control"
if(BORG_WIRE_LAWCHECK)
return "Law Check"
/datum/wires/robot/New(atom/_holder)
wires = list(WIRE_AI_CONTROL, WIRE_BORG_CAMERA, WIRE_BORG_LAWCHECK, WIRE_BORG_LOCKED)
return ..()
/datum/wires/robot/get_status()
. = ..()
@@ -36,70 +18,53 @@
. += "The Camera light is [(R.camera && R.camera.status == 1) ? "on" : "off"]."
. += "The lockdown light is [R.lockcharge ? "on" : "off"]."
/datum/wires/robot/UpdateCut(index, mended)
/datum/wires/robot/on_cut(wire, mend)
var/mob/living/silicon/robot/R = holder
switch(index)
if(BORG_WIRE_LAWCHECK) //Cut the law wire, and the borg will no longer receive law updates from its AI
if(!mended)
if(R.lawupdate == 1)
switch(wire)
if(WIRE_BORG_LAWCHECK) //Cut the law wire, and the borg will no longer receive law updates from its AI
if(!mend)
if(R.lawupdate)
to_chat(R, "LawSync protocol engaged.")
R.lawsync()
R.show_laws()
else
if(R.lawupdate == 0 && !R.emagged)
R.lawupdate = 1
if(!R.lawupdate && !R.emagged)
R.lawupdate = TRUE
if(BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
if(!mended)
if(WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
if(!mend)
if(R.connected_ai)
R.disconnect_from_ai()
if(BORG_WIRE_CAMERA)
if(WIRE_BORG_CAMERA)
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.status = mended
R.camera.status = mend
R.camera.toggle_cam(usr, 0) // Will kick anyone who is watching the Cyborg's camera.
if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh
if(R.lawupdate)
R.lawsync()
if(BORG_WIRE_LOCKED_DOWN)
R.SetLockdown(!mended)
if(WIRE_BORG_LOCKED)
R.SetLockdown(!mend)
..()
/datum/wires/robot/UpdatePulsed(index)
/datum/wires/robot/on_pulse(wire)
var/mob/living/silicon/robot/R = holder
switch(index)
if(BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
switch(wire)
if(WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!R.emagged)
R.connect_to_ai(select_active_ai())
if(BORG_WIRE_CAMERA)
if(WIRE_BORG_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
R.camera.toggle_cam(usr, 0) // Kick anyone watching the Cyborg's camera, doesn't display you disconnecting the camera.
R.visible_message("[R]'s camera lense focuses loudly.")
to_chat(R, "Your camera lense focuses loudly.")
if(BORG_WIRE_LOCKED_DOWN)
if(WIRE_BORG_LOCKED)
R.SetLockdown(!R.lockcharge) // Toggle
..()
/datum/wires/robot/CanUse(mob/living/L)
/datum/wires/robot/interactable(mob/user)
var/mob/living/silicon/robot/R = holder
if(R.wiresexposed)
return 1
return 0
/datum/wires/robot/proc/IsCameraCut()
return wires_status & BORG_WIRE_CAMERA
/datum/wires/robot/proc/LockedCut()
return wires_status & BORG_WIRE_LOCKED_DOWN
/datum/wires/robot/proc/CanLawCheck()
return wires_status & BORG_WIRE_LAWCHECK
/datum/wires/robot/proc/AIHasControl()
return wires_status & BORG_WIRE_AI_CONTROL
return TRUE
return FALSE
+28 -37
View File
@@ -1,35 +1,26 @@
/datum/wires/smartfridge
holder_type = /obj/machinery/smartfridge
wire_count = 3
proper_name = "Smartfridge"
window_x = 340
window_y = 103
/datum/wires/smartfridge/New(atom/_holder)
wires = list(WIRE_ELECTRIFY, WIRE_IDSCAN, WIRE_THROW_ITEM)
return ..()
/datum/wires/smartfridge/secure
random = 1
wire_count = 4
randomize = TRUE
wire_count = 4 // 3 actual, 1 dud.
window_y = 97
#define SMARTFRIDGE_WIRE_ELECTRIFY 1
#define SMARTFRIDGE_WIRE_THROW 2
#define SMARTFRIDGE_WIRE_IDSCAN 4
/datum/wires/smartfridge/GetWireName(index)
switch(index)
if(SMARTFRIDGE_WIRE_ELECTRIFY)
return "Electrification"
if(SMARTFRIDGE_WIRE_THROW)
return "Item Throw"
if(SMARTFRIDGE_WIRE_IDSCAN)
return "ID Scan"
/datum/wires/smartfridge/CanUse(mob/living/L)
/datum/wires/smartfridge/interactable(mob/user)
var/obj/machinery/smartfridge/S = holder
if(!issilicon(L))
if(S.seconds_electrified)
if(S.shock(L, 100))
return 0
if(iscarbon(user) && S.Adjacent(user) && S.seconds_electrified && S.shock(user, 100))
return FALSE
if(S.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/smartfridge/get_status()
. = ..()
@@ -38,27 +29,27 @@
. += "The red light is [S.shoot_inventory ? "off" : "blinking"]."
. += "A [S.scan_id ? "purple" : "yellow"] light is on."
/datum/wires/smartfridge/UpdatePulsed(index)
/datum/wires/smartfridge/on_pulse(wire)
var/obj/machinery/smartfridge/S = holder
switch(index)
if(SMARTFRIDGE_WIRE_THROW)
switch(wire)
if(WIRE_THROW_ITEM)
S.shoot_inventory = !S.shoot_inventory
if(SMARTFRIDGE_WIRE_ELECTRIFY)
if(WIRE_ELECTRIFY)
S.seconds_electrified = 30
if(SMARTFRIDGE_WIRE_IDSCAN)
if(WIRE_IDSCAN)
S.scan_id = !S.scan_id
..()
/datum/wires/smartfridge/UpdateCut(index, mended)
/datum/wires/smartfridge/on_cut(wire, mend)
var/obj/machinery/smartfridge/S = holder
switch(index)
if(SMARTFRIDGE_WIRE_THROW)
S.shoot_inventory = !mended
if(SMARTFRIDGE_WIRE_ELECTRIFY)
if(mended)
switch(wire)
if(WIRE_THROW_ITEM)
S.shoot_inventory = !mend
if(WIRE_ELECTRIFY)
if(mend)
S.seconds_electrified = 0
else
S.seconds_electrified = -1
if(SMARTFRIDGE_WIRE_IDSCAN)
S.scan_id = 1
if(WIRE_IDSCAN)
S.scan_id = TRUE
..()
+35 -40
View File
@@ -1,24 +1,13 @@
/datum/wires/suitstorage
holder_type = /obj/machinery/suit_storage_unit
wire_count = 8
proper_name = "Suit storage unit"
window_x = 350
window_y = 85
#define SSU_WIRE_ID 1
#define SSU_WIRE_SHOCK 2
#define SSU_WIRE_SAFETY 4
#define SSU_WIRE_UV 8
/datum/wires/suitstorage/GetWireName(index)
switch(index)
if(SSU_WIRE_ID)
return "ID lock"
if(SSU_WIRE_SHOCK)
return "Shock wire"
if(SSU_WIRE_SAFETY)
return "Safety wire"
if(SSU_WIRE_UV)
return "UV wire"
/datum/wires/suitstorage/New(atom/_holder)
wires = list(WIRE_IDSCAN, WIRE_ELECTRIFY, WIRE_SAFETY, WIRE_SSU_UV)
return ..()
/datum/wires/suitstorage/get_status()
. = ..()
@@ -28,42 +17,48 @@
. += "The green light is [A.shocked ? "on" : "off"]."
. += "The UV display shows [A.uv_super ? "15 nm" : "185 nm"]."
datum/wires/suitstorage/CanUse()
datum/wires/suitstorage/interactable(mob/user)
var/obj/machinery/suit_storage_unit/A = holder
if(iscarbon(user) && A.Adjacent(user) && A.shocked)
return A.shock(user, 100)
if(A.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/suitstorage/UpdateCut(index, mended)
/datum/wires/suitstorage/on_cut(wire, mend)
var/obj/machinery/suit_storage_unit/A = holder
switch(index)
if(SSU_WIRE_ID)
A.secure = mended
if(SSU_WIRE_SAFETY)
A.safeties = mended
if(SSU_WIRE_SHOCK)
A.shocked = !mended
switch(wire)
if(WIRE_IDSCAN)
A.secure = mend
if(WIRE_SAFETY)
A.safeties = mend
if(WIRE_ELECTRIFY)
A.shocked = !mend
A.shock(usr, 50)
if(SSU_WIRE_UV)
A.uv_super = !mended
if(WIRE_SSU_UV)
A.uv_super = !mend
..()
datum/wires/suitstorage/UpdatePulsed(index)
datum/wires/suitstorage/on_pulse(wire)
var/obj/machinery/suit_storage_unit/A = holder
if(IsIndexCut(index))
if(is_cut(wire))
return
switch(index)
if(SSU_WIRE_ID)
switch(wire)
if(WIRE_IDSCAN)
A.secure = !A.secure
if(SSU_WIRE_SAFETY)
if(WIRE_SAFETY)
A.safeties = !A.safeties
if(SSU_WIRE_SHOCK)
if(WIRE_ELECTRIFY)
A.shocked = !A.shocked
if(A.shocked)
A.shock(usr, 100)
spawn(50)
if(A && !IsIndexCut(index))
A.shocked = FALSE
if(SSU_WIRE_UV)
addtimer(CALLBACK(A, /obj/machinery/suit_storage_unit/.proc/check_electrified_callback), 5 SECONDS)
if(WIRE_SSU_UV)
A.uv_super = !A.uv_super
..()
+25 -41
View File
@@ -1,47 +1,31 @@
/datum/wires/syndicatebomb
random = TRUE
randomize = TRUE
holder_type = /obj/machinery/syndicatebomb
wire_count = 5
proper_name = "Syndicate bomb"
window_x = 320
window_y = 22
#define BOMB_WIRE_BOOM 1 // Explodes if pulsed or cut while active, defuses a bomb that isn't active on cut
#define BOMB_WIRE_UNBOLT 2 // Unbolts the bomb if cut, hint on pulsed
#define BOMB_WIRE_DELAY 4 // Raises the timer on pulse, does nothing on cut
#define BOMB_WIRE_PROCEED 8 // Lowers the timer, explodes if cut while the bomb is active
#define BOMB_WIRE_ACTIVATE 16 // Will start a bombs timer if pulsed, will hint if pulsed while already active, will stop a timer a bomb on cut
/datum/wires/syndicatebomb/New(atom/_holder)
wires = list(WIRE_BOMB_DELAY, WIRE_EXPLODE, WIRE_BOMB_UNBOLT,WIRE_BOMB_PROCEED, WIRE_BOMB_ACTIVATE)
return ..()
/datum/wires/syndicatebomb/GetWireName(index)
switch(index)
if(BOMB_WIRE_BOOM)
return "Explode"
if(BOMB_WIRE_UNBOLT)
return "Unbolt"
if(BOMB_WIRE_DELAY)
return "Delay"
if(BOMB_WIRE_PROCEED)
return "Proceed"
if(BOMB_WIRE_ACTIVATE)
return "Activate"
/datum/wires/syndicatebomb/CanUse(mob/living/L)
/datum/wires/syndicatebomb/interactable(mob/user)
var/obj/machinery/syndicatebomb/P = holder
if(P.open_panel)
return TRUE
return FALSE
/datum/wires/syndicatebomb/UpdatePulsed(index)
/datum/wires/syndicatebomb/on_pulse(wire)
var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(BOMB_WIRE_BOOM)
switch(wire)
if(WIRE_EXPLODE)
if(B.active)
holder.visible_message("<span class='danger'>[bicon(B)] An alarm sounds! It's go-</span>")
B.explode_now = TRUE
if(BOMB_WIRE_UNBOLT)
if(WIRE_BOMB_UNBOLT)
holder.visible_message("<span class='notice'>[bicon(holder)] The bolts spin in place for a moment.</span>")
if(BOMB_WIRE_DELAY)
if(WIRE_BOMB_DELAY)
if(B.delayedbig)
holder.visible_message("<span class='notice'>[bicon(B)] The bomb has already been delayed.</span>")
else
@@ -49,7 +33,7 @@
playsound(B, 'sound/machines/chime.ogg', 30, 1)
B.detonation_timer += 300
B.delayedbig = TRUE
if(BOMB_WIRE_PROCEED)
if(WIRE_BOMB_PROCEED)
holder.visible_message("<span class='danger'>[bicon(B)] The bomb buzzes ominously!</span>")
playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1)
var/seconds = B.seconds_remaining()
@@ -59,7 +43,7 @@
B.detonation_timer -= 100
else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy.
B.detonation_timer = world.time + 100
if(BOMB_WIRE_ACTIVATE)
if(WIRE_BOMB_ACTIVATE)
if(!B.active && !B.defused)
holder.visible_message("<span class='danger'>[bicon(B)] You hear the bomb start ticking!</span>")
B.activate()
@@ -72,11 +56,11 @@
B.delayedlittle = TRUE
..()
/datum/wires/syndicatebomb/UpdateCut(index, mended)
/datum/wires/syndicatebomb/on_cut(wire, mend)
var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(BOMB_WIRE_BOOM)
if(mended)
switch(wire)
if(WIRE_EXPLODE)
if(mend)
B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
if(B.active)
@@ -84,17 +68,17 @@
B.explode_now = TRUE
else
B.defused = TRUE
if(BOMB_WIRE_UNBOLT)
if(!mended && B.anchored)
if(WIRE_BOMB_UNBOLT)
if(!mend && B.anchored)
holder.visible_message("<span class='notice'>[bicon(B)] The bolts lift out of the ground!</span>")
playsound(B, 'sound/effects/stealthoff.ogg', 30, 1)
B.anchored = FALSE
if(BOMB_WIRE_PROCEED)
if(!mended && B.active)
if(WIRE_BOMB_PROCEED)
if(!mend && B.active)
holder.visible_message("<span class='danger'>[bicon(B)] An alarm sounds! It's go-</span>")
B.explode_now = TRUE
if(BOMB_WIRE_ACTIVATE)
if(!mended && B.active)
if(WIRE_BOMB_ACTIVATE)
if(!mend && B.active)
holder.visible_message("<span class='notice'>[bicon(B)] The timer stops! The bomb has been defused!</span>")
B.defused = TRUE
B.update_icon()
+12 -12
View File
@@ -1,23 +1,23 @@
/datum/wires/tesla_coil
wire_count = 1
holder_type = /obj/machinery/power/tesla_coil
proper_name = "Tesla coil"
window_x = 320
window_y = 50
#define TESLACOIL_WIRE_ZAP 1
/datum/wires/tesla_coil/New(atom/_holder)
wires = list(WIRE_TESLACOIL_ZAP)
return ..()
/datum/wires/tesla_coil/GetWireName(index)
switch(index)
if(TESLACOIL_WIRE_ZAP)
return "Zap"
/datum/wires/tesla_coil/CanUse(mob/living/L)
/datum/wires/tesla_coil/interactable(mob/user)
var/obj/machinery/power/tesla_coil/T = holder
if(T && T.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/tesla_coil/UpdatePulsed(index)
/datum/wires/tesla_coil/on_pulse(wire)
var/obj/machinery/power/tesla_coil/T = holder
switch(index)
if(TESLACOIL_WIRE_ZAP)
switch(wire)
if(WIRE_TESLACOIL_ZAP)
T.zap()
..()
+26 -40
View File
@@ -1,35 +1,21 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
wire_count = 4
window_y = 112
window_x = 350
proper_name = "Vending machine"
#define VENDING_WIRE_THROW 1
#define VENDING_WIRE_CONTRABAND 2
#define VENDING_WIRE_ELECTRIFY 4
#define VENDING_WIRE_IDSCAN 8
/datum/wires/vending/New(atom/_holder)
wires = list(WIRE_THROW_ITEM, WIRE_IDSCAN, WIRE_ELECTRIFY, WIRE_CONTRABAND)
return ..()
/datum/wires/vending/GetWireName(index)
switch(index)
if(VENDING_WIRE_THROW)
return "Item Throw"
if(VENDING_WIRE_CONTRABAND)
return "Contraband"
if(VENDING_WIRE_ELECTRIFY)
return "Electrification"
if(VENDING_WIRE_IDSCAN)
return "ID Scan"
/datum/wires/vending/CanUse(mob/living/L)
/datum/wires/vending/interactable(mob/user)
var/obj/machinery/vending/V = holder
if(!istype(L, /mob/living/silicon))
if(V.seconds_electrified)
if(V.shock(L, 100))
return 0
if(!istype(user, /mob/living/silicon) && V.seconds_electrified && V.shock(user, 100))
return FALSE
if(V.panel_open)
return 1
return 0
return TRUE
return FALSE
/datum/wires/vending/get_status()
. = ..()
@@ -39,31 +25,31 @@
. += "The green light is [V.extended_inventory ? "on" : "off"]."
. += "A [V.scan_id ? "purple" : "yellow"] light is on."
/datum/wires/vending/UpdatePulsed(index)
/datum/wires/vending/on_pulse(wire)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
switch(wire)
if(WIRE_THROW_ITEM)
V.shoot_inventory = !V.shoot_inventory
if(VENDING_WIRE_CONTRABAND)
if(WIRE_CONTRABAND)
V.extended_inventory = !V.extended_inventory
if(VENDING_WIRE_ELECTRIFY)
if(WIRE_ELECTRIFY)
V.seconds_electrified = 30
if(VENDING_WIRE_IDSCAN)
if(WIRE_IDSCAN)
V.scan_id = !V.scan_id
..()
/datum/wires/vending/UpdateCut(index, mended)
/datum/wires/vending/on_cut(wire, mend)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
V.shoot_inventory = !mended
if(VENDING_WIRE_CONTRABAND)
switch(wire)
if(WIRE_THROW_ITEM)
V.shoot_inventory = !mend
if(WIRE_CONTRABAND)
V.extended_inventory = FALSE
if(VENDING_WIRE_ELECTRIFY)
if(mended)
if(WIRE_ELECTRIFY)
if(mend)
V.seconds_electrified = 0
else
V.seconds_electrified = -1
if(VENDING_WIRE_IDSCAN)
V.scan_id = 1
if(WIRE_IDSCAN)
V.scan_id = TRUE
..()
+395 -270
View File
@@ -1,331 +1,456 @@
// Wire datums. Created by Giacomand.
// Was created to replace a horrible case of copy and pasted code with no care for maintability.
// Goodbye Door wires, Cyborg wires, Vending Machine wires, Autolathe wires
// Protolathe wires, APC wires and Camera wires!
#define MAX_FLAG 65535
GLOBAL_LIST_EMPTY(same_wires)
// 12 colours, if you're adding more than 12 wires then add more colours here
GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink"))
/datum/wires
/// TRUE if the wires will be different every time a new wire datum is created.
var/randomize = FALSE
/// The atom the wires belong too. For example: an airlock.
var/atom/holder
/// The holder type; used to make sure that the holder is the correct type.
var/holder_type
/// The display name for the TGUI window. For example, given the var is "APC"...
/// When the TGUI window is opened, "wires" will be appended to it's title, and it would become "APC wires".
var/proper_name = "Unknown"
/// The total number of wires that our holder atom has.
var/wire_count = NONE
/// A list of all wires. For a list of valid wires defines that can go here, see `code/__DEFINES/wires.dm`
var/list/wires
/// A list of all cut wires. The same values that can go into `wires` will get added and removed from this list.
var/list/cut_wires
/// An associative list with the wire color as the key, and the wire define as the value.
var/list/colors
/// An associative list of signalers attached to the wires. The wire color is the key, and the signaler object reference is the value.
var/list/assemblies
/// The width of the wire TGUI window.
var/window_x = 300
/// The height of the wire TGUI window. Will get longer as needed, based on the `wire_count`.
var/window_y = 100
var/random = 0 // Will the wires be different for every single instance.
var/atom/holder = null // The holder
var/holder_type = null // The holder type; used to make sure that the holder is the correct type.
var/wire_count = 0 // Max is 16
var/wires_status = 0 // BITFLAG OF WIRES
var/list/wires = list()
var/list/signallers = list()
var/table_options = " align='center'"
var/row_options1 = " width='80px'"
var/row_options2 = " width='260px'"
var/window_x = 370
var/window_y = 470
/datum/wires/New(atom/holder)
/datum/wires/New(atom/_holder)
..()
src.holder = holder
if(!istype(holder, holder_type))
if(!istype(_holder, holder_type))
CRASH("Our holder is null/the wrong type!")
// Generate new wires
if(random)
GenerateWires()
// Get the same wires
holder = _holder
cut_wires = list()
colors = list()
assemblies = list()
// Add in the appropriate amount of dud wires.
var/wire_len = length(wires)
if(wire_len < wire_count) // If the amount of "real" wires is less than the total we're suppose to have...
add_duds(wire_count - wire_len) // Add in the appropriate amount of duds to reach `wire_count`.
// If the randomize is true, we need to generate a new set of wires and ignore any wire color directories.
if(randomize)
randomize()
return
if(!GLOB.wire_color_directory[holder_type])
randomize()
GLOB.wire_color_directory[holder_type] = colors
else
// We don't have any wires to copy yet, generate some and then copy it.
if(!GLOB.same_wires[holder_type])
GenerateWires()
GLOB.same_wires[holder_type] = src.wires.Copy()
else
var/list/wires = GLOB.same_wires[holder_type]
src.wires = wires // Reference the wires list.
colors = GLOB.wire_color_directory[holder_type]
/datum/wires/Destroy()
holder = null
for(var/color in colors)
detach_assembly(color)
return ..()
/datum/wires/proc/GenerateWires()
var/list/colours_to_pick = GLOB.wireColours.Copy() // Get a copy, not a reference.
var/list/indexes_to_pick = list()
//Generate our indexes
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
indexes_to_pick += i
colours_to_pick.len = wire_count // Downsize it to our specifications.
/**
* Randomly generates a new set of wires. and corresponding colors from the given pool. Assigns the information as an associative list, to `colors`.
*
* In the `colors` list, the name of the color is the key, and the wire is the value.
* For example: `colors["red"] = WIRE_ELECTRIFY`. This will look like `list("red" = WIRE_ELECTRIFY)` internally.
*/
datum/wires/proc/randomize()
var/static/list/possible_colors = list("red", "blue", "green", "silver", "orange", "brown", "gold", "white", "cyan", "magenta", "purple", "pink")
var/list/my_possible_colors = possible_colors.Copy()
while(colours_to_pick.len && indexes_to_pick.len)
// Pick and remove a colour
var/colour = pick_n_take(colours_to_pick)
// Pick and remove an index
var/index = pick_n_take(indexes_to_pick)
src.wires[colour] = index
//wires = shuffle(wires)
/datum/wires/proc/get_status()
return list()
for(var/wire in shuffle(wires))
colors[pick_n_take(my_possible_colors)] = wire
/**
* Proc called when the user attempts to interact with wires UI.
*
* Checks if the user exists, is a mob, the wires are attached to something (`holder`) and makes sure `interactable(user)` returns TRUE.
* If all the checks succeed, open the TGUI interface for the user.
*
* Arugments:
* * user - the mob trying to interact with the wires.
*/
/datum/wires/proc/Interact(mob/user)
if(user && istype(user) && holder && CanUse(user))
ui_interact(user)
if(user && istype(user) && holder && interactable(user))
tgui_interact(user)
/datum/wires/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
/**
* Base proc, intended to be overriden. Wire datum specific checks you want to run before the TGUI is shown to the user should go here.
*/
/datum/wires/proc/interactable(mob/user)
return TRUE
/// Users will be interacting with our holder object and not the wire datum directly, therefore we need to return the holder.
/datum/wires/tgui_host()
return holder
/datum/wires/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "wires.tmpl", holder.name, window_x, window_y)
ui = new(user, src, ui_key, "Wires", "[proper_name] wires", window_x, window_y + wire_count * 30, master_ui, state)
ui.open()
/datum/wires/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.physical_state)
var/data[0]
var/list/replace_colours = null
/datum/wires/tgui_data(mob/user)
var/list/data = list()
var/list/replace_colors
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
if(eyes && (COLOURBLIND in H.mutations))
replace_colours = eyes.replace_colours
if(eyes && (COLOURBLIND in H.mutations)) // Check if the human has colorblindness.
replace_colors = eyes.replace_colours // Get the colorblind replacement colors list.
var/list/wires_list = list()
var/list/W[0]
for(var/colour in wires)
var/new_colour = colour
var/colour_name = colour
if(colour in replace_colours)
new_colour = replace_colours[colour]
if(new_colour in LIST_REPLACE_RENAME)
colour_name = LIST_REPLACE_RENAME[new_colour]
for(var/color in colors)
var/replaced_color = color
var/color_name = color
if(color in replace_colors) // If this color is one that needs to be replaced using the colorblindness list.
replaced_color = replace_colors[color]
if(replaced_color in LIST_COLOR_RENAME) // If its an ugly written color name like "darkolivegreen", rename it to something like "dark green".
color_name = LIST_COLOR_RENAME[replaced_color]
else
colour_name = new_colour
else
new_colour = colour
colour_name = new_colour
W[++W.len] = list("colour_name" = capitalize(colour_name), "seen_colour" = capitalize(new_colour),"colour" = capitalize(colour), "cut" = IsColourCut(colour), "index" = can_see_wire_index(user) ? GetWireName(GetIndex(colour)) : null, "attached" = IsAttached(colour))
color_name = replaced_color // Else just keep the normal color name
if(W.len > 0)
data["wires"] = W
wires_list += list(list(
"seen_color" = replaced_color, // The color of the wire that the mob will see. This will be the same as `color` if the user is NOT colorblind.
"color_name" = color_name, // The wire's name. This will be the same as `color` if the user is NOT colorblind.
"color" = color, // The "real" color of the wire. No replacements.
"wire" = can_see_wire_info(user) && !is_dud_color(color) ? get_wire(color) : null, // Wire define information like "Contraband" or "Door Bolts".
"cut" = is_color_cut(color), // Whether the wire is cut or not. Used to display "cut" or "mend".
"attached" = is_attached(color) // Whether or not a signaler is attached to this wire.
))
data["wires"] = wires_list
// Get the information shown at the bottom of wire TGUI window, such as "The red light is blinking", etc.
// If the user is colorblind, we need to replace these colors as well.
var/list/status = get_status()
if(replace_colours)
var/i
for(i=1, i<=status.len, i++)
for(var/colour in replace_colours)
var/new_colour = replace_colours[colour]
if(new_colour in LIST_REPLACE_RENAME)
new_colour = LIST_REPLACE_RENAME[new_colour]
if(findtext(status[i],colour))
status[i] = replacetext(status[i],colour,new_colour)
break
data["status_len"] = status.len
data["status"] = status
if(replace_colors)
var/i
for(i in 1 to length(status))
for(var/color in replace_colors)
var/new_color = replace_colors[color]
if(new_color in LIST_COLOR_RENAME)
new_color = LIST_COLOR_RENAME[new_color]
if(findtext(status[i], color))
status[i] = replacetext(status[i], color, new_color)
break
data["status"] = status
return data
/datum/wires/nano_host()
return holder
/datum/wires/tgui_act(action, list/params)
if(..())
return
/datum/wires/proc/can_see_wire_index(mob/user)
var/mob/user = usr
if(!interactable(user))
return
var/obj/item/I = user.get_active_hand()
var/color = lowertext(params["wire"])
holder.add_hiddenprint(user)
switch(action)
// Toggles the cut/mend status.
if("cut")
if(!istype(I, /obj/item/wirecutters) && !user.can_admin_interact())
to_chat(user, "<span class='error'>You need wirecutters!</span>")
return
if(istype(I))
playsound(holder, I.usesound, 20, 1)
cut_color(color)
return TRUE
// Pulse a wire.
if("pulse")
if(!istype(I, /obj/item/multitool) && !user.can_admin_interact())
to_chat(user, "<span class='error'>You need a multitool!</span>")
return
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
pulse_color(color)
// If they pulse the electrify wire, call interactable() and try to shock them.
if(get_wire(color) == WIRE_ELECTRIFY)
interactable(user)
return TRUE
// Attach a signaler to a wire.
if("attach")
if(is_attached(color))
var/obj/item/O = detach_assembly(color)
if(O)
user.put_in_hands(O)
return TRUE
if(!istype(I, /obj/item/assembly/signaler))
to_chat(user, "<span class='error'>You need a remote signaller!</span>")
return
if(user.drop_item())
attach_assembly(color, I)
return TRUE
else
to_chat(user, "<span class='warning'>[user.get_active_hand()] is stuck to your hand!</span>")
/**
* Proc called to determine if the user can see wire define information, such as "Contraband", "Door Bolts", etc.
*
* If the user is an admin, or has a multitool which reveals wire information in their active hand, the proc returns TRUE.
*
* Arguments:
* * user - the mob who is interacting with the wires.
*/
/datum/wires/proc/can_see_wire_info(mob/user)
if(user.can_admin_interact())
return TRUE
else if(istype(user.get_active_hand(), /obj/item/multitool))
var/obj/item/multitool/M = user.get_active_hand()
if(M.shows_wire_information)
return TRUE
return FALSE
/datum/wires/Topic(href, href_list)
if(..())
return 1
var/mob/L = usr
if(CanUse(L) && href_list["action"])
var/obj/item/I = L.get_active_hand()
var/colour = lowertext(href_list["wire"])
holder.add_hiddenprint(L)
switch(href_list["action"])
if("cut") // Toggles the cut/mend status
if(istype(I, /obj/item/wirecutters) || L.can_admin_interact())
if(istype(I))
playsound(holder, I.usesound, 20, 1)
CutWireColour(colour)
else
to_chat(L, "<span class='error'>You need wirecutters!</span>")
if("pulse")
if(istype(I, /obj/item/multitool) || L.can_admin_interact())
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
PulseColour(colour)
else
to_chat(L, "<span class='error'>You need a multitool!</span>")
if("attach")
if(IsAttached(colour))
var/obj/item/O = Detach(colour)
if(O)
L.put_in_hands(O)
else
if(istype(I, /obj/item/assembly/signaler))
if(L.drop_item())
Attach(colour, I)
else
to_chat(L, "<span class='warning'>[L.get_active_hand()] is stuck to your hand!</span>")
else
to_chat(L, "<span class='error'>You need a remote signaller!</span>")
/**
* Base proc, intended to be overwritten. Put wire information you'll see at the botton of the TGUI window here, such as "The red light is blinking".
*/
/datum/wires/proc/get_status()
return list()
SSnanoui.update_uis(src)
return 1
/**
* Clears the `colors` list, and randomizes it to a new set of color-to-wire relations.
*/
/datum/wires/proc/shuffle_wires()
colors.Cut()
randomize()
//
// Overridable Procs
//
/**
* Repairs all cut wires.
*/
/datum/wires/proc/repair()
cut_wires.Cut()
// Called when wires cut/mended.
/datum/wires/proc/UpdateCut(index, mended)
if(holder)
SSnanoui.update_uis(holder)
/**
* Adds in dud wires, which do nothing when cut/pulsed.
*
* Arguments:
* * duds - the amount of dud wires to generate.
*/
/datum/wires/proc/add_duds(duds)
while(duds)
var/dud = WIRE_DUD_PREFIX + "[--duds]"
if(dud in wires)
continue
wires += dud
// Called when wire pulsed. Add code here.
/datum/wires/proc/UpdatePulsed(index)
if(holder)
SSnanoui.update_uis(holder)
/**
* Determines if the passed in wire is a dud or not. Returns TRUE if the wire is a dud, FALSE otherwise.
*
* Arugments:
* * wire - a wire define, NOT a color. For example `WIRE_ELECTRIFY`.
*/
/datum/wires/proc/is_dud(wire)
return findtext(wire, WIRE_DUD_PREFIX, 1, length(WIRE_DUD_PREFIX) + 1)
/datum/wires/proc/CanUse(mob/L)
return 1
/**
* Returns TRUE if the wire that corresponds to the passed in color is a dud. FALSE otherwise.
*
* Arugments:
* * color - a wire color.
*/
/datum/wires/proc/is_dud_color(color)
return is_dud(get_wire(color))
/datum/wires/CanUseTopic(mob/user, datum/topic_state/state)
if(!CanUse(user))
return STATUS_CLOSE
return ..()
/**
* Gets the wire associated with the color passed in.
*
* Arugments:
* * color - a wire color.
*/
/datum/wires/proc/get_wire(color)
return colors[color]
// Example of use:
/*
/**
* Determines if the passed in wire is cut or not. Returns TRUE if it's cut, FALSE otherwise.
*
* Arugments:
* * wire - a wire define, NOT a color. For example `WIRE_ELECTRIFY`.
*/
/datum/wires/proc/is_cut(wire)
return (wire in cut_wires)
#define NAME_WIRE_BOLTED 1
#define NAME_WIRE_SHOCKED 2
#define NAME_WIRE_SAFETY 4
#define NAME_WIRE_POWER 8
/**
* Determines if the wire associated with the passed in color, is cut or not. Returns TRUE if it's cut, FALSE otherwise.
*
* Arugments:
* * wire - a wire color.
*/
/datum/wires/proc/is_color_cut(color)
return is_cut(get_wire(color))
/datum/wires/door/UpdateCut(var/index, var/mended)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(NAME_WIRE_BOLTED)
if(!mended)
A.bolt()
if(NAME_WIRE_SHOCKED)
A.shock()
if(NAME_WIRE_SAFETY)
A.safety()
/**
* Determines if all of the wires are cut. Returns TRUE they're all cut, FALSE otherwise.
*/
/datum/wires/proc/is_all_cut()
return (length(cut_wires) == length(wires))
*/
//
// Helper Procs
//
/datum/wires/proc/PulseColour(colour)
PulseIndex(GetIndex(colour))
/datum/wires/proc/PulseIndex(index)
if(IsIndexCut(index))
return
UpdatePulsed(index)
/datum/wires/proc/GetIndex(colour)
if(wires[colour])
var/index = wires[colour]
return index
/**
* Cut or mend a wire. Calls `on_cut()`.
*
* Arugments:
* * wire - a wire define, NOT a color. For example `WIRE_ELECTRIFY`.
*/
/datum/wires/proc/cut(wire)
if(is_cut(wire))
cut_wires -= wire
on_cut(wire, mend = TRUE)
else
CRASH("[colour] is not a key in wires.")
cut_wires += wire
on_cut(wire, mend = FALSE)
/datum/wires/proc/GetWireName(index)
/**
* Cut the wire which corresponds with the passed in color.
*
* Arugments:
* * color - a wire color.
*/
/datum/wires/proc/cut_color(color)
cut(get_wire(color))
/**
* Cuts a random wire.
*/
/datum/wires/proc/cut_random()
cut(wires[rand(1, length(wires))])
/**
* Cuts all wires.
*/
/datum/wires/proc/cut_all()
for(var/wire in wires)
cut(wire)
/**
* Proc called when any wire is cut.
*
* Base proc, intended to be overriden.
* Place an behavior you want to happen when certain wires are cut, into this proc.
*
* Arugments:
* * wire - a wire define, NOT color. For example 'WIRE_ELECTRIFY'.
* * mend - TRUE if we're mending the wire. FALSE if we're cutting.
*/
/datum/wires/proc/on_cut(wire, mend = FALSE)
return
//
// Is Index/Colour Cut procs
//
/**
* Pulses the given wire. Calls `on_pulse()`.
*
* Arugments:
* * wire - a wire define, NOT a color. For example `WIRE_ELECTRIFY`.
*/
/datum/wires/proc/pulse(wire)
if(is_cut(wire))
return
on_pulse(wire)
/datum/wires/proc/IsColourCut(colour)
var/index = GetIndex(colour)
return IsIndexCut(index)
/**
* Pulses the wire associated with the given color.
*
* Arugments:
* * wire - a wire color.
*/
/datum/wires/proc/pulse_color(color)
pulse(get_wire(color))
/datum/wires/proc/IsIndexCut(index)
return (index & wires_status)
/**
* Proc called when any wire is pulsed.
*
* Base proc, intended to be overriden.
* Place behavior you want to happen when certain wires are pulsed, into this proc.
*
* Arugments:
* * wire - a wire define, NOT color. For example 'WIRE_ELECTRIFY'.
*/
/datum/wires/proc/on_pulse(wire)
return
//
// Signaller Procs
//
/**
* Proc called when an attached signaler receives a signal.
*
* Searches through the `assemblies` list for the wire that the signaler is attached to. Pulses the wire when it's found.
*
* Arugments:
* * S - the attached signaler receiving the signal.
*/
/datum/wires/proc/pulse_assembly(obj/item/assembly/signaler/S)
for(var/color in assemblies)
if(S == assemblies[color])
pulse_color(color)
return TRUE
/datum/wires/proc/IsAttached(colour)
if(signallers[colour])
return 1
return 0
/**
* Proc called when a mob tries to attach a signaler to a wire.
*
* Makes sure that `S` is actually a signaler and that something is not already attached to the wire.
* Adds the signaler to the `assemblies` list as a value, with the `color` as a the key.
*
* Arguments:
* * color - the wire color.
* * S - the signaler that a mob is trying to attach.
*/
/datum/wires/proc/attach_assembly(color, obj/item/assembly/signaler/S)
if(S && istype(S) && !is_attached(color))
assemblies[color] = S
S.forceMove(holder)
S.connected = src
return S
/datum/wires/proc/GetAttached(colour)
if(signallers[colour])
return signallers[colour]
/**
* Proc called when a mob tries to detach a signaler from a wire.
*
* First checks if there is a signaler on the wire. If so, removes the signaler, and clears it from `assemblies` list.
*
* Arguments:
* * color - the wire color.
*/
/datum/wires/proc/detach_assembly(color)
var/obj/item/assembly/signaler/S = get_attached(color)
if(S && istype(S))
assemblies -= color
S.connected = null
S.forceMove(holder.drop_location())
return S
/**
* Gets the signaler attached to the given wire color, if there is one.
*
* Arguments:
* * color - the wire color.
*/
/datum/wires/proc/get_attached(color)
if(assemblies[color])
return assemblies[color]
return null
/datum/wires/proc/Attach(colour, obj/item/assembly/signaler/S)
if(colour && S)
if(!IsAttached(colour))
signallers[colour] = S
S.loc = holder
S.connected = src
return S
/datum/wires/proc/Detach(colour)
if(colour)
var/obj/item/assembly/signaler/S = GetAttached(colour)
if(S)
signallers -= colour
S.connected = null
S.loc = holder.loc
return S
/datum/wires/proc/Pulse(obj/item/assembly/signaler/S)
for(var/colour in signallers)
if(S == signallers[colour])
PulseColour(colour)
break
//
// Cut Wire Colour/Index procs
//
/datum/wires/proc/CutWireColour(colour)
var/index = GetIndex(colour)
CutWireIndex(index)
/datum/wires/proc/CutWireIndex(index)
if(IsIndexCut(index))
wires_status &= ~index
UpdateCut(index, 1)
else
wires_status |= index
UpdateCut(index, 0)
/datum/wires/proc/RandomCut()
var/r = rand(1, wires.len)
CutWireIndex(r)
/datum/wires/proc/CutAll()
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
CutWireIndex(i)
/datum/wires/proc/IsAllCut()
if(wires_status == (1 << wire_count) - 1)
return 1
return 0
//
//Shuffle and Mend
//
/datum/wires/proc/Shuffle()
wires_status = 0
GenerateWires()
/**
* Checks if the given wire has a signaler on it.
*
* Arguments:
* * color - the wire color.
*/
/datum/wires/proc/is_attached(color)
if(assemblies[color])
return TRUE