From 5e6e477e37f63f3955262a6c5d6c3450d560ffb1 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Tue, 7 Feb 2012 19:54:09 -0500 Subject: [PATCH 01/19] allowed lizards to talk normal --- code/modules/mob/living/carbon/human/say.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 3255689111..947ada101d 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,7 +1,4 @@ /mob/living/carbon/human/say(var/message) - if(src.mutantrace == "lizard") - if(copytext(message, 1, 2) != "*") - message = dd_replaceText(message, "s", stutter("ss")) if(src.mutantrace == "metroid" && prob(5)) if(copytext(message, 1, 2) != "*") if(copytext(message, 1, 2) == ";") From 726116774195783bde9864af27f6c775497168de Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Tue, 7 Feb 2012 22:58:00 -0500 Subject: [PATCH 02/19] added modes to sink --- code/game/machinery/sink.dm | 53 ++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/code/game/machinery/sink.dm b/code/game/machinery/sink.dm index d0319d4de4..2c75cacad8 100644 --- a/code/game/machinery/sink.dm +++ b/code/game/machinery/sink.dm @@ -5,13 +5,18 @@ desc = "A sink used for washing one's hands and face." anchored = 1 var/busy = 0 //Something's being washed at the moment + var/mode = 0 //0 == fill, 1 == pour + New() + ..() + verbs += /obj/machinery/sink/proc/mode_pour + attack_hand(mob/M as mob) if(busy) M << "\red Someone's already washing something here." return - usr << "\blue You start washing up." + M << "\blue You start washing up." busy = 1 if(do_after(M,40)) @@ -43,6 +48,25 @@ V.show_message(text("\blue [M] washes up using \the [src].")) busy = 0 + proc/mode_pour() + set name = "Mode -> Pour" + set category = "Object" + set src in oview(1) + + mode = 1 + verbs -= /obj/machinery/sink/proc/mode_pour + verbs += /obj/machinery/sink/proc/mode_fill + usr << "You will now pour reagents down \the [src]." + + proc/mode_fill() + set name = "Mode -> Fill" + set category = "Object" + set src in oview(1) + + mode = 0 + verbs -= /obj/machinery/sink/proc/mode_fill + verbs += /obj/machinery/sink/proc/mode_pour + usr << "You will now fill your container from the faucet." attackby(var/obj/item/O as obj, var/mob/user as mob) if(busy) @@ -50,15 +74,26 @@ return if (istype(O, /obj/item/weapon/reagent_containers/glass) || istype(O,/obj/item/weapon/reagent_containers/food/drinks)) - if(O.reagents.total_volume < O.reagents.maximum_volume) - O:reagents.add_reagent("water", 10) - user.visible_message( \ - "\blue [user] fills the [O] using the [src].", \ - "\blue You fill the [O] using the [src].") + if(!mode) + // fill + if(O.reagents.total_volume < O.reagents.maximum_volume) + O:reagents.add_reagent("water", 10) + user.visible_message( \ + "\blue [user] fills the [O] using the [src].", \ + "\blue You fill the [O] using the [src].") + else + user.visible_message( \ + "\blue [user] spills water out of the overflowing [O] into the [src].", \ + "\blue You spill water out of the overflowing [O] into the [src].") else - user.visible_message( \ - "\blue [user] spills water out of the overflowing [O] into the [src].", \ - "\blue You spill water out of the overflowing [O] into the [src].") + // pour + if(O.reagents.total_volume > 0) + O.reagents.clear_reagents() + user.visible_message( \ + "\blue [user] pours the contents of \the [O] into \the [src].", \ + "\blue You pour the contents of \the [O] into \the [src].") + else + user << "\The [O] is empty." return else if (istype(O, /obj/item/weapon/melee/baton)) var/obj/item/weapon/melee/baton/B = O From 96df31b9cde914bb227a70a2c3cf3608032c7cb7 Mon Sep 17 00:00:00 2001 From: Albert Iordache Date: Wed, 8 Feb 2012 13:23:57 +0200 Subject: [PATCH 03/19] Fixed compiling error. --- code/WorkInProgress/Cael_Aislinn/Tajara/examine.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/WorkInProgress/Cael_Aislinn/Tajara/examine.dm b/code/WorkInProgress/Cael_Aislinn/Tajara/examine.dm index 649bd2aa4d..adf2b5b698 100644 --- a/code/WorkInProgress/Cael_Aislinn/Tajara/examine.dm +++ b/code/WorkInProgress/Cael_Aislinn/Tajara/examine.dm @@ -86,7 +86,7 @@ var/obj/item/device/pda/pda = src:wear_id id = pda.owner else - id = src.wear_id.registered + id = src.wear_id.registered_name if (src.wear_id.PHOTO) photo = 1 if (id != src.real_name && in_range(src, usr) && prob(10)) From f8f3f290c548f9ac688c3702d9c1b17c58d5e870 Mon Sep 17 00:00:00 2001 From: Melvin Melonstorm Date: Wed, 8 Feb 2012 19:15:10 +0100 Subject: [PATCH 04/19] Fixed a bug with the wardrobe, changed a lot of strings and added a seal for the wardrobe, allowing people to check whether a wardrobe has been opened before or not. --- code/WorkInProgress/SkyMarshal/wardrobes.dm | 78 +++++++++++--------- code/game/objects/items/item.dm | 13 +++- icons/obj/clothing/suits.dmi | Bin 49832 -> 49963 bytes 3 files changed, 53 insertions(+), 38 deletions(-) mode change 100644 => 100755 code/WorkInProgress/SkyMarshal/wardrobes.dm mode change 100644 => 100755 code/game/objects/items/item.dm mode change 100644 => 100755 icons/obj/clothing/suits.dmi diff --git a/code/WorkInProgress/SkyMarshal/wardrobes.dm b/code/WorkInProgress/SkyMarshal/wardrobes.dm old mode 100644 new mode 100755 index 9cb9942a94..2e798900b1 --- a/code/WorkInProgress/SkyMarshal/wardrobes.dm +++ b/code/WorkInProgress/SkyMarshal/wardrobes.dm @@ -1,19 +1,22 @@ /obj/item/wardrobe name = "wardrobe" - desc = "Seems to have everything I need for my job in it, sweet." + desc = "A standard-issue bag for clothing and equipment. Usually comes sealed, stocked with everything you need for a particular job." icon = 'suits.dmi' - icon_state = "wardrobe" + icon_state = "wardrobe_sealed" item_state = "wardrobe" w_class = 4 layer = 2.9 var - descriptor = "various clothing." + descriptor = "various clothing" + seal_torn = 0 attack_self(mob/user) if(!contents.len) user << "It's empty!" else - user.visible_message("\blue [user] unwraps the clothing from the [src]") + user.visible_message("\blue [user] unwraps the clothing from the [src][seal_torn ? "" : ", tearing the seal"].") + seal_torn = 1 + for(var/obj/item/I in src) I.loc = get_turf(src) update_icon() @@ -26,8 +29,11 @@ if(istype(I, /obj/item/weapon/grab)) return user.drop_item() + if(I) - I.loc = src.loc + I.loc = src + + update_icon() else user << "\red There's not enough space to fit that!" return @@ -35,7 +41,11 @@ examine() set src in usr ..() - usr << "It claims to contain [contents.len ? descriptor : descriptor + "... but it looks empty"]" + usr << "It claims to contain [contents.len ? descriptor : descriptor + "... but it looks empty"]." + if(seal_torn && !contents.len) + usr << "The seal on the bag is broken." + else + usr << "The seal on the bag is[seal_torn ? ", however, not intact" : " intact"]." return update_icon() @@ -52,7 +62,7 @@ /obj/item/wardrobe/assistant name = "assistant wardrobe" - descriptor = "clothing for an assistant" + descriptor = "clothing and basic equipment for an assistant" New() ..() @@ -66,7 +76,7 @@ /obj/item/wardrobe/chief_engineer name = "Chief Engineer wardrobe" - descriptor = "clothing for a Chief Engineer" + descriptor = "clothing and basic equipment for a Chief Engineer" New() ..() @@ -90,7 +100,7 @@ /obj/item/wardrobe/engineer name = "Station Engineer wardrobe" - descriptor = "clothing for a Station Engineer" + descriptor = "clothing and basic equipment for a Station Engineer" New() ..() @@ -111,7 +121,7 @@ /obj/item/wardrobe/atmos name = "Atmospheric Technician wardrobe" - descriptor = "clothing for an Atmospheric Technician" + descriptor = "clothing and basic equipment for an Atmospheric Technician" New() ..() @@ -126,7 +136,7 @@ /obj/item/wardrobe/roboticist name = "Roboticist wardrobe" - descriptor = "clothing for a Roboticist" + descriptor = "clothing and basic equipment for a Roboticist" New() ..() @@ -143,7 +153,7 @@ /obj/item/wardrobe/chaplain name = "Chaplain wardrobe" - descriptor = "clothing for a Chaplain" + descriptor = "clothing and basic equipment for a Chaplain" New() ..() @@ -158,7 +168,7 @@ /obj/item/wardrobe/captain name = "Captain wardrobe" - descriptor = "clothing for a Captain" + descriptor = "clothing and basic equipment for a Captain" New() ..() @@ -181,7 +191,7 @@ /obj/item/wardrobe/hop name = "Head of Personnel wardrobe" - descriptor = "clothing for a Head of Personnel" + descriptor = "clothing and basic equipment for a Head of Personnel" New() ..() @@ -202,7 +212,7 @@ /obj/item/wardrobe/cmo name = "Chief Medical Officer wardrobe" - descriptor = "clothing for a Chief Medical Officer" + descriptor = "clothing and basic equipment for a Chief Medical Officer" New() ..() @@ -222,7 +232,7 @@ /obj/item/wardrobe/doctor name = "Medical Doctor wardrobe" - descriptor = "clothing for a Medical Doctor" + descriptor = "clothing and basic equipment for a Medical Doctor" New() ..() @@ -242,7 +252,7 @@ /obj/item/wardrobe/geneticist name = "Geneticist wardrobe" - descriptor = "clothing for a Geneticist" + descriptor = "clothing and basic equipment for a Geneticist" New() ..() @@ -258,7 +268,7 @@ /obj/item/wardrobe/virologist name = "Virologist wardrobe" - descriptor = "clothing for a Virologist" + descriptor = "clothing and basic equipment for a Virologist" New() ..() @@ -275,7 +285,7 @@ /obj/item/wardrobe/rd name = "Research Director wardrobe" - descriptor = "clothing for a Research Director" + descriptor = "clothing and basic equipment for a Research Director" New() ..() @@ -296,7 +306,7 @@ /obj/item/wardrobe/scientist name = "Scientist wardrobe" - descriptor = "clothing for a Scientist" + descriptor = "clothing and basic equipment for a Scientist" New() ..() @@ -313,7 +323,7 @@ /obj/item/wardrobe/chemist name = "Chemist wardrobe" - descriptor = "clothing for a Chemist" + descriptor = "clothing and basic equipment for a Chemist" New() ..() @@ -328,7 +338,7 @@ /obj/item/wardrobe/hos name = "Head of Security wardrobe" - descriptor = "clothing for a Head of Security" + descriptor = "clothing and basic equipment for a Head of Security" New() ..() @@ -351,7 +361,7 @@ /obj/item/wardrobe/warden name = "Warden wardrobe" - descriptor = "clothing for a Warden" + descriptor = "clothing and basic equipment for a Warden" New() ..() @@ -374,7 +384,7 @@ /obj/item/wardrobe/detective name = "Detective wardrobe" - descriptor = "clothing for a Detective" + descriptor = "clothing and basic equipment for a Detective" New() ..() @@ -396,7 +406,7 @@ /obj/item/wardrobe/officer name = "Security Officer wardrobe" - descriptor = "clothing for a Security Officer" + descriptor = "clothing and basic equipment for a Security Officer" New() ..() @@ -424,7 +434,7 @@ /obj/item/wardrobe/bartender name = "Bartender wardrobe" - descriptor = "clothing for a Bartender" + descriptor = "clothing and basic equipment for a Bartender" New() ..() @@ -442,7 +452,7 @@ /obj/item/wardrobe/chef name = "Chef wardrobe" - descriptor = "clothing for a Chef" + descriptor = "clothing and basic equipment for a Chef" New() ..() @@ -457,7 +467,7 @@ /obj/item/wardrobe/hydro name = "Botanist wardrobe" - descriptor = "clothing for a Botanist" + descriptor = "clothing and basic equipment for a Botanist" New() ..() @@ -473,7 +483,7 @@ /obj/item/wardrobe/qm name = "Quartermaster wardrobe" - descriptor = "clothing for a Quartermaster" + descriptor = "clothing and basic equipment for a Quartermaster" New() ..() @@ -489,7 +499,7 @@ /obj/item/wardrobe/cargo_tech name = "Cargo Technician wardrobe" - descriptor = "clothing for a Cargo Technician" + descriptor = "clothing and basic equipment for a Cargo Technician" New() ..() @@ -503,7 +513,7 @@ /obj/item/wardrobe/mining name = "Shaft Miner wardrobe" - descriptor = "clothing for a Shaft Miner" + descriptor = "clothing and basic equipment for a Shaft Miner" New() ..() @@ -523,7 +533,7 @@ /obj/item/wardrobe/janitor name = "Janitor wardrobe" - descriptor = "clothing for a Janitor" + descriptor = "clothing and basic equipment for a Janitor" New() ..() @@ -536,7 +546,7 @@ /obj/item/wardrobe/librarian name = "Librarian wardrobe" - descriptor = "clothing for a Librarian" + descriptor = "clothing and basic equipment for a Librarian" New() ..() @@ -549,7 +559,7 @@ /obj/item/wardrobe/lawyer name = "Lawyer wardrobe" - descriptor = "clothing for a Lawyer" + descriptor = "clothing and basic equipment for a Lawyer" New() ..() diff --git a/code/game/objects/items/item.dm b/code/game/objects/items/item.dm old mode 100644 new mode 100755 index e0ad793502..44c9d1bd3a --- a/code/game/objects/items/item.dm +++ b/code/game/objects/items/item.dm @@ -219,6 +219,7 @@ O.amount -= 1 else if(istype(W,/obj/item/wardrobe)) var/obj/item/wardrobe/I = W + var/could_fill = 1 for (var/obj/O in locate(src.x,src.y,src.z)) if (I.contents.len < 20) if(istype(O,/obj/item/wardrobe)) @@ -227,10 +228,14 @@ continue I.contents += O; else - user << "\blue The wardrobe is full." - return - user << "\blue You pick up all the items." - user.visible_message("\blue [user] gathers up the pile of stuff, and puts it into \the [W]") + could_fill = 0 + break + + if(could_fill) + user << "\blue You pick up all the items." + else + user << "\blue You try to pick up all of the items, but run out of space in the bag." + user.visible_message("\blue [user] gathers up[could_fill ? " " : " most of "]the pile of items and puts it into the [W].") I.update_icon() /obj/item/attack_self(mob/user as mob) diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi old mode 100644 new mode 100755 index 36b5b03632d70df7c1a18dc7eec312f083c0b20d..ce98885241eaf9098136602b1e75d9633d66d78d GIT binary patch delta 13737 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 Date: Wed, 8 Feb 2012 12:07:12 -0700 Subject: [PATCH 05/19] Secure Airlock update! 4 new wires, completely randomised! (2nd bolt wire, 2 only-drop-bolts wires, and an AI alert wire that alerts an AI 20% of the time, when messed with) Emags have a limited number of uses, between 3 and 7, and cost 5 TC Hacktools are more useful than they were, and have a lower chance of alerting the AI (This is unmapped ATM) --- baystation12.dme | 3 - code/defines/obj/weapon.dm | 6 + code/game/events/Events/ElectricalStorm.dm | 2 +- code/game/events/Events/PrisonBreak.dm | 2 +- code/game/gamemodes/game_mode.dm | 4 +- code/game/machinery/bots/bots.dm | 5 + code/game/machinery/bots/mulebot.dm | 5 + code/game/machinery/camera_circuit.dm | 10 + code/game/machinery/cloning.dm | 5 + code/game/machinery/computer/arcade.dm | 5 + code/game/machinery/deployable.dm | 5 + code/game/machinery/doors/airlock.dm | 2125 +++++++++-------- code/game/machinery/doors/door.dm | 21 +- code/game/machinery/doors/windowdoor.dm | 6 + code/game/machinery/kitchen/gibber.dm | 5 + code/game/machinery/portable_turret.dm | 10 + code/game/machinery/telecomms/logbrowser.dm | 5 + code/game/machinery/telecomms/telemonitor.dm | 5 + code/game/machinery/vending.dm | 5 + code/game/magic/library.dm | 5 + code/game/objects/closets/secure/personal.dm | 6 + .../objects/closets/secure/secure_closets.dm | 6 + code/game/objects/closets/walllocker.dm | 5 + code/game/objects/door_assembly.dm | 6 +- code/game/objects/secstorage/secstorage.dm | 8 +- code/game/objects/storage/crates.dm | 6 + code/game/objects/storage/lockbox.dm | 6 + code/game/prisonshuttle.dm | 5 + code/game/supplyshuttle.dm | 5 + code/modules/mining/mine_items.dm | 5 + .../modules/mob/living/silicon/robot/robot.dm | 5 + code/modules/power/apc.dm | 18 +- code/modules/power/pacman2.dm | 5 + code/modules/power/port_gen.dm | 5 + code/modules/research/rdconsole.dm | 5 + code/modules/research/server.dm | 5 + 36 files changed, 1362 insertions(+), 978 deletions(-) diff --git a/baystation12.dme b/baystation12.dme index 3d325141d4..c98d894638 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -144,10 +144,7 @@ #define FILE_DIR "code/unused/spacecraft" #define FILE_DIR "code/WorkInProgress" #define FILE_DIR "code/WorkInProgress/Cael_Aislinn" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Jumper" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Rust" #define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Tajara" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/tajara_sprites" #define FILE_DIR "code/WorkInProgress/mapload" #define FILE_DIR "code/WorkInProgress/Mini" #define FILE_DIR "code/WorkInProgress/organs" diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 40cb84a6d1..1105c84947 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -453,6 +453,12 @@ icon_state = "emag" item_state = "card-id" origin_tech = "magnets=2;syndicate=2" + var/uses = 5 + + New() + ..() + uses = rand(3,7) + return /obj/item/weapon/card/id name = "identification card" diff --git a/code/game/events/Events/ElectricalStorm.dm b/code/game/events/Events/ElectricalStorm.dm index 22c7cbf9d3..5337a4f6f2 100644 --- a/code/game/events/Events/ElectricalStorm.dm +++ b/code/game/events/Events/ElectricalStorm.dm @@ -17,7 +17,7 @@ APCs += APC for(var/obj/machinery/door/airlock/Door in world) - if(Door.z == 1) + if(Door.z == 1 && !istype(Door,/obj/machinery/door/airlock/secure)) Doors += Door for(var/obj/machinery/telecomms/processor/T in world) diff --git a/code/game/events/Events/PrisonBreak.dm b/code/game/events/Events/PrisonBreak.dm index 5380d82f33..e9500a0f6c 100644 --- a/code/game/events/Events/PrisonBreak.dm +++ b/code/game/events/Events/PrisonBreak.dm @@ -14,7 +14,7 @@ for (var/obj/machinery/door/airlock/security/temp_airlock in world) if(istype(get_area(temp_airlock), /area/security/brig)) temp_airlock.prison_open() - for (var/obj/machinery/door/airlock/glass_security/temp_glassairlock in world) + for (var/obj/machinery/door/airlock/glass/glass_security/temp_glassairlock in world) if(istype(get_area(temp_glassairlock), /area/security/brig)) temp_glassairlock.prison_open() for (var/obj/machinery/door_timer/temp_timer in world) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index b2860af20c..20425c7896 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -48,8 +48,8 @@ Stealth and Camouflage Items; /obj/item/weapon/stamperaser:1:Stamp Remover; Whitespace:Seperator; Devices and Tools; -/obj/item/weapon/card/emag:3:Cryptographic Sequencer; -/obj/item/device/hacktool:3:Hacktool; +/obj/item/weapon/card/emag:5:Cryptographic Sequencer (Limited uses, almost full access); +/obj/item/device/hacktool:3:Hacktool (Slow, but stealthy. Unlimited uses); /obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; /obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; /obj/item/device/radio/headset/traitor:3:Headset with Binary Translator; diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 83ba4e215d..7b58c68f7a 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -69,6 +69,11 @@ else user << "\blue [src] does not need a repair!" else if (istype(W, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return Emag(user) else switch(W.damtype) diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm index 7e72529084..4fa1630dd5 100644 --- a/code/game/machinery/bots/mulebot.dm +++ b/code/game/machinery/bots/mulebot.dm @@ -123,6 +123,11 @@ // other: chance to knock rider off bot /obj/machinery/bot/mulebot/attackby(var/obj/item/I, var/mob/user) if(istype(I,/obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return locked = !locked user << "\blue You [locked ? "lock" : "unlock"] the mulebot's controls!" flick("mulebot-emagged", src) diff --git a/code/game/machinery/camera_circuit.dm b/code/game/machinery/camera_circuit.dm index 1efcc9af70..3114f537e3 100644 --- a/code/game/machinery/camera_circuit.dm +++ b/code/game/machinery/camera_circuit.dm @@ -39,6 +39,11 @@ ..() if(istype(I,/obj/item/weapon/card/emag)) if(network) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return authorised = 1 user << "\blue You authorised the circuit network!" updateDialog() @@ -103,6 +108,11 @@ authorised = 1 if(istype(I,/obj/item/weapon/card/emag)) if(network) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return authorised = 1 usr << "\blue You authorised the circuit network!" updateDialog() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 9027ed0023..ce3adee94f 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -653,6 +653,11 @@ else if (istype(W, /obj/item/weapon/card/emag)) if (isnull(src.occupant)) return + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return user << "You force an emergency ejection." src.locked = 0 src.go_out() diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 57b87ae93f..b2e1f3f557 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -202,6 +202,11 @@ /obj/machinery/computer/arcade/attackby(I as obj, user as mob) if(istype(I, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return temp = "If you die in the game, you die for real!" player_hp = 30 player_mp = 10 diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index f05d34a3fd..a1043334fd 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -187,6 +187,11 @@ for reference: return return else if (istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return if (src.emagged == 0) src.emagged = 1 src.req_access = null diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index f7535887f9..65a75a0b56 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -10,6 +10,11 @@ #define AIRLOCK_WIRE_CRUSH 10 #define AIRLOCK_WIRE_LIGHT 11 #define AIRLOCK_WIRE_HOLDOPEN 12 +#define AIRLOCK_WIRE_FAKEBOLT1 13 +#define AIRLOCK_WIRE_FAKEBOLT2 14 +#define AIRLOCK_WIRE_ALERTAI 15 +#define AIRLOCK_WIRE_DOOR_BOLTS_2 16 +//#define AIRLOCK_WIRE_FINGERPRINT 17 /* New methods: @@ -63,132 +68,722 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. icon = 'doorint.dmi' icon_state = "door_closed" - var/aiControlDisabled = 0 //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. - var/synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no - var/synHacking = 0 // Is hack in process y/n? - var/secondsMainPowerLost = 0 //The number of seconds until power is restored. - var/secondsBackupPowerLost = 0 //The number of seconds until power is restored. - var/spawnPowerRestoreRunning = 0 - var/welded = null - var/locked = 0 - var/wires = 4095 - secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. - var/aiDisabledIdScanner = 0 - var/aiHacking = 0 - var/obj/machinery/door/airlock/closeOther = null - var/closeOtherId = null - var/list/signalers[12] - var/lockdownbyai = 0 - autoclose = 1 - var/doortype = 0 - var/justzap = 0 - var/safetylight = 1 - var/obj/item/weapon/airlock_electronics/electronics = null + var + aiControlDisabled = 0 //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. + synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no + synHacking = 0 // Is hack in process y/n? + secondsMainPowerLost = 0 //The number of seconds until power is restored. + secondsBackupPowerLost = 0 //The number of seconds until power is restored. + spawnPowerRestoreRunning = 0 + welded = null + locked = 0 + wires = 4095 + aiDisabledIdScanner = 0 + aiHacking = 0 + obj/machinery/door/airlock/closeOther = null + closeOtherId = null + list/signalers[12] + lockdownbyai = 0 + doortype = 0 + justzap = 0 + safetylight = 1 + obj/item/weapon/airlock_electronics/electronics = null + alert_probability = 3 + list/wire_index = list( + "Orange" = 1, + "Dark red" = 2, + "White" = 3, + "Yellow" = 4, + "Red" = 5, + "Blue" = 6, + "Green" = 7, + "Grey" = 8, + "Black" = 9, + "Pink" = 10, + "Brown" = 11, + "Maroon" = 12, + "Aqua" = 13, + "Turgoise" = 14, + "Purple" = 15, + "Rainbow" = 16, + "Atomic Tangerine" = 17, + "Neon Green" = 18, + "Cotton Candy" = 19, + "Plum" = 20, + "Shamrock" = 21, + "Indigo" = 22 + ) + wirenum = 12 holdopen = 1 + autoclose = 1 + secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. -/obj/machinery/door/airlock/command - name = "Airlock" - icon = 'Doorcom.dmi' - doortype = 1 - holdopen = 0 -/obj/machinery/door/airlock/security - name = "Airlock" - icon = 'Doorsec.dmi' - doortype = 2 + command + name = "Airlock" + icon = 'Doorcom.dmi' + doortype = 1 + holdopen = 0 -/obj/machinery/door/airlock/engineering - name = "Airlock" - icon = 'Dooreng.dmi' - doortype = 3 -/obj/machinery/door/airlock/medical - name = "Airlock" - icon = 'Doormed.dmi' - doortype = 4 + security + name = "Airlock" + icon = 'Doorsec.dmi' + doortype = 2 -/obj/machinery/door/airlock/maintenance - name = "Maintenance Access" - icon = 'Doormaint.dmi' - doortype = 5 -/obj/machinery/door/airlock/external - name = "External Airlock" - icon = 'Doorext.dmi' - doortype = 6 - holdopen = 0 + engineering + name = "Airlock" + icon = 'Dooreng.dmi' + doortype = 3 -/obj/machinery/door/airlock/glass - name = "Glass Airlock" - icon = 'Doorglass.dmi' - opacity = 0 - doortype = 7 - glass = 1 -/obj/machinery/door/airlock/centcom - name = "Airlock" - icon = 'Doorele.dmi' - opacity = 0 - doortype = 8 + medical + name = "Airlock" + icon = 'Doormed.dmi' + doortype = 4 -/obj/machinery/door/airlock/vault - name = "Vault" - icon = 'vault.dmi' - opacity = 1 - doortype = 9 -/obj/machinery/door/airlock/glass_large - name = "Glass Airlock" - icon = 'Door2x1glassfull.dmi' - opacity = 0 - doortype = 10 - glass = 1 + maintenance + name = "Maintenance Access" + icon = 'Doormaint.dmi' + doortype = 5 -/obj/machinery/door/airlock/freezer - name = "Freezer Airlock" - icon = 'Doorfreezer.dmi' - opacity = 1 - doortype = 11 + external + name = "External Airlock" + icon = 'Doorext.dmi' + doortype = 6 -/obj/machinery/door/airlock/hatch - name = "Airtight Hatch" - icon = 'Doorhatchele.dmi' - opacity = 1 - doortype = 12 -/obj/machinery/door/airlock/maintenance_hatch - name = "Maintenance Hatch" - icon = 'Doorhatchmaint2.dmi' - opacity = 1 - doortype = 13 + glass + name = "Glass Airlock" + icon = 'Doorglass.dmi' + opacity = 0 + doortype = 7 + glass = 1 -/obj/machinery/door/airlock/glass/glass_command - name = "Maintenance Hatch" - icon = 'Doorcomglass.dmi' - opacity = 0 - doortype = 14 - glass = 1 -/obj/machinery/door/airlock/glass_engineering - name = "Maintenance Hatch" - icon = 'Doorengglass.dmi' - opacity = 0 - doortype = 15 - glass = 1 + glass_command + name = "Maintenance Hatch" + icon = 'Doorcomglass.dmi' + opacity = 0 + doortype = 14 + glass = 1 + + + glass_engineering + name = "Maintenance Hatch" + icon = 'Doorengglass.dmi' + opacity = 0 + doortype = 15 + glass = 1 + + + glass_security + name = "Maintenance Hatch" + icon = 'Doorsecglass.dmi' + opacity = 0 + doortype = 16 + glass = 1 + + + glass_medical + name = "Maintenance Hatch" + icon = 'doormedglass.dmi' + opacity = 0 + doortype = 17 + glass = 1 + + + centcom + name = "Airlock" + icon = 'Doorele.dmi' + opacity = 0 + doortype = 8 + + + vault + name = "Vault" + icon = 'vault.dmi' + opacity = 1 + doortype = 9 + + + glass_large + name = "Glass Airlock" + icon = 'Door2x1glassfull.dmi' + opacity = 0 + doortype = 10 + glass = 1 + + + freezer + name = "Freezer Airlock" + icon = 'Doorfreezer.dmi' + opacity = 1 + doortype = 11 + + + hatch + name = "Airtight Hatch" + icon = 'Doorhatchele.dmi' + opacity = 1 + doortype = 12 + + + maintenance_hatch + name = "Maintenance Hatch" + icon = 'Doorhatchmaint2.dmi' + opacity = 1 + doortype = 13 + + + New() + ..() + if (src.closeOtherId != null) + spawn (5) + for (var/obj/machinery/door/airlock/A in machines) + if (A.closeOtherId == src.closeOtherId && A != src) + src.closeOther = A + break + + + open() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + return 0 + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) + src.closeOther.close() + return ..() + + + close() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + return + ..() + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) + if(killthis) + killthis.ex_act(2)//Smashin windows + return + + + bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if (!src.justzap) + if(src.shock(user, 100)) + src.justzap = 1 + spawn (10) + src.justzap = 0 + return + else /*if (src.justzap)*/ + return + else if(user.hallucination > 50 && prob(10) && src.operating == 0) + user << "\red You feel a powerful shock course through your body!" + user.halloss += 10 + user.stunned += 10 + return + ..(user) + + + update_icon() + if(overlays) overlays = null + if(density) + if(locked && safetylight) + icon_state = "door_locked" + else + icon_state = "door_closed" + if(p_open || welded) + overlays = list() + if(p_open) + overlays += image(icon, "panel_open") + if(welded) + overlays += image(icon, "welded") + else + icon_state = "door_open" + return + + + animate(animation) + switch(animation) + if("opening") + if(overlays) overlays = null + if(p_open) + icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking + else + flick("door_opening", src) + if("closing") + if(overlays) overlays = null + if(p_open) + flick("o_door_closing", src) + else + flick("door_closing", src) + if("spark") + flick("door_spark", src) + if("deny") + flick("door_deny", src) + return + + requiresID() + return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/weapon/screwdriver)) + src.p_open = !( src.p_open ) + src.update_icon() + else if (istype(C, /obj/item/weapon/wirecutters)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/multitool)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/device/assembly/signaler)) + return src.attack_hand(user) + else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE + var/obj/item/weapon/pai_cable/cable = C + cable.plugin(src, user) + else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) + var/beingcrowbarred = null + if(istype(C, /obj/item/weapon/crowbar) ) + beingcrowbarred = 1 //derp, Agouri + else + beingcrowbarred = 0 + if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) + playsound(src.loc, 'Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") + if(do_after(user,40)) + user << "\blue You removed the airlock electronics!" + switch(src.doortype) + if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) + if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) + if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) + if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) + if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) + if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) + if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) + if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) + var/obj/item/weapon/airlock_electronics/ae + if (!electronics) + ae = new/obj/item/weapon/airlock_electronics( src.loc ) + ae.conf_access = src.req_access + else + ae = electronics + electronics = null + ae.loc = src.loc + + del(src) + return + else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) + user << "\blue The airlock's motors resist your efforts to pry it open." + else if (src.locked) + user << "\blue The airlock's bolts prevent it from being pried open." + if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) + + if(beingcrowbarred == 0) //being fireaxe'd + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + user << "\red You need to be wielding the Fire axe to do that." + return + else + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + + else + if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) + if(beingcrowbarred == 0) + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("closing") + + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + else + user << "\red You need to be wielding the Fire axe to do that." + else + spawn( 0 ) + src.operating = 1 + animate("closing") + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + + else + ..() + return + + + attack_paw(mob/user as mob) + return src.attack_hand(user) + + + attack_hand(mob/user as mob) + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 100)) + return + + if (ishuman(user) && prob(40) && src.density) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + playsound(src.loc, 'bang.ogg', 25, 1) + if(!istype(H.head, /obj/item/clothing/head/helmet)) + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock." + var/datum/organ/external/affecting = H.get_organ("head") + affecting.take_damage(10, 0) + H.Stun(8) + H.Weaken(5) + H.UpdateDamageIcon() + else + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." + return + + if (src.p_open) + user.machine = src + var/t1 = text("Access Panel
\n") + + //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) + t1 += getAirlockWires() + + t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) + + t1 += text("

Close

\n", src) + + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + else + ..(user) + return + +//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 engage engineer smasher, 9 enable bolt indicator, 10 wait for clearance +//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 disable engineer smasher, 9 disable bolt indicator, 10 autoclose + //This has been converted to be called by either the AI or a mob with a hacktool, permitting either to directly operate the airlock + attack_ai(mob/user as mob, obj/item/device/hacktool/C) + if(isAI(user)) + if (!src.canAIControl()) + if (src.canAIHack()) + src.hack(user) + return + else if(user) + if(!C) + return + if(C.in_use) + user << "We are already hacking another airlock." + return + if (!src.canSynControl() && src.canSynHack(C)) + src.synhack(user, C) + return + else + world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" + return + + + //Separate interface for the AI. + user.machine = src + var/t1 = text("Airlock Control
\n") + if (src.secondsMainPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) + else + t1 += text("Main power is offline indefinitely.
\n") + else + t1 += text("Main power is online.") + + if (src.secondsBackupPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) + else + t1 += text("Backup power is offline indefinitely.
\n") + else if (src.secondsMainPowerLost > 0) + t1 += text("Backup power is online.") + else + t1 += text("Backup power is offline, but will turn on if main power fails.") + t1 += "
\n" + + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + t1 += text("IdScan wire is cut.
\n") + else if (src.aiDisabledIdScanner) + t1 += text("IdScan disabled. Enable?
\n", src) + else + t1 += text("IdScan enabled. Disable?
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) + t1 += text("Main Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main Power Output wire is cut.
\n") + if (src.secondsMainPowerLost == 0) + t1 += text("Temporarily disrupt main power?.
\n", src) + if (src.secondsBackupPowerLost == 0) + t1 += text("Temporarily disrupt backup power?.
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) + t1 += text("Backup Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup Power Output wire is cut.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) + t1 += text("Airlock extra force wire is cut.
\n") + else if(!src.forcecrush) + t1 += text("Airlock extra force disabled Enable it?
\n") + else + t1 += text("Airlock extra force enabled Disable it?
\n") + + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + t1 += text("Door bolt drop wire is cut.
\n") + else if (!src.locked) + t1 += text("Door bolts are up. Drop them?
\n", src) + else + t1 += text("Door bolts are down.") + if (src.arePowerSystemsOn()) + t1 += text(" Raise?
\n", src) + else + t1 += text(" Cannot raise door bolts due to power failure.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + t1 += text("Electrification wire is cut.
\n") + if (src.secondsElectrified==-1) + t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) + else if (src.secondsElectrified>0) + t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) + else + t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) + + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + t1 += "Bolt indication light wire is cut.
\n" + else if(!src.safetylight) + t1 += text("Bolt Indication light is disabled Enable it?
\n") + else + t1 += text("Bolt Indication light is enabled Disable it?
\n") + + if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) + t1 += "Behavior Control light wire is cut.
\n" + else if(!src.holdopen) + t1 += text("Door behavior is set to: Automatically close Toggle?
\n") + else + t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") + + if (src.welded) + t1 += text("Door appears to have been welded shut.
\n") + else if (!src.locked) + if (src.density) + t1 += text("Open door
\n", src) + else + t1 += text("Close door
\n", src) + + t1 += text("

Close

\n", src) + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + + proc + hack(mob/user as mob) + if (src.aiHacking==0) + src.aiHacking=1 + spawn(20) + //TODO: Make this take a minute + user << "Airlock AI control has been blocked. Beginning fault-detection." + sleep(50) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Fault confirmed: airlock control wire disabled or cut." + sleep(20) + user << "Attempting to hack into airlock. This may take some time." + sleep(200) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(170) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(50) + //disable blocked control + src.aiControlDisabled = 2 + user << "Receiving control information from airlock." + sleep(10) + //bring up airlock dialog + src.aiHacking = 0 + src.attack_ai(user) + + + synhack(mob/user as mob, obj/item/device/hacktool/I) + if (src.synHacking==0) + src.synHacking=1 + I.in_use = 1 + user << "You begin hacking..." + spawn(20) + user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." + sleep(25) + if (src.canSynControl()) + user << "Hack cancelled, control already possible." + src.synHacking=0 + I.in_use = 0 + return + else if (!src.canSynHack(I)) + user << "\red Connection lost. Stand still and stay near the airlock!" + src.synHacking=0 + I.in_use = 0 + return + user << "Connection established." + sleep(10) + user << "Attempting to hack into airlock. This may take some time." + sleep(50) + + // Alerting the AIs + var/list/cameras = list() + for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area + cameras += C + var/alertoption = prob(alert_probability) // Chance of warning AI, based on doortype's probability + if(alertoption) + if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) + alertoption = 3 + else if (prob(18)) //18% chance of sending the AI just the area + alertoption = 2 + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + switch(alertoption) + if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) + if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + switch(alertoption) + if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") + // ...And done + + if (!src.canSynHack(I)) + user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Local override already in place, hack aborted." + src.synHacking=0 + I.in_use = 0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(35) + if (!src.canSynHack(I)) + user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Upload access aborted, local override already in place." + src.synHacking=0 + I.in_use = 0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(25) + //disable blocked control + src.synDoorHacked = 1 + user << "Bingo! We're in. Airlock control panel coming right up." + sleep(5) + //bring up airlock dialog + src.synHacking = 0 + I.in_use = 0 + src.attack_ai(user, I) + + + canAIControl() + return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); + + + canAIHack() + return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); + + + canSynControl() + return (src.synDoorHacked && (!src.isAllPowerCut())); + + + canSynHack(obj/item/device/hacktool/H) + return (in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()); -/obj/machinery/door/airlock/glass_security - name = "Maintenance Hatch" - icon = 'Doorsecglass.dmi' - opacity = 0 - doortype = 16 - glass = 1 -/obj/machinery/door/airlock/glass_medical - name = "Maintenance Hatch" - icon = 'doormedglass.dmi' - opacity = 0 - doortype = 17 - glass = 1 /* About the new airlock wires panel: @@ -202,615 +797,233 @@ About the new airlock wires panel: * one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) */ -/obj/machinery/door/airlock/bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if (!src.justzap) - if(src.shock(user, 100)) - src.justzap = 1 - spawn (10) - src.justzap = 0 - return - else /*if (src.justzap)*/ - return - else if(user.hallucination > 50 && prob(10) && src.operating == 0) - user << "\red You feel a powerful shock course through your body!" - user.halloss += 10 - user.stunned += 10 - return - ..(user) + pulse(var/wireColor) + //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function + var/wireIndex = airlockWireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen -/obj/machinery/door/airlock/proc/pulse(var/wireColor) - //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function - var/wireIndex = airlockWireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - animate("deny") - if (AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - //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). - src.loseMainPower() - if (AIRLOCK_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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - else - if(src.arePowerSystemsOn()) //only can raise bolts if power's on - src.locked = 0 - usr << "You hear a click from inside the door." + cut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) src.updateUsrDialog() - update_icon() + if (AIRLOCK_WIRE_DOOR_BOLTS) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 - if (AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - //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). - src.loseBackupPower() - if (AIRLOCK_WIRE_AI_CONTROL) - if (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if (src.secondsElectrified==0) - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 -// src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_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 - if (!src.requiresID() || src.check_access(null)) - if (src.density) - open() - else - close() - if(AIRLOCK_WIRE_CRUSH) - src.forcecrush = !src.forcecrush - if(AIRLOCK_WIRE_LIGHT) - src.safetylight = !src.safetylight - if(AIRLOCK_WIRE_HOLDOPEN) - src.holdopen = !src.holdopen - - - -/obj/machinery/door/airlock/proc/cut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - //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. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_DOOR_BOLTS) - //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) - if (src.locked!=1) - src.locked = 1 - update_icon() - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if (src.secondsElectrified != -1) - src.secondsElectrified = -1 - - -/obj/machinery/door/airlock/proc/mend(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - if (src.secondsElectrified == -1) - src.secondsElectrified = 0 - -/obj/machinery/door/airlock/proc/isElectrified() - if(src.secondsElectrified != 0) - return 1 - else return 0 - -/obj/machinery/door/airlock/proc/isWireColorCut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/door/airlock/proc/isWireCut(var/wireIndex) - var/wireFlag = airlockIndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - -/obj/machinery/door/airlock/proc/canAIControl() - return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); - -/obj/machinery/door/airlock/proc/canAIHack() - return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); - -/obj/machinery/door/airlock/proc/canSynControl() - return (src.synDoorHacked && (!src.isAllPowerCut())); - -/obj/machinery/door/airlock/proc/canSynHack(obj/item/device/hacktool/H) - if(in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()) - return 1 - -/obj/machinery/door/airlock/proc/arePowerSystemsOn() - return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) - -/obj/machinery/door/airlock/requiresID() - return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) - -/obj/machinery/door/airlock/proc/isAllPowerCut() - var/retval=0 - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - retval=1 - return retval - -/obj/machinery/door/airlock/proc/regainMainPower() - if (src.secondsMainPowerLost > 0) - src.secondsMainPowerLost = 0 - -/obj/machinery/door/airlock/proc/loseMainPower() - if (src.secondsMainPowerLost <= 0) - src.secondsMainPowerLost = 60 - if (src.secondsBackupPowerLost < 10) - src.secondsBackupPowerLost = 10 - if (!src.spawnPowerRestoreRunning) - src.spawnPowerRestoreRunning = 1 - spawn(0) - var/cont = 1 - while (cont) - sleep(10) - cont = 0 - if (src.secondsMainPowerLost>0) + mend(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.secondsMainPowerLost -= 1 - src.updateDialog() - cont = 1 - - if (src.secondsBackupPowerLost>0) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.secondsBackupPowerLost -= 1 - src.updateDialog() - cont = 1 - src.spawnPowerRestoreRunning = 0 - src.updateDialog() + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 -/obj/machinery/door/airlock/proc/loseBackupPower() - if (src.secondsBackupPowerLost < 60) - src.secondsBackupPowerLost = 60 - -/obj/machinery/door/airlock/proc/regainBackupPower() - if (src.secondsBackupPowerLost > 0) - src.secondsBackupPowerLost = 0 - -// shock user with probability prb (if all connections & power are working) -// returns 1 if shocked, 0 otherwise -// The preceding comment was borrowed from the grille's shock script -/obj/machinery/door/airlock/proc/shock(mob/user, prb) - if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 //you lucked out, no shock for you - if(istype(usr.equipped(),/obj/item/weapon/shard)) - return 0 - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if (electrocute_mob(user, get_area(src), src)) - return 1 - else - return 0 - - -/obj/machinery/door/airlock/update_icon() - if(overlays) overlays = null - if(density) - if(locked && safetylight) - icon_state = "door_locked" - else - icon_state = "door_closed" - if(p_open || welded) - overlays = list() - if(p_open) - overlays += image(icon, "panel_open") - if(welded) - overlays += image(icon, "welded") - else - icon_state = "door_open" - - return - -/obj/machinery/door/airlock/animate(animation) - switch(animation) - if("opening") - if(overlays) overlays = null - if(p_open) - icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking - else - flick("door_opening", src) - if("closing") - if(overlays) overlays = null - if(p_open) - flick("o_door_closing", src) - else - flick("door_closing", src) - if("spark") - flick("door_spark", src) - if("deny") - flick("door_deny", src) - return - -/obj/machinery/door/airlock/attack_ai(mob/user as mob) - if (!src.canAIControl()) - if (src.canAIHack()) - src.hack(user) - return - - //Separate interface for the AI. - user.machine = src - var/t1 = text("Airlock Control
\n") - if (src.secondsMainPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
\n") - else - t1 += text("Main power is online.") - - if (src.secondsBackupPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
\n") - else if (src.secondsMainPowerLost > 0) - t1 += text("Backup power is online.") - else - t1 += text("Backup power is offline, but will turn on if main power fails.") - t1 += "
\n" - - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
\n") - else if (src.aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
\n", src) - else - t1 += text("IdScan enabled. Disable?
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
\n") - if (src.secondsMainPowerLost == 0) - t1 += text("Temporarily disrupt main power?.
\n", src) - if (src.secondsBackupPowerLost == 0) - t1 += text("Temporarily disrupt backup power?.
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) - t1 += text("Airlock extra force wire is cut.
\n") - else if(!src.forcecrush) - t1 += text("Airlock extra force disabled Enable it?
\n") - else - t1 += text("Airlock extra force enabled Disable it?
\n") - - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
\n") - else if (!src.locked) - t1 += text("Door bolts are up. Drop them?
\n", src) - else - t1 += text("Door bolts are down.") - if (src.arePowerSystemsOn()) - t1 += text(" Raise?
\n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
\n") - if (src.secondsElectrified==-1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) - else if (src.secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) - else - t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) - - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += "Bolt indication light wire is cut.
\n" - else if(!src.safetylight) - t1 += text("Bolt Indication light is disabled Enable it?
\n") - else - t1 += text("Bolt Indication light is enabled Disable it?
\n") - - if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) - t1 += "Behavior Control light wire is cut.
\n" - else if(!src.holdopen) - t1 += text("Door behavior is set to: Automatically close Toggle?
\n") - else - t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") - - if (src.welded) - t1 += text("Door appears to have been welded shut.
\n") - else if (!src.locked) - if (src.density) - t1 += text("Open door
\n", src) - else - t1 += text("Close door
\n", src) - - t1 += text("

Close

\n", src) - user << browse(t1, "window=airlock") - onclose(user, "airlock") - -//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door -//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door - -/obj/machinery/door/airlock/proc/attack_hack(mob/user as mob, obj/item/device/hacktool/C) - if(!C) - return - if(C.in_use) - user << "We are already hacking another airlock." - return - if (!src.canSynControl() && src.canSynHack(C)) - src.synhack(user, C) - return - - //Separate interface for the hacker. - var/t1 = text("Airlock Control
\n") - if (src.secondsMainPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
\n") - else - t1 += text("Main power is online.") - - if (src.secondsBackupPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
\n") - else if (src.secondsMainPowerLost > 0) - t1 += text("Backup power is online.") - else - t1 += text("Backup power is offline, but will turn on if main power fails.") - t1 += "
\n" - - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
\n") - else if (src.aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
\n", src) - else - t1 += text("IdScan enabled. Disable?
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
\n") - if (src.secondsMainPowerLost == 0) - t1 += text("Temporarily disrupt main power?.
\n", src) - if (src.secondsBackupPowerLost == 0) - t1 += text("Temporarily disrupt backup power?.
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) - t1 += text("Airlock extra force wire is cut.
\n") - else if(!src.forcecrush) - t1 += text("Airlock extra force disabled Enable it?
\n") - else - t1 += text("Airlock extra force enabled Disable it?
\n") - - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
\n") - else if (!src.locked) - t1 += text("Door bolts are up. Drop them?
\n", src) - else - t1 += text("Door bolts are down.") - if (src.arePowerSystemsOn()) - t1 += text(" Raise?
\n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
\n") - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
\n") - if (src.secondsElectrified==-1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) - else if (src.secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) - else - t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) - - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += "Bolt indication light wire is cut.
\n" - else if(!src.safetylight) - t1 += text("Bolt indication light is disabled Enable it?
\n") - else - t1 += text("Bolt indication light is enabled Disable it?
\n") - - if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) - t1 += "Behavior Control light wire is cut.
\n" - else if(!src.holdopen) - t1 += text("Door behavior is set to: Automatically close Toggle?
\n") - else - t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") - - if (src.welded) - t1 += text("Door appears to have been welded shut.
\n") - else if (!src.locked) - if (src.density) - t1 += text("Open door
\n", src) - else - t1 += text("Close door
\n", src) - - t1 += text("

Close

\n", src) - user << browse(t1, "window=airlock") - onclose(user, "airlock") - -/obj/machinery/door/airlock/proc/hack(mob/user as mob) - if (src.aiHacking==0) - src.aiHacking=1 - spawn(20) - //TODO: Make this take a minute - user << "Airlock AI control has been blocked. Beginning fault-detection." - sleep(50) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Fault confirmed: airlock control wire disabled or cut." - sleep(20) - user << "Attempting to hack into airlock. This may take some time." - sleep(200) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(170) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(50) - //disable blocked control - src.aiControlDisabled = 2 - user << "Receiving control information from airlock." - sleep(10) - //bring up airlock dialog - src.aiHacking = 0 - src.attack_ai(user) - - -/obj/machinery/door/airlock/attack_paw(mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/door/airlock/attack_hand(mob/user as mob) - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 100)) - return - - if (ishuman(user) && prob(40) && src.density) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - playsound(src.loc, 'bang.ogg', 25, 1) - if(!istype(H.head, /obj/item/clothing/head/helmet)) - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock." - var/datum/organ/external/affecting = H.get_organ("head") - affecting.take_damage(10, 0) - H.Stun(8) - H.Weaken(5) - H.UpdateDamageIcon() - else - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." - return - - if (src.p_open) - user.machine = src - var/t1 = text("Access Panel
\n") - - //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) - var/list/wires = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Red" = 5, - "Blue" = 6, - "Green" = 7, - "Grey" = 8, - "Black" = 9, - "Pink" = 10, - "Brown" = 11, - "Maroon" = 12 - ) - for(var/wiredesc in wires) - var/is_uncut = src.wires & airlockWireColorToFlag[wires[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - if(src.signalers[wires[wiredesc]]) - t1 += "Detach signaler" + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & airlockWireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" else - t1 += "Attach signaler" - t1 += "
" + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 - t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) + isElectrified() + return (src.secondsElectrified != 0); - t1 += text("

Close

\n", src) + isWireColorCut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) - user << browse(t1, "window=airlock") - onclose(user, "airlock") + isWireCut(var/wireIndex) + var/wireFlag = airlockIndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + arePowerSystemsOn() + return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) + + isAllPowerCut() + return ((src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) && (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + + regainMainPower() + if (src.secondsMainPowerLost > 0) + src.secondsMainPowerLost = 0 + + loseMainPower() + if (src.secondsMainPowerLost <= 0) + src.secondsMainPowerLost = 60 + if (src.secondsBackupPowerLost < 10) + src.secondsBackupPowerLost = 10 + if (!src.spawnPowerRestoreRunning) + src.spawnPowerRestoreRunning = 1 + spawn(0) + var/cont = 1 + while (cont) + sleep(10) + cont = 0 + if (src.secondsMainPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.secondsMainPowerLost -= 1 + src.updateDialog() + cont = 1 + + if (src.secondsBackupPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.secondsBackupPowerLost -= 1 + src.updateDialog() + cont = 1 + src.spawnPowerRestoreRunning = 0 + src.updateDialog() + + loseBackupPower() + if (src.secondsBackupPowerLost < 60) + src.secondsBackupPowerLost = 60 + + regainBackupPower() + if (src.secondsBackupPowerLost > 0) + src.secondsBackupPowerLost = 0 + + // shock user with probability prb (if all connections & power are working) + // returns 1 if shocked, 0 otherwise + // The preceding comment was borrowed from the grille's shock script + shock(mob/user, prb) + if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock + return 0 + if(!prob(prb)) + return 0 //you lucked out, no shock for you + if(istype(usr.equipped(),/obj/item/weapon/shard)) + return 0 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if (electrocute_mob(user, get_area(src), src)) + return 1 + else + return 0 + + prison_open() + src.locked = 0 + src.open() + src.locked = 1 + return - else - ..(user) - return /obj/machinery/door/airlock/Topic(href, href_list) @@ -1024,265 +1237,269 @@ About the new airlock wires panel: src.update_icon() src.updateUsrDialog() if((istype(usr.equipped(), /obj/item/device/hacktool))) - attack_hack(usr, usr.equipped()) - + return attack_ai(usr, usr.equipped()) return -/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob) - //world << text("airlock attackby src [] obj [] mob []", src, C, user) - if(istype(C, /obj/item/device/detective_scanner)) - return - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 75)) - return - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/weapon/screwdriver)) - src.p_open = !( src.p_open ) - src.update_icon() - else if (istype(C, /obj/item/weapon/wirecutters)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/multitool)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/hacktool)) - return src.attack_hack(user, C) - else if (istype(C, /obj/item/device/assembly/signaler)) - return src.attack_hand(user) - else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE - var/obj/item/weapon/pai_cable/cable = C - cable.plugin(src, user) - else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) - var/beingcrowbarred = null - if(istype(C, /obj/item/weapon/crowbar) ) - beingcrowbarred = 1 //derp, Agouri - else - beingcrowbarred = 0 - if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) - playsound(src.loc, 'Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") - if(do_after(user,40)) - user << "\blue You removed the airlock electronics!" - switch(src.doortype) - if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) - if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) - if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) - if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) - if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) - if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) - if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) - if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) - var/obj/item/weapon/airlock_electronics/ae - if (!electronics) - ae = new/obj/item/weapon/airlock_electronics( src.loc ) - ae.conf_access = src.req_access - else - ae = electronics - electronics = null - ae.loc = src.loc - del(src) - return - else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) - user << "\blue The airlock's motors resist your efforts to pry it open." - else if (src.locked) - user << "\blue The airlock's bolts prevent it from being pried open." - if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) - if(beingcrowbarred == 0) //being fireaxe'd - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("opening") +/obj/machinery/door/airlock/secure + name = "Secure Airlock" + desc = "Good lord, at least they left out the overcomplicated death traps. Looks to be a layer of armor plate you might be able to remove with a wrench." + icon = 'Doorhatchele.dmi' - sleep(15) + wires = 65535 + wirenum = 16 + alert_probability = 20 + holdopen = 0 + signalers = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + var + list/WireColorToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + is_detached = 0 - layer = 2.7 - src.density = 0 - update_icon() - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - user << "\red You need to be wielding the Fire axe to do that." - return - else - spawn( 0 ) - src.operating = 1 - animate("opening") - sleep(15) - - layer = 2.7 - src.density = 0 - update_icon() - - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - - else - if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) - if(beingcrowbarred == 0) - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("closing") - - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - else - user << "\red You need to be wielding the Fire axe to do that." - else - spawn( 0 ) - src.operating = 1 - animate("closing") - - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - - else + New() ..() - return - -/obj/machinery/door/airlock/proc/synhack(mob/user as mob, obj/item/device/hacktool/I) - if (src.synHacking==0) - src.synHacking=1 - I.in_use = 1 - spawn(20 ) - user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." - sleep(25 ) - if (src.canSynControl()) - user << "Hack cancelled, control already possible." - src.synHacking=0 - I.in_use = 0 - return - else if (!src.canSynHack(I)) - user << "\red Connection lost. Stand still and stay near the airlock!" - src.synHacking=0 - I.in_use = 0 - return - user << "Connection established." - sleep(10 ) - user << "Attempting to hack into airlock. This may take some time." - sleep(100 ) - // Alerting the AIs - var/list/cameras = list() - for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area - cameras += C - - var/alertoption = prob(50) // 50% chance of warning the AI - if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) - alertoption = 3 - else if (prob(18)) //18% chance of sending the AI just the area - alertoption = 2 - - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - switch(alertoption) - if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) - if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - switch(alertoption) - if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") - - // ...And done - - if (!src.canSynHack(I)) - user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Local override already in place, hack aborted." - src.synHacking=0 - I.in_use = 0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(85 ) - if (!src.canSynHack(I)) - user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Upload access aborted, local override already in place." - src.synHacking=0 - I.in_use = 0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(25 ) - //disable blocked control - src.synDoorHacked = 1 - user << "Bingo! We're in. Airlock control panel coming right up." - sleep(5 ) - //bring up airlock dialog - src.synHacking = 0 - I.in_use = 0 - src.attack_hack(user, I) - -/obj/machinery/door/airlock/open() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) - return 0 - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) - src.closeOther.close() - return ..() - -/obj/machinery/door/airlock/close() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). + var/flagIndex = 1 + for (var/flag=1, flag<65536, flag+=flag) + var/valid = 0 + while (!valid) + var/colorIndex = rand(1, 16) + if (WireColorToFlag[colorIndex] == 0) + valid = 1 + WireColorToFlag[colorIndex] = flag + IndexToFlag[flagIndex] = flag + IndexToWireColor[flagIndex] = colorIndex + WireColorToIndex[colorIndex] = flagIndex + flagIndex+=1 return - ..() - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) - if(killthis) - killthis.ex_act(2)//Smashin windows - return - -/obj/machinery/door/airlock/New() - ..() - if (src.closeOtherId != null) - spawn (5) - for (var/obj/machinery/door/airlock/A in machines) - if (A.closeOtherId == src.closeOtherId && A != src) - src.closeOther = A - break -/obj/machinery/door/airlock/proc/prison_open() - src.locked = 0 - src.open() - src.locked = 1 - return \ No newline at end of file + isWireColorCut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) + + isWireCut(var/wireIndex) + var/wireFlag = IndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + pulse(var/wireColor) + var/wireIndex = WireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + cut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + mend(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 + + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & WireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + else + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if(!src.is_detached) + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start to remove the armor plate..." + if(do_after(user,30)) + user << "Armor plates removed" + src.is_detached = 1 + else + if (istype(C, /obj/item/weapon/wrench)) + user << "You start to reattach the armor plate..." + if(do_after(user,30)) + user << "Armor plates attached" + src.is_detached = 0 + else + return ..(C, user) \ No newline at end of file diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 0a697d414c..fe46d91232 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -137,7 +137,13 @@ if (!src.requiresID()) //don't care who they are or what they have, act as if they're NOTHING user = null - if (src.density && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade))) + if (src.density && (istype(I, /obj/item/weapon/card/emag) ||istype(I, /obj/item/weapon/melee/energy/blade))) + if(istype(I, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return src.operating = -1 if(istype(I, /obj/item/weapon/melee/energy/blade)) if(istype(src, /obj/machinery/door/airlock)) @@ -342,12 +348,13 @@ if(T) L.loc = T - for(var/obj/item/I in src.loc) // Move items out of the way - if(!I.anchored) - var/list/lst = list(NORTH,SOUTH,EAST,WEST) - var/turf/T = get_random_turf(I, lst) - if(T) - I.loc = T + if(!src.forcecrush) + for(var/obj/item/I in src.loc) // Move items out of the way + if(!I.anchored) + var/list/lst = list(NORTH,SOUTH,EAST,WEST) + var/turf/T = get_random_turf(I, lst) + if(T) + I.loc = T sleep(6) update_icon() diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index d91c2b56bc..76280d6b56 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -121,6 +121,12 @@ //don't care who they are or what they have, act as if they're NOTHING user = null if (src.density && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade))) + if(istype(I, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return src.operating = -1 if(istype(I, /obj/item/weapon/melee/energy/blade)) var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index 09abb12e1a..987406df37 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -50,6 +50,11 @@ /obj/machinery/gibber/attackby(obj/item/weapon/grab/G as obj, mob/user as mob) if(istype(G,/obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = G + if(E.uses) + E.uses-- + else + return user.visible_message( \ "\red [user] swipes a strange card through \the [src]'s control panel!", \ "\red You swipe a strange card through \the [src]'s control panel!", \ diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 7949cbae65..6726520c80 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -172,6 +172,11 @@ Neutralize All Unidentified Life Signs: []
"}, if ((istype(W, /obj/item/weapon/card/emag)) && (!src.emagged)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return // Emagging the turret makes it go bonkers and stun everyone. It also makes // the turret shoot much, much faster. @@ -861,6 +866,11 @@ Neutralize All Unidentified Life Signs: []
"}, /obj/machinery/porta_turret_cover/attackby(obj/item/W as obj, mob/user as mob) if ((istype(W, /obj/item/weapon/card/emag)) && (!Parent_Turret.emagged)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return user << "\red You short out [Parent_Turret]'s threat assessment circuits." spawn(0) for(var/mob/O in hearers(Parent_Turret, null)) diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm index 6d939c6016..03665dda37 100644 --- a/code/game/machinery/telecomms/logbrowser.dm +++ b/code/game/machinery/telecomms/logbrowser.dm @@ -224,6 +224,11 @@ A.anchored = 1 del(src) else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = D + if(E.uses) + E.uses-- + else + return playsound(src.loc, 'sparks4.ogg', 75, 1) emagged = 1 user << "\blue You you disable the security protocols" diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm index 670673179f..a7ee7e827e 100644 --- a/code/game/machinery/telecomms/telemonitor.dm +++ b/code/game/machinery/telecomms/telemonitor.dm @@ -154,6 +154,11 @@ A.anchored = 1 del(src) else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = D + if(E.uses) + E.uses-- + else + return playsound(src.loc, 'sparks4.ogg', 75, 1) emagged = 1 user << "\blue You you disable the security protocols" diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index ab73e09e80..4feca37b7a 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -319,6 +319,11 @@ To combat this, I changed the window name. -- Doohl /obj/machinery/vending/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return src.emagged = 1 user << "You short out the ID lock on [src]" return diff --git a/code/game/magic/library.dm b/code/game/magic/library.dm index 7c9942f3ae..348b64470b 100644 --- a/code/game/magic/library.dm +++ b/code/game/magic/library.dm @@ -720,6 +720,11 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f /obj/machinery/librarycomp/attackby(obj/item/weapon/W as obj, mob/user as mob) if (src.density && istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return src.emagged = 1 if(istype(W, /obj/item/weapon/barcodescanner)) var/obj/item/weapon/barcodescanner/scanner = W diff --git a/code/game/objects/closets/secure/personal.dm b/code/game/objects/closets/secure/personal.dm index c3d09c48bc..16726cc7ef 100644 --- a/code/game/objects/closets/secure/personal.dm +++ b/code/game/objects/closets/secure/personal.dm @@ -41,6 +41,12 @@ else user << "\red Access Denied" else if( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && !src.broken) + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return broken = 1 locked = 0 desc = "It appears to be broken." diff --git a/code/game/objects/closets/secure/secure_closets.dm b/code/game/objects/closets/secure/secure_closets.dm index 1923e0cf84..f971a61c63 100644 --- a/code/game/objects/closets/secure/secure_closets.dm +++ b/code/game/objects/closets/secure/secure_closets.dm @@ -38,6 +38,12 @@ user << "\red It appears to be broken." return else if((istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && !src.broken) + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return broken = 1 locked = 0 desc = "It appears to be broken." diff --git a/code/game/objects/closets/walllocker.dm b/code/game/objects/closets/walllocker.dm index cea7e6e2e9..0aea34dcdb 100644 --- a/code/game/objects/closets/walllocker.dm +++ b/code/game/objects/closets/walllocker.dm @@ -48,6 +48,11 @@ user << "\red It appears to be broken." return else if(istype(W, /obj/item/weapon/card/emag) && !src.broken) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return src.broken = 1 src.locked = 0 src.icon_state = src.icon_broken diff --git a/code/game/objects/door_assembly.dm b/code/game/objects/door_assembly.dm index f9e605d55a..22d53ef572 100644 --- a/code/game/objects/door_assembly.dm +++ b/code/game/objects/door_assembly.dm @@ -43,7 +43,7 @@ obj/structure/door_assembly name = "Security Airlock Assembly" icon_state = "door_as_sec1" glass_base_icon_state = "door_as_gsec" - glass_type = /obj/machinery/door/airlock/glass_security + glass_type = /obj/machinery/door/airlock/glass/glass_security airlock_type = /obj/machinery/door/airlock/security anchored = 1 density = 1 @@ -58,7 +58,7 @@ obj/structure/door_assembly name = "Engineering Airlock Assembly" icon_state = "door_as_eng1" glass_base_icon_state = "door_as_geng" - glass_type = /obj/machinery/door/airlock/glass_engineering + glass_type = /obj/machinery/door/airlock/glass/glass_engineering airlock_type = /obj/machinery/door/airlock/engineering anchored = 1 density = 1 @@ -73,7 +73,7 @@ obj/structure/door_assembly name = "Medical Airlock Assembly" icon_state = "door_as_med1" glass_base_icon_state = "door_as_gmed" - glass_type = /obj/machinery/door/airlock/glass_medical + glass_type = /obj/machinery/door/airlock/glass/glass_medical airlock_type = /obj/machinery/door/airlock/medical anchored = 1 density = 1 diff --git a/code/game/objects/secstorage/secstorage.dm b/code/game/objects/secstorage/secstorage.dm index 5a9defccdc..9458f05a85 100644 --- a/code/game/objects/secstorage/secstorage.dm +++ b/code/game/objects/secstorage/secstorage.dm @@ -93,7 +93,13 @@ /obj/item/weapon/secstorage/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() - if ( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && (src.locked == 1) && (!src.emagged)) + if ((istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && (src.locked == 1) && (!src.emagged)) + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return emagged = 1 src.overlays += image('storage.dmi', icon_sparking) sleep(6) diff --git a/code/game/objects/storage/crates.dm b/code/game/objects/storage/crates.dm index c111c52acd..af16542f58 100644 --- a/code/game/objects/storage/crates.dm +++ b/code/game/objects/storage/crates.dm @@ -258,6 +258,12 @@ overlays += redlight return else if ( (istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && locked &&!broken) + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return overlays = null overlays += emag overlays += sparks diff --git a/code/game/objects/storage/lockbox.dm b/code/game/objects/storage/lockbox.dm index 49b9d3b3fd..d3cba8ecfc 100644 --- a/code/game/objects/storage/lockbox.dm +++ b/code/game/objects/storage/lockbox.dm @@ -34,6 +34,12 @@ else user << "\red Access Denied" else if((istype(W, /obj/item/weapon/card/emag)||istype(W, /obj/item/weapon/melee/energy/blade)) && !src.broken) + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return broken = 1 locked = 0 desc = "It appears to be broken." diff --git a/code/game/prisonshuttle.dm b/code/game/prisonshuttle.dm index dd01888d03..8fa447c9ae 100644 --- a/code/game/prisonshuttle.dm +++ b/code/game/prisonshuttle.dm @@ -35,6 +35,11 @@ var/prison_shuttle_timeleft = 0 attackby(I as obj, user as mob) if(istype(I,/obj/item/weapon/card/emag) && (!hacked)) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return hacked = 1 user << "\blue You disable the lock." else diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index e3d27b1256..b9e0187786 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -402,6 +402,11 @@ var/list/supply_groups = new() /obj/machinery/computer/supplycomp/attackby(I as obj, user as mob) if(istype(I,/obj/item/weapon/card/emag) && !hacked) + var/obj/item/weapon/card/emag/E = I + if(E.uses) + E.uses-- + else + return user << "\blue Special supplies unlocked." src.hacked = 1 return diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 79157b40fa..35fc955cd2 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -86,6 +86,11 @@ proc/move_mining_shuttle() /obj/machinery/computer/mining_shuttle/attackby(obj/item/weapon/W as obj, mob/user as mob) if (istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return src.req_access = list() hacked = 1 usr << "You fried the consoles ID checking system. It's now available to everyone!" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 62331f8276..2794e49889 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -421,6 +421,11 @@ user << "\red Access denied." else if(istype(W, /obj/item/weapon/card/emag)) // trying to unlock with an emag card + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return if(!opened)//Cover is closed if(locked) if(prob(90)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index c691bd5326..8494727395 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -300,6 +300,12 @@ else user << "\red Access denied." else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card + if(istype(W, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = W + if(E.uses) + E.uses-- + else + return if(opened) user << "You must close the cover to swipe an ID card." else if(wiresexposed) @@ -859,7 +865,7 @@ else src.malfai = usr malfai << "Hack complete. The APC is now under your exclusive control." - updateicon() + updateicon() else if (href_list["occupyapc"]) malfoccupy(usr) @@ -876,21 +882,21 @@ return if(src.z != 1) return - + src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1) src.occupant.adjustOxyLoss(malf.getOxyLoss()) src.occupant.name = "[malf.name] APC Copy" - + if(malf.parent) src.occupant.parent = malf.parent else src.occupant.parent = malf - + malf.mind.transfer_to(src.occupant) - + if(malf.parent) del(malf) - + src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn src.occupant.cancel_camera() diff --git a/code/modules/power/pacman2.dm b/code/modules/power/pacman2.dm index 930877d441..98d3eb1e8f 100644 --- a/code/modules/power/pacman2.dm +++ b/code/modules/power/pacman2.dm @@ -81,6 +81,11 @@ O.loc = src user << "\blue You add the plasma tank to the generator." else if (istype(O, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = O + if(E.uses) + E.uses-- + else + return emagged = 1 emp_act(1) else if(!active) diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 2ad21eb5cd..dd5f262e99 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -196,6 +196,11 @@ display round(lastgen) and plasmatank amount del(O) user << "\blue You add a coin to the generator." else if (istype(O, /obj/item/weapon/card/emag)) + var/obj/item/weapon/card/emag/E = O + if(E.uses) + E.uses-- + else + return emagged = 1 emp_act(1) else if(!active) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index fa6178bdee..6dd2fcdb4c 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -176,6 +176,11 @@ won't update every console in existence) but it's more of a hassle to do. Also, D.loc = src user << "\blue You add the disk to the machine!" else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = D + if(E.uses) + E.uses-- + else + return playsound(src.loc, 'sparks4.ogg', 75, 1) emagged = 1 user << "\blue You you disable the security protocols" diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index e898808c66..8467ab99ff 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -326,6 +326,11 @@ A.anchored = 1 del(src) else if(istype(D, /obj/item/weapon/card/emag) && !emagged) + var/obj/item/weapon/card/emag/E = D + if(E.uses) + E.uses-- + else + return playsound(src.loc, 'sparks4.ogg', 75, 1) emagged = 1 user << "\blue You you disable the security protocols" From 7298e8619b25c873aa09a49740e9b4b5edf7e3f6 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 13:33:55 -0700 Subject: [PATCH 06/19] Adding in cut down hacktool for CE. --- code/defines/obj.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/code/defines/obj.dm b/code/defines/obj.dm index 4b3cd52c64..f537f56aaa 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -356,6 +356,10 @@ m_amt = 60 g_amt = 20 +/obj/item/device/hacktool/engineer + name = "door debugger" + desc = "An item of immense complexion, it appears to work by magic." + /obj/item/blueprints name = "station blueprints" desc = "Blueprints of the station. There's stamp \"Classified\" and several coffee stains on it." From b967f6b5774251096610e56e3b04865d2b38e2fd Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 13:46:10 -0700 Subject: [PATCH 07/19] Should make the engineer hacktool auto raise the bolts, at the cost of alerting the AI. --- code/game/machinery/doors/airlock.dm | 3061 +++++++++++++++++++++++++- 1 file changed, 3054 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 65a75a0b56..b56589fcbc 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -537,6 +537,8 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. if (!src.canSynControl() && src.canSynHack(C)) src.synhack(user, C) return + if(istype(C, /obj/item/device/hacktool/engineer)) + return else world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" return @@ -690,12 +692,18 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. synhack(mob/user as mob, obj/item/device/hacktool/I) if (src.synHacking==0) + var/multiplier = 1 + if(istype(C, /obj/item/device/hacktool/engineer)) + if(!src.locked) + user << "The door bolts are already up!" + return + multiplier++ src.synHacking=1 I.in_use = 1 user << "You begin hacking..." - spawn(20) + spawn(20*multiplier) user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." - sleep(25) + sleep(25*multiplier) if (src.canSynControl()) user << "Hack cancelled, control already possible." src.synHacking=0 @@ -707,15 +715,15 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. I.in_use = 0 return user << "Connection established." - sleep(10) + sleep(10*multiplier) user << "Attempting to hack into airlock. This may take some time." - sleep(50) + sleep(50*multiplier) // Alerting the AIs var/list/cameras = list() for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area cameras += C - var/alertoption = prob(alert_probability) // Chance of warning AI, based on doortype's probability + var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability if(alertoption) if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) alertoption = 3 @@ -745,7 +753,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. I.in_use = 0 return user << "Upload access confirmed. Loading control program into airlock software." - sleep(35) + sleep(35*multiplier) if (!src.canSynHack(I)) user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." src.synHacking=0 @@ -757,8 +765,1499 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. I.in_use = 0 return user << "Transfer complete. Forcing airlock to execute program." - sleep(25) + sleep(25*multiplier) //disable blocked control + if(istype(C, /obj/item/device/hacktool/engineer)) + user << "Raising door bolts..." + src.locked = 0 + update_icon() + return + src.synDoorHacked = 1 + user << "Bingo! We're in. Airlock control panel coming right up." + sleep(5) + //bring up airlock dialog + src.synHacking = 0 + I.in_use = 0 + src.attack_ai(user, I) + + + canAIControl() + return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); + + + canAIHack() + return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); + + + canSynControl() + return (src.synDoorHacked && (!src.isAllPowerCut())); + + + canSynHack(obj/item/device/hacktool/H) + return (in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()); + + + +/* +About the new airlock wires panel: +* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. +* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) +* two wires for power. 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). 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 \red open, but bolts-raising will not work. Cutting these wires may electrocute the user. +* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. +* 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). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. +* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. +* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). 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. +* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) +*/ + + pulse(var/wireColor) + //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function + var/wireIndex = airlockWireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + + cut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + + mend(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 + + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & airlockWireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + else + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 + + isElectrified() + return (src.secondsElectrified != 0); + + isWireColorCut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) + + isWireCut(var/wireIndex) + var/wireFlag = airlockIndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + arePowerSystemsOn() + return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) + + isAllPowerCut() + return ((src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) && (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + + regainMainPower() + if (src.secondsMainPowerLost > 0) + src.secondsMainPowerLost = 0 + + loseMainPower() + if (src.secondsMainPowerLost <= 0) + src.secondsMainPowerLost = 60 + if (src.secondsBackupPowerLost < 10) + src.secondsBackupPowerLost = 10 + if (!src.spawnPowerRestoreRunning) + src.spawnPowerRestoreRunning = 1 + spawn(0) + var/cont = 1 + while (cont) + sleep(10) + cont = 0 + if (src.secondsMainPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.secondsMainPowerLost -= 1 + src.updateDialog() + cont = 1 + + if (src.secondsBackupPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.secondsBackupPowerLost -= 1 + src.updateDialog() + cont = 1 + src.spawnPowerRestoreRunning = 0 + src.updateDialog() + + loseBackupPower() + if (src.secondsBackupPowerLost < 60) + src.secondsBackupPowerLost = 60 + + regainBackupPower() + if (src.secondsBackupPowerLost > 0) + src.secondsBackupPowerLost = 0 + + // shock user with probability prb (if all connections & power are working) + // returns 1 if shocked, 0 otherwise + // The preceding comment was borrowed from the grille's shock script + shock(mob/user, prb) + if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock + return 0 + if(!prob(prb)) + return 0 //you lucked out, no shock for you + if(istype(usr.equipped(),/obj/item/weapon/shard)) + return 0 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if (electrocute_mob(user, get_area(src), src)) + return 1 + else + return 0 + + prison_open() + src.locked = 0 + src.open() + src.locked = 1 + return + + + +/obj/machinery/door/airlock/Topic(href, href_list) + ..() + if (usr.stat || usr.restrained() ) + return + if (href_list["close"]) + usr << browse(null, "window=airlock") + if (usr.machine==src) + usr.machine = null + return + if(in_range(src, usr) && istype(src.loc, /turf) && p_open) + usr.machine = src + if (href_list["wires"]) + var/t1 = text2num(href_list["wires"]) + if (!(istype(usr.equipped(), /obj/item/weapon/wirecutters) || istype(usr.equipped(),/obj/item/weapon/shard))) + usr << "You need wirecutters!" + return + if (src.isWireColorCut(t1) && istype(usr.equipped(), /obj/item/weapon/wirecutters)) + src.mend(t1) + else + src.cut(t1) + else if (href_list["pulse"]) + var/t1 = text2num(href_list["pulse"]) + if (!istype(usr.equipped(), /obj/item/device/multitool)) + usr << "You need a multitool!" + return + if (src.isWireColorCut(t1)) + usr << "You can't pulse a cut wire." + return + else + src.pulse(t1) + else if(href_list["signaler"]) + var/wirenum = text2num(href_list["signaler"]) + if(!istype(usr.equipped(), /obj/item/device/assembly/signaler)) + usr << "You need a signaller!" + return + if(src.isWireColorCut(wirenum)) + usr << "You can't attach a signaller to a cut wire." + return + var/obj/item/device/assembly/signaler/R = usr.equipped() + if(R.secured) + usr << "This radio can't be attached!" + return + var/mob/M = usr + M.drop_item() + R.loc = src + R.airlock_wire = wirenum + src.signalers[wirenum] = R + else if(href_list["remove-signaler"]) + var/wirenum = text2num(href_list["remove-signaler"]) + if(!(src.signalers[wirenum])) + usr << "There's no signaller attached to that wire!" + return + var/obj/item/device/assembly/signaler/R = src.signalers[wirenum] + R.loc = usr.loc + R.airlock_wire = null + src.signalers[wirenum] = null + + src.update_icon() + add_fingerprint(usr) + src.updateUsrDialog() + else //AI or Syndicate using hacktool + if (!src.canAIControl() || (istype(usr.equipped(), /obj/item/device/hacktool/) && (!src.canSynControl() || !in_range(src, usr)))) + usr << "Airlock control connection lost!" + return + //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door + //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door + if (href_list["aiDisable"]) + var/code = text2num(href_list["aiDisable"]) + switch (code) + if (1) + //disable idscan + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + usr << "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways." + else if (src.aiDisabledIdScanner) + usr << "You've already disabled the IdScan feature." + else + src.aiDisabledIdScanner = 1 + if (2) + //disrupt main power + if (src.secondsMainPowerLost == 0) + src.loseMainPower() + else + usr << "Main power is already offline." + if (3) + //disrupt backup power + if (src.secondsBackupPowerLost == 0) + src.loseBackupPower() + else + usr << "Backup power is already offline." + if (4) + //drop door bolts + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + usr << "You can't drop the door bolts - The door bolt dropping wire has been cut." + else if (src.locked!=1) + src.locked = 1 + update_icon() + if (5) + //un-electrify door + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("Can't un-electrify the airlock - The electrification wire is cut.
\n") + else if (src.secondsElectrified==-1) + src.secondsElectrified = 0 + else if (src.secondsElectrified>0) + src.secondsElectrified = 0 + if (7) + //close door + if (src.welded) + usr << text("The airlock has been welded shut!
\n") + else if (src.locked) + usr << text("The door bolts are down!
\n") + else if (!src.density) + close() + else + usr << text("The airlock is already closed.
\n") + if (8) + if(!src.forcecrush) + usr << text("Door extra force not enabled!
\n") + else + src.forcecrush = 0 + if (9) + if(!src.safetylight) + usr << text("Bolt indication light not enabled!
\n") + else + src.safetylight = 0 + if (10) + if(!src.holdopen) + usr << text("Door Behavior already set to: Wait for clearance to close
\n") + else + src.holdopen = 0 + + else if (href_list["aiEnable"]) + var/code = text2num(href_list["aiEnable"]) + switch (code) + if (1) + //enable idscan + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + usr << "You can't enable IdScan - The IdScan wire has been cut." + else if (src.aiDisabledIdScanner) + src.aiDisabledIdScanner = 0 + else + usr << "The IdScan feature is not disabled." + if (4) + //raise door bolts + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + usr << text("The door bolt drop wire is cut - you can't raise the door bolts.
\n") + else if (!src.locked) + usr << text("The door bolts are already up.
\n") + else + if (src.arePowerSystemsOn()) + src.locked = 0 + update_icon() + else + usr << text("Cannot raise door bolts due to power failure.
\n") + + if (5) + //electrify door for 30 seconds + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("The electrification wire has been cut.
\n") + else if (src.secondsElectrified==-1) + usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
\n") + else if (src.secondsElectrified!=0) + usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") + else + src.secondsElectrified = 30 + spawn(10) + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + src.updateUsrDialog() + sleep(10) + if (6) + //electrify door indefinitely + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("The electrification wire has been cut.
\n") + else if (src.secondsElectrified==-1) + usr << text("The door is already indefinitely electrified.
\n") + else if (src.secondsElectrified!=0) + usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") + else + src.secondsElectrified = -1 + if (7) + //open door + if (src.welded) + usr << text("The airlock has been welded shut!
\n") + else if (src.locked) + usr << text("The door bolts are down!
\n") + else if (src.density) + open() + // close() + else + usr << text("The airlock is already opened.
\n") + if (8) + if(src.forcecrush) + usr << text("Door extra force already enabled!
\n") + else + src.forcecrush = 1 + if (9) + if(src.safetylight) + usr << text("Bolt indication light already enabled!
\n") + else + src.safetylight = 1 + if (10) + if(src.holdopen) + usr << text("Door Behavior already set to: Automatically close
\n") + else + src.holdopen = 1 + + src.update_icon() + src.updateUsrDialog() + if((istype(usr.equipped(), /obj/item/device/hacktool))) + return attack_ai(usr, usr.equipped()) + return + + + + +/obj/machinery/door/airlock/secure + name = "Secure Airlock" + desc = "Good lord, at least they left out the overcomplicated death traps. Looks to be a layer of armor plate you might be able to remove with a wrench." + icon = 'Doorhatchele.dmi' + + wires = 65535 + wirenum = 16 + alert_probability = 20 + holdopen = 0 + signalers = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + var + list/WireColorToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + is_detached = 0 + + + + New() + ..() + //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). + var/flagIndex = 1 + for (var/flag=1, flag<65536, flag+=flag) + var/valid = 0 + while (!valid) + var/colorIndex = rand(1, 16) + if (WireColorToFlag[colorIndex] == 0) + valid = 1 + WireColorToFlag[colorIndex] = flag + IndexToFlag[flagIndex] = flag + IndexToWireColor[flagIndex] = colorIndex + WireColorToIndex[colorIndex] = flagIndex + flagIndex+=1 + return + + + isWireColorCut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) + + isWireCut(var/wireIndex) + var/wireFlag = IndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + pulse(var/wireColor) + var/wireIndex = WireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + cut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + mend(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 + + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & WireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + else + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if(!src.is_detached) + if (!istype(usr, /mob/living/silicon))#define AIRLOCK_WIRE_IDSCAN 1 +#define AIRLOCK_WIRE_MAIN_POWER1 2 +#define AIRLOCK_WIRE_MAIN_POWER2 3 +#define AIRLOCK_WIRE_DOOR_BOLTS 4 +#define AIRLOCK_WIRE_BACKUP_POWER1 5 +#define AIRLOCK_WIRE_BACKUP_POWER2 6 +#define AIRLOCK_WIRE_OPEN_DOOR 7 +#define AIRLOCK_WIRE_AI_CONTROL 8 +#define AIRLOCK_WIRE_ELECTRIFY 9 +#define AIRLOCK_WIRE_CRUSH 10 +#define AIRLOCK_WIRE_LIGHT 11 +#define AIRLOCK_WIRE_HOLDOPEN 12 +#define AIRLOCK_WIRE_FAKEBOLT1 13 +#define AIRLOCK_WIRE_FAKEBOLT2 14 +#define AIRLOCK_WIRE_ALERTAI 15 +#define AIRLOCK_WIRE_DOOR_BOLTS_2 16 +//#define AIRLOCK_WIRE_FINGERPRINT 17 + +/* + New methods: + pulse - sends a pulse into a wire for hacking purposes + cut - cuts a wire and makes any necessary state changes + mend - mends a wire and makes any necessary state changes + isWireColorCut - returns 1 if that color wire is cut, or 0 if not + isWireCut - returns 1 if that wire (e.g. AIRLOCK_WIRE_DOOR_BOLTS) is cut, or 0 if not + canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) + canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. + arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) + requiresIDs - 1 if the airlock is requiring IDs, 0 if not + isAllPowerCut - 1 if the main and backup power both have cut wires. + regainMainPower - handles the effect of main power coming back on. + loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. + loseBackupPower - handles the effect of backup power going offline. + regainBackupPower - handles the effect of main power coming back on. + shock - has a chance of electrocuting its target. +*/ + +//This generates the randomized airlock wire assignments for the game. +/proc/RandomAirlockWires() + //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). + var/list/wires = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockIndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockIndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockWireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + var/flagIndex = 1 + for (var/flag=1, flag<4096, flag+=flag) + var/valid = 0 + while (!valid) + var/colorIndex = rand(1, 12) + if (wires[colorIndex] == 0) + valid = 1 + wires[colorIndex] = flag + airlockIndexToFlag[flagIndex] = flag + airlockIndexToWireColor[flagIndex] = colorIndex + airlockWireColorToIndex[colorIndex] = flagIndex + flagIndex+=1 + return wires + +/* Example: +Airlock wires color -> flag are { 64, 128, 256, 2, 16, 4, 8, 32, 1 }. +Airlock wires color -> index are { 7, 8, 9, 2, 5, 3, 4, 6, 1 }. +Airlock index -> flag are { 1, 2, 4, 8, 16, 32, 64, 128, 256 }. +Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. +*/ + +/obj/machinery/door/airlock + name = "Airlock" + icon = 'doorint.dmi' + icon_state = "door_closed" + + var + aiControlDisabled = 0 //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. + synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no + synHacking = 0 // Is hack in process y/n? + secondsMainPowerLost = 0 //The number of seconds until power is restored. + secondsBackupPowerLost = 0 //The number of seconds until power is restored. + spawnPowerRestoreRunning = 0 + welded = null + locked = 0 + wires = 4095 + aiDisabledIdScanner = 0 + aiHacking = 0 + obj/machinery/door/airlock/closeOther = null + closeOtherId = null + list/signalers[12] + lockdownbyai = 0 + doortype = 0 + justzap = 0 + safetylight = 1 + obj/item/weapon/airlock_electronics/electronics = null + alert_probability = 3 + list/wire_index = list( + "Orange" = 1, + "Dark red" = 2, + "White" = 3, + "Yellow" = 4, + "Red" = 5, + "Blue" = 6, + "Green" = 7, + "Grey" = 8, + "Black" = 9, + "Pink" = 10, + "Brown" = 11, + "Maroon" = 12, + "Aqua" = 13, + "Turgoise" = 14, + "Purple" = 15, + "Rainbow" = 16, + "Atomic Tangerine" = 17, + "Neon Green" = 18, + "Cotton Candy" = 19, + "Plum" = 20, + "Shamrock" = 21, + "Indigo" = 22 + ) + wirenum = 12 + holdopen = 1 + autoclose = 1 + secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. + + + command + name = "Airlock" + icon = 'Doorcom.dmi' + doortype = 1 + holdopen = 0 + + + security + name = "Airlock" + icon = 'Doorsec.dmi' + doortype = 2 + + + engineering + name = "Airlock" + icon = 'Dooreng.dmi' + doortype = 3 + + + medical + name = "Airlock" + icon = 'Doormed.dmi' + doortype = 4 + + + maintenance + name = "Maintenance Access" + icon = 'Doormaint.dmi' + doortype = 5 + + external + name = "External Airlock" + icon = 'Doorext.dmi' + doortype = 6 + + + glass + name = "Glass Airlock" + icon = 'Doorglass.dmi' + opacity = 0 + doortype = 7 + glass = 1 + + + glass_command + name = "Maintenance Hatch" + icon = 'Doorcomglass.dmi' + opacity = 0 + doortype = 14 + glass = 1 + + + glass_engineering + name = "Maintenance Hatch" + icon = 'Doorengglass.dmi' + opacity = 0 + doortype = 15 + glass = 1 + + + glass_security + name = "Maintenance Hatch" + icon = 'Doorsecglass.dmi' + opacity = 0 + doortype = 16 + glass = 1 + + + glass_medical + name = "Maintenance Hatch" + icon = 'doormedglass.dmi' + opacity = 0 + doortype = 17 + glass = 1 + + + centcom + name = "Airlock" + icon = 'Doorele.dmi' + opacity = 0 + doortype = 8 + + + vault + name = "Vault" + icon = 'vault.dmi' + opacity = 1 + doortype = 9 + + + glass_large + name = "Glass Airlock" + icon = 'Door2x1glassfull.dmi' + opacity = 0 + doortype = 10 + glass = 1 + + + freezer + name = "Freezer Airlock" + icon = 'Doorfreezer.dmi' + opacity = 1 + doortype = 11 + + + hatch + name = "Airtight Hatch" + icon = 'Doorhatchele.dmi' + opacity = 1 + doortype = 12 + + + maintenance_hatch + name = "Maintenance Hatch" + icon = 'Doorhatchmaint2.dmi' + opacity = 1 + doortype = 13 + + + New() + ..() + if (src.closeOtherId != null) + spawn (5) + for (var/obj/machinery/door/airlock/A in machines) + if (A.closeOtherId == src.closeOtherId && A != src) + src.closeOther = A + break + + + open() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + return 0 + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) + src.closeOther.close() + return ..() + + + close() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + return + ..() + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) + if(killthis) + killthis.ex_act(2)//Smashin windows + return + + + bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if (!src.justzap) + if(src.shock(user, 100)) + src.justzap = 1 + spawn (10) + src.justzap = 0 + return + else /*if (src.justzap)*/ + return + else if(user.hallucination > 50 && prob(10) && src.operating == 0) + user << "\red You feel a powerful shock course through your body!" + user.halloss += 10 + user.stunned += 10 + return + ..(user) + + + update_icon() + if(overlays) overlays = null + if(density) + if(locked && safetylight) + icon_state = "door_locked" + else + icon_state = "door_closed" + if(p_open || welded) + overlays = list() + if(p_open) + overlays += image(icon, "panel_open") + if(welded) + overlays += image(icon, "welded") + else + icon_state = "door_open" + return + + + animate(animation) + switch(animation) + if("opening") + if(overlays) overlays = null + if(p_open) + icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking + else + flick("door_opening", src) + if("closing") + if(overlays) overlays = null + if(p_open) + flick("o_door_closing", src) + else + flick("door_closing", src) + if("spark") + flick("door_spark", src) + if("deny") + flick("door_deny", src) + return + + requiresID() + return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/weapon/screwdriver)) + src.p_open = !( src.p_open ) + src.update_icon() + else if (istype(C, /obj/item/weapon/wirecutters)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/multitool)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/device/assembly/signaler)) + return src.attack_hand(user) + else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE + var/obj/item/weapon/pai_cable/cable = C + cable.plugin(src, user) + else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) + var/beingcrowbarred = null + if(istype(C, /obj/item/weapon/crowbar) ) + beingcrowbarred = 1 //derp, Agouri + else + beingcrowbarred = 0 + if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) + playsound(src.loc, 'Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") + if(do_after(user,40)) + user << "\blue You removed the airlock electronics!" + switch(src.doortype) + if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) + if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) + if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) + if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) + if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) + if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) + if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) + if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) + var/obj/item/weapon/airlock_electronics/ae + if (!electronics) + ae = new/obj/item/weapon/airlock_electronics( src.loc ) + ae.conf_access = src.req_access + else + ae = electronics + electronics = null + ae.loc = src.loc + + del(src) + return + else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) + user << "\blue The airlock's motors resist your efforts to pry it open." + else if (src.locked) + user << "\blue The airlock's bolts prevent it from being pried open." + if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) + + if(beingcrowbarred == 0) //being fireaxe'd + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + user << "\red You need to be wielding the Fire axe to do that." + return + else + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + + else + if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) + if(beingcrowbarred == 0) + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("closing") + + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + else + user << "\red You need to be wielding the Fire axe to do that." + else + spawn( 0 ) + src.operating = 1 + animate("closing") + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + + else + ..() + return + + + attack_paw(mob/user as mob) + return src.attack_hand(user) + + + attack_hand(mob/user as mob) + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 100)) + return + + if (ishuman(user) && prob(40) && src.density) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + playsound(src.loc, 'bang.ogg', 25, 1) + if(!istype(H.head, /obj/item/clothing/head/helmet)) + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock." + var/datum/organ/external/affecting = H.get_organ("head") + affecting.take_damage(10, 0) + H.Stun(8) + H.Weaken(5) + H.UpdateDamageIcon() + else + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." + return + + if (src.p_open) + user.machine = src + var/t1 = text("Access Panel
\n") + + //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) + t1 += getAirlockWires() + + t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) + + t1 += text("

Close

\n", src) + + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + else + ..(user) + return + +//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 engage engineer smasher, 9 enable bolt indicator, 10 wait for clearance +//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 disable engineer smasher, 9 disable bolt indicator, 10 autoclose + //This has been converted to be called by either the AI or a mob with a hacktool, permitting either to directly operate the airlock + attack_ai(mob/user as mob, obj/item/device/hacktool/C) + if(isAI(user)) + if (!src.canAIControl()) + if (src.canAIHack()) + src.hack(user) + return + else if(user) + if(!C) + return + if(C.in_use) + user << "We are already hacking another airlock." + return + if (!src.canSynControl() && src.canSynHack(C)) + src.synhack(user, C) + return + if(istype(C, /obj/item/device/hacktool/engineer)) + return + else + world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" + return + + + //Separate interface for the AI. + user.machine = src + var/t1 = text("Airlock Control
\n") + if (src.secondsMainPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) + else + t1 += text("Main power is offline indefinitely.
\n") + else + t1 += text("Main power is online.") + + if (src.secondsBackupPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) + else + t1 += text("Backup power is offline indefinitely.
\n") + else if (src.secondsMainPowerLost > 0) + t1 += text("Backup power is online.") + else + t1 += text("Backup power is offline, but will turn on if main power fails.") + t1 += "
\n" + + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + t1 += text("IdScan wire is cut.
\n") + else if (src.aiDisabledIdScanner) + t1 += text("IdScan disabled. Enable?
\n", src) + else + t1 += text("IdScan enabled. Disable?
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) + t1 += text("Main Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main Power Output wire is cut.
\n") + if (src.secondsMainPowerLost == 0) + t1 += text("Temporarily disrupt main power?.
\n", src) + if (src.secondsBackupPowerLost == 0) + t1 += text("Temporarily disrupt backup power?.
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) + t1 += text("Backup Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup Power Output wire is cut.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) + t1 += text("Airlock extra force wire is cut.
\n") + else if(!src.forcecrush) + t1 += text("Airlock extra force disabled Enable it?
\n") + else + t1 += text("Airlock extra force enabled Disable it?
\n") + + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + t1 += text("Door bolt drop wire is cut.
\n") + else if (!src.locked) + t1 += text("Door bolts are up. Drop them?
\n", src) + else + t1 += text("Door bolts are down.") + if (src.arePowerSystemsOn()) + t1 += text(" Raise?
\n", src) + else + t1 += text(" Cannot raise door bolts due to power failure.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + t1 += text("Electrification wire is cut.
\n") + if (src.secondsElectrified==-1) + t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) + else if (src.secondsElectrified>0) + t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) + else + t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) + + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + t1 += "Bolt indication light wire is cut.
\n" + else if(!src.safetylight) + t1 += text("Bolt Indication light is disabled Enable it?
\n") + else + t1 += text("Bolt Indication light is enabled Disable it?
\n") + + if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) + t1 += "Behavior Control light wire is cut.
\n" + else if(!src.holdopen) + t1 += text("Door behavior is set to: Automatically close Toggle?
\n") + else + t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") + + if (src.welded) + t1 += text("Door appears to have been welded shut.
\n") + else if (!src.locked) + if (src.density) + t1 += text("Open door
\n", src) + else + t1 += text("Close door
\n", src) + + t1 += text("

Close

\n", src) + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + + proc + hack(mob/user as mob) + if (src.aiHacking==0) + src.aiHacking=1 + spawn(20) + //TODO: Make this take a minute + user << "Airlock AI control has been blocked. Beginning fault-detection." + sleep(50) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Fault confirmed: airlock control wire disabled or cut." + sleep(20) + user << "Attempting to hack into airlock. This may take some time." + sleep(200) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(170) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(50) + //disable blocked control + src.aiControlDisabled = 2 + user << "Receiving control information from airlock." + sleep(10) + //bring up airlock dialog + src.aiHacking = 0 + src.attack_ai(user) + + + synhack(mob/user as mob, obj/item/device/hacktool/I) + if (src.synHacking==0) + var/multiplier = 1 + if(istype(C, /obj/item/device/hacktool/engineer)) + if(!src.locked) + user << "The door bolts are already up!" + return + multiplier++ + src.synHacking=1 + I.in_use = 1 + user << "You begin hacking..." + spawn(20*multiplier) + user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." + sleep(25*multiplier) + if (src.canSynControl()) + user << "Hack cancelled, control already possible." + src.synHacking=0 + I.in_use = 0 + return + else if (!src.canSynHack(I)) + user << "\red Connection lost. Stand still and stay near the airlock!" + src.synHacking=0 + I.in_use = 0 + return + user << "Connection established." + sleep(10*multiplier) + user << "Attempting to hack into airlock. This may take some time." + sleep(50*multiplier) + + // Alerting the AIs + var/list/cameras = list() + for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area + cameras += C + var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability + if(alertoption) + if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) + alertoption = 3 + else if (prob(18)) //18% chance of sending the AI just the area + alertoption = 2 + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + switch(alertoption) + if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) + if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + switch(alertoption) + if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") + // ...And done + + if (!src.canSynHack(I)) + user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Local override already in place, hack aborted." + src.synHacking=0 + I.in_use = 0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(35*multiplier) + if (!src.canSynHack(I)) + user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Upload access aborted, local override already in place." + src.synHacking=0 + I.in_use = 0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(25*multiplier) + //disable blocked control + if(istype(C, /obj/item/device/hacktool/engineer)) + user << "Raising door bolts..." + src.locked = 0 + update_icon() + return src.synDoorHacked = 1 user << "Bingo! We're in. Airlock control panel coming right up." sleep(5) @@ -1476,6 +2975,1554 @@ About the new airlock wires panel: if(src.shock(user, 75)) return + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start to remove the armor plate..." + if(do_after(user,30)) + user << "Armor plates removed" + src.is_detached = 1 + else + if (istype(C, /obj/item/weapon/wrench)) + user << "You start to reattach the armor plate..." + if(do_after(user,30)) + user << "Armor plates attached" + src.is_detached = 0 + else + return ..(C, user)#define AIRLOCK_WIRE_IDSCAN 1 +#define AIRLOCK_WIRE_MAIN_POWER1 2 +#define AIRLOCK_WIRE_MAIN_POWER2 3 +#define AIRLOCK_WIRE_DOOR_BOLTS 4 +#define AIRLOCK_WIRE_BACKUP_POWER1 5 +#define AIRLOCK_WIRE_BACKUP_POWER2 6 +#define AIRLOCK_WIRE_OPEN_DOOR 7 +#define AIRLOCK_WIRE_AI_CONTROL 8 +#define AIRLOCK_WIRE_ELECTRIFY 9 +#define AIRLOCK_WIRE_CRUSH 10 +#define AIRLOCK_WIRE_LIGHT 11 +#define AIRLOCK_WIRE_HOLDOPEN 12 +#define AIRLOCK_WIRE_FAKEBOLT1 13 +#define AIRLOCK_WIRE_FAKEBOLT2 14 +#define AIRLOCK_WIRE_ALERTAI 15 +#define AIRLOCK_WIRE_DOOR_BOLTS_2 16 +//#define AIRLOCK_WIRE_FINGERPRINT 17 + +/* + New methods: + pulse - sends a pulse into a wire for hacking purposes + cut - cuts a wire and makes any necessary state changes + mend - mends a wire and makes any necessary state changes + isWireColorCut - returns 1 if that color wire is cut, or 0 if not + isWireCut - returns 1 if that wire (e.g. AIRLOCK_WIRE_DOOR_BOLTS) is cut, or 0 if not + canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) + canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. + arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) + requiresIDs - 1 if the airlock is requiring IDs, 0 if not + isAllPowerCut - 1 if the main and backup power both have cut wires. + regainMainPower - handles the effect of main power coming back on. + loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. + loseBackupPower - handles the effect of backup power going offline. + regainBackupPower - handles the effect of main power coming back on. + shock - has a chance of electrocuting its target. +*/ + +//This generates the randomized airlock wire assignments for the game. +/proc/RandomAirlockWires() + //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). + var/list/wires = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockIndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockIndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + airlockWireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + var/flagIndex = 1 + for (var/flag=1, flag<4096, flag+=flag) + var/valid = 0 + while (!valid) + var/colorIndex = rand(1, 12) + if (wires[colorIndex] == 0) + valid = 1 + wires[colorIndex] = flag + airlockIndexToFlag[flagIndex] = flag + airlockIndexToWireColor[flagIndex] = colorIndex + airlockWireColorToIndex[colorIndex] = flagIndex + flagIndex+=1 + return wires + +/* Example: +Airlock wires color -> flag are { 64, 128, 256, 2, 16, 4, 8, 32, 1 }. +Airlock wires color -> index are { 7, 8, 9, 2, 5, 3, 4, 6, 1 }. +Airlock index -> flag are { 1, 2, 4, 8, 16, 32, 64, 128, 256 }. +Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. +*/ + +/obj/machinery/door/airlock + name = "Airlock" + icon = 'doorint.dmi' + icon_state = "door_closed" + + var + aiControlDisabled = 0 //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. + synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no + synHacking = 0 // Is hack in process y/n? + secondsMainPowerLost = 0 //The number of seconds until power is restored. + secondsBackupPowerLost = 0 //The number of seconds until power is restored. + spawnPowerRestoreRunning = 0 + welded = null + locked = 0 + wires = 4095 + aiDisabledIdScanner = 0 + aiHacking = 0 + obj/machinery/door/airlock/closeOther = null + closeOtherId = null + list/signalers[12] + lockdownbyai = 0 + doortype = 0 + justzap = 0 + safetylight = 1 + obj/item/weapon/airlock_electronics/electronics = null + alert_probability = 3 + list/wire_index = list( + "Orange" = 1, + "Dark red" = 2, + "White" = 3, + "Yellow" = 4, + "Red" = 5, + "Blue" = 6, + "Green" = 7, + "Grey" = 8, + "Black" = 9, + "Pink" = 10, + "Brown" = 11, + "Maroon" = 12, + "Aqua" = 13, + "Turgoise" = 14, + "Purple" = 15, + "Rainbow" = 16, + "Atomic Tangerine" = 17, + "Neon Green" = 18, + "Cotton Candy" = 19, + "Plum" = 20, + "Shamrock" = 21, + "Indigo" = 22 + ) + wirenum = 12 + holdopen = 1 + autoclose = 1 + secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. + + + command + name = "Airlock" + icon = 'Doorcom.dmi' + doortype = 1 + holdopen = 0 + + + security + name = "Airlock" + icon = 'Doorsec.dmi' + doortype = 2 + + + engineering + name = "Airlock" + icon = 'Dooreng.dmi' + doortype = 3 + + + medical + name = "Airlock" + icon = 'Doormed.dmi' + doortype = 4 + + + maintenance + name = "Maintenance Access" + icon = 'Doormaint.dmi' + doortype = 5 + + external + name = "External Airlock" + icon = 'Doorext.dmi' + doortype = 6 + + + glass + name = "Glass Airlock" + icon = 'Doorglass.dmi' + opacity = 0 + doortype = 7 + glass = 1 + + + glass_command + name = "Maintenance Hatch" + icon = 'Doorcomglass.dmi' + opacity = 0 + doortype = 14 + glass = 1 + + + glass_engineering + name = "Maintenance Hatch" + icon = 'Doorengglass.dmi' + opacity = 0 + doortype = 15 + glass = 1 + + + glass_security + name = "Maintenance Hatch" + icon = 'Doorsecglass.dmi' + opacity = 0 + doortype = 16 + glass = 1 + + + glass_medical + name = "Maintenance Hatch" + icon = 'doormedglass.dmi' + opacity = 0 + doortype = 17 + glass = 1 + + + centcom + name = "Airlock" + icon = 'Doorele.dmi' + opacity = 0 + doortype = 8 + + + vault + name = "Vault" + icon = 'vault.dmi' + opacity = 1 + doortype = 9 + + + glass_large + name = "Glass Airlock" + icon = 'Door2x1glassfull.dmi' + opacity = 0 + doortype = 10 + glass = 1 + + + freezer + name = "Freezer Airlock" + icon = 'Doorfreezer.dmi' + opacity = 1 + doortype = 11 + + + hatch + name = "Airtight Hatch" + icon = 'Doorhatchele.dmi' + opacity = 1 + doortype = 12 + + + maintenance_hatch + name = "Maintenance Hatch" + icon = 'Doorhatchmaint2.dmi' + opacity = 1 + doortype = 13 + + + New() + ..() + if (src.closeOtherId != null) + spawn (5) + for (var/obj/machinery/door/airlock/A in machines) + if (A.closeOtherId == src.closeOtherId && A != src) + src.closeOther = A + break + + + open() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + return 0 + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) + src.closeOther.close() + return ..() + + + close() + if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + return + ..() + use_power(50) + playsound(src.loc, 'airlock.ogg', 30, 1) + var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) + if(killthis) + killthis.ex_act(2)//Smashin windows + return + + + bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if (!src.justzap) + if(src.shock(user, 100)) + src.justzap = 1 + spawn (10) + src.justzap = 0 + return + else /*if (src.justzap)*/ + return + else if(user.hallucination > 50 && prob(10) && src.operating == 0) + user << "\red You feel a powerful shock course through your body!" + user.halloss += 10 + user.stunned += 10 + return + ..(user) + + + update_icon() + if(overlays) overlays = null + if(density) + if(locked && safetylight) + icon_state = "door_locked" + else + icon_state = "door_closed" + if(p_open || welded) + overlays = list() + if(p_open) + overlays += image(icon, "panel_open") + if(welded) + overlays += image(icon, "welded") + else + icon_state = "door_open" + return + + + animate(animation) + switch(animation) + if("opening") + if(overlays) overlays = null + if(p_open) + icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking + else + flick("door_opening", src) + if("closing") + if(overlays) overlays = null + if(p_open) + flick("o_door_closing", src) + else + flick("door_closing", src) + if("spark") + flick("door_spark", src) + if("deny") + flick("door_deny", src) + return + + requiresID() + return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/weapon/screwdriver)) + src.p_open = !( src.p_open ) + src.update_icon() + else if (istype(C, /obj/item/weapon/wirecutters)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/multitool)) + return src.attack_hand(user) + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/device/assembly/signaler)) + return src.attack_hand(user) + else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE + var/obj/item/weapon/pai_cable/cable = C + cable.plugin(src, user) + else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) + var/beingcrowbarred = null + if(istype(C, /obj/item/weapon/crowbar) ) + beingcrowbarred = 1 //derp, Agouri + else + beingcrowbarred = 0 + if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) + playsound(src.loc, 'Crowbar.ogg', 100, 1) + user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") + if(do_after(user,40)) + user << "\blue You removed the airlock electronics!" + switch(src.doortype) + if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) + if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) + if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) + if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) + if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) + if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) + if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) + if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) + var/obj/item/weapon/airlock_electronics/ae + if (!electronics) + ae = new/obj/item/weapon/airlock_electronics( src.loc ) + ae.conf_access = src.req_access + else + ae = electronics + electronics = null + ae.loc = src.loc + + del(src) + return + else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) + user << "\blue The airlock's motors resist your efforts to pry it open." + else if (src.locked) + user << "\blue The airlock's bolts prevent it from being pried open." + if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) + + if(beingcrowbarred == 0) //being fireaxe'd + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + user << "\red You need to be wielding the Fire axe to do that." + return + else + spawn( 0 ) + src.operating = 1 + animate("opening") + + sleep(15) + + layer = 2.7 + src.density = 0 + update_icon() + + if (!istype(src, /obj/machinery/door/airlock/glass)) + src.sd_SetOpacity(0) + src.operating = 0 + return + + else + if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) + if(beingcrowbarred == 0) + var/obj/item/weapon/fireaxe/F = C + if(F.wielded == 1) + spawn( 0 ) + src.operating = 1 + animate("closing") + + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + else + user << "\red You need to be wielding the Fire axe to do that." + else + spawn( 0 ) + src.operating = 1 + animate("closing") + layer = 3.1 + src.density = 1 + sleep(15) + update_icon() + + if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) + src.sd_SetOpacity(1) + src.operating = 0 + + else + ..() + return + + + attack_paw(mob/user as mob) + return src.attack_hand(user) + + + attack_hand(mob/user as mob) + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 100)) + return + + if (ishuman(user) && prob(40) && src.density) + var/mob/living/carbon/human/H = user + if(H.getBrainLoss() >= 60) + playsound(src.loc, 'bang.ogg', 25, 1) + if(!istype(H.head, /obj/item/clothing/head/helmet)) + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock." + var/datum/organ/external/affecting = H.get_organ("head") + affecting.take_damage(10, 0) + H.Stun(8) + H.Weaken(5) + H.UpdateDamageIcon() + else + for(var/mob/M in viewers(src, null)) + M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." + return + + if (src.p_open) + user.machine = src + var/t1 = text("Access Panel
\n") + + //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) + t1 += getAirlockWires() + + t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) + + t1 += text("

Close

\n", src) + + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + else + ..(user) + return + +//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 engage engineer smasher, 9 enable bolt indicator, 10 wait for clearance +//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 disable engineer smasher, 9 disable bolt indicator, 10 autoclose + //This has been converted to be called by either the AI or a mob with a hacktool, permitting either to directly operate the airlock + attack_ai(mob/user as mob, obj/item/device/hacktool/C) + if(isAI(user)) + if (!src.canAIControl()) + if (src.canAIHack()) + src.hack(user) + return + else if(user) + if(!C) + return + if(C.in_use) + user << "We are already hacking another airlock." + return + if (!src.canSynControl() && src.canSynHack(C)) + src.synhack(user, C) + return + if(istype(C, /obj/item/device/hacktool/engineer)) + return + else + world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" + return + + + //Separate interface for the AI. + user.machine = src + var/t1 = text("Airlock Control
\n") + if (src.secondsMainPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) + else + t1 += text("Main power is offline indefinitely.
\n") + else + t1 += text("Main power is online.") + + if (src.secondsBackupPowerLost > 0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) + else + t1 += text("Backup power is offline indefinitely.
\n") + else if (src.secondsMainPowerLost > 0) + t1 += text("Backup power is online.") + else + t1 += text("Backup power is offline, but will turn on if main power fails.") + t1 += "
\n" + + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + t1 += text("IdScan wire is cut.
\n") + else if (src.aiDisabledIdScanner) + t1 += text("IdScan disabled. Enable?
\n", src) + else + t1 += text("IdScan enabled. Disable?
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) + t1 += text("Main Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) + t1 += text("Main Power Output wire is cut.
\n") + if (src.secondsMainPowerLost == 0) + t1 += text("Temporarily disrupt main power?.
\n", src) + if (src.secondsBackupPowerLost == 0) + t1 += text("Temporarily disrupt backup power?.
\n", src) + + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) + t1 += text("Backup Power Input wire is cut.
\n") + if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) + t1 += text("Backup Power Output wire is cut.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) + t1 += text("Airlock extra force wire is cut.
\n") + else if(!src.forcecrush) + t1 += text("Airlock extra force disabled Enable it?
\n") + else + t1 += text("Airlock extra force enabled Disable it?
\n") + + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + t1 += text("Door bolt drop wire is cut.
\n") + else if (!src.locked) + t1 += text("Door bolts are up. Drop them?
\n", src) + else + t1 += text("Door bolts are down.") + if (src.arePowerSystemsOn()) + t1 += text(" Raise?
\n", src) + else + t1 += text(" Cannot raise door bolts due to power failure.
\n") + + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + t1 += text("Electrification wire is cut.
\n") + if (src.secondsElectrified==-1) + t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) + else if (src.secondsElectrified>0) + t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) + else + t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) + + if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) + t1 += "Bolt indication light wire is cut.
\n" + else if(!src.safetylight) + t1 += text("Bolt Indication light is disabled Enable it?
\n") + else + t1 += text("Bolt Indication light is enabled Disable it?
\n") + + if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) + t1 += "Behavior Control light wire is cut.
\n" + else if(!src.holdopen) + t1 += text("Door behavior is set to: Automatically close Toggle?
\n") + else + t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") + + if (src.welded) + t1 += text("Door appears to have been welded shut.
\n") + else if (!src.locked) + if (src.density) + t1 += text("Open door
\n", src) + else + t1 += text("Close door
\n", src) + + t1 += text("

Close

\n", src) + user << browse(t1, "window=airlock") + onclose(user, "airlock") + + + proc + hack(mob/user as mob) + if (src.aiHacking==0) + src.aiHacking=1 + spawn(20) + //TODO: Make this take a minute + user << "Airlock AI control has been blocked. Beginning fault-detection." + sleep(50) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Fault confirmed: airlock control wire disabled or cut." + sleep(20) + user << "Attempting to hack into airlock. This may take some time." + sleep(200) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(170) + if (src.canAIControl()) + user << "Alert cancelled. Airlock control has been restored without our assistance." + src.aiHacking=0 + return + else if (!src.canAIHack()) + user << "We've lost our connection! Unable to hack airlock." + src.aiHacking=0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(50) + //disable blocked control + src.aiControlDisabled = 2 + user << "Receiving control information from airlock." + sleep(10) + //bring up airlock dialog + src.aiHacking = 0 + src.attack_ai(user) + + + synhack(mob/user as mob, obj/item/device/hacktool/I) + if (src.synHacking==0) + var/multiplier = 1 + if(istype(C, /obj/item/device/hacktool/engineer)) + if(!src.locked) + user << "The door bolts are already up!" + return + multiplier++ + src.synHacking=1 + I.in_use = 1 + user << "You begin hacking..." + spawn(20*multiplier) + user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." + sleep(25*multiplier) + if (src.canSynControl()) + user << "Hack cancelled, control already possible." + src.synHacking=0 + I.in_use = 0 + return + else if (!src.canSynHack(I)) + user << "\red Connection lost. Stand still and stay near the airlock!" + src.synHacking=0 + I.in_use = 0 + return + user << "Connection established." + sleep(10*multiplier) + user << "Attempting to hack into airlock. This may take some time." + sleep(50*multiplier) + + // Alerting the AIs + var/list/cameras = list() + for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area + cameras += C + var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability + if(alertoption) + if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) + alertoption = 3 + else if (prob(18)) //18% chance of sending the AI just the area + alertoption = 2 + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + switch(alertoption) + if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) + if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + switch(alertoption) + if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") + // ...And done + + if (!src.canSynHack(I)) + user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Local override already in place, hack aborted." + src.synHacking=0 + I.in_use = 0 + return + user << "Upload access confirmed. Loading control program into airlock software." + sleep(35*multiplier) + if (!src.canSynHack(I)) + user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." + src.synHacking=0 + I.in_use = 0 + return + else if (src.canSynControl()) + user << "Upload access aborted, local override already in place." + src.synHacking=0 + I.in_use = 0 + return + user << "Transfer complete. Forcing airlock to execute program." + sleep(25*multiplier) + //disable blocked control + if(istype(C, /obj/item/device/hacktool/engineer)) + user << "Raising door bolts..." + src.locked = 0 + update_icon() + return + src.synDoorHacked = 1 + user << "Bingo! We're in. Airlock control panel coming right up." + sleep(5) + //bring up airlock dialog + src.synHacking = 0 + I.in_use = 0 + src.attack_ai(user, I) + + + canAIControl() + return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); + + + canAIHack() + return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); + + + canSynControl() + return (src.synDoorHacked && (!src.isAllPowerCut())); + + + canSynHack(obj/item/device/hacktool/H) + return (in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()); + + + +/* +About the new airlock wires panel: +* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. +* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) +* two wires for power. 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). 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 \red open, but bolts-raising will not work. Cutting these wires may electrocute the user. +* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. +* 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). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. +* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. +* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). 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. +* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) +*/ + + pulse(var/wireColor) + //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function + var/wireIndex = airlockWireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + + cut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + + mend(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 + + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & airlockWireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + else + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 + + isElectrified() + return (src.secondsElectrified != 0); + + isWireColorCut(var/wireColor) + var/wireFlag = airlockWireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) + + isWireCut(var/wireIndex) + var/wireFlag = airlockIndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + arePowerSystemsOn() + return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) + + isAllPowerCut() + return ((src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) && (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + + regainMainPower() + if (src.secondsMainPowerLost > 0) + src.secondsMainPowerLost = 0 + + loseMainPower() + if (src.secondsMainPowerLost <= 0) + src.secondsMainPowerLost = 60 + if (src.secondsBackupPowerLost < 10) + src.secondsBackupPowerLost = 10 + if (!src.spawnPowerRestoreRunning) + src.spawnPowerRestoreRunning = 1 + spawn(0) + var/cont = 1 + while (cont) + sleep(10) + cont = 0 + if (src.secondsMainPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.secondsMainPowerLost -= 1 + src.updateDialog() + cont = 1 + + if (src.secondsBackupPowerLost>0) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.secondsBackupPowerLost -= 1 + src.updateDialog() + cont = 1 + src.spawnPowerRestoreRunning = 0 + src.updateDialog() + + loseBackupPower() + if (src.secondsBackupPowerLost < 60) + src.secondsBackupPowerLost = 60 + + regainBackupPower() + if (src.secondsBackupPowerLost > 0) + src.secondsBackupPowerLost = 0 + + // shock user with probability prb (if all connections & power are working) + // returns 1 if shocked, 0 otherwise + // The preceding comment was borrowed from the grille's shock script + shock(mob/user, prb) + if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock + return 0 + if(!prob(prb)) + return 0 //you lucked out, no shock for you + if(istype(usr.equipped(),/obj/item/weapon/shard)) + return 0 + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() //sparks always. + if (electrocute_mob(user, get_area(src), src)) + return 1 + else + return 0 + + prison_open() + src.locked = 0 + src.open() + src.locked = 1 + return + + + +/obj/machinery/door/airlock/Topic(href, href_list) + ..() + if (usr.stat || usr.restrained() ) + return + if (href_list["close"]) + usr << browse(null, "window=airlock") + if (usr.machine==src) + usr.machine = null + return + if(in_range(src, usr) && istype(src.loc, /turf) && p_open) + usr.machine = src + if (href_list["wires"]) + var/t1 = text2num(href_list["wires"]) + if (!(istype(usr.equipped(), /obj/item/weapon/wirecutters) || istype(usr.equipped(),/obj/item/weapon/shard))) + usr << "You need wirecutters!" + return + if (src.isWireColorCut(t1) && istype(usr.equipped(), /obj/item/weapon/wirecutters)) + src.mend(t1) + else + src.cut(t1) + else if (href_list["pulse"]) + var/t1 = text2num(href_list["pulse"]) + if (!istype(usr.equipped(), /obj/item/device/multitool)) + usr << "You need a multitool!" + return + if (src.isWireColorCut(t1)) + usr << "You can't pulse a cut wire." + return + else + src.pulse(t1) + else if(href_list["signaler"]) + var/wirenum = text2num(href_list["signaler"]) + if(!istype(usr.equipped(), /obj/item/device/assembly/signaler)) + usr << "You need a signaller!" + return + if(src.isWireColorCut(wirenum)) + usr << "You can't attach a signaller to a cut wire." + return + var/obj/item/device/assembly/signaler/R = usr.equipped() + if(R.secured) + usr << "This radio can't be attached!" + return + var/mob/M = usr + M.drop_item() + R.loc = src + R.airlock_wire = wirenum + src.signalers[wirenum] = R + else if(href_list["remove-signaler"]) + var/wirenum = text2num(href_list["remove-signaler"]) + if(!(src.signalers[wirenum])) + usr << "There's no signaller attached to that wire!" + return + var/obj/item/device/assembly/signaler/R = src.signalers[wirenum] + R.loc = usr.loc + R.airlock_wire = null + src.signalers[wirenum] = null + + src.update_icon() + add_fingerprint(usr) + src.updateUsrDialog() + else //AI or Syndicate using hacktool + if (!src.canAIControl() || (istype(usr.equipped(), /obj/item/device/hacktool/) && (!src.canSynControl() || !in_range(src, usr)))) + usr << "Airlock control connection lost!" + return + //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door + //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door + if (href_list["aiDisable"]) + var/code = text2num(href_list["aiDisable"]) + switch (code) + if (1) + //disable idscan + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + usr << "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways." + else if (src.aiDisabledIdScanner) + usr << "You've already disabled the IdScan feature." + else + src.aiDisabledIdScanner = 1 + if (2) + //disrupt main power + if (src.secondsMainPowerLost == 0) + src.loseMainPower() + else + usr << "Main power is already offline." + if (3) + //disrupt backup power + if (src.secondsBackupPowerLost == 0) + src.loseBackupPower() + else + usr << "Backup power is already offline." + if (4) + //drop door bolts + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + usr << "You can't drop the door bolts - The door bolt dropping wire has been cut." + else if (src.locked!=1) + src.locked = 1 + update_icon() + if (5) + //un-electrify door + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("Can't un-electrify the airlock - The electrification wire is cut.
\n") + else if (src.secondsElectrified==-1) + src.secondsElectrified = 0 + else if (src.secondsElectrified>0) + src.secondsElectrified = 0 + if (7) + //close door + if (src.welded) + usr << text("The airlock has been welded shut!
\n") + else if (src.locked) + usr << text("The door bolts are down!
\n") + else if (!src.density) + close() + else + usr << text("The airlock is already closed.
\n") + if (8) + if(!src.forcecrush) + usr << text("Door extra force not enabled!
\n") + else + src.forcecrush = 0 + if (9) + if(!src.safetylight) + usr << text("Bolt indication light not enabled!
\n") + else + src.safetylight = 0 + if (10) + if(!src.holdopen) + usr << text("Door Behavior already set to: Wait for clearance to close
\n") + else + src.holdopen = 0 + + else if (href_list["aiEnable"]) + var/code = text2num(href_list["aiEnable"]) + switch (code) + if (1) + //enable idscan + if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) + usr << "You can't enable IdScan - The IdScan wire has been cut." + else if (src.aiDisabledIdScanner) + src.aiDisabledIdScanner = 0 + else + usr << "The IdScan feature is not disabled." + if (4) + //raise door bolts + if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + usr << text("The door bolt drop wire is cut - you can't raise the door bolts.
\n") + else if (!src.locked) + usr << text("The door bolts are already up.
\n") + else + if (src.arePowerSystemsOn()) + src.locked = 0 + update_icon() + else + usr << text("Cannot raise door bolts due to power failure.
\n") + + if (5) + //electrify door for 30 seconds + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("The electrification wire has been cut.
\n") + else if (src.secondsElectrified==-1) + usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
\n") + else if (src.secondsElectrified!=0) + usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") + else + src.secondsElectrified = 30 + spawn(10) + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + src.updateUsrDialog() + sleep(10) + if (6) + //electrify door indefinitely + if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) + usr << text("The electrification wire has been cut.
\n") + else if (src.secondsElectrified==-1) + usr << text("The door is already indefinitely electrified.
\n") + else if (src.secondsElectrified!=0) + usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") + else + src.secondsElectrified = -1 + if (7) + //open door + if (src.welded) + usr << text("The airlock has been welded shut!
\n") + else if (src.locked) + usr << text("The door bolts are down!
\n") + else if (src.density) + open() + // close() + else + usr << text("The airlock is already opened.
\n") + if (8) + if(src.forcecrush) + usr << text("Door extra force already enabled!
\n") + else + src.forcecrush = 1 + if (9) + if(src.safetylight) + usr << text("Bolt indication light already enabled!
\n") + else + src.safetylight = 1 + if (10) + if(src.holdopen) + usr << text("Door Behavior already set to: Automatically close
\n") + else + src.holdopen = 1 + + src.update_icon() + src.updateUsrDialog() + if((istype(usr.equipped(), /obj/item/device/hacktool))) + return attack_ai(usr, usr.equipped()) + return + + + + +/obj/machinery/door/airlock/secure + name = "Secure Airlock" + desc = "Good lord, at least they left out the overcomplicated death traps. Looks to be a layer of armor plate you might be able to remove with a wrench." + icon = 'Doorhatchele.dmi' + + wires = 65535 + wirenum = 16 + alert_probability = 20 + holdopen = 0 + signalers = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + var + list/WireColorToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + is_detached = 0 + + + + New() + ..() + //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). + var/flagIndex = 1 + for (var/flag=1, flag<65536, flag+=flag) + var/valid = 0 + while (!valid) + var/colorIndex = rand(1, 16) + if (WireColorToFlag[colorIndex] == 0) + valid = 1 + WireColorToFlag[colorIndex] = flag + IndexToFlag[flagIndex] = flag + IndexToWireColor[flagIndex] = colorIndex + WireColorToIndex[colorIndex] = flagIndex + flagIndex+=1 + return + + + isWireColorCut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + return ((src.wires & wireFlag) == 0) + + isWireCut(var/wireIndex) + var/wireFlag = IndexToFlag[wireIndex] + return ((src.wires & wireFlag) == 0) + + pulse(var/wireColor) + var/wireIndex = WireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 + // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + cut(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + mend(var/wireColor) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] //not used in this function + wires |= wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) + src.regainMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) + src.regainBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + if (src.secondsElectrified == -1) + src.secondsElectrified = 0 + + getAirlockWires() + var/t1 + var/iterator = 0 + for(var/wiredesc in wire_index) + if(iterator == wirenum) + break + var/is_uncut = src.wires & WireColorToFlag[wire_index[wiredesc]] + t1 += "[wiredesc] wire: " + if(!is_uncut) + t1 += "Mend" + else + t1 += "Cut " + t1 += "Pulse " + if(src.signalers[wire_index[wiredesc]]) + t1 += "Detach signaler" + else + t1 += "Attach signaler" + t1 += "
" + iterator++ + return t1 + + attackby(C as obj, mob/user as mob) + //world << text("airlock attackby src [] obj [] mob []", src, C, user) + if(istype(C, /obj/item/device/detective_scanner)) + return + if(!src.is_detached) + if (!istype(usr, /mob/living/silicon)) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + + src.add_fingerprint(user) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else + return + else if (istype(C, /obj/item/device/hacktool)) + return src.attack_ai(user, C) + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start to remove the armor plate..." + if(do_after(user,30)) + user << "Armor plates removed" + src.is_detached = 1 + else + if (istype(C, /obj/item/weapon/wrench)) + user << "You start to reattach the armor plate..." + if(do_after(user,30)) + user << "Armor plates attached" + src.is_detached = 0 + else + return ..(C, user) + if (src.isElectrified()) + if(src.shock(user, 75)) + return + src.add_fingerprint(user) if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) var/obj/item/weapon/weldingtool/W = C From 6f149af6ba3a85137319581995bc376186822be7 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 13:48:34 -0700 Subject: [PATCH 08/19] *sigh* Lets hope that worked. --- code/game/machinery/doors/airlock.dm | 3034 -------------------------- 1 file changed, 3034 deletions(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index b56589fcbc..1cb1a6ca9a 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1479,1492 +1479,6 @@ About the new airlock wires panel: iterator++ return t1 - attackby(C as obj, mob/user as mob) - //world << text("airlock attackby src [] obj [] mob []", src, C, user) - if(istype(C, /obj/item/device/detective_scanner)) - return - if(!src.is_detached) - if (!istype(usr, /mob/living/silicon))#define AIRLOCK_WIRE_IDSCAN 1 -#define AIRLOCK_WIRE_MAIN_POWER1 2 -#define AIRLOCK_WIRE_MAIN_POWER2 3 -#define AIRLOCK_WIRE_DOOR_BOLTS 4 -#define AIRLOCK_WIRE_BACKUP_POWER1 5 -#define AIRLOCK_WIRE_BACKUP_POWER2 6 -#define AIRLOCK_WIRE_OPEN_DOOR 7 -#define AIRLOCK_WIRE_AI_CONTROL 8 -#define AIRLOCK_WIRE_ELECTRIFY 9 -#define AIRLOCK_WIRE_CRUSH 10 -#define AIRLOCK_WIRE_LIGHT 11 -#define AIRLOCK_WIRE_HOLDOPEN 12 -#define AIRLOCK_WIRE_FAKEBOLT1 13 -#define AIRLOCK_WIRE_FAKEBOLT2 14 -#define AIRLOCK_WIRE_ALERTAI 15 -#define AIRLOCK_WIRE_DOOR_BOLTS_2 16 -//#define AIRLOCK_WIRE_FINGERPRINT 17 - -/* - New methods: - pulse - sends a pulse into a wire for hacking purposes - cut - cuts a wire and makes any necessary state changes - mend - mends a wire and makes any necessary state changes - isWireColorCut - returns 1 if that color wire is cut, or 0 if not - isWireCut - returns 1 if that wire (e.g. AIRLOCK_WIRE_DOOR_BOLTS) is cut, or 0 if not - canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) - canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. - arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) - requiresIDs - 1 if the airlock is requiring IDs, 0 if not - isAllPowerCut - 1 if the main and backup power both have cut wires. - regainMainPower - handles the effect of main power coming back on. - loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. - loseBackupPower - handles the effect of backup power going offline. - regainBackupPower - handles the effect of main power coming back on. - shock - has a chance of electrocuting its target. -*/ - -//This generates the randomized airlock wire assignments for the game. -/proc/RandomAirlockWires() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/list/wires = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockIndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockIndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockWireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - var/flagIndex = 1 - for (var/flag=1, flag<4096, flag+=flag) - var/valid = 0 - while (!valid) - var/colorIndex = rand(1, 12) - if (wires[colorIndex] == 0) - valid = 1 - wires[colorIndex] = flag - airlockIndexToFlag[flagIndex] = flag - airlockIndexToWireColor[flagIndex] = colorIndex - airlockWireColorToIndex[colorIndex] = flagIndex - flagIndex+=1 - return wires - -/* Example: -Airlock wires color -> flag are { 64, 128, 256, 2, 16, 4, 8, 32, 1 }. -Airlock wires color -> index are { 7, 8, 9, 2, 5, 3, 4, 6, 1 }. -Airlock index -> flag are { 1, 2, 4, 8, 16, 32, 64, 128, 256 }. -Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. -*/ - -/obj/machinery/door/airlock - name = "Airlock" - icon = 'doorint.dmi' - icon_state = "door_closed" - - var - aiControlDisabled = 0 //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. - synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no - synHacking = 0 // Is hack in process y/n? - secondsMainPowerLost = 0 //The number of seconds until power is restored. - secondsBackupPowerLost = 0 //The number of seconds until power is restored. - spawnPowerRestoreRunning = 0 - welded = null - locked = 0 - wires = 4095 - aiDisabledIdScanner = 0 - aiHacking = 0 - obj/machinery/door/airlock/closeOther = null - closeOtherId = null - list/signalers[12] - lockdownbyai = 0 - doortype = 0 - justzap = 0 - safetylight = 1 - obj/item/weapon/airlock_electronics/electronics = null - alert_probability = 3 - list/wire_index = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Red" = 5, - "Blue" = 6, - "Green" = 7, - "Grey" = 8, - "Black" = 9, - "Pink" = 10, - "Brown" = 11, - "Maroon" = 12, - "Aqua" = 13, - "Turgoise" = 14, - "Purple" = 15, - "Rainbow" = 16, - "Atomic Tangerine" = 17, - "Neon Green" = 18, - "Cotton Candy" = 19, - "Plum" = 20, - "Shamrock" = 21, - "Indigo" = 22 - ) - wirenum = 12 - holdopen = 1 - autoclose = 1 - secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. - - - command - name = "Airlock" - icon = 'Doorcom.dmi' - doortype = 1 - holdopen = 0 - - - security - name = "Airlock" - icon = 'Doorsec.dmi' - doortype = 2 - - - engineering - name = "Airlock" - icon = 'Dooreng.dmi' - doortype = 3 - - - medical - name = "Airlock" - icon = 'Doormed.dmi' - doortype = 4 - - - maintenance - name = "Maintenance Access" - icon = 'Doormaint.dmi' - doortype = 5 - - external - name = "External Airlock" - icon = 'Doorext.dmi' - doortype = 6 - - - glass - name = "Glass Airlock" - icon = 'Doorglass.dmi' - opacity = 0 - doortype = 7 - glass = 1 - - - glass_command - name = "Maintenance Hatch" - icon = 'Doorcomglass.dmi' - opacity = 0 - doortype = 14 - glass = 1 - - - glass_engineering - name = "Maintenance Hatch" - icon = 'Doorengglass.dmi' - opacity = 0 - doortype = 15 - glass = 1 - - - glass_security - name = "Maintenance Hatch" - icon = 'Doorsecglass.dmi' - opacity = 0 - doortype = 16 - glass = 1 - - - glass_medical - name = "Maintenance Hatch" - icon = 'doormedglass.dmi' - opacity = 0 - doortype = 17 - glass = 1 - - - centcom - name = "Airlock" - icon = 'Doorele.dmi' - opacity = 0 - doortype = 8 - - - vault - name = "Vault" - icon = 'vault.dmi' - opacity = 1 - doortype = 9 - - - glass_large - name = "Glass Airlock" - icon = 'Door2x1glassfull.dmi' - opacity = 0 - doortype = 10 - glass = 1 - - - freezer - name = "Freezer Airlock" - icon = 'Doorfreezer.dmi' - opacity = 1 - doortype = 11 - - - hatch - name = "Airtight Hatch" - icon = 'Doorhatchele.dmi' - opacity = 1 - doortype = 12 - - - maintenance_hatch - name = "Maintenance Hatch" - icon = 'Doorhatchmaint2.dmi' - opacity = 1 - doortype = 13 - - - New() - ..() - if (src.closeOtherId != null) - spawn (5) - for (var/obj/machinery/door/airlock/A in machines) - if (A.closeOtherId == src.closeOtherId && A != src) - src.closeOther = A - break - - - open() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) - return 0 - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) - src.closeOther.close() - return ..() - - - close() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - return - ..() - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) - if(killthis) - killthis.ex_act(2)//Smashin windows - return - - - bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if (!src.justzap) - if(src.shock(user, 100)) - src.justzap = 1 - spawn (10) - src.justzap = 0 - return - else /*if (src.justzap)*/ - return - else if(user.hallucination > 50 && prob(10) && src.operating == 0) - user << "\red You feel a powerful shock course through your body!" - user.halloss += 10 - user.stunned += 10 - return - ..(user) - - - update_icon() - if(overlays) overlays = null - if(density) - if(locked && safetylight) - icon_state = "door_locked" - else - icon_state = "door_closed" - if(p_open || welded) - overlays = list() - if(p_open) - overlays += image(icon, "panel_open") - if(welded) - overlays += image(icon, "welded") - else - icon_state = "door_open" - return - - - animate(animation) - switch(animation) - if("opening") - if(overlays) overlays = null - if(p_open) - icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking - else - flick("door_opening", src) - if("closing") - if(overlays) overlays = null - if(p_open) - flick("o_door_closing", src) - else - flick("door_closing", src) - if("spark") - flick("door_spark", src) - if("deny") - flick("door_deny", src) - return - - requiresID() - return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) - - attackby(C as obj, mob/user as mob) - //world << text("airlock attackby src [] obj [] mob []", src, C, user) - if(istype(C, /obj/item/device/detective_scanner)) - return - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 75)) - return - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/weapon/screwdriver)) - src.p_open = !( src.p_open ) - src.update_icon() - else if (istype(C, /obj/item/weapon/wirecutters)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/multitool)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/hacktool)) - return src.attack_ai(user, C) - else if (istype(C, /obj/item/device/assembly/signaler)) - return src.attack_hand(user) - else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE - var/obj/item/weapon/pai_cable/cable = C - cable.plugin(src, user) - else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) - var/beingcrowbarred = null - if(istype(C, /obj/item/weapon/crowbar) ) - beingcrowbarred = 1 //derp, Agouri - else - beingcrowbarred = 0 - if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) - playsound(src.loc, 'Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") - if(do_after(user,40)) - user << "\blue You removed the airlock electronics!" - switch(src.doortype) - if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) - if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) - if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) - if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) - if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) - if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) - if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) - if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) - var/obj/item/weapon/airlock_electronics/ae - if (!electronics) - ae = new/obj/item/weapon/airlock_electronics( src.loc ) - ae.conf_access = src.req_access - else - ae = electronics - electronics = null - ae.loc = src.loc - - del(src) - return - else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) - user << "\blue The airlock's motors resist your efforts to pry it open." - else if (src.locked) - user << "\blue The airlock's bolts prevent it from being pried open." - if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) - - if(beingcrowbarred == 0) //being fireaxe'd - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("opening") - - sleep(15) - - layer = 2.7 - src.density = 0 - update_icon() - - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - user << "\red You need to be wielding the Fire axe to do that." - return - else - spawn( 0 ) - src.operating = 1 - animate("opening") - - sleep(15) - - layer = 2.7 - src.density = 0 - update_icon() - - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - - else - if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) - if(beingcrowbarred == 0) - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("closing") - - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - else - user << "\red You need to be wielding the Fire axe to do that." - else - spawn( 0 ) - src.operating = 1 - animate("closing") - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - - else - ..() - return - - - attack_paw(mob/user as mob) - return src.attack_hand(user) - - - attack_hand(mob/user as mob) - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 100)) - return - - if (ishuman(user) && prob(40) && src.density) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - playsound(src.loc, 'bang.ogg', 25, 1) - if(!istype(H.head, /obj/item/clothing/head/helmet)) - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock." - var/datum/organ/external/affecting = H.get_organ("head") - affecting.take_damage(10, 0) - H.Stun(8) - H.Weaken(5) - H.UpdateDamageIcon() - else - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." - return - - if (src.p_open) - user.machine = src - var/t1 = text("Access Panel
\n") - - //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) - t1 += getAirlockWires() - - t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) - - t1 += text("

Close

\n", src) - - user << browse(t1, "window=airlock") - onclose(user, "airlock") - - else - ..(user) - return - -//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 engage engineer smasher, 9 enable bolt indicator, 10 wait for clearance -//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 disable engineer smasher, 9 disable bolt indicator, 10 autoclose - //This has been converted to be called by either the AI or a mob with a hacktool, permitting either to directly operate the airlock - attack_ai(mob/user as mob, obj/item/device/hacktool/C) - if(isAI(user)) - if (!src.canAIControl()) - if (src.canAIHack()) - src.hack(user) - return - else if(user) - if(!C) - return - if(C.in_use) - user << "We are already hacking another airlock." - return - if (!src.canSynControl() && src.canSynHack(C)) - src.synhack(user, C) - return - if(istype(C, /obj/item/device/hacktool/engineer)) - return - else - world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" - return - - - //Separate interface for the AI. - user.machine = src - var/t1 = text("Airlock Control
\n") - if (src.secondsMainPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
\n") - else - t1 += text("Main power is online.") - - if (src.secondsBackupPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
\n") - else if (src.secondsMainPowerLost > 0) - t1 += text("Backup power is online.") - else - t1 += text("Backup power is offline, but will turn on if main power fails.") - t1 += "
\n" - - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
\n") - else if (src.aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
\n", src) - else - t1 += text("IdScan enabled. Disable?
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
\n") - if (src.secondsMainPowerLost == 0) - t1 += text("Temporarily disrupt main power?.
\n", src) - if (src.secondsBackupPowerLost == 0) - t1 += text("Temporarily disrupt backup power?.
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) - t1 += text("Airlock extra force wire is cut.
\n") - else if(!src.forcecrush) - t1 += text("Airlock extra force disabled Enable it?
\n") - else - t1 += text("Airlock extra force enabled Disable it?
\n") - - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
\n") - else if (!src.locked) - t1 += text("Door bolts are up. Drop them?
\n", src) - else - t1 += text("Door bolts are down.") - if (src.arePowerSystemsOn()) - t1 += text(" Raise?
\n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
\n") - if (src.secondsElectrified==-1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) - else if (src.secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) - else - t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) - - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += "Bolt indication light wire is cut.
\n" - else if(!src.safetylight) - t1 += text("Bolt Indication light is disabled Enable it?
\n") - else - t1 += text("Bolt Indication light is enabled Disable it?
\n") - - if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) - t1 += "Behavior Control light wire is cut.
\n" - else if(!src.holdopen) - t1 += text("Door behavior is set to: Automatically close Toggle?
\n") - else - t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") - - if (src.welded) - t1 += text("Door appears to have been welded shut.
\n") - else if (!src.locked) - if (src.density) - t1 += text("Open door
\n", src) - else - t1 += text("Close door
\n", src) - - t1 += text("

Close

\n", src) - user << browse(t1, "window=airlock") - onclose(user, "airlock") - - - proc - hack(mob/user as mob) - if (src.aiHacking==0) - src.aiHacking=1 - spawn(20) - //TODO: Make this take a minute - user << "Airlock AI control has been blocked. Beginning fault-detection." - sleep(50) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Fault confirmed: airlock control wire disabled or cut." - sleep(20) - user << "Attempting to hack into airlock. This may take some time." - sleep(200) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(170) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(50) - //disable blocked control - src.aiControlDisabled = 2 - user << "Receiving control information from airlock." - sleep(10) - //bring up airlock dialog - src.aiHacking = 0 - src.attack_ai(user) - - - synhack(mob/user as mob, obj/item/device/hacktool/I) - if (src.synHacking==0) - var/multiplier = 1 - if(istype(C, /obj/item/device/hacktool/engineer)) - if(!src.locked) - user << "The door bolts are already up!" - return - multiplier++ - src.synHacking=1 - I.in_use = 1 - user << "You begin hacking..." - spawn(20*multiplier) - user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." - sleep(25*multiplier) - if (src.canSynControl()) - user << "Hack cancelled, control already possible." - src.synHacking=0 - I.in_use = 0 - return - else if (!src.canSynHack(I)) - user << "\red Connection lost. Stand still and stay near the airlock!" - src.synHacking=0 - I.in_use = 0 - return - user << "Connection established." - sleep(10*multiplier) - user << "Attempting to hack into airlock. This may take some time." - sleep(50*multiplier) - - // Alerting the AIs - var/list/cameras = list() - for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area - cameras += C - var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability - if(alertoption) - if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) - alertoption = 3 - else if (prob(18)) //18% chance of sending the AI just the area - alertoption = 2 - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - switch(alertoption) - if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) - if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - switch(alertoption) - if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") - // ...And done - - if (!src.canSynHack(I)) - user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Local override already in place, hack aborted." - src.synHacking=0 - I.in_use = 0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(35*multiplier) - if (!src.canSynHack(I)) - user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Upload access aborted, local override already in place." - src.synHacking=0 - I.in_use = 0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(25*multiplier) - //disable blocked control - if(istype(C, /obj/item/device/hacktool/engineer)) - user << "Raising door bolts..." - src.locked = 0 - update_icon() - return - src.synDoorHacked = 1 - user << "Bingo! We're in. Airlock control panel coming right up." - sleep(5) - //bring up airlock dialog - src.synHacking = 0 - I.in_use = 0 - src.attack_ai(user, I) - - - canAIControl() - return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); - - - canAIHack() - return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); - - - canSynControl() - return (src.synDoorHacked && (!src.isAllPowerCut())); - - - canSynHack(obj/item/device/hacktool/H) - return (in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()); - - - -/* -About the new airlock wires panel: -* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. -* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) -* two wires for power. 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). 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 \red open, but bolts-raising will not work. Cutting these wires may electrocute the user. -* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. -* 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). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. -* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. -* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). 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. -* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) -*/ - - pulse(var/wireColor) - //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function - var/wireIndex = airlockWireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - animate("deny") - if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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). - src.loseMainPower() - if (AIRLOCK_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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - else - if(src.arePowerSystemsOn()) //only can raise bolts if power's on - src.locked = 0 - usr << "You hear a click from inside the door." - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //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). - src.loseBackupPower() - if (AIRLOCK_WIRE_AI_CONTROL) - if (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if (src.secondsElectrified==0) - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_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 - if (!src.requiresID() || src.check_access(null)) - if (src.density) - open() - else - close() - if(AIRLOCK_WIRE_CRUSH) - src.forcecrush = !src.forcecrush - if(AIRLOCK_WIRE_LIGHT) - src.safetylight = !src.safetylight - if(AIRLOCK_WIRE_HOLDOPEN) - src.holdopen = !src.holdopen - - cut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_DOOR_BOLTS) - //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) - if (src.locked!=1) - src.locked = 1 - update_icon() - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if (src.secondsElectrified != -1) - src.secondsElectrified = -1 - - mend(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - if (src.secondsElectrified == -1) - src.secondsElectrified = 0 - - getAirlockWires() - var/t1 - var/iterator = 0 - for(var/wiredesc in wire_index) - if(iterator == wirenum) - break - var/is_uncut = src.wires & airlockWireColorToFlag[wire_index[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - if(src.signalers[wire_index[wiredesc]]) - t1 += "Detach signaler" - else - t1 += "Attach signaler" - t1 += "
" - iterator++ - return t1 - - isElectrified() - return (src.secondsElectrified != 0); - - isWireColorCut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - - isWireCut(var/wireIndex) - var/wireFlag = airlockIndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - - arePowerSystemsOn() - return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) - - isAllPowerCut() - return ((src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) && (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - - regainMainPower() - if (src.secondsMainPowerLost > 0) - src.secondsMainPowerLost = 0 - - loseMainPower() - if (src.secondsMainPowerLost <= 0) - src.secondsMainPowerLost = 60 - if (src.secondsBackupPowerLost < 10) - src.secondsBackupPowerLost = 10 - if (!src.spawnPowerRestoreRunning) - src.spawnPowerRestoreRunning = 1 - spawn(0) - var/cont = 1 - while (cont) - sleep(10) - cont = 0 - if (src.secondsMainPowerLost>0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.secondsMainPowerLost -= 1 - src.updateDialog() - cont = 1 - - if (src.secondsBackupPowerLost>0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.secondsBackupPowerLost -= 1 - src.updateDialog() - cont = 1 - src.spawnPowerRestoreRunning = 0 - src.updateDialog() - - loseBackupPower() - if (src.secondsBackupPowerLost < 60) - src.secondsBackupPowerLost = 60 - - regainBackupPower() - if (src.secondsBackupPowerLost > 0) - src.secondsBackupPowerLost = 0 - - // shock user with probability prb (if all connections & power are working) - // returns 1 if shocked, 0 otherwise - // The preceding comment was borrowed from the grille's shock script - shock(mob/user, prb) - if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 //you lucked out, no shock for you - if(istype(usr.equipped(),/obj/item/weapon/shard)) - return 0 - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if (electrocute_mob(user, get_area(src), src)) - return 1 - else - return 0 - - prison_open() - src.locked = 0 - src.open() - src.locked = 1 - return - - - -/obj/machinery/door/airlock/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained() ) - return - if (href_list["close"]) - usr << browse(null, "window=airlock") - if (usr.machine==src) - usr.machine = null - return - if(in_range(src, usr) && istype(src.loc, /turf) && p_open) - usr.machine = src - if (href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if (!(istype(usr.equipped(), /obj/item/weapon/wirecutters) || istype(usr.equipped(),/obj/item/weapon/shard))) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(t1) && istype(usr.equipped(), /obj/item/weapon/wirecutters)) - src.mend(t1) - else - src.cut(t1) - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.equipped(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(t1) - else if(href_list["signaler"]) - var/wirenum = text2num(href_list["signaler"]) - if(!istype(usr.equipped(), /obj/item/device/assembly/signaler)) - usr << "You need a signaller!" - return - if(src.isWireColorCut(wirenum)) - usr << "You can't attach a signaller to a cut wire." - return - var/obj/item/device/assembly/signaler/R = usr.equipped() - if(R.secured) - usr << "This radio can't be attached!" - return - var/mob/M = usr - M.drop_item() - R.loc = src - R.airlock_wire = wirenum - src.signalers[wirenum] = R - else if(href_list["remove-signaler"]) - var/wirenum = text2num(href_list["remove-signaler"]) - if(!(src.signalers[wirenum])) - usr << "There's no signaller attached to that wire!" - return - var/obj/item/device/assembly/signaler/R = src.signalers[wirenum] - R.loc = usr.loc - R.airlock_wire = null - src.signalers[wirenum] = null - - src.update_icon() - add_fingerprint(usr) - src.updateUsrDialog() - else //AI or Syndicate using hacktool - if (!src.canAIControl() || (istype(usr.equipped(), /obj/item/device/hacktool/) && (!src.canSynControl() || !in_range(src, usr)))) - usr << "Airlock control connection lost!" - return - //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door - //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door - if (href_list["aiDisable"]) - var/code = text2num(href_list["aiDisable"]) - switch (code) - if (1) - //disable idscan - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - usr << "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways." - else if (src.aiDisabledIdScanner) - usr << "You've already disabled the IdScan feature." - else - src.aiDisabledIdScanner = 1 - if (2) - //disrupt main power - if (src.secondsMainPowerLost == 0) - src.loseMainPower() - else - usr << "Main power is already offline." - if (3) - //disrupt backup power - if (src.secondsBackupPowerLost == 0) - src.loseBackupPower() - else - usr << "Backup power is already offline." - if (4) - //drop door bolts - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - usr << "You can't drop the door bolts - The door bolt dropping wire has been cut." - else if (src.locked!=1) - src.locked = 1 - update_icon() - if (5) - //un-electrify door - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("Can't un-electrify the airlock - The electrification wire is cut.
\n") - else if (src.secondsElectrified==-1) - src.secondsElectrified = 0 - else if (src.secondsElectrified>0) - src.secondsElectrified = 0 - if (7) - //close door - if (src.welded) - usr << text("The airlock has been welded shut!
\n") - else if (src.locked) - usr << text("The door bolts are down!
\n") - else if (!src.density) - close() - else - usr << text("The airlock is already closed.
\n") - if (8) - if(!src.forcecrush) - usr << text("Door extra force not enabled!
\n") - else - src.forcecrush = 0 - if (9) - if(!src.safetylight) - usr << text("Bolt indication light not enabled!
\n") - else - src.safetylight = 0 - if (10) - if(!src.holdopen) - usr << text("Door Behavior already set to: Wait for clearance to close
\n") - else - src.holdopen = 0 - - else if (href_list["aiEnable"]) - var/code = text2num(href_list["aiEnable"]) - switch (code) - if (1) - //enable idscan - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - usr << "You can't enable IdScan - The IdScan wire has been cut." - else if (src.aiDisabledIdScanner) - src.aiDisabledIdScanner = 0 - else - usr << "The IdScan feature is not disabled." - if (4) - //raise door bolts - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - usr << text("The door bolt drop wire is cut - you can't raise the door bolts.
\n") - else if (!src.locked) - usr << text("The door bolts are already up.
\n") - else - if (src.arePowerSystemsOn()) - src.locked = 0 - update_icon() - else - usr << text("Cannot raise door bolts due to power failure.
\n") - - if (5) - //electrify door for 30 seconds - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("The electrification wire has been cut.
\n") - else if (src.secondsElectrified==-1) - usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
\n") - else if (src.secondsElectrified!=0) - usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") - else - src.secondsElectrified = 30 - spawn(10) - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - src.updateUsrDialog() - sleep(10) - if (6) - //electrify door indefinitely - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("The electrification wire has been cut.
\n") - else if (src.secondsElectrified==-1) - usr << text("The door is already indefinitely electrified.
\n") - else if (src.secondsElectrified!=0) - usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") - else - src.secondsElectrified = -1 - if (7) - //open door - if (src.welded) - usr << text("The airlock has been welded shut!
\n") - else if (src.locked) - usr << text("The door bolts are down!
\n") - else if (src.density) - open() - // close() - else - usr << text("The airlock is already opened.
\n") - if (8) - if(src.forcecrush) - usr << text("Door extra force already enabled!
\n") - else - src.forcecrush = 1 - if (9) - if(src.safetylight) - usr << text("Bolt indication light already enabled!
\n") - else - src.safetylight = 1 - if (10) - if(src.holdopen) - usr << text("Door Behavior already set to: Automatically close
\n") - else - src.holdopen = 1 - - src.update_icon() - src.updateUsrDialog() - if((istype(usr.equipped(), /obj/item/device/hacktool))) - return attack_ai(usr, usr.equipped()) - return - - - - -/obj/machinery/door/airlock/secure - name = "Secure Airlock" - desc = "Good lord, at least they left out the overcomplicated death traps. Looks to be a layer of armor plate you might be able to remove with a wrench." - icon = 'Doorhatchele.dmi' - - wires = 65535 - wirenum = 16 - alert_probability = 20 - holdopen = 0 - signalers = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - var - list/WireColorToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/IndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - is_detached = 0 - - - - New() - ..() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/flagIndex = 1 - for (var/flag=1, flag<65536, flag+=flag) - var/valid = 0 - while (!valid) - var/colorIndex = rand(1, 16) - if (WireColorToFlag[colorIndex] == 0) - valid = 1 - WireColorToFlag[colorIndex] = flag - IndexToFlag[flagIndex] = flag - IndexToWireColor[flagIndex] = colorIndex - WireColorToIndex[colorIndex] = flagIndex - flagIndex+=1 - return - - - isWireColorCut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - - isWireCut(var/wireIndex) - var/wireFlag = IndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - - pulse(var/wireColor) - var/wireIndex = WireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - animate("deny") - if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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). - src.loseMainPower() - if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - else - if(src.arePowerSystemsOn()) //only can raise bolts if power's on - src.locked = 0 - usr << "You hear a click from inside the door." - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //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). - src.loseBackupPower() - if (AIRLOCK_WIRE_AI_CONTROL) - if (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if (src.secondsElectrified==0) - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_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 - if (!src.requiresID() || src.check_access(null)) - if (src.density) - open() - else - close() - if(AIRLOCK_WIRE_CRUSH) - src.forcecrush = !src.forcecrush - if(AIRLOCK_WIRE_LIGHT) - src.safetylight = !src.safetylight - if(AIRLOCK_WIRE_HOLDOPEN) - src.holdopen = !src.holdopen - if(AIRLOCK_WIRE_ALERTAI) - if(prob(alert_probability)) - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - - cut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) - //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) - if (src.locked!=1) - src.locked = 1 - update_icon() - src.updateUsrDialog() - if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - update_icon() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if (src.secondsElectrified != -1) - src.secondsElectrified = -1 - if(AIRLOCK_WIRE_ALERTAI) - if(prob(alert_probability)) - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - - mend(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - if (src.secondsElectrified == -1) - src.secondsElectrified = 0 - - getAirlockWires() - var/t1 - var/iterator = 0 - for(var/wiredesc in wire_index) - if(iterator == wirenum) - break - var/is_uncut = src.wires & WireColorToFlag[wire_index[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - if(src.signalers[wire_index[wiredesc]]) - t1 += "Detach signaler" - else - t1 += "Attach signaler" - t1 += "
" - iterator++ - return t1 - attackby(C as obj, mob/user as mob) //world << text("airlock attackby src [] obj [] mob []", src, C, user) if(istype(C, /obj/item/device/detective_scanner)) @@ -2975,1554 +1489,6 @@ About the new airlock wires panel: if(src.shock(user, 75)) return - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/device/hacktool)) - return src.attack_ai(user, C) - else if (istype(C, /obj/item/weapon/wrench)) - user << "You start to remove the armor plate..." - if(do_after(user,30)) - user << "Armor plates removed" - src.is_detached = 1 - else - if (istype(C, /obj/item/weapon/wrench)) - user << "You start to reattach the armor plate..." - if(do_after(user,30)) - user << "Armor plates attached" - src.is_detached = 0 - else - return ..(C, user)#define AIRLOCK_WIRE_IDSCAN 1 -#define AIRLOCK_WIRE_MAIN_POWER1 2 -#define AIRLOCK_WIRE_MAIN_POWER2 3 -#define AIRLOCK_WIRE_DOOR_BOLTS 4 -#define AIRLOCK_WIRE_BACKUP_POWER1 5 -#define AIRLOCK_WIRE_BACKUP_POWER2 6 -#define AIRLOCK_WIRE_OPEN_DOOR 7 -#define AIRLOCK_WIRE_AI_CONTROL 8 -#define AIRLOCK_WIRE_ELECTRIFY 9 -#define AIRLOCK_WIRE_CRUSH 10 -#define AIRLOCK_WIRE_LIGHT 11 -#define AIRLOCK_WIRE_HOLDOPEN 12 -#define AIRLOCK_WIRE_FAKEBOLT1 13 -#define AIRLOCK_WIRE_FAKEBOLT2 14 -#define AIRLOCK_WIRE_ALERTAI 15 -#define AIRLOCK_WIRE_DOOR_BOLTS_2 16 -//#define AIRLOCK_WIRE_FINGERPRINT 17 - -/* - New methods: - pulse - sends a pulse into a wire for hacking purposes - cut - cuts a wire and makes any necessary state changes - mend - mends a wire and makes any necessary state changes - isWireColorCut - returns 1 if that color wire is cut, or 0 if not - isWireCut - returns 1 if that wire (e.g. AIRLOCK_WIRE_DOOR_BOLTS) is cut, or 0 if not - canAIControl - 1 if the AI can control the airlock, 0 if not (then check canAIHack to see if it can hack in) - canAIHack - 1 if the AI can hack into the airlock to recover control, 0 if not. Also returns 0 if the AI does not *need* to hack it. - arePowerSystemsOn - 1 if the main or backup power are functioning, 0 if not. Does not check whether the power grid is charged or an APC has equipment on or anything like that. (Check (stat & NOPOWER) for that) - requiresIDs - 1 if the airlock is requiring IDs, 0 if not - isAllPowerCut - 1 if the main and backup power both have cut wires. - regainMainPower - handles the effect of main power coming back on. - loseMainPower - handles the effect of main power going offline. Usually (if one isn't already running) spawn a thread to count down how long it will be offline - counting down won't happen if main power was completely cut along with backup power, though, the thread will just sleep. - loseBackupPower - handles the effect of backup power going offline. - regainBackupPower - handles the effect of main power coming back on. - shock - has a chance of electrocuting its target. -*/ - -//This generates the randomized airlock wire assignments for the game. -/proc/RandomAirlockWires() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/list/wires = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockIndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockIndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - airlockWireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - var/flagIndex = 1 - for (var/flag=1, flag<4096, flag+=flag) - var/valid = 0 - while (!valid) - var/colorIndex = rand(1, 12) - if (wires[colorIndex] == 0) - valid = 1 - wires[colorIndex] = flag - airlockIndexToFlag[flagIndex] = flag - airlockIndexToWireColor[flagIndex] = colorIndex - airlockWireColorToIndex[colorIndex] = flagIndex - flagIndex+=1 - return wires - -/* Example: -Airlock wires color -> flag are { 64, 128, 256, 2, 16, 4, 8, 32, 1 }. -Airlock wires color -> index are { 7, 8, 9, 2, 5, 3, 4, 6, 1 }. -Airlock index -> flag are { 1, 2, 4, 8, 16, 32, 64, 128, 256 }. -Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. -*/ - -/obj/machinery/door/airlock - name = "Airlock" - icon = 'doorint.dmi' - icon_state = "door_closed" - - var - aiControlDisabled = 0 //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. - synDoorHacked = 0 // Has it been hacked? bool 1 = yes / 0 = no - synHacking = 0 // Is hack in process y/n? - secondsMainPowerLost = 0 //The number of seconds until power is restored. - secondsBackupPowerLost = 0 //The number of seconds until power is restored. - spawnPowerRestoreRunning = 0 - welded = null - locked = 0 - wires = 4095 - aiDisabledIdScanner = 0 - aiHacking = 0 - obj/machinery/door/airlock/closeOther = null - closeOtherId = null - list/signalers[12] - lockdownbyai = 0 - doortype = 0 - justzap = 0 - safetylight = 1 - obj/item/weapon/airlock_electronics/electronics = null - alert_probability = 3 - list/wire_index = list( - "Orange" = 1, - "Dark red" = 2, - "White" = 3, - "Yellow" = 4, - "Red" = 5, - "Blue" = 6, - "Green" = 7, - "Grey" = 8, - "Black" = 9, - "Pink" = 10, - "Brown" = 11, - "Maroon" = 12, - "Aqua" = 13, - "Turgoise" = 14, - "Purple" = 15, - "Rainbow" = 16, - "Atomic Tangerine" = 17, - "Neon Green" = 18, - "Cotton Candy" = 19, - "Plum" = 20, - "Shamrock" = 21, - "Indigo" = 22 - ) - wirenum = 12 - holdopen = 1 - autoclose = 1 - secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. - - - command - name = "Airlock" - icon = 'Doorcom.dmi' - doortype = 1 - holdopen = 0 - - - security - name = "Airlock" - icon = 'Doorsec.dmi' - doortype = 2 - - - engineering - name = "Airlock" - icon = 'Dooreng.dmi' - doortype = 3 - - - medical - name = "Airlock" - icon = 'Doormed.dmi' - doortype = 4 - - - maintenance - name = "Maintenance Access" - icon = 'Doormaint.dmi' - doortype = 5 - - external - name = "External Airlock" - icon = 'Doorext.dmi' - doortype = 6 - - - glass - name = "Glass Airlock" - icon = 'Doorglass.dmi' - opacity = 0 - doortype = 7 - glass = 1 - - - glass_command - name = "Maintenance Hatch" - icon = 'Doorcomglass.dmi' - opacity = 0 - doortype = 14 - glass = 1 - - - glass_engineering - name = "Maintenance Hatch" - icon = 'Doorengglass.dmi' - opacity = 0 - doortype = 15 - glass = 1 - - - glass_security - name = "Maintenance Hatch" - icon = 'Doorsecglass.dmi' - opacity = 0 - doortype = 16 - glass = 1 - - - glass_medical - name = "Maintenance Hatch" - icon = 'doormedglass.dmi' - opacity = 0 - doortype = 17 - glass = 1 - - - centcom - name = "Airlock" - icon = 'Doorele.dmi' - opacity = 0 - doortype = 8 - - - vault - name = "Vault" - icon = 'vault.dmi' - opacity = 1 - doortype = 9 - - - glass_large - name = "Glass Airlock" - icon = 'Door2x1glassfull.dmi' - opacity = 0 - doortype = 10 - glass = 1 - - - freezer - name = "Freezer Airlock" - icon = 'Doorfreezer.dmi' - opacity = 1 - doortype = 11 - - - hatch - name = "Airtight Hatch" - icon = 'Doorhatchele.dmi' - opacity = 1 - doortype = 12 - - - maintenance_hatch - name = "Maintenance Hatch" - icon = 'Doorhatchmaint2.dmi' - opacity = 1 - doortype = 13 - - - New() - ..() - if (src.closeOtherId != null) - spawn (5) - for (var/obj/machinery/door/airlock/A in machines) - if (A.closeOtherId == src.closeOtherId && A != src) - src.closeOther = A - break - - - open() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) - return 0 - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - if (src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) - src.closeOther.close() - return ..() - - - close() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - return - ..() - use_power(50) - playsound(src.loc, 'airlock.ogg', 30, 1) - var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src)) - if(killthis) - killthis.ex_act(2)//Smashin windows - return - - - bumpopen(mob/user as mob) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if (!src.justzap) - if(src.shock(user, 100)) - src.justzap = 1 - spawn (10) - src.justzap = 0 - return - else /*if (src.justzap)*/ - return - else if(user.hallucination > 50 && prob(10) && src.operating == 0) - user << "\red You feel a powerful shock course through your body!" - user.halloss += 10 - user.stunned += 10 - return - ..(user) - - - update_icon() - if(overlays) overlays = null - if(density) - if(locked && safetylight) - icon_state = "door_locked" - else - icon_state = "door_closed" - if(p_open || welded) - overlays = list() - if(p_open) - overlays += image(icon, "panel_open") - if(welded) - overlays += image(icon, "welded") - else - icon_state = "door_open" - return - - - animate(animation) - switch(animation) - if("opening") - if(overlays) overlays = null - if(p_open) - icon_state = "o_door_opening" //can not use flick due to BYOND bug updating overlays right before flicking - else - flick("door_opening", src) - if("closing") - if(overlays) overlays = null - if(p_open) - flick("o_door_closing", src) - else - flick("door_closing", src) - if("spark") - flick("door_spark", src) - if("deny") - flick("door_deny", src) - return - - requiresID() - return !(src.isWireCut(AIRLOCK_WIRE_IDSCAN) || aiDisabledIdScanner) - - attackby(C as obj, mob/user as mob) - //world << text("airlock attackby src [] obj [] mob []", src, C, user) - if(istype(C, /obj/item/device/detective_scanner)) - return - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 75)) - return - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/weapon/screwdriver)) - src.p_open = !( src.p_open ) - src.update_icon() - else if (istype(C, /obj/item/weapon/wirecutters)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/multitool)) - return src.attack_hand(user) - else if (istype(C, /obj/item/device/hacktool)) - return src.attack_ai(user, C) - else if (istype(C, /obj/item/device/assembly/signaler)) - return src.attack_hand(user) - else if (istype(C, /obj/item/weapon/pai_cable)) // -- TLE - var/obj/item/weapon/pai_cable/cable = C - cable.plugin(src, user) - else if (istype(C, /obj/item/weapon/crowbar) || istype(C, /obj/item/weapon/fireaxe) ) - var/beingcrowbarred = null - if(istype(C, /obj/item/weapon/crowbar) ) - beingcrowbarred = 1 //derp, Agouri - else - beingcrowbarred = 0 - if ( ((src.density) && ( src.welded ) && !( src.operating ) && src.p_open && (!src.arePowerSystemsOn() || (stat & NOPOWER)) && !src.locked) && beingcrowbarred == 1 ) - playsound(src.loc, 'Crowbar.ogg', 100, 1) - user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to remove electronics into the airlock assembly.") - if(do_after(user,40)) - user << "\blue You removed the airlock electronics!" - switch(src.doortype) - if(0) new/obj/structure/door_assembly/door_assembly_0( src.loc ) - if(1) new/obj/structure/door_assembly/door_assembly_com( src.loc ) - if(2) new/obj/structure/door_assembly/door_assembly_sec( src.loc ) - if(3) new/obj/structure/door_assembly/door_assembly_eng( src.loc ) - if(4) new/obj/structure/door_assembly/door_assembly_med( src.loc ) - if(5) new/obj/structure/door_assembly/door_assembly_mai( src.loc ) - if(6) new/obj/structure/door_assembly/door_assembly_ext( src.loc ) - if(7) new/obj/structure/door_assembly/door_assembly_g( src.loc ) - var/obj/item/weapon/airlock_electronics/ae - if (!electronics) - ae = new/obj/item/weapon/airlock_electronics( src.loc ) - ae.conf_access = src.req_access - else - ae = electronics - electronics = null - ae.loc = src.loc - - del(src) - return - else if (src.arePowerSystemsOn() && !(stat & NOPOWER)) - user << "\blue The airlock's motors resist your efforts to pry it open." - else if (src.locked) - user << "\blue The airlock's bolts prevent it from being pried open." - if ((src.density) && (!( src.welded ) && !( src.operating ) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER)) && !( src.locked ))) - - if(beingcrowbarred == 0) //being fireaxe'd - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("opening") - - sleep(15) - - layer = 2.7 - src.density = 0 - update_icon() - - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - user << "\red You need to be wielding the Fire axe to do that." - return - else - spawn( 0 ) - src.operating = 1 - animate("opening") - - sleep(15) - - layer = 2.7 - src.density = 0 - update_icon() - - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return - - else - if ((!src.density) && (!( src.welded ) && !( src.operating ) && !( src.locked ))) - if(beingcrowbarred == 0) - var/obj/item/weapon/fireaxe/F = C - if(F.wielded == 1) - spawn( 0 ) - src.operating = 1 - animate("closing") - - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - else - user << "\red You need to be wielding the Fire axe to do that." - else - spawn( 0 ) - src.operating = 1 - animate("closing") - layer = 3.1 - src.density = 1 - sleep(15) - update_icon() - - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - - else - ..() - return - - - attack_paw(mob/user as mob) - return src.attack_hand(user) - - - attack_hand(mob/user as mob) - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 100)) - return - - if (ishuman(user) && prob(40) && src.density) - var/mob/living/carbon/human/H = user - if(H.getBrainLoss() >= 60) - playsound(src.loc, 'bang.ogg', 25, 1) - if(!istype(H.head, /obj/item/clothing/head/helmet)) - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock." - var/datum/organ/external/affecting = H.get_organ("head") - affecting.take_damage(10, 0) - H.Stun(8) - H.Weaken(5) - H.UpdateDamageIcon() - else - for(var/mob/M in viewers(src, null)) - M << "\red [user] headbutts the airlock. Good thing they're wearing a helmet." - return - - if (src.p_open) - user.machine = src - var/t1 = text("Access Panel
\n") - - //t1 += text("[]: ", airlockFeatureNames[airlockWireColorToIndex[9]]) - t1 += getAirlockWires() - - t1 += text("
\n[]
\n[]
\n[]
\n[]
\n[]", (src.locked ? "The door bolts have fallen!" : "The door bolts look up."), ((src.arePowerSystemsOn() && !(stat & NOPOWER)) ? "The test light is on." : "The test light is off!"), (src.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."), (src.secondsElectrified!=0 ? "The safety light is flashing!" : "The safety light is on."), (src.forcecrush==0 ? "The hydraulics control light is a solid green." : "The hydraulics control light is flashing red.")) - - t1 += text("

Close

\n", src) - - user << browse(t1, "window=airlock") - onclose(user, "airlock") - - else - ..(user) - return - -//aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 engage engineer smasher, 9 enable bolt indicator, 10 wait for clearance -//aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 disable engineer smasher, 9 disable bolt indicator, 10 autoclose - //This has been converted to be called by either the AI or a mob with a hacktool, permitting either to directly operate the airlock - attack_ai(mob/user as mob, obj/item/device/hacktool/C) - if(isAI(user)) - if (!src.canAIControl()) - if (src.canAIHack()) - src.hack(user) - return - else if(user) - if(!C) - return - if(C.in_use) - user << "We are already hacking another airlock." - return - if (!src.canSynControl() && src.canSynHack(C)) - src.synhack(user, C) - return - if(istype(C, /obj/item/device/hacktool/engineer)) - return - else - world << "ERROR: Mob was null when calling attack_ai on [src.name] at [src.x],[src.y],[src.z]" - return - - - //Separate interface for the AI. - user.machine = src - var/t1 = text("Airlock Control
\n") - if (src.secondsMainPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - t1 += text("Main power is offline for [] seconds.
\n", src.secondsMainPowerLost) - else - t1 += text("Main power is offline indefinitely.
\n") - else - t1 += text("Main power is online.") - - if (src.secondsBackupPowerLost > 0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - t1 += text("Backup power is offline for [] seconds.
\n", src.secondsBackupPowerLost) - else - t1 += text("Backup power is offline indefinitely.
\n") - else if (src.secondsMainPowerLost > 0) - t1 += text("Backup power is online.") - else - t1 += text("Backup power is offline, but will turn on if main power fails.") - t1 += "
\n" - - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - t1 += text("IdScan wire is cut.
\n") - else if (src.aiDisabledIdScanner) - t1 += text("IdScan disabled. Enable?
\n", src) - else - t1 += text("IdScan enabled. Disable?
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) - t1 += text("Main Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) - t1 += text("Main Power Output wire is cut.
\n") - if (src.secondsMainPowerLost == 0) - t1 += text("Temporarily disrupt main power?.
\n", src) - if (src.secondsBackupPowerLost == 0) - t1 += text("Temporarily disrupt backup power?.
\n", src) - - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) - t1 += text("Backup Power Input wire is cut.
\n") - if (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2)) - t1 += text("Backup Power Output wire is cut.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_CRUSH)) - t1 += text("Airlock extra force wire is cut.
\n") - else if(!src.forcecrush) - t1 += text("Airlock extra force disabled Enable it?
\n") - else - t1 += text("Airlock extra force enabled Disable it?
\n") - - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - t1 += text("Door bolt drop wire is cut.
\n") - else if (!src.locked) - t1 += text("Door bolts are up. Drop them?
\n", src) - else - t1 += text("Door bolts are down.") - if (src.arePowerSystemsOn()) - t1 += text(" Raise?
\n", src) - else - t1 += text(" Cannot raise door bolts due to power failure.
\n") - - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - t1 += text("Electrification wire is cut.
\n") - if (src.secondsElectrified==-1) - t1 += text("Door is electrified indefinitely. Un-electrify it?
\n", src) - else if (src.secondsElectrified>0) - t1 += text("Door is electrified temporarily ([] seconds). Un-electrify it?
\n", src.secondsElectrified, src) - else - t1 += text("Door is not electrified. Electrify it for 30 seconds? Or, Electrify it indefinitely until someone cancels the electrification?
\n", src, src) - - if(src.isWireCut(AIRLOCK_WIRE_LIGHT)) - t1 += "Bolt indication light wire is cut.
\n" - else if(!src.safetylight) - t1 += text("Bolt Indication light is disabled Enable it?
\n") - else - t1 += text("Bolt Indication light is enabled Disable it?
\n") - - if(src.isWireCut(AIRLOCK_WIRE_HOLDOPEN)) - t1 += "Behavior Control light wire is cut.
\n" - else if(!src.holdopen) - t1 += text("Door behavior is set to: Automatically close Toggle?
\n") - else - t1 += text("Door behavior is set to: Wait for clearance to close Toggle?
\n") - - if (src.welded) - t1 += text("Door appears to have been welded shut.
\n") - else if (!src.locked) - if (src.density) - t1 += text("Open door
\n", src) - else - t1 += text("Close door
\n", src) - - t1 += text("

Close

\n", src) - user << browse(t1, "window=airlock") - onclose(user, "airlock") - - - proc - hack(mob/user as mob) - if (src.aiHacking==0) - src.aiHacking=1 - spawn(20) - //TODO: Make this take a minute - user << "Airlock AI control has been blocked. Beginning fault-detection." - sleep(50) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Fault confirmed: airlock control wire disabled or cut." - sleep(20) - user << "Attempting to hack into airlock. This may take some time." - sleep(200) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(170) - if (src.canAIControl()) - user << "Alert cancelled. Airlock control has been restored without our assistance." - src.aiHacking=0 - return - else if (!src.canAIHack()) - user << "We've lost our connection! Unable to hack airlock." - src.aiHacking=0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(50) - //disable blocked control - src.aiControlDisabled = 2 - user << "Receiving control information from airlock." - sleep(10) - //bring up airlock dialog - src.aiHacking = 0 - src.attack_ai(user) - - - synhack(mob/user as mob, obj/item/device/hacktool/I) - if (src.synHacking==0) - var/multiplier = 1 - if(istype(C, /obj/item/device/hacktool/engineer)) - if(!src.locked) - user << "The door bolts are already up!" - return - multiplier++ - src.synHacking=1 - I.in_use = 1 - user << "You begin hacking..." - spawn(20*multiplier) - user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." - sleep(25*multiplier) - if (src.canSynControl()) - user << "Hack cancelled, control already possible." - src.synHacking=0 - I.in_use = 0 - return - else if (!src.canSynHack(I)) - user << "\red Connection lost. Stand still and stay near the airlock!" - src.synHacking=0 - I.in_use = 0 - return - user << "Connection established." - sleep(10*multiplier) - user << "Attempting to hack into airlock. This may take some time." - sleep(50*multiplier) - - // Alerting the AIs - var/list/cameras = list() - for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area - cameras += C - var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability - if(alertoption) - if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) - alertoption = 3 - else if (prob(18)) //18% chance of sending the AI just the area - alertoption = 2 - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - switch(alertoption) - if(3) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc, cameras) - if(2) aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) aiPlayer.triggerUnmarkedAlarm("AirlockHacking") - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - switch(alertoption) - if(2,3) robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - if(1) robotPlayer.triggerUnmarkedAlarm("AirlockHacking") - // ...And done - - if (!src.canSynHack(I)) - user << "\red Hack aborted: landline connection lost. Stay closer to the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Local override already in place, hack aborted." - src.synHacking=0 - I.in_use = 0 - return - user << "Upload access confirmed. Loading control program into airlock software." - sleep(35*multiplier) - if (!src.canSynHack(I)) - user << "\red Hack aborted: cable connection lost. Do not move away from the airlock." - src.synHacking=0 - I.in_use = 0 - return - else if (src.canSynControl()) - user << "Upload access aborted, local override already in place." - src.synHacking=0 - I.in_use = 0 - return - user << "Transfer complete. Forcing airlock to execute program." - sleep(25*multiplier) - //disable blocked control - if(istype(C, /obj/item/device/hacktool/engineer)) - user << "Raising door bolts..." - src.locked = 0 - update_icon() - return - src.synDoorHacked = 1 - user << "Bingo! We're in. Airlock control panel coming right up." - sleep(5) - //bring up airlock dialog - src.synHacking = 0 - I.in_use = 0 - src.attack_ai(user, I) - - - canAIControl() - return ((src.aiControlDisabled!=1) && (!src.isAllPowerCut())); - - - canAIHack() - return ((src.aiControlDisabled==1) && (!src.isAllPowerCut())); - - - canSynControl() - return (src.synDoorHacked && (!src.isAllPowerCut())); - - - canSynHack(obj/item/device/hacktool/H) - return (in_range(src, usr) && get_dist(src, H) <= 1 && src.synDoorHacked==0 && !src.isAllPowerCut()); - - - -/* -About the new airlock wires panel: -* An airlock wire dialog can be accessed by the normal way or by using wirecutters or a multitool on the door while the wire-panel is open. This would show the following wires, which you can either wirecut/mend or send a multitool pulse through. There are 9 wires. -* one wire from the ID scanner. Sending a pulse through this flashes the red light on the door (if the door has power). If you cut this wire, the door will stop recognizing valid IDs. (If the door has 0000 access, it still opens and closes, though) -* two wires for power. 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). 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 \red open, but bolts-raising will not work. Cutting these wires may electrocute the user. -* one wire for door bolts. Sending a pulse through this drops door bolts (whether the door is powered or not) or raises them (if it is). Cutting this wire also drops the door bolts, and mending it does not raise them. If the wire is cut, trying to raise the door bolts will not work. -* 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). Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. -* one wire for opening the door. Sending a pulse through this while the door has power makes it open the door if no access is required. -* one wire for AI control. Sending a pulse through this blocks AI control for a second or so (which is enough to see the AI control light on the panel dialog go off and back on again). 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. -* one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. (Currently it is also STAYING electrified until someone mends the wire) -*/ - - pulse(var/wireColor) - //var/wireFlag = airlockWireColorToFlag[wireColor] //not used in this function - var/wireIndex = airlockWireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - animate("deny") - if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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). - src.loseMainPower() - if (AIRLOCK_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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - else - if(src.arePowerSystemsOn()) //only can raise bolts if power's on - src.locked = 0 - usr << "You hear a click from inside the door." - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //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). - src.loseBackupPower() - if (AIRLOCK_WIRE_AI_CONTROL) - if (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if (src.secondsElectrified==0) - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_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 - if (!src.requiresID() || src.check_access(null)) - if (src.density) - open() - else - close() - if(AIRLOCK_WIRE_CRUSH) - src.forcecrush = !src.forcecrush - if(AIRLOCK_WIRE_LIGHT) - src.safetylight = !src.safetylight - if(AIRLOCK_WIRE_HOLDOPEN) - src.holdopen = !src.holdopen - - cut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_DOOR_BOLTS) - //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) - if (src.locked!=1) - src.locked = 1 - update_icon() - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if (src.secondsElectrified != -1) - src.secondsElectrified = -1 - - mend(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - var/wireIndex = airlockWireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - if (src.secondsElectrified == -1) - src.secondsElectrified = 0 - - getAirlockWires() - var/t1 - var/iterator = 0 - for(var/wiredesc in wire_index) - if(iterator == wirenum) - break - var/is_uncut = src.wires & airlockWireColorToFlag[wire_index[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - if(src.signalers[wire_index[wiredesc]]) - t1 += "Detach signaler" - else - t1 += "Attach signaler" - t1 += "
" - iterator++ - return t1 - - isElectrified() - return (src.secondsElectrified != 0); - - isWireColorCut(var/wireColor) - var/wireFlag = airlockWireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - - isWireCut(var/wireIndex) - var/wireFlag = airlockIndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - - arePowerSystemsOn() - return (src.secondsMainPowerLost==0 || src.secondsBackupPowerLost==0) - - isAllPowerCut() - return ((src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1) || src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2)) && (src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1) || src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - - regainMainPower() - if (src.secondsMainPowerLost > 0) - src.secondsMainPowerLost = 0 - - loseMainPower() - if (src.secondsMainPowerLost <= 0) - src.secondsMainPowerLost = 60 - if (src.secondsBackupPowerLost < 10) - src.secondsBackupPowerLost = 10 - if (!src.spawnPowerRestoreRunning) - src.spawnPowerRestoreRunning = 1 - spawn(0) - var/cont = 1 - while (cont) - sleep(10) - cont = 0 - if (src.secondsMainPowerLost>0) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.secondsMainPowerLost -= 1 - src.updateDialog() - cont = 1 - - if (src.secondsBackupPowerLost>0) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.secondsBackupPowerLost -= 1 - src.updateDialog() - cont = 1 - src.spawnPowerRestoreRunning = 0 - src.updateDialog() - - loseBackupPower() - if (src.secondsBackupPowerLost < 60) - src.secondsBackupPowerLost = 60 - - regainBackupPower() - if (src.secondsBackupPowerLost > 0) - src.secondsBackupPowerLost = 0 - - // shock user with probability prb (if all connections & power are working) - // returns 1 if shocked, 0 otherwise - // The preceding comment was borrowed from the grille's shock script - shock(mob/user, prb) - if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock - return 0 - if(!prob(prb)) - return 0 //you lucked out, no shock for you - if(istype(usr.equipped(),/obj/item/weapon/shard)) - return 0 - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() //sparks always. - if (electrocute_mob(user, get_area(src), src)) - return 1 - else - return 0 - - prison_open() - src.locked = 0 - src.open() - src.locked = 1 - return - - - -/obj/machinery/door/airlock/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained() ) - return - if (href_list["close"]) - usr << browse(null, "window=airlock") - if (usr.machine==src) - usr.machine = null - return - if(in_range(src, usr) && istype(src.loc, /turf) && p_open) - usr.machine = src - if (href_list["wires"]) - var/t1 = text2num(href_list["wires"]) - if (!(istype(usr.equipped(), /obj/item/weapon/wirecutters) || istype(usr.equipped(),/obj/item/weapon/shard))) - usr << "You need wirecutters!" - return - if (src.isWireColorCut(t1) && istype(usr.equipped(), /obj/item/weapon/wirecutters)) - src.mend(t1) - else - src.cut(t1) - else if (href_list["pulse"]) - var/t1 = text2num(href_list["pulse"]) - if (!istype(usr.equipped(), /obj/item/device/multitool)) - usr << "You need a multitool!" - return - if (src.isWireColorCut(t1)) - usr << "You can't pulse a cut wire." - return - else - src.pulse(t1) - else if(href_list["signaler"]) - var/wirenum = text2num(href_list["signaler"]) - if(!istype(usr.equipped(), /obj/item/device/assembly/signaler)) - usr << "You need a signaller!" - return - if(src.isWireColorCut(wirenum)) - usr << "You can't attach a signaller to a cut wire." - return - var/obj/item/device/assembly/signaler/R = usr.equipped() - if(R.secured) - usr << "This radio can't be attached!" - return - var/mob/M = usr - M.drop_item() - R.loc = src - R.airlock_wire = wirenum - src.signalers[wirenum] = R - else if(href_list["remove-signaler"]) - var/wirenum = text2num(href_list["remove-signaler"]) - if(!(src.signalers[wirenum])) - usr << "There's no signaller attached to that wire!" - return - var/obj/item/device/assembly/signaler/R = src.signalers[wirenum] - R.loc = usr.loc - R.airlock_wire = null - src.signalers[wirenum] = null - - src.update_icon() - add_fingerprint(usr) - src.updateUsrDialog() - else //AI or Syndicate using hacktool - if (!src.canAIControl() || (istype(usr.equipped(), /obj/item/device/hacktool/) && (!src.canSynControl() || !in_range(src, usr)))) - usr << "Airlock control connection lost!" - return - //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door - //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door - if (href_list["aiDisable"]) - var/code = text2num(href_list["aiDisable"]) - switch (code) - if (1) - //disable idscan - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - usr << "The IdScan wire has been cut - So, you can't disable it, but it is already disabled anyways." - else if (src.aiDisabledIdScanner) - usr << "You've already disabled the IdScan feature." - else - src.aiDisabledIdScanner = 1 - if (2) - //disrupt main power - if (src.secondsMainPowerLost == 0) - src.loseMainPower() - else - usr << "Main power is already offline." - if (3) - //disrupt backup power - if (src.secondsBackupPowerLost == 0) - src.loseBackupPower() - else - usr << "Backup power is already offline." - if (4) - //drop door bolts - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - usr << "You can't drop the door bolts - The door bolt dropping wire has been cut." - else if (src.locked!=1) - src.locked = 1 - update_icon() - if (5) - //un-electrify door - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("Can't un-electrify the airlock - The electrification wire is cut.
\n") - else if (src.secondsElectrified==-1) - src.secondsElectrified = 0 - else if (src.secondsElectrified>0) - src.secondsElectrified = 0 - if (7) - //close door - if (src.welded) - usr << text("The airlock has been welded shut!
\n") - else if (src.locked) - usr << text("The door bolts are down!
\n") - else if (!src.density) - close() - else - usr << text("The airlock is already closed.
\n") - if (8) - if(!src.forcecrush) - usr << text("Door extra force not enabled!
\n") - else - src.forcecrush = 0 - if (9) - if(!src.safetylight) - usr << text("Bolt indication light not enabled!
\n") - else - src.safetylight = 0 - if (10) - if(!src.holdopen) - usr << text("Door Behavior already set to: Wait for clearance to close
\n") - else - src.holdopen = 0 - - else if (href_list["aiEnable"]) - var/code = text2num(href_list["aiEnable"]) - switch (code) - if (1) - //enable idscan - if (src.isWireCut(AIRLOCK_WIRE_IDSCAN)) - usr << "You can't enable IdScan - The IdScan wire has been cut." - else if (src.aiDisabledIdScanner) - src.aiDisabledIdScanner = 0 - else - usr << "The IdScan feature is not disabled." - if (4) - //raise door bolts - if (src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) - usr << text("The door bolt drop wire is cut - you can't raise the door bolts.
\n") - else if (!src.locked) - usr << text("The door bolts are already up.
\n") - else - if (src.arePowerSystemsOn()) - src.locked = 0 - update_icon() - else - usr << text("Cannot raise door bolts due to power failure.
\n") - - if (5) - //electrify door for 30 seconds - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("The electrification wire has been cut.
\n") - else if (src.secondsElectrified==-1) - usr << text("The door is already indefinitely electrified. You'd have to un-electrify it before you can re-electrify it with a non-forever duration.
\n") - else if (src.secondsElectrified!=0) - usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") - else - src.secondsElectrified = 30 - spawn(10) - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - src.updateUsrDialog() - sleep(10) - if (6) - //electrify door indefinitely - if (src.isWireCut(AIRLOCK_WIRE_ELECTRIFY)) - usr << text("The electrification wire has been cut.
\n") - else if (src.secondsElectrified==-1) - usr << text("The door is already indefinitely electrified.
\n") - else if (src.secondsElectrified!=0) - usr << text("The door is already electrified. You can't re-electrify it while it's already electrified.
\n") - else - src.secondsElectrified = -1 - if (7) - //open door - if (src.welded) - usr << text("The airlock has been welded shut!
\n") - else if (src.locked) - usr << text("The door bolts are down!
\n") - else if (src.density) - open() - // close() - else - usr << text("The airlock is already opened.
\n") - if (8) - if(src.forcecrush) - usr << text("Door extra force already enabled!
\n") - else - src.forcecrush = 1 - if (9) - if(src.safetylight) - usr << text("Bolt indication light already enabled!
\n") - else - src.safetylight = 1 - if (10) - if(src.holdopen) - usr << text("Door Behavior already set to: Automatically close
\n") - else - src.holdopen = 1 - - src.update_icon() - src.updateUsrDialog() - if((istype(usr.equipped(), /obj/item/device/hacktool))) - return attack_ai(usr, usr.equipped()) - return - - - - -/obj/machinery/door/airlock/secure - name = "Secure Airlock" - desc = "Good lord, at least they left out the overcomplicated death traps. Looks to be a layer of armor plate you might be able to remove with a wrench." - icon = 'Doorhatchele.dmi' - - wires = 65535 - wirenum = 16 - alert_probability = 20 - holdopen = 0 - signalers = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - var - list/WireColorToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/IndexToFlag = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - is_detached = 0 - - - - New() - ..() - //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else). - var/flagIndex = 1 - for (var/flag=1, flag<65536, flag+=flag) - var/valid = 0 - while (!valid) - var/colorIndex = rand(1, 16) - if (WireColorToFlag[colorIndex] == 0) - valid = 1 - WireColorToFlag[colorIndex] = flag - IndexToFlag[flagIndex] = flag - IndexToWireColor[flagIndex] = colorIndex - WireColorToIndex[colorIndex] = flagIndex - flagIndex+=1 - return - - - isWireColorCut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - return ((src.wires & wireFlag) == 0) - - isWireCut(var/wireIndex) - var/wireFlag = IndexToFlag[wireIndex] - return ((src.wires & wireFlag) == 0) - - pulse(var/wireColor) - var/wireIndex = WireColorToIndex[wireColor] - switch(wireIndex) - if(AIRLOCK_WIRE_IDSCAN) - //Sending a pulse through this flashes the red light on the door (if the door has power). - if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) - animate("deny") - if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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). - src.loseMainPower() - if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - else - if(src.arePowerSystemsOn()) //only can raise bolts if power's on - src.locked = 0 - usr << "You hear a click from inside the door." - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - update_icon() - - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //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). - src.loseBackupPower() - if (AIRLOCK_WIRE_AI_CONTROL) - if (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateDialog() - spawn(10) - if (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds. - if (src.secondsElectrified==0) - src.secondsElectrified = 30 - spawn(10) - //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 - while (src.secondsElectrified>0) - src.secondsElectrified-=1 - if (src.secondsElectrified<0) - src.secondsElectrified = 0 - // src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite - sleep(10) - if(AIRLOCK_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 - if (!src.requiresID() || src.check_access(null)) - if (src.density) - open() - else - close() - if(AIRLOCK_WIRE_CRUSH) - src.forcecrush = !src.forcecrush - if(AIRLOCK_WIRE_LIGHT) - src.safetylight = !src.safetylight - if(AIRLOCK_WIRE_HOLDOPEN) - src.holdopen = !src.holdopen - if(AIRLOCK_WIRE_ALERTAI) - if(prob(alert_probability)) - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - - cut(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] - wires &= ~wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - //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. - src.loseMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) - //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) - if (src.locked!=1) - src.locked = 1 - update_icon() - src.updateUsrDialog() - if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) - //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 (!src.locked) - src.locked = 1 - src.updateUsrDialog() - update_icon() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. - src.loseBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 0) - src.aiControlDisabled = 1 - else if (src.aiControlDisabled == -1) - src.aiControlDisabled = 2 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. - if (src.secondsElectrified != -1) - src.secondsElectrified = -1 - if(AIRLOCK_WIRE_ALERTAI) - if(prob(alert_probability)) - for (var/mob/living/silicon/ai/aiPlayer in world) - if (aiPlayer.stat != 2) - aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - for (var/mob/living/silicon/robot/robotPlayer in world) - if (robotPlayer.stat != 2) - robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) - - mend(var/wireColor) - var/wireFlag = WireColorToFlag[wireColor] - var/wireIndex = WireColorToIndex[wireColor] //not used in this function - wires |= wireFlag - switch(wireIndex) - if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))) - src.regainMainPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) - if ((!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!src.isWireCut(AIRLOCK_WIRE_BACKUP_POWER2))) - src.regainBackupPower() - src.shock(usr, 50) - src.updateUsrDialog() - if (AIRLOCK_WIRE_AI_CONTROL) - //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 (src.aiControlDisabled == 1) - src.aiControlDisabled = 0 - else if (src.aiControlDisabled == 2) - src.aiControlDisabled = -1 - src.updateUsrDialog() - if (AIRLOCK_WIRE_ELECTRIFY) - if (src.secondsElectrified == -1) - src.secondsElectrified = 0 - - getAirlockWires() - var/t1 - var/iterator = 0 - for(var/wiredesc in wire_index) - if(iterator == wirenum) - break - var/is_uncut = src.wires & WireColorToFlag[wire_index[wiredesc]] - t1 += "[wiredesc] wire: " - if(!is_uncut) - t1 += "Mend" - else - t1 += "Cut " - t1 += "Pulse " - if(src.signalers[wire_index[wiredesc]]) - t1 += "Detach signaler" - else - t1 += "Attach signaler" - t1 += "
" - iterator++ - return t1 - - attackby(C as obj, mob/user as mob) - //world << text("airlock attackby src [] obj [] mob []", src, C, user) - if(istype(C, /obj/item/device/detective_scanner)) - return - if(!src.is_detached) - if (!istype(usr, /mob/living/silicon)) - if (src.isElectrified()) - if(src.shock(user, 75)) - return - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/device/hacktool)) - return src.attack_ai(user, C) - else if (istype(C, /obj/item/weapon/wrench)) - user << "You start to remove the armor plate..." - if(do_after(user,30)) - user << "Armor plates removed" - src.is_detached = 1 - else - if (istype(C, /obj/item/weapon/wrench)) - user << "You start to reattach the armor plate..." - if(do_after(user,30)) - user << "Armor plates attached" - src.is_detached = 0 - else - return ..(C, user) - if (src.isElectrified()) - if(src.shock(user, 75)) - return - src.add_fingerprint(user) if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) var/obj/item/weapon/weldingtool/W = C From bd756112a184e98d9d32c8631d4f7e1a7b0e98c9 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 14:18:49 -0700 Subject: [PATCH 09/19] There. That /should/ make it work. --- code/game/machinery/doors/airlock.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 1cb1a6ca9a..914cb684b5 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -704,7 +704,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. spawn(20*multiplier) user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." sleep(25*multiplier) - if (src.canSynControl()) + if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) user << "Hack cancelled, control already possible." src.synHacking=0 I.in_use = 0 @@ -747,7 +747,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. src.synHacking=0 I.in_use = 0 return - else if (src.canSynControl()) + else if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) user << "Local override already in place, hack aborted." src.synHacking=0 I.in_use = 0 @@ -759,7 +759,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. src.synHacking=0 I.in_use = 0 return - else if (src.canSynControl()) + else if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) user << "Upload access aborted, local override already in place." src.synHacking=0 I.in_use = 0 From b5f271c18d555f0e3ff3d67b0eaf759ceb0de641 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 15:08:21 -0700 Subject: [PATCH 10/19] .dme stuff --- baystation12.dme | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/baystation12.dme b/baystation12.dme index e179fa09ad..80277811e6 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -144,10 +144,7 @@ #define FILE_DIR "code/unused/spacecraft" #define FILE_DIR "code/WorkInProgress" #define FILE_DIR "code/WorkInProgress/Cael_Aislinn" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Jumper" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Rust" #define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Tajara" -#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/tajara_sprites" #define FILE_DIR "code/WorkInProgress/mapload" #define FILE_DIR "code/WorkInProgress/Mini" #define FILE_DIR "code/WorkInProgress/organs" @@ -179,7 +176,6 @@ #define FILE_DIR "icons/vending_icons" #define FILE_DIR "interface" #define FILE_DIR "maps" -#define FILE_DIR "maps/backup" #define FILE_DIR "sound" #define FILE_DIR "sound/ambience" #define FILE_DIR "sound/announcer" @@ -521,7 +517,7 @@ #include "code\game\machinery\computer\id.dm" #include "code\game\machinery\computer\lockdown.dm" #include "code\game\machinery\computer\medical.dm" -#include "code\game\machinery\computer\operating.dm" +#include "code\game\machinery\computer\Operating.dm" #include "code\game\machinery\computer\power.dm" #include "code\game\machinery\computer\robot.dm" #include "code\game\machinery\computer\security.dm" From 7b0a083a687cc160766e90381a6540e308b78bd9 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 8 Feb 2012 18:45:25 -0500 Subject: [PATCH 11/19] merge form upstream/master --- code/game/jobs/job_controller.dm | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 0ffb81b43e..5bea81d596 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -44,6 +44,12 @@ var/global/datum/controller/occupations/job_master return null + proc/GetAltTitle(mob/new_player/player, rank) + . = player.preferences.GetAltTitle(GetJob(rank)) + world << "AT: [rank]: [.]" + return . + + proc/AssignRole(var/mob/new_player/player, var/rank, var/latejoin = 0) Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]") if((player) && (player.mind) && (rank)) @@ -56,6 +62,7 @@ var/global/datum/controller/occupations/job_master if((job.current_positions < position_limit) || position_limit == -1) Debug("Player: [player] is now Rank: [rank], JCP:[job.current_positions], JPL:[position_limit]") player.mind.assigned_role = rank + player.mind.role_alt_title = GetAltTitle(player, rank) unassigned -= player job.current_positions++ return 1 @@ -83,6 +90,7 @@ var/global/datum/controller/occupations/job_master for(var/mob/new_player/player in world) if((player) && (player.mind)) player.mind.assigned_role = null + player.mind.role_alt_title = null player.mind.special_role = null SetupOccupations() unassigned = list() @@ -207,12 +215,16 @@ var/global/datum/controller/occupations/job_master else H << "Your job is [rank] and the game just can't handle it! Please report this bug to an administrator." - spawnId(H,rank) + if(H.mind.assigned_role == rank && H.mind.role_alt_title) + spawnId(H, rank, H.mind.role_alt_title) + else + spawnId(H, rank) H << "You are the [rank]." H << "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this." H.job = rank - if(H.mind) + if(H.mind && H.mind.assigned_role != rank) H.mind.assigned_role = rank + H.mind.role_alt_title = null if(!joined_late && rank != "Tourist") var/obj/S = null @@ -239,8 +251,9 @@ var/global/datum/controller/occupations/job_master return 1 - proc/spawnId(var/mob/living/carbon/human/H, rank) + proc/spawnId(var/mob/living/carbon/human/H, rank, title) if(!H) return 0 + if(!title) title = rank var/obj/item/weapon/card/id/C = null switch(rank) if("Cyborg") @@ -249,11 +262,11 @@ var/global/datum/controller/occupations/job_master C = new /obj/item/weapon/card/id/gold(H) else C = new /obj/item/weapon/card/id(H) - if(C) + if(C) C.registered_name = H.real_name - C.assignment = rank + C.assignment = title C.name = "[C.registered_name]'s ID Card ([C.assignment])" - C.access = get_access(C.assignment) + C.access = get_access(rank) H.equip_if_possible(C, H.slot_wear_id) if(!H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_r_store)) H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_ears) From 8b4c314fa4d4640ebdb964688745d62890393119 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 8 Feb 2012 19:15:40 -0500 Subject: [PATCH 12/19] fixed livestock bugs other livestock commit whoops --- code/WorkInProgress/Tastyfish/livestock.dm | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/code/WorkInProgress/Tastyfish/livestock.dm b/code/WorkInProgress/Tastyfish/livestock.dm index 9c9e7cc495..36d2ba6385 100644 --- a/code/WorkInProgress/Tastyfish/livestock.dm +++ b/code/WorkInProgress/Tastyfish/livestock.dm @@ -6,9 +6,9 @@ speak_chance = 1 turns_per_move = 15 meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat - response_help = "pets " - response_disarm = "gently pushes aside " - response_harm = "kicks " + response_help = "pets" + response_disarm = "gently pushes aside" + response_harm = "kicks" var/max_nutrition = 100 // different animals get hungry faster, basically number of 5-second steps from full to starving (60 == 5 minutes) var/nutrition_step // cycle step in nutrition system var/obj/movement_target // eating-ing target @@ -17,6 +17,9 @@ if(!nutrition) nutrition = max_nutrition * 0.33 // at 1/3 nutrition + reagents = new() + reagents.my_atom = src + Life() ..() @@ -38,12 +41,14 @@ if(nutrition >= max_nutrition) return - if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) )) + if((movement_target) && !(isturf(movement_target.loc))) movement_target = null - stop_automated_movement = 0 + a_intent = "help" + turns_per_move = initial(turns_per_move) if( !movement_target || !(movement_target.loc in oview(src, 3)) ) movement_target = null - stop_automated_movement = 0 + a_intent = "help" + turns_per_move = initial(turns_per_move) for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3)) if(isturf(S.loc) || ishuman(S.loc)) movement_target = S From 710bcbb42bc792ebe31c6537f721130135de399c Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Wed, 8 Feb 2012 17:42:34 -0700 Subject: [PATCH 13/19] Final parts for the airlocks. Wrench -> Weld -> Wrench removes the cover secure/centcom has all wires electrocute Emag is now tweaked Implanted uplink now works. --- code/WorkInProgress/Ported/Abi79/uplinks.dm | 34 ++- code/game/gamemodes/game_mode.dm | 2 +- code/game/machinery/doors/airlock.dm | 242 +++++++++++++++--- .../objects/closets/secure/engineering.dm | 1 + code/game/objects/items/weapons/cards_ids.dm | 2 +- 5 files changed, 236 insertions(+), 45 deletions(-) diff --git a/code/WorkInProgress/Ported/Abi79/uplinks.dm b/code/WorkInProgress/Ported/Abi79/uplinks.dm index b6bcefe1f8..85ffa1f891 100644 --- a/code/WorkInProgress/Ported/Abi79/uplinks.dm +++ b/code/WorkInProgress/Ported/Abi79/uplinks.dm @@ -187,7 +187,17 @@ A list of items and costs is stored under the datum of every game mode, alongsid //A Syndicate uplink disguised as a portable radio /obj/item/device/uplink/radio/implanted - uses = 5 + New() + ..() + uses = 5 + return + + explode() + var/obj/item/weapon/implant/uplink/U = src.loc + var/mob/living/A = U.imp_in + A.gib() + ..() + /obj/item/device/uplink/radio name = "ship bounced radio" @@ -228,12 +238,10 @@ A list of items and costs is stored under the datum of every game mode, alongsid if (usr.stat || usr.restrained()) return - var/mob/living/carbon/human/H = usr - - if (!( istype(H, /mob/living/carbon/human))) + if (!( istype(usr, /mob/living/carbon/human))) return 1 - if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)))) + if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf)) || istype(src.loc,/obj/item/weapon/implant/uplink))) usr.machine = src if(href_list["buy_item"]) @@ -241,6 +249,9 @@ A list of items and costs is stored under the datum of every game mode, alongsid var/path_obj = text2path(href_list["buy_item"]) var/item = new path_obj(get_turf(src.loc)) var/mob/A = src.loc + if(istype(src.loc,/obj/item/weapon/implant/uplink)) + var/obj/item/weapon/implant/uplink/U = src.loc + A = U.imp_in if(ismob(A) && !(locate(item) in NotInHand)) //&& !istype(item, /obj/spawner)) if(!A.r_hand) item:loc = A @@ -295,12 +306,13 @@ A list of items and costs is stored under the datum of every game mode, alongsid else if (href_list["clear_selfdestruct"]) src.temp = null - if (istype(src.loc, /mob)) - attack_self(src.loc) - else - for(var/mob/M in viewers(1, src)) - if (M.client) - src.attack_self(M) + attack_self(usr) +// if (istype(src.loc, /mob)) +// attack_self(src.loc) +// else +// for(var/mob/M in viewers(1, src)) +// if (M.client) +// src.attack_self(M) return proc/explode() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 9b012b32b8..df605dd7d0 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -48,7 +48,7 @@ Stealth and Camouflage Items; /obj/item/weapon/stamperaser:1:Stamp Remover; Whitespace:Seperator; Devices and Tools; -/obj/item/weapon/card/emag:5:Cryptographic Sequencer (Limited uses, almost full access); +/obj/item/weapon/card/emag:4:Cryptographic Sequencer (Limited uses, almost full access); /obj/item/device/hacktool:3:Hacktool (Slow, but stealthy. Unlimited uses); /obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; /obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 914cb684b5..920351ba8c 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -537,6 +537,9 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. if (!src.canSynControl() && src.canSynHack(C)) src.synhack(user, C) return + if(!src.canSynHack(C)) + user << "The power is cut or something, I can't hack it!" + return if(istype(C, /obj/item/device/hacktool/engineer)) return else @@ -692,19 +695,19 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. synhack(mob/user as mob, obj/item/device/hacktool/I) if (src.synHacking==0) - var/multiplier = 1 - if(istype(C, /obj/item/device/hacktool/engineer)) + var/multiplier = 1.5 + if(istype(I, /obj/item/device/hacktool/engineer)) if(!src.locked) user << "The door bolts are already up!" return - multiplier++ + multiplier -= 0.5 src.synHacking=1 I.in_use = 1 user << "You begin hacking..." spawn(20*multiplier) user << "Jacking in. Stay close to the airlock or you'll rip the cables out and we'll have to start over." sleep(25*multiplier) - if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) + if (src.canSynControl() && !istype(I, /obj/item/device/hacktool/engineer)) user << "Hack cancelled, control already possible." src.synHacking=0 I.in_use = 0 @@ -723,7 +726,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. var/list/cameras = list() for (var/obj/machinery/camera/C in src.loc.loc.contents) // getting all cameras in the area cameras += C - var/alertoption = (prob(alert_probability) || istype(C, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability + var/alertoption = (prob(alert_probability) || istype(I, /obj/item/device/hacktool/engineer)) // Chance of warning AI, based on doortype's probability if(alertoption) if(prob(15)) //15% chance of sending the AI all the details (camera, area, warning) alertoption = 3 @@ -747,7 +750,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. src.synHacking=0 I.in_use = 0 return - else if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) + else if (src.canSynControl() && !istype(I, /obj/item/device/hacktool/engineer)) user << "Local override already in place, hack aborted." src.synHacking=0 I.in_use = 0 @@ -759,7 +762,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. src.synHacking=0 I.in_use = 0 return - else if (src.canSynControl() && !istype(C, /obj/item/device/hacktool/engineer)) + else if (src.canSynControl() && !istype(I, /obj/item/device/hacktool/engineer)) user << "Upload access aborted, local override already in place." src.synHacking=0 I.in_use = 0 @@ -767,9 +770,11 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. user << "Transfer complete. Forcing airlock to execute program." sleep(25*multiplier) //disable blocked control - if(istype(C, /obj/item/device/hacktool/engineer)) + if(istype(I, /obj/item/device/hacktool/engineer)) user << "Raising door bolts..." + src.synHacking = 0 src.locked = 0 + I.in_use = 0 update_icon() return src.synDoorHacked = 1 @@ -1272,6 +1277,7 @@ About the new airlock wires panel: list/IndexToWireColor = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) list/WireColorToIndex = list(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) is_detached = 0 + removal_step = 0 @@ -1483,36 +1489,208 @@ About the new airlock wires panel: //world << text("airlock attackby src [] obj [] mob []", src, C, user) if(istype(C, /obj/item/device/detective_scanner)) return - if(!src.is_detached) + if(!src.is_detached && C) if (!istype(usr, /mob/living/silicon)) if (src.isElectrified()) if(src.shock(user, 75)) return - - src.add_fingerprint(user) - if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) - var/obj/item/weapon/weldingtool/W = C - if(W.remove_fuel(0,user)) - if (!src.welded) - src.welded = 1 - else - src.welded = null - src.update_icon() - return - else - return - else if (istype(C, /obj/item/device/hacktool)) + if (istype(C, /obj/item/device/hacktool)) return src.attack_ai(user, C) - else if (istype(C, /obj/item/weapon/wrench)) - user << "You start to remove the armor plate..." - if(do_after(user,30)) - user << "Armor plates removed" - src.is_detached = 1 + src.add_fingerprint(user) + switch(removal_step) + if(0) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + if (!src.welded) + src.welded = 1 + else + src.welded = null + src.update_icon() + return + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start to remove the bolts..." + if(do_after(user,30)) + user << "Bolts removed" + src.removal_step = 1 + if(1) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + user << "You start to slice the armor..." + if(do_after(user,20)) + user << "Armor sliced open" + src.removal_step = 2 + return + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start wrench down the bolts..." + if(do_after(user,30)) + user << "Bolts secured." + src.removal_step = 0 + if(2) + if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density)) + var/obj/item/weapon/weldingtool/W = C + if(W.remove_fuel(0,user)) + user << "You start to fuse together the armor..." + if(do_after(user,20)) + user << "Armor repaired" + src.removal_step = 1 + return + else if (istype(C, /obj/item/weapon/wrench)) + user << "You start to unfasted the armor from the circuits..." + if(do_after(user,40)) + user << "Circuits exposed." + src.removal_step = 3 + src.is_detached = 1 else if (istype(C, /obj/item/weapon/wrench)) - user << "You start to reattach the armor plate..." - if(do_after(user,30)) - user << "Armor plates attached" + user << "You start to fix the armor plate..." + if(do_after(user,40)) + user << "Armor plates are back in position." src.is_detached = 0 + src.removal_step = 2 else - return ..(C, user) \ No newline at end of file + return ..(C, user) + + centcom + name = "CentCom Secure Airlock" + desc = "I hope you have insulated gloves...." + icon = 'Doorhatchele.dmi' + + pulse(var/wireColor) + if (src.secondsElectrified==0) + src.secondsElectrified = 10 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 +// src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + var/wireIndex = WireColorToIndex[wireColor] + switch(wireIndex) + if(AIRLOCK_WIRE_IDSCAN) + //Sending a pulse through this flashes the red light on the door (if the door has power). + if ((src.arePowerSystemsOn()) && (!(stat & NOPOWER))) + animate("deny") + if (AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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). + src.loseMainPower() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + else + if(src.arePowerSystemsOn()) //only can raise bolts if power's on + src.locked = 0 + usr << "You hear a click from inside the door." + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //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). + src.loseBackupPower() + if (AIRLOCK_WIRE_AI_CONTROL) + if (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateDialog() + spawn(10) + if (src.aiControlDisabled == 1) + src.aiControlDisabled = 0 + else if (src.aiControlDisabled == 2) + src.aiControlDisabled = -1 + src.updateDialog() + if(AIRLOCK_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 + if (!src.requiresID() || src.check_access(null)) + if (src.density) + open() + else + close() + if(AIRLOCK_WIRE_CRUSH) + src.forcecrush = !src.forcecrush + if(AIRLOCK_WIRE_LIGHT) + src.safetylight = !src.safetylight + if(AIRLOCK_WIRE_HOLDOPEN) + src.holdopen = !src.holdopen + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + + cut(var/wireColor) + if (src.secondsElectrified==0) + src.secondsElectrified = 30 + spawn(10) + //TODO: Move this into process() and make pulsing reset secondsElectrified to 30 + while (src.secondsElectrified>0) + src.secondsElectrified-=1 + if (src.secondsElectrified<0) + src.secondsElectrified = 0 +// src.updateUsrDialog() //Commented this line out to keep the airlock from clusterfucking you with electricity. --NeoFite + sleep(10) + var/wireFlag = WireColorToFlag[wireColor] + var/wireIndex = WireColorToIndex[wireColor] + wires &= ~wireFlag + switch(wireIndex) + if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2) + //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. + src.loseMainPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_DOOR_BOLTS, AIRLOCK_WIRE_DOOR_BOLTS_2) + //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) + if (src.locked!=1) + src.locked = 1 + update_icon() + src.updateUsrDialog() + if (AIRLOCK_WIRE_FAKEBOLT1, AIRLOCK_WIRE_FAKEBOLT2) + //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 (!src.locked) + src.locked = 1 + src.updateUsrDialog() + update_icon() + if (AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2) + //Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user. + src.loseBackupPower() + src.shock(usr, 50) + src.updateUsrDialog() + if (AIRLOCK_WIRE_AI_CONTROL) + //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 (src.aiControlDisabled == 0) + src.aiControlDisabled = 1 + else if (src.aiControlDisabled == -1) + src.aiControlDisabled = 2 + src.updateUsrDialog() + if (AIRLOCK_WIRE_ELECTRIFY) + //Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted. + if (src.secondsElectrified != -1) + src.secondsElectrified = -1 + if(AIRLOCK_WIRE_ALERTAI) + if(prob(alert_probability)) + for (var/mob/living/silicon/ai/aiPlayer in world) + if (aiPlayer.stat != 2) + aiPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) + for (var/mob/living/silicon/robot/robotPlayer in world) + if (robotPlayer.stat != 2) + robotPlayer.triggerUnmarkedAlarm("AirlockHacking", src.loc.loc) \ No newline at end of file diff --git a/code/game/objects/closets/secure/engineering.dm b/code/game/objects/closets/secure/engineering.dm index f5bb2fefd0..516d6b35fb 100644 --- a/code/game/objects/closets/secure/engineering.dm +++ b/code/game/objects/closets/secure/engineering.dm @@ -9,6 +9,7 @@ new /obj/item/wardrobe/chief_engineer(src) new /obj/item/wardrobe/chief_engineer(src) new /obj/item/blueprints(src) + new /obj/item/device/hacktool/engineer(src) return diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 83ec575d26..37d1370d4a 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -24,7 +24,7 @@ FINGERPRINT CARD New() ..() - uses = rand(3,7) + uses = rand(3,5) return // DATA CARDS From 0ebbe456b3b7fa76813d2d81ea013ba7f96cf4e2 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 8 Feb 2012 20:43:04 -0500 Subject: [PATCH 14/19] job titles --- code/datums/mind.dm | 5 +++- code/game/gamemodes/cult/cult.dm | 6 ++-- code/game/gamemodes/objective.dm | 18 ++++++------ code/game/gamemodes/revolution/revolution.dm | 4 +-- code/game/jobs/job/civilian_chaplain.dm | 3 +- code/game/jobs/job/job.dm | 3 ++ code/game/jobs/job/medical.dm | 5 ++-- code/game/jobs/job/science.dm | 1 + code/game/jobs/job/security.dm | 1 + code/game/jobs/job_controller.dm | 4 +-- code/game/jobs/jobs.dm | 4 +-- code/game/machinery/computer/computer.dm | 4 +-- code/modules/admin/admin.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 1 + code/modules/mob/new_player/new_player.dm | 4 +-- code/modules/mob/new_player/preferences.dm | 31 ++++++++++++++++++-- code/modules/mob/new_player/savefile.dm | 6 ++++ 17 files changed, 72 insertions(+), 30 deletions(-) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 5466ab60ef..5457a2832c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -9,6 +9,8 @@ datum/mind var/assigned_role var/special_role + var/role_alt_title + var/datum/job/assigned_job var/list/datum/objective/objectives = list() @@ -287,6 +289,7 @@ datum/mind var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() if (!new_role) return assigned_role = new_role + role_alt_title = null else if (href_list["memory_edit"]) var/new_memo = input("Write new memory", "Memory", memory) as null|message @@ -345,7 +348,7 @@ datum/mind new_objective.owner = src new_objective:target = new_target:mind //Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops. - new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]." + new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:role_alt_title ? new_target:mind:role_alt_title : new_target:mind:assigned_role)]." if ("hijack") new_objective = new /datum/objective/hijack diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index f516247850..a4900fb067 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -108,7 +108,7 @@ explanation = "Our knowledge must live on. Make sure at least [acolytes_needed] acolytes escape on the shuttle to spread their work on an another station." if("sacrifice") if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." + explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.role_alt_title ? sacrifice_target.role_alt_title : sacrifice_target.assigned_role]. You will need the sacrifice rune (Hell blood join) and three acolytes to do so." else explanation = "Free objective." if("eldergod") @@ -307,9 +307,9 @@ explanation = "Free objective" else if(sacrificed.Find(sacrifice_target)) - explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. \green Success!" + explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.role_alt_title ? sacrifice_target.role_alt_title : sacrifice_target.assigned_role]. \green Success!" else if(sacrifice_target && sacrifice_target.current) - explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.assigned_role]. \red Failed." + explanation = "Sacrifice [sacrifice_target.current.real_name], the [sacrifice_target.role_alt_title ? sacrifice_target.role_alt_title : sacrifice_target.assigned_role]. \red Failed." else explanation = "Sacrifice Unknown, the Unknown whos body was likely gibbed. \red Failed." if("eldergod") diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index cb2f4a46a8..2f9a9747e3 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -33,7 +33,7 @@ datum/objective/decapitate find_target() ..() if(target && target.current) - explanation_text = "[target.current.real_name], the [target.assigned_role], has defied us for the last time. Make an example of him, and bring us his severed head." + explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role], has defied us for the last time. Make an example of him, and bring us his severed head." else explanation_text = "Free Objective" return target @@ -42,7 +42,7 @@ datum/objective/decapitate find_target_by_role(role, role_type=0) ..(role, role_type) if(target && target.current) - explanation_text = "[target.current.real_name], the [!role_type ? target.assigned_role : target.special_role], has defied us for the last time. Make an example of him, and bring us his severed head." + explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)], has defied us for the last time. Make an example of him, and bring us his severed head." else explanation_text = "Free Objective" return target @@ -66,7 +66,7 @@ datum/objective/assassinate find_target() ..() if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." else explanation_text = "Free Objective" return target @@ -75,7 +75,7 @@ datum/objective/assassinate find_target_by_role(role, role_type=0) ..(role, role_type) if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." else explanation_text = "Free Objective" return target @@ -96,7 +96,7 @@ datum/objective/mutiny find_target() ..() if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." else explanation_text = "Free Objective" return target @@ -105,7 +105,7 @@ datum/objective/mutiny find_target_by_role(role, role_type=0) ..(role, role_type) if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." else explanation_text = "Free Objective" return target @@ -138,7 +138,7 @@ datum/objective/debrain//I want braaaainssss find_target_by_role(role, role_type=0) ..(role, role_type) if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name] the [!role_type ? target.assigned_role : target.special_role]." + explanation_text = "Steal the brain of [target.current.real_name] the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." else explanation_text = "Free Objective" return target @@ -162,7 +162,7 @@ datum/objective/protect//The opposite of killing a dude. find_target() ..() if(target && target.current) - explanation_text = "Protect [target.current.real_name], the [target.assigned_role]." + explanation_text = "Protect [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." else explanation_text = "Free Objective" return target @@ -171,7 +171,7 @@ datum/objective/protect//The opposite of killing a dude. find_target_by_role(role, role_type=0) ..(role, role_type) if(target && target.current) - explanation_text = "Protect [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]." + explanation_text = "Protect [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." else explanation_text = "Free Objective" return target diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 5fe771c796..4210ac52d5 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -72,7 +72,7 @@ var/datum/objective/assassinate/rev_obj = new rev_obj.owner = rev_mind rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.assigned_role]." + rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.role_alt_title ? head_mind.role_alt_title : head_mind.assigned_role]." rev_mind.objectives += rev_obj equip_traitor(rev_mind.current, 1) //changing how revs get assigned their uplink so they can get PDA uplinks. --NEO @@ -102,7 +102,7 @@ var/datum/objective/mutiny/rev_obj = new rev_obj.owner = rev_mind rev_obj.target = head_mind - rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.assigned_role]." + rev_obj.explanation_text = "Assassinate [head_mind.current.real_name], the [head_mind.role_alt_title ? head_mind.role_alt_title : head_mind.assigned_role]." rev_mind.objectives += rev_obj /datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1) diff --git a/code/game/jobs/job/civilian_chaplain.dm b/code/game/jobs/job/civilian_chaplain.dm index 93fa084042..489f5433ab 100644 --- a/code/game/jobs/job/civilian_chaplain.dm +++ b/code/game/jobs/job/civilian_chaplain.dm @@ -7,6 +7,7 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" + alt_titles = list("Counselor") equip(var/mob/living/carbon/human/H) @@ -19,7 +20,7 @@ H.equip_if_possible(new /obj/item/clothing/shoes/black(H), H.slot_shoes) spawn(0) var/religion_name = "Christianity" - var/new_religion = input(H, "You are the Chaplain. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name) + var/new_religion = input(H, "You are the Chaplain / Councelor. For game mechanics purposes, you need to choose a religion either way. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name) if ((length(new_religion) == 0) || (new_religion == "Christianity")) new_religion = religion_name diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index c8ae094586..7a005104b9 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -22,5 +22,8 @@ //Supervisors, who this person answers to directly var/supervisors = "" + //List of alternate titles, if any + var/list/alt_titles + /datum/job/proc/equip(var/mob/living/carbon/human/H) return 1 diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 46484f681d..501200ebcf 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -30,6 +30,7 @@ total_positions = 5 spawn_positions = 3 supervisors = "the chief medical officer" + alt_titles = list("Virologist", "Surgeon") equip(var/mob/living/carbon/human/H) @@ -68,7 +69,7 @@ return 1 - +/* /datum/job/virologist title = "Virologist" flag = VIROLOGIST @@ -90,5 +91,5 @@ H.equip_if_possible(new /obj/item/clothing/suit/storage/labcoat/virologist(H), H.slot_wear_suit) H.equip_if_possible(new /obj/item/device/flashlight/pen(H), H.slot_s_store) return 1 - +*/ diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm index 2aa27c4ead..a764f6e98f 100644 --- a/code/game/jobs/job/science.dm +++ b/code/game/jobs/job/science.dm @@ -28,6 +28,7 @@ total_positions = 5 spawn_positions = 3 supervisors = "the research director" + alt_titles = list("Plasma Researcher", "Xenobiologist") equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index c6c6631fb9..2f4dc783ad 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -68,6 +68,7 @@ total_positions = 1 spawn_positions = 1 supervisors = "the head of security" + alt_titles = list("Forensic Technician") equip(var/mob/living/carbon/human/H) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 5bea81d596..ef382c34ba 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -262,11 +262,11 @@ var/global/datum/controller/occupations/job_master C = new /obj/item/weapon/card/id/gold(H) else C = new /obj/item/weapon/card/id(H) - if(C) + if(C) C.registered_name = H.real_name C.assignment = title C.name = "[C.registered_name]'s ID Card ([C.assignment])" - C.access = get_access(rank) + C.access = get_access(rank) H.equip_if_possible(C, H.slot_wear_id) if(!H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_r_store)) H.equip_if_possible(new /obj/item/weapon/pen(H), H.slot_ears) diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index fc90968815..f831625543 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -22,7 +22,6 @@ var/const CMO =(1<<3) DOCTOR =(1<<4) GENETICIST =(1<<5) - VIROLOGIST =(1<<6) CIVILIAN =(1<<2) @@ -74,8 +73,7 @@ var/list/engineering_positions = list( var/list/medical_positions = list( "Chief Medical Officer", "Medical Doctor", - "Geneticist", - "Virologist" + "Geneticist" ) diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 397de4f9b2..7a168c4d4e 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -189,7 +189,7 @@ Pod/Blast Doors computer L.fields["sex"] = H.gender L.fields["age"] = H.age L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") - L.fields["rank"] = H.mind.assigned_role + L.fields["rank"] = H.mind.role_alt_title ? H.mind.role_alt_title : H.mind.assigned_role L.fields["b_type"] = H.dna.b_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.struc_enzymes @@ -266,7 +266,7 @@ Pod/Blast Doors computer L.fields["sex"] = H.gender L.fields["age"] = H.age L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") - L.fields["rank"] = H.mind.assigned_role + L.fields["rank"] = H.mind.role_alt_title ? H.mind.role_alt_title : H.mind.assigned_role L.fields["b_type"] = H.dna.b_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.struc_enzymes diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index fac90da513..454e0df955 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -335,7 +335,7 @@ jobs += "Chemist+RD+CMO
" jobs += "Geneticist+RD+CMO
" jobs += "MD+CMO
" - jobs += "Virologist+RD+CMO
" + /*jobs += "Virologist+RD+CMO
"*/ jobs += "Scientist+RD
" jobs += "AI+Cyborg
" jobs += "Detective+HoS

" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 1c8d2d9139..8337882b31 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -315,6 +315,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(!record_found)//We have to pick their role if they have no record. if(G_found.mind&&G_found.mind.assigned_role)//But they may have an assigned role already. new_character.mind.assigned_role = G_found.mind.assigned_role//Also makes sure our MODE people are equipped right later on. + new_character.mind.role_alt_title = G_found.mind.role_alt_title else var/assigned_role = input("Please specify which job the character will be respawned as.", "Assigned role") as null|anything in get_all_jobs() if(!assigned_role) new_character.mind.assigned_role = "Assistant"//Defaults to assistant. diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 64f207624f..d864340eff 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -253,9 +253,9 @@ src << alert("[rank] is not available. Please try another.") return 0 + job_master.AssignRole(src, rank, 1) var/mob/living/carbon/human/character = create_character() var/icon/char_icon = getFlatIcon(character,0)//We're creating out own cache so it's not needed. - job_master.AssignRole(character, rank, 1) job_master.EquipRank(character, rank, 1) EquipCustomItems(character) character.loc = pick(latejoin) @@ -327,7 +327,7 @@ L.fields["sex"] = H.gender L.fields["age"] = H.age L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") - L.fields["rank"] = H.mind.assigned_role + L.fields["rank"] = H.mind.role_alt_title ? H.mind.role_alt_title : H.mind.assigned_role L.fields["b_type"] = H.dna.b_type L.fields["b_dna"] = H.dna.unique_enzymes L.fields["enzymes"] = H.dna.struc_enzymes diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm index 4f51f45141..0af5050991 100644 --- a/code/modules/mob/new_player/preferences.dm +++ b/code/modules/mob/new_player/preferences.dm @@ -104,6 +104,8 @@ datum/preferences job_engsec_med = 0 job_engsec_low = 0 + list/job_alt_titles = new() // the default name of a job like "Medical Doctor" + flavor_text = "" // slot stuff @@ -213,6 +215,19 @@ datum/preferences proc/closesave(mob/user) user << browse(null, "window=saves;size=300x640") + proc/GetAltTitle(datum/job/job) + return job_alt_titles.Find(job.title) > 0 \ + ? job_alt_titles[job.title] \ + : job.title + + proc/SetAltTitle(datum/job/job, new_title) + // remove existing entry + if(job_alt_titles.Find(job.title)) + job_alt_titles -= job.title + // add one if it's not default + if(job.title != new_title) + job_alt_titles[job.title] = new_title + proc/SetChoices(mob/user, changedjob) var/HTML = "" HTML += "
" @@ -246,14 +261,17 @@ datum/preferences HTML += "\[Low]" else HTML += "\[NEVER]" - HTML += "
" + if(job.alt_titles) + HTML += " \[[GetAltTitle(job)]\]
" + else + HTML += "
" HTML += "
" HTML += "\[Done\]" HTML += "
" user << browse(null, "window=preferences") - user << browse(HTML, "window=mob_occupation;size=320x600") + user << browse(HTML, "window=mob_occupation;size=350x600") return @@ -378,6 +396,14 @@ datum/preferences return 1 + if(link_tags["alt_title"] && link_tags["job"]) + var/datum/job/job = locate(link_tags["job"]) + var/choices = list(job.title) + job.alt_titles + var/choice = input("Pick a title for [job.title].", "Character Generation", GetAltTitle(job)) as anything in choices | null + if(choice) + SetAltTitle(job, choice) + SetChoices(user) + if(link_tags["real_name"]) var/new_name @@ -638,6 +664,7 @@ datum/preferences job_engsec_high = 0 job_engsec_med = 0 job_engsec_low = 0 + job_alt_titles = new() underwear = 1 be_special = 0 be_random_name = 0 diff --git a/code/modules/mob/new_player/savefile.dm b/code/modules/mob/new_player/savefile.dm index 17f6d826cb..95ba0bdb75 100644 --- a/code/modules/mob/new_player/savefile.dm +++ b/code/modules/mob/new_player/savefile.dm @@ -115,6 +115,8 @@ datum/preferences/proc/savefile_save(mob/user, slot) F["job_engsec_med"] << src.job_engsec_med F["job_engsec_low"] << src.job_engsec_low + F["job_alt_titles"] << job_alt_titles + //Body data F["hair_red"] << src.r_hair F["hair_green"] << src.g_hair @@ -212,6 +214,10 @@ datum/preferences/proc/savefile_load(mob/user, slot) F["job_engsec_med"] >> src.job_engsec_med F["job_engsec_low"] >> src.job_engsec_low + F["job_alt_titles"] >> job_alt_titles + if(!job_alt_titles) + job_alt_titles = new() + //NOTE: Conversion things go inside this if statement //When updating the save file remember to add 1 to BOTH the savefile constants //Also take the old conversion things that no longer apply out of this if From 2dc3a5cc6effa2803f45fa9761ca1531c791f57f Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 8 Feb 2012 20:56:04 -0500 Subject: [PATCH 15/19] fixed horribly buggy camera assembly --- code/modules/chemical/Chemistry-Tools.dm | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/code/modules/chemical/Chemistry-Tools.dm b/code/modules/chemical/Chemistry-Tools.dm index 9f7d5ec418..4adbfcce93 100644 --- a/code/modules/chemical/Chemistry-Tools.dm +++ b/code/modules/chemical/Chemistry-Tools.dm @@ -132,17 +132,27 @@ playsound(src.loc, 'Crowbar.ogg', 50, 1) user << "\blue You remove the remote signalling device." src.state = 3 - new /obj/item/device/assembly/signaler( src.loc, 1 ) + var/obj/item/device/assembly/signaler/S = locate() in src + if(S) + S.loc = src.loc + else + new /obj/item/device/assembly/signaler( src.loc, 1 ) if(isprox(W) && motion == 0) // if(W:amount >= 1) playsound(src.loc, 'Deconstruct.ogg', 50, 1) // W:use(1) user << "\blue You attach the proximity sensor." + user.drop_item() + W.loc = src motion = 1 if(istype(W, /obj/item/weapon/crowbar) && motion) playsound(src.loc, 'Crowbar.ogg', 50, 1) user << "\blue You remove the proximity sensor." - new /obj/item/device/assembly/prox_sensor( src.loc, 1 ) + var/obj/item/device/assembly/prox_sensor/S = locate() in src + if(S) + S.loc = src.loc + else + new /obj/item/device/assembly/prox_sensor( src.loc, 1 ) motion = 0 if(istype(W, /obj/item/stack/sheet/glass)) if(W:amount >= 1) From a7fcef6d450bb0a3579ad0f2a2ead874f052434f Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Thu, 9 Feb 2012 00:17:54 -0500 Subject: [PATCH 16/19] oops, left in debug code --- code/game/jobs/job_controller.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index ef382c34ba..7de7e40134 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -45,9 +45,7 @@ var/global/datum/controller/occupations/job_master proc/GetAltTitle(mob/new_player/player, rank) - . = player.preferences.GetAltTitle(GetJob(rank)) - world << "AT: [rank]: [.]" - return . + return player.preferences.GetAltTitle(GetJob(rank)) proc/AssignRole(var/mob/new_player/player, var/rank, var/latejoin = 0) From 92dc961c10916326d18fa052d263c56b00443c54 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Thu, 9 Feb 2012 01:29:21 -0500 Subject: [PATCH 17/19] disable meteors for now, until atmos fixed --- code/game/events/EventsMain.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/events/EventsMain.dm b/code/game/events/EventsMain.dm index 64ec941423..e8b769d6a9 100644 --- a/code/game/events/EventsMain.dm +++ b/code/game/events/EventsMain.dm @@ -6,7 +6,7 @@ */ -var/list/DisallowedEvents = list(/datum/event/spaceninja, /datum/event/prisonbreak, /datum/event/immovablerod, /datum/event/gravitationalanomaly, /datum/event/alieninfestation) +var/list/DisallowedEvents = list(/datum/event/spaceninja, /datum/event/prisonbreak, /datum/event/immovablerod, /datum/event/gravitationalanomaly, /datum/event/alieninfestation, /datum/event/meteorstorm) var/list/EventTypes = typesof(/datum/event) - /datum/event - DisallowedEvents var/list/OneTimeEvents = list(/datum/event/spacecarp, /datum/event/miniblob) var/datum/event/ActiveEvent = null From 8b62eff01a84c2666265789b9c62d5a08a96f9b5 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Thu, 9 Feb 2012 09:42:08 -0700 Subject: [PATCH 18/19] Cleaned up the fingerprint code Added sanity checks to the clean blood proc. --- code/WorkInProgress/detective_work.dm | 55 +++++++++++--------- code/defines/obj.dm | 1 + code/game/atom_procs.dm | 9 +++- code/game/objects/devices/scanners.dm | 20 ++++--- code/game/objects/items/weapons/cards_ids.dm | 2 +- code/game/objects/items/weapons/manuals.dm | 2 +- 6 files changed, 51 insertions(+), 38 deletions(-) diff --git a/code/WorkInProgress/detective_work.dm b/code/WorkInProgress/detective_work.dm index d4b450ce6e..1ac12140cf 100644 --- a/code/WorkInProgress/detective_work.dm +++ b/code/WorkInProgress/detective_work.dm @@ -83,7 +83,7 @@ obj/machinery/computer/forensic_scanning New() ..() - new /obj/item/weapon/book/manual/detective(get_turf(src)) //DEEEERP + new /obj/item/weapon/book/manual/detective(get_turf(src)) return @@ -187,7 +187,7 @@ obj/machinery/computer/forensic_scanning if(files && files.len) temp = "Criminal Evidence Database

" temp += "Consolidated data points:
" - for(var/i = 1, i < (files.len + 1), i++) + for(var/i = 1, i <= files.len, i++) temp += "{Dossier [i]}
" temp += "
{Insert Finger Print Card}


" else @@ -197,7 +197,7 @@ obj/machinery/computer/forensic_scanning delete_record(text2num(href_list["delete"])) temp += "Auxiliary Evidence Database

" temp += "This is where anything without fingerprints goes.

" - for(var/i = 1, i < (misc.len + 1), i++) + for(var/i = 1, i <= misc.len, i++) var/list/temp_list = misc[i] var/item_name = get_name(temp_list[1]) temp += "{[item_name]}
" @@ -213,7 +213,7 @@ obj/machinery/computer/forensic_scanning if(stringpercent(prints[num2text(2)]) <= FINGERPRINT_COMPLETE) print_string = "Fingerprints: (80% or higher completion reached)
" + prints[num2text(2)] + "
" temp += print_string - for(var/i = 2, i < (dossier.len + 1), i++) + for(var/i = 2, i <= dossier.len, i++) var/list/outputs = dossier[i] var/item_name = get_name(outputs[1]) var/list/prints_len = outputs[2] @@ -222,7 +222,7 @@ obj/machinery/computer/forensic_scanning var/list/fibers = outputs[3] if(fibers && fibers.len) var/dat = "[fibers[1]]" - for(var/j = 2, j < (fibers.len + 1), j++) + for(var/j = 2, j <= fibers.len, j++) dat += ",
      [fibers[j]]" temp += "    Fibers: [dat]
" else @@ -231,7 +231,7 @@ obj/machinery/computer/forensic_scanning if(blood && blood.len) var/dat = "[blood[1]]" if(blood.len > 1) - for(var/j = 2, j < (blood.len + 1), j++) + for(var/j = 2, j <= blood.len, j++) dat += ",
      [blood[j]]" temp += "    Blood: [dat]
" else @@ -253,7 +253,7 @@ obj/machinery/computer/forensic_scanning if(stringpercent(prints[num2text(2)]) <= FINGERPRINT_COMPLETE) print_string = "Fingerprints: " + prints[num2text(2)] + "
" P.info += print_string - for(var/i = 2, i < (dossier.len + 1), i++) + for(var/i = 2, i <= dossier.len, i++) var/list/outputs = dossier[i] var/item_name = get_name(outputs[1]) var/list/prints_len = outputs[2] @@ -262,7 +262,7 @@ obj/machinery/computer/forensic_scanning var/list/fibers = outputs[3] if(fibers && fibers.len) var/dat = "[fibers[1]]" - for(var/j = 2, j < (fibers.len + 1), j++) + for(var/j = 2, j <= fibers.len, j++) dat += ",
      [fibers[j]]" P.info += "    Fibers: [dat]
" else @@ -271,7 +271,7 @@ obj/machinery/computer/forensic_scanning if(blood && blood.len) var/dat = "[blood[1]]" if(blood.len > 1) - for(var/j = 2, j < (blood.len + 1), j++) + for(var/j = 2, j <= blood.len, j++) dat += ",
      [blood[j]]" P.info += "    Blood: [dat]
" else @@ -366,7 +366,7 @@ obj/machinery/computer/forensic_scanning scan_data = "[scanning]

" if (scanning.blood_DNA.len) scan_data += "Blood Found:
" - for(var/i = 1, i < (scanning.blood_DNA.len + 1), i++) + for(var/i = 1, i <= scanning.blood_DNA.len, i++) var/list/templist = scanning.blood_DNA[i] scan_data += "-Blood type: [templist[2]]\nDNA: [templist[1]]

" else @@ -432,11 +432,13 @@ obj/machinery/computer/forensic_scanning updateUsrDialog() verb/reset() - set name = "Reset Screen" + set name = "Reset Database" set category = "Object" set src in oview(1) temp = "" add_fingerprint(usr) + files = list() + misc = list() return @@ -445,9 +447,10 @@ obj/machinery/computer/forensic_scanning proc/add_data_scanner(var/obj/item/device/detective_scanner/W) - for(var/i = 1, i < (W.stored.len + 1), i++) + for(var/i = 1, i <= W.stored.len, i++) var/list/data = W.stored[i] add_data(data[1],1,data[2],data[3],data[4]) + W.stored = list() proc/add_data(var/atom/A, var/override = 0, var/tempfingerprints, var/tempsuit_fibers,var/tempblood_DNA) @@ -469,7 +472,7 @@ obj/machinery/computer/forensic_scanning if(!misc) misc = list() if(misc) - for(var/i = 1, i < (misc.len + 1), i++) //Lets see if we can find it. + for(var/i = 1, i <= misc.len, i++) //Lets see if we can find it. var/list/templist = misc[i] var/check = templist[1] if(check == A) //There it is! @@ -478,14 +481,14 @@ obj/machinery/computer/forensic_scanning if(!fibers) fibers = list() if(A.suit_fibers) - for(var/j = 1, j < (A.suit_fibers.len + 1), j++) //Fibers~~~ + for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~ if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add! fibers += A.suit_fibers[j] var/list/blood = templist[3] if(!blood) blood = list() if(A.blood_DNA) - for(var/j = 1, j < (A.blood_DNA.len + 1), j++) //Blood~~~ + for(var/j = 1, j <= A.blood_DNA.len, j++) //Blood~~~ if(!blood.Find(A.blood_DNA[j])) //It isn't! Add! blood += A.blood_DNA[j] var/list/sum_list[3] //Pack it back up! @@ -504,21 +507,21 @@ obj/machinery/computer/forensic_scanning return !merged else //Has prints. var/list/found_prints[A.fingerprints.len + 1] - for(var/i = 1, i < (found_prints.len + 1), i++) + for(var/i = 1, i <= found_prints.len, i++) found_prints[i] = 0 if(!files) files = list() - for(var/i = 1, i < (files.len + 1), i++) //Lets see if we can find the owner of the prints + for(var/i = 1, i <= files.len, i++) //Lets see if we can find the owner of the prints var/list/perp_list = files[i] var/list/perp_prints = params2list(perp_list[1]) var/perp = perp_prints[num2text(1)] var/found2 = 0 - for(var/m = 1, m < (A.fingerprints.len + 1), m++) //Compare database prints with prints on object. + for(var/m = 1, m <= A.fingerprints.len, m++) //Compare database prints with prints on object. var/list/test_prints_list = params2list(A.fingerprints[m]) var/checker = test_prints_list[num2text(1)] if(checker == perp) //Found 'em! Merge! found_prints[m] = 1 - for(var/n = 2, n < (perp_list.len + 1), n++) //Lets see if it is already in the database + for(var/n = 2, n <= perp_list.len, n++) //Lets see if it is already in the database var/list/target = perp_list[n] if(target[1] == A) //Found the original object! found2 = 1 @@ -526,11 +529,11 @@ obj/machinery/computer/forensic_scanning if(!prints) prints = list() if(A.fingerprints) - for(var/j = 1, j < (A.fingerprints.len + 1), j++) //Fingerprints~~~ + for(var/j = 1, j <= A.fingerprints.len, j++) //Fingerprints~~~ var/list/print_test1 = params2list(A.fingerprints[j]) var/test_print1 = print_test1[num2text(1)] var/found = 0 - for(var/k = 1, k <= (prints.len + 1), k++) //Lets see if the print is already in there + for(var/k = 1, k <= prints.len, k++) //Lets see if the print is already in there var/list/print_test2 = params2list(prints[k]) var/test_print2 = print_test2[num2text(1)] if(test_print2 == test_print1) //It is! Merge! @@ -594,15 +597,15 @@ obj/machinery/computer/forensic_scanning proc/update_fingerprints() //I am tired, but this updates the master print, which is used to determine completion of a print. - for(var/k = 1, k < (files.len + 1), k++) + for(var/k = 1, k <= files.len, k++) var/list/perp_list = files[k] var/list/perp_prints = params2list(perp_list[1]) var/perp = perp_prints[num2text(1)] var/list/found_prints = list() - for(var/i = 2, i < (perp_list.len + 1), i++) + for(var/i = 2, i <= perp_list.len, i++) var/list/test_list = perp_list[i] var/list/test_prints = test_list[2] - for(var/j = 1, j < (test_prints.len + 1), j++) + for(var/j = 1, j <= test_prints.len, j++) var/list/test_list_2 = params2list(test_prints[j]) var/test_prints_2 = test_list_2[num2text(1)] if(test_prints_2 == perp) @@ -617,10 +620,10 @@ obj/machinery/computer/forensic_scanning proc/process_card() //I am tired, but this updates the master print from a fingerprint card //which is used to determine completion of a print. if(card.fingerprints) - for(var/k = 1, k < (card.fingerprints.len + 1), k++) + for(var/k = 1, k <= card.fingerprints.len, k++) var/list/test_prints = params2list(card.fingerprints[k]) var/print = test_prints[num2text(1)] - for(var/i = 1, i < (files.len + 1), i++) + for(var/i = 1, i <= files.len, i++) var/list/test_list = files[i] var/list/perp_prints = params2list(test_list[1]) var/perp = perp_prints[num2text(1)] diff --git a/code/defines/obj.dm b/code/defines/obj.dm index f537f56aaa..6e19ed87e7 100644 --- a/code/defines/obj.dm +++ b/code/defines/obj.dm @@ -359,6 +359,7 @@ /obj/item/device/hacktool/engineer name = "door debugger" desc = "An item of immense complexion, it appears to work by magic." + icon_state = "hacktool-g" /obj/item/blueprints name = "station blueprints" diff --git a/code/game/atom_procs.dm b/code/game/atom_procs.dm index aeac2e04bb..978a4679a6 100644 --- a/code/game/atom_procs.dm +++ b/code/game/atom_procs.dm @@ -122,6 +122,8 @@ if(new_prints) src.fingerprints[new_prints] = text("1=[]&2=[]", md5(H.dna.uni_identity), stringmerge(prints,stars(md5(H.dna.uni_identity), (H.gloves ? rand(10,20) : rand(25,40))))) else if(new_prints == 0) + if(!src.fingerprints) + src.fingerprints = list(text("1=[]&2=[]", md5(H.dna.uni_identity), stars(md5(H.dna.uni_identity), H.gloves ? rand(10,20) : rand(25,40)))) src.fingerprints += text("1=[]&2=[]", md5(H.dna.uni_identity), stars(md5(H.dna.uni_identity), H.gloves ? rand(10,20) : rand(25,40))) for(var/i = 1, i <= src.fingerprints.len, i++) if(length(src.fingerprints[i]) != 69) @@ -254,8 +256,9 @@ if (istype(src, /turf/simulated)) var/obj/item/source2 = src source2.blood_DNA = list() - var/icon/I = new /icon(source2.icon_old, source2.icon_state) - source2.icon = I + if(source2.icon_old) + var/icon/I = new /icon(source2.icon_old, source2.icon_state) + source2.icon = I if(src.fingerprints && src.fingerprints.len) var/done = 0 while(!done) @@ -275,6 +278,8 @@ break else src.fingerprints[i] = "1=" + prints["1"] + "&2=" + new_print + if(!src.fingerprints) + src.fingerprints = list() return /atom/MouseDrop(atom/over_object as mob|obj|turf|area) diff --git a/code/game/objects/devices/scanners.dm b/code/game/objects/devices/scanners.dm index 182730a526..2b6ccd576d 100644 --- a/code/game/objects/devices/scanners.dm +++ b/code/game/objects/devices/scanners.dm @@ -207,12 +207,12 @@ MASS SPECTROMETER var/list/prints = temp[2] if(!prints) prints = list() - if(A.fingerprints) - for(var/j = 1, j < (A.fingerprints.len + 1), j++) //Fingerprints~~~ + if(A.fingerprints && A.fingerprints.len) + for(var/j = 1, j <= A.fingerprints.len, j++) //Fingerprints~~~ var/list/print_test1 = params2list(A.fingerprints[j]) var/test_print1 = print_test1[num2text(1)] var/found = 0 - for(var/k = 1, k < (prints.len + 1), k++) //Lets see if the print is already in there + for(var/k = 1, k <= prints.len, k++) //Lets see if the print is already in there var/list/print_test2 = params2list(prints[k]) var/test_print2 = print_test2[num2text(1)] if(test_print2 == test_print1) //It is! Merge! @@ -224,15 +224,15 @@ MASS SPECTROMETER var/list/fibers = temp[3] if(!fibers) fibers = list() - if(A.suit_fibers) - for(var/j = 1, j < (A.suit_fibers.len + 1), j++) //Fibers~~~ + if(A.suit_fibers && A.suit_fibers.len) + for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~ if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add! fibers += A.suit_fibers[j] var/list/blood = temp[4] if(!blood) blood = list() - if(A.blood_DNA.len) - for(var/j = 1, j < (A.blood_DNA.len + 1), j++) //Blood~~~ + if(A.blood_DNA.len && A.blood_DNA) + for(var/j = 1, j <= A.blood_DNA.len, j++) //Blood~~~ if(!blood.Find(A.blood_DNA[j])) //It isn't! Add! blood += A.blood_DNA[j] var/list/sum_list[4] //Pack it back up! @@ -245,7 +245,11 @@ MASS SPECTROMETER if(!merged) //Uh, oh! New data point! var/list/sum_list[4] //Pack it back up! sum_list[1] = A - sum_list[2] = A.fingerprints + if(!A.fingerprints) + world << "Report this to a dev! [A] was lacking a list() for fingerprints!" + sum_list[2] = list() + else + sum_list[2] = A.fingerprints sum_list[3] = A.suit_fibers sum_list[4] = A.blood_DNA stored.len++ diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 37d1370d4a..27a5155766 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -276,7 +276,7 @@ FINGERPRINT CARD var/dat = "Fingerprints on Card
" for(var/i = 1, i < (src.fingerprints.len + 1), i++) var/list/L = params2list(src.fingerprints[i]) - dat += text("[]
", L[1]) + dat += text("[]
", L["1"]) //Foreach goto(41) return dat else diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 7dd5fea99b..161fcab6d3 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -929,7 +929,7 @@ /obj/item/weapon/book/manual/detective name = "The Film Noir: Proper Procedures for Investigations" icon_state ="bookHacking" - author = "Nanotrasen" + author = "NanoTrasen" dat = {" From 463d078cd4d7741619500d5915f2d2d57bbc3fc3 Mon Sep 17 00:00:00 2001 From: SkyMarshal Date: Thu, 9 Feb 2012 10:53:09 -0700 Subject: [PATCH 19/19] Added chemistry's big beakers to the supply pack. Security vending machines now have Evidence Bag boxes. --- code/defines/obj/supplypacks.dm | 7 ++++--- code/defines/obj/vending.dm | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/code/defines/obj/supplypacks.dm b/code/defines/obj/supplypacks.dm index a64ea20d0a..4aa5b52898 100644 --- a/code/defines/obj/supplypacks.dm +++ b/code/defines/obj/supplypacks.dm @@ -322,7 +322,7 @@ containertype = "/obj/structure/closet/crate" containername = "Replacement lights" -/*/datum/supply_packs/costume +/datum/supply_packs/costume name = "Standard Costume crate" contains = list("/obj/item/weapon/storage/backpack/clown", "/obj/item/clothing/shoes/clown_shoes", @@ -340,7 +340,7 @@ containertype = "/obj/structure/closet/crate/secure" containername = "Standard Costumes" access = access_theatre - group = "Clothing" */ + group = "Clothing" /datum/supply_packs/wizard name = "Wizard costume" @@ -421,7 +421,8 @@ "/obj/item/weapon/reagent_containers/glass/bottle/antitoxin", "/obj/item/weapon/reagent_containers/glass/bottle/inaprovaline", "/obj/item/weapon/reagent_containers/glass/bottle/stoxin", - "/obj/item/weapon/storage/syringes") + "/obj/item/weapon/storage/syringes", + "/obj/item/weapon/reagent_containers/glass/large") cost = 10 containertype = "/obj/structure/closet/crate/medical" containername = "Medical crate" diff --git a/code/defines/obj/vending.dm b/code/defines/obj/vending.dm index abd5e10790..6289fb1db5 100644 --- a/code/defines/obj/vending.dm +++ b/code/defines/obj/vending.dm @@ -168,7 +168,7 @@ icon_state = "sec" icon_deny = "sec-deny" req_access_txt = "1" - product_paths = "/obj/item/weapon/handcuffs;/obj/item/weapon/flashbang;/obj/item/device/flash;/obj/item/weapon/reagent_containers/food/snacks/donut;/obj/item/weapon/evidencebag" + product_paths = "/obj/item/weapon/handcuffs;/obj/item/weapon/flashbang;/obj/item/device/flash;/obj/item/weapon/reagent_containers/food/snacks/donut;/obj/item/weapon/storage/box/evidence" product_amounts = "8;4;5;12;6" product_hidden = "/obj/item/clothing/glasses/sunglasses;/obj/item/kitchen/donut_box" product_hideamt = "2;2"