diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index e24dc3825bc..62d2c9ec126 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -1337,7 +1337,7 @@ "azK" = (/obj/effect/spawner/window/reinforced,/turf/simulated/floor/plating,/area/crew_quarters/fitness) "azL" = (/turf/simulated/wall,/area/mimeoffice) "azM" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/structure/table/woodentable,/obj/item/weapon/reagent_containers/spray/waterflower,/turf/simulated/floor/wood,/area/mimeoffice) -"azN" = (/obj/structure/table/woodentable,/obj/item/weapon/pen/red{pixel_x = 2; pixel_y = 6},/obj/item/weapon/paper_bin,/obj/item/toy/crayon/mime,/obj/machinery/light_switch{name = "light switch "; dir = 2; pixel_x = 0; pixel_y = -22},/turf/simulated/floor/wood,/area/mimeoffice) +"azN" = (/obj/structure/table/woodentable,/obj/item/weapon/pen/red{pixel_x = 2; pixel_y = 6},/obj/item/weapon/paper_bin,/obj/item/toy/crayon/mime,/turf/simulated/floor/wood,/area/mimeoffice) "azO" = (/obj/machinery/camera{c_tag = "Magistrate's Office"; dir = 4; network = list("SS13")},/turf/simulated/floor/carpet,/area/magistrateoffice) "azP" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/carpet,/area/magistrateoffice) "azQ" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/carpet,/area/magistrateoffice) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index d686095ea59..0f2d499e5ba 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -134,6 +134,11 @@ #define RESIZE_DEFAULT_SIZE 1 +//transfer_ai() defines. Main proc in ai_core.dm +#define AI_TRANS_TO_CARD 1 //Downloading AI to InteliCard. +#define AI_TRANS_FROM_CARD 2 //Uploading AI from InteliCard +#define AI_MECH_HACK 3 //Malfunctioning AI hijacking mecha + //singularity defines #define STAGE_ONE 1 #define STAGE_TWO 3 diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 8c419cc35fb..690ac0e5c5b 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -17,6 +17,6 @@ var/global/list/table_recipes = list() //list of all table craft recipes var/global/list/all_areas = list() var/global/list/machines = list() -var/global/list/processing_power_items = list() - //items that ask to be called every cycle +var/global/list/processing_power_items = list() //items that ask to be called every cycle +var/global/list/rcd_list = list() //list of Rapid Construction Devices. diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index ca02a66a463..ed0e976c5da 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -43,6 +43,8 @@ return if(modifiers["middle"]) MiddleClickOn(A) + if(controlled_mech) //Are we piloting a mech? Placed here so the modifiers are not overridden. + controlled_mech.click_action(A, src) //Override AI normal click behavior. return if(modifiers["shift"]) ShiftClickOn(A) diff --git a/code/controllers/shuttle_controller.dm b/code/controllers/shuttle_controller.dm index 9c536931ce1..7c8a9847496 100644 --- a/code/controllers/shuttle_controller.dm +++ b/code/controllers/shuttle_controller.dm @@ -279,7 +279,7 @@ var/global/datum/shuttle_controller/shuttle_controller ) WS.announcer = "NSV Icarus" - WS.arrival_message = "Attention, [station_name()], we just tracked a large medical vessel approaching the station from the telecommunications satellite. Can't fire on them without hitting the station - prepare for visitors." + WS.arrival_message = "Attention, [station_name()], we just tracked a large medical vessel approaching the station from the telecommunications satellite. Might have wounded on board, can't destroy it - prepare for visitors." WS.departure_message = "Your guests are pulling away, [station_name()] - moving too fast for us to draw a bead on them. Looks like they're heading back to the telecommunications satellite." WS.interim = locate(/area/shuttle/derelict/ship/transit) diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index 7df1764a2a9..2a4a3d3a14b 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -141,7 +141,7 @@ var/list/uplink_items = list() /datum/uplink_item/jobspecific/syndidonk name = "Syndicate Donk Pockets" - desc = "A box of highly specialized donk pockets with a number of regenerative and stimulating chemicals inside of them; the box comes equipped with a self-heating mechanism." + desc = "A box of highly specialized Donk pockets with a number of regenerative and stimulating chemicals inside of them; the box comes equipped with a self-heating mechanism." reference = "SDP" item = /obj/item/weapon/storage/box/syndidonkpockets cost = 2 @@ -162,7 +162,7 @@ var/list/uplink_items = list() /datum/uplink_item/jobspecific/rad_laser name = "Radiation Laser" - desc = "A radiation laser concealed inside of a Health Analyser, After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyser, only appears like one. May not function correctly on radiation resistant humanoids!" + desc = "A radiation laser concealed inside of a Health Analyser. After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyser, only appears like one. May not function correctly on radiation resistant humanoids!" reference = "RL" item = /obj/item/device/rad_laser cost = 6 @@ -270,7 +270,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/car name = "C-90gl Compact Assault Rifle" - desc = "A fully-loaded Zashchita Industriya toploading bullpup assault rifle that uses 30-round 5.45x39mm magazines with a togglable underslung 40mm grenade launcher." + desc = "A fully-loaded Zashchita Industriya toploading bullpup assault rifle that uses 30-round 5.45x39mm magazines with a toggleable underslung 40mm grenade launcher." reference = "AR" item = /obj/item/weapon/gun/projectile/automatic/c90gl cost = 18 @@ -297,7 +297,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/flamethrower name = "Flamethrower" - desc = "A flamethrower, fueled by a portion of highly flammable biotoxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution." + desc = "A flamethrower, fuelled by a portion of highly flammable bio-toxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution." reference = "FT" item = /obj/item/weapon/flamethrower/full/tank cost = 11 @@ -306,7 +306,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/sword name = "Energy Sword" - desc = "The esword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise." + desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise." reference = "ES" item = /obj/item/weapon/melee/energy/sword cost = 8 @@ -329,7 +329,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/tabungrenades name = "Tabun Gas Grenades" - desc = "A box of four (4) grenades filled with tabun, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintaind with team to avoid accidental gassings." + desc = "A box of four (4) grenades filled with Tabun, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintained with team to avoid accidental gassings." reference = "TGG" item = /obj/item/weapon/storage/box/syndie_kit/tabun cost = 15 @@ -345,7 +345,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/syndicate_minibomb name = "Syndicate Minibomb" - desc = "The Minibomb is a grenade with a five-second fuse." + desc = "The minibomb is a grenade with a five-second fuse." reference = "SMB" item = /obj/item/weapon/grenade/syndieminibomb cost = 6 @@ -362,7 +362,7 @@ var/list/uplink_items = list() /datum/uplink_item/dangerous/mauler name = "Mauler Exosuit" - desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targetting, thrust vectoring, and deployable smoke." + desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targeting, thrust vectoring, and deployable smoke." reference = "ME" item = /obj/mecha/combat/marauder/mauler/loaded cost = 140 @@ -453,8 +453,8 @@ var/list/uplink_items = list() gamemodes = list("nuclear emergency") /datum/uplink_item/ammo/machinegun - name = "Box Magazine - 7.62×51mm" - desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses." + name = "Box Magazine - 7.62x51mm" + desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW machine gun. By the time you need to use this, you'll already be on a pile of corpses." reference = "762" item = /obj/item/ammo_box/magazine/m762 cost = 12 @@ -489,8 +489,6 @@ var/list/uplink_items = list() item = /obj/item/weapon/cartridge/syndicate cost = 6 -// Commented out until a fix can be found, currently doesn't work with the PDA NanoUI and people keep wasting Telecrystals on it. -- Dave - /datum/uplink_item/stealthy_weapons/silencer name = "Universal Suppressor" desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the shots of the weapon for increased stealth and superior ambushing capability." @@ -528,7 +526,7 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_tools/chameleon_stamp name = "Chameleon Stamp" - desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp™. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \ + desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \ it can also be used in a washing machine to forge clothing." reference = "CHST" item = /obj/item/weapon/stamp/chameleon @@ -551,14 +549,14 @@ var/list/uplink_items = list() /datum/uplink_item/stealthy_tools/voice_changer name = "Voice Changer" - desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognizable." + desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognisable." reference = "VC" item = /obj/item/clothing/mask/gas/voice cost = 5 /datum/uplink_item/stealthy_tools/chameleon_proj name = "Chameleon-Projector" - desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and rojectiles pass over them." + desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and projectiles pass over them." reference = "CP" item = /obj/item/device/chameleon cost = 7 @@ -594,7 +592,7 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/emag name = "Cryptographic Sequencer" - desc = "The emag is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms." + desc = "The cryptographic sequencer, also known as an emag, is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms." reference = "EMAG" item = /obj/item/weapon/card/emag cost = 6 @@ -609,7 +607,7 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/medkit name = "Syndicate Combat Medic Kit" - desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical hud for quick identification of injured comrades, \ + desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical HUD for quick identification of injured comrades, \ and other medical supplies helpful for a medical field operative." reference = "SCMK" item = /obj/item/weapon/storage/firstaid/tactical @@ -632,8 +630,8 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/hardsuit name = "Blood-red Hardsuit" - desc = "The feared suit of a syndicate nuclear agent. Features slightly better armoring. When the helmet is deployed your identity will be protected. Toggling the suit into combat mode \ - will allow you all the mobility of a loose fitting uniform without sacrificing armoring. Additionally the suit is collapsible, small enough to fit within a backpack. \ + desc = "The feared suit of a syndicate nuclear agent. Features slightly better armor. When the helmet is deployed your identity will be protected. Toggling the suit into combat mode \ + will allow you all the mobility of a loose fitting uniform without sacrificing armor. Additionally the suit is collapsible, small enough to fit within a backpack. \ Nanotrasen crewmembers are trained to report red space suit sightings, these suits in particular are known to drive employees into a panic." reference = "BRHS" item = /obj/item/weapon/storage/box/syndie_kit/hardsuit @@ -641,7 +639,7 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/thermal name = "Thermal Imaging Glasses" - desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infrared light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks." + desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infra-red light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks." reference = "THIG" item = /obj/item/clothing/glasses/thermal/syndi cost = 6 @@ -680,7 +678,7 @@ var/list/uplink_items = list() /datum/uplink_item/device_tools/plastic_explosives name = "Composition C-4" - desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaler to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds." + desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaller to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds." reference = "C4" item = /obj/item/weapon/c4 cost = 1 @@ -762,7 +760,7 @@ var/list/uplink_items = list() /datum/uplink_item/implants/uplink name = "Uplink Implant" - desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their posessions have been stripped from them makes this implant excellent for escaping confinement." + desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement." reference = "UI" item = /obj/item/weapon/implanter/uplink cost = 14 diff --git a/code/datums/wires/nuclearbomb.dm b/code/datums/wires/nuclearbomb.dm new file mode 100644 index 00000000000..0e28c23fb91 --- /dev/null +++ b/code/datums/wires/nuclearbomb.dm @@ -0,0 +1,64 @@ +/datum/wires/nuclearbomb + holder_type = /obj/machinery/nuclearbomb + random = 1 + wire_count = 7 + +var/const/NUCLEARBOMB_WIRE_LIGHT = 1 +var/const/NUCLEARBOMB_WIRE_TIMING = 2 +var/const/NUCLEARBOMB_WIRE_SAFETY = 4 + +/datum/wires/nuclearbomb/CanUse(var/mob/living/L) + var/obj/machinery/nuclearbomb/N = holder + if(N.panel_open) + return 1 + return 0 + +/datum/wires/nuclearbomb/GetInteractWindow() + var/obj/machinery/nuclearbomb/N = holder + . += ..() + . += "
The device is [N.timing ? "shaking!" : "still."]
" + . += "The device is is [N.safety ? "quiet" : "whirring"].
" + . += "The lights are [N.lighthack ? "static" : "functional"].
" + +/datum/wires/nuclearbomb/UpdatePulsed(var/index) + var/obj/machinery/nuclearbomb/N = holder + switch(index) + if(NUCLEARBOMB_WIRE_LIGHT) + N.lighthack = !N.lighthack + spawn(100) + N.lighthack = !N.lighthack + if(NUCLEARBOMB_WIRE_TIMING) + if(N.timing) + spawn + message_admins("[key_name_admin(usr)] pulsed a nuclear bomb's detonation wire, causing it to explode (JMP)") + N.explode() + if(NUCLEARBOMB_WIRE_SAFETY) + N.safety = !N.safety + spawn(100) + N.safety = !N.safety + if(N.safety == 1) + if(!N.is_syndicate) + set_security_level(N.previous_level) + N.visible_message("\blue The [N] quiets down.") + if(!N.lighthack) + if (N.icon_state == "nuclearbomb2") + N.icon_state = "nuclearbomb1" + else + N.visible_message("\blue The [N] emits a quiet whirling noise!") + +/datum/wires/nuclearbomb/UpdateCut(var/index, var/mended) + var/obj/machinery/nuclearbomb/N = holder + switch(index) + if(NUCLEARBOMB_WIRE_SAFETY) + if(N.timing) + spawn + message_admins("[key_name_admin(usr)] cut a nuclear bomb's timing wire, causing it to explode (JMP)") + N.explode() + if(NUCLEARBOMB_WIRE_TIMING) + if(!N.lighthack) + if (N.icon_state == "nuclearbomb2") + N.icon_state = "nuclearbomb1" + N.timing = 0 + bomb_set = 0 + if(NUCLEARBOMB_WIRE_LIGHT) + N.lighthack = !N.lighthack diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index 1211f9e14f8..34822d2d509 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -1,3 +1,4 @@ +/var/datum/announcement/minor/minor_announcement = new() /var/datum/announcement/priority/priority_announcement = new(do_log = 0) /var/datum/announcement/priority/command/command_announcement = new(do_log = 0, do_newscast = 1) @@ -15,6 +16,11 @@ sound = new_sound log = do_log newscast = do_newscast + +/datum/announcement/minor/New(var/do_log = 0, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) + ..(do_log, new_sound, do_newscast) + title = "Attention" + announcement_type = "Minor Announcement" /datum/announcement/priority/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) ..(do_log, new_sound, do_newscast) @@ -55,8 +61,9 @@ datum/announcement/proc/Message(message as text, message_title as text) if (announcer) M << " -[html_encode(announcer)]" -datum/announcement/minor/Message(message as text, message_title as text) - world << "[message]" +/datum/announcement/minor/Message(message as text, message_title as text) + world << "[message_title]" + world << "[message]" datum/announcement/priority/Message(message as text, message_title as text) world << "

[message_title]

" diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index aec9b2580b5..497e69bc10c 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -224,7 +224,7 @@ Obviously, requires DNA2. var/list/validtargets = new /list() for(var/mob/M in living_mob_list) if(M && M.mind) - if(isAntag(M)) + if(M.z != user.z || isNonCrewAntag(M)) continue validtargets += M @@ -277,17 +277,22 @@ Obviously, requires DNA2. action_icon_state = "genetic_view" -/obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr) +/obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr) var/list/targets = living_mob_list - var/list/remoteviewers = new /list() + var/list/validtargets = new /list() for(var/mob/M in targets) - if(REMOTE_VIEW in M.mutations) - remoteviewers += M - if(!remoteviewers.len || remoteviewers.len == 1) + if(M && M.mind) + if(M.z != user.z || isNonCrewAntag(M)) + continue + + validtargets += M + + if(!validtargets.len || validtargets.len == 1) usr << "No valid targets with remote view were found!" start_recharge() return - targets += input("Choose the target to spy on.", "Targeting") as mob in remoteviewers + + targets += input("Choose the target to spy on.", "Targeting") as mob in validtargets perform(targets) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index d0e2228162c..8809476c3ed 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -238,7 +238,7 @@ var/list/suspects = list() for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) // NT relation option - if(isAntag(man)) + if(isNonCrewAntag(man)) continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) @@ -246,6 +246,7 @@ // Antags else if(special_role == "traitor" && prob(40) || \ special_role == "Changeling" && prob(50) || \ + special_role == "Vampire" && prob(40) || \ special_role == "Cultist" && prob(30) || \ special_role == "Head Revolutionary" && prob(30) || \ special_role == "Shadowling" && prob(15)) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index f32407a62af..622ec56bf4f 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -34,7 +34,7 @@ rcd light flash thingy on matter drain /datum/AI_Module/large/fireproof_core - module_name = "Core upgrade" + module_name = "Core Upgrade" mod_pick_name = "coreup" description = "An upgrade to improve core resistance, making it immune to fire and heat. This effect is permanent." cost = 50 @@ -51,9 +51,9 @@ rcd light flash thingy on matter drain src << "Core fireproofed." /datum/AI_Module/large/upgrade_turrets - module_name = "AI Turret upgrade" + module_name = "AI Turret Upgrade" mod_pick_name = "turret" - description = "Improves the firing speed and health of all AI turrets. This effect is permanent." + description = "Improves the firing power and health of all AI turrets. This effect is permanent." cost = 50 one_time = 1 @@ -62,26 +62,25 @@ rcd light flash thingy on matter drain /mob/living/silicon/ai/proc/upgrade_turrets() set category = "Malfunction" set name = "Upgrade Turrets" + + if(stat) + return + src.verbs -= /mob/living/silicon/ai/proc/upgrade_turrets - for(var/obj/machinery/turret/turret in machines) - var/turf/T = get_turf(turret) - if(T.z in config.station_levels) - turret.health += 30 - turret.shot_delay = 20 for(var/obj/machinery/porta_turret/turret in machines) var/turf/T = get_turf(turret) if(T.z in config.station_levels) // Increase health by 37.5% of original max, decrease delays between shots to 66% turret.health += initial(turret.health) * 3 / 8 - turret.shot_delay = initial(turret.shot_delay) * 2 / 3 + turret.eprojectile = /obj/item/projectile/beam/heavylaser //Once you see it, you will know what it means to FEAR. + turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg' src << "Turrets upgraded." /datum/AI_Module/large/lockdown module_name = "Hostile Station Lockdown" mod_pick_name = "lockdown" - description = "Take control of the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks." + description = "Overload the airlock, blast door and fire control networks, locking them down. Caution! This command also electrifies all airlocks. The networks will automatically reset after 120 seconds." cost = 20 - one_time = 1 power_type = /mob/living/silicon/ai/proc/lockdown @@ -89,12 +88,43 @@ rcd light flash thingy on matter drain set category = "Malfunction" set name = "Initiate Hostile Lockdown" - if(src.stat == 2) - src <<"You cannot begin a lockdown because you are dead!" + if(stat) return + + for(var/datum/AI_Module/large/lockdown/lockdown in current_modules) + if(lockdown.uses > 0) + lockdown.uses -- + + var/obj/machinery/door/airlock/AL + for(var/obj/machinery/door/D in airlocks) + if(!(D.z in config.contact_levels)) + continue + spawn() + if(istype(D, /obj/machinery/door/airlock)) + AL = D + if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. + AL.locked = 0 //For airlocks that were bolted open. + AL.safe = 0 //DOOR CRUSH + AL.close() + AL.lock() + AL.electrified_until = -1 //Shock it! + else if(!D.stat) //So that only powered doors are closed. + D.close() //Close ALL the doors! - if(malf_cooldown) - return + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("alert", "lockdown") + + minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.","Network Alert") + src << "Lockdown initiated. Network reset in two minutes." + spawn(1200) //120 Seconds. + disablelockdown() //Reset the lockdown after 120 seconds. + else + src << "Out of uses." + +/mob/living/silicon/ai/proc/disablelockdown() + set category = "Malfunction" + set name = "Disable Lockdown" var/obj/machinery/door/airlock/AL for(var/obj/machinery/door/D in airlocks) @@ -104,77 +134,73 @@ rcd light flash thingy on matter drain if(istype(D, /obj/machinery/door/airlock)) AL = D if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. - AL.locked = 0 //For airlocks that were bolted open. - AL.safe = 0 //DOOR CRUSH - AL.close() - AL.locked = 1 //Bolt it! - AL.lights = 0 //Stealth bolt for a classic AI door trap. - AL.electrified_until = -1 //Shock it! - else if(!D.stat) //So that only powered doors are closed. - D.close() //Close ALL the doors! - - var/obj/machinery/computer/communications/C = locate() in machines - if(C) - C.post_status("alert", "lockdown") - - src.verbs += /mob/living/silicon/ai/proc/disablelockdown - src << "Lockdown Initiated." - malf_cooldown = 1 - spawn(30) - malf_cooldown = 0 - -/mob/living/silicon/ai/proc/disablelockdown() - set category = "Malfunction" - set name = "Disable Lockdown" - - if(src.stat == 2) - src <<"You cannot disable lockdown because you are dead!" - return - if(malf_cooldown) - return - - var/obj/machinery/door/airlock/AL - for(var/obj/machinery/door/D in airlocks) - spawn() - if(istype(D, /obj/machinery/door/airlock)) - AL = D - if(AL.canAIControl() && !AL.stat) //Must be powered and have working AI wire. - AL.locked = 0 + AL.unlock() AL.electrified_until = 0 AL.open() AL.safe = 1 - AL.lights = 1 //Essentially reset the airlock to normal. else if(!D.stat) //Opens only powered doors. - D.open() //Open everything! + D.open() //Open everything! + + var/obj/machinery/computer/communications/C = locate() in machines + if(C) + C.post_status("alert", "default") + + minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network Reset") - src << "Lockdown Lifted." - malf_cooldown = 1 - spawn(30) - malf_cooldown = 0 - -/datum/AI_Module/large/disable_rcd - module_name = "RCD disable" +/datum/AI_Module/large/destroy_rcd + module_name = "Destroy RCDs" mod_pick_name = "rcd" - description = "Send a specialised pulse to break all RCD devices on the station." - cost = 50 + description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Cconstruction Devices on the station." + cost = 25 + one_time = 1 power_type = /mob/living/silicon/ai/proc/disable_rcd /mob/living/silicon/ai/proc/disable_rcd() set category = "Malfunction" - set name = "Disable RCDs" - for(var/datum/AI_Module/large/disable_rcd/rcdmod in current_modules) - if(rcdmod.uses > 0) - rcdmod.uses -- - for(var/obj/item/weapon/rcd/rcd in world) - rcd.disabled = 1 - for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) - rcd.disabled = 1 - src << "Out of uses." + set name = "Destroy RCDs" + set desc = "Detonate all RCDs on the station, while sparing onboard cyborg RCDs." + + if(stat || malf_cooldown) + return + + for(var/obj/item/RCD in rcd_list) + if(!istype(RCD, /obj/item/weapon/rcd/borg)) //Ensures that cyborg RCDs are spared. + RCD.audible_message("[RCD] begins to vibrate and buzz loudly!","[RCD] begins vibrating violently!") + spawn(50) //5 seconds to get rid of it! + if(RCD) //Make sure it still exists (In case of chain-reaction) + explosion(RCD, 0, 0, 3, 1, flame_range = 1) + qdel(RCD) + src << "RCD detonation pulse emitted." + malf_cooldown = 1 + spawn(100) + malf_cooldown = 0 + +/datum/AI_Module/large/mecha_domination + module_name = "Viral Mech Domination" + mod_pick_name = "mechjack" + description = "Hack into a mech's onboard computer, shunting all processes into it and ejecting any occupants. Once uploaded to the mech, it is impossible to leave.\ + Do not allow the mech to leave the station's vicinity or allow it to be destroyed." + cost = 30 + one_time = 1 + + power_type = /mob/living/silicon/ai/proc/mech_takeover + +/mob/living/silicon/ai/proc/mech_takeover() + set name = "Compile Mecha Virus" + set category = "Malfunction" + set desc = "Target a mech by clicking it. Click the appropriate command when ready." + + if(stat) + return + + can_dominate_mechs = 1 //Yep. This is all it does. Honk! + src << "Virus package compiled. Select a target mech at any time. You must remain on the station at all times. Loss of signal will result in total system lockout." + verbs -= /mob/living/silicon/ai/proc/mech_takeover + /datum/AI_Module/small/overload_machine - module_name = "Machine overload" + module_name = "Machine Overload" mod_pick_name = "overload" description = "Overloads an electrical machine, causing a small explosion. 2 uses." uses = 2 @@ -185,6 +211,10 @@ rcd light flash thingy on matter drain /mob/living/silicon/ai/proc/overload_machine(obj/machinery/M as obj in world) set name = "Overload Machine" set category = "Malfunction" + + if(stat) + return + if (istype(M, /obj/machinery)) if(istype(M,/obj/machinery/field_generator)) src << "This machine can not be overloaded due to a firewall." @@ -197,11 +227,11 @@ rcd light flash thingy on matter drain spawn(50) explosion(get_turf(M), 0,1,1,0) qdel(M) - else src << "Out of uses." + else src << "Out of uses." else src << "That's not a machine." /datum/AI_Module/small/override_machine - module_name = "Machine override" + module_name = "Machine Override" mod_pick_name = "override" description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. 4 uses." uses = 4 @@ -213,6 +243,10 @@ rcd light flash thingy on matter drain /mob/living/silicon/ai/proc/override_machine(obj/machinery/M as obj in world) set name = "Override Machine" set category = "Malfunction" + + if(stat) + return + if (istype(M, /obj/machinery)) if(istype(M,/obj/machinery/field_generator)) src << "This machine can not be overloaded due to a firewall." @@ -226,7 +260,7 @@ rcd light flash thingy on matter drain spawn(50) if(M) new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, src, 1) - else src << "Out of uses." + else src << "Out of uses." else src << "That's not a machine." /datum/AI_Module/large/place_cyborg_transformer @@ -246,8 +280,10 @@ rcd light flash thingy on matter drain /mob/living/silicon/ai/proc/place_transformer() set name = "Place Robotic Factory" set category = "Malfunction" + if(!canPlaceTransformer()) return + var/sure = alert(src, "Are you sure you want to place the machine here?", "Are you sure?", "Yes", "No") if(sure == "Yes") if(!canPlaceTransformer()) @@ -312,6 +348,10 @@ rcd light flash thingy on matter drain /mob/living/silicon/ai/proc/blackout() set category = "Malfunction" set name = "Blackout" + + if(stat) + return + for(var/datum/AI_Module/small/blackout/blackout in current_modules) if(blackout.uses > 0) blackout.uses -- @@ -320,72 +360,88 @@ rcd light flash thingy on matter drain apc.overload_lighting() else apc.overload++ src << "Overcurrent applied to the powernet." - else src << "Out of uses." + else src << "Out of uses." -/datum/AI_Module/small/reactivate_camera - module_name = "Reactivate camera" +/datum/AI_Module/small/reactivate_cameras + module_name = "Reactivate Camera Network" mod_pick_name = "recam" - description = "Reactivates a currently disabled camera. 5 uses." - uses = 5 - cost = 5 + description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. Can be used to repair up to 30 cameras." + uses = 30 + cost = 10 + one_time = 1 - power_type = /client/proc/reactivate_camera + power_type = /mob/living/silicon/ai/proc/reactivate_cameras -/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Reactivate Camera" +/mob/living/silicon/ai/proc/reactivate_cameras() + set name = "Reactivate Cameranet" set category = "Malfunction" - if (istype (C, /obj/machinery/camera)) - for(var/datum/AI_Module/small/reactivate_camera/camera in usr:current_modules) + + if(stat || malf_cooldown) + return + var/fixedcams = 0 //Tells the AI how many cams it fixed. Stats are fun. + + for(var/datum/AI_Module/small/reactivate_cameras/camera in current_modules) + for(var/obj/machinery/camera/C in cameranet.cameras) + var/initial_range = initial(C.view_range) //To prevent calling the proc twice if(camera.uses > 0) if(!C.status) - C.deactivate(src) - camera.uses -- - src << "Camera reactivated." - else - src << "This camera is either active, or not repairable." - else src << "Out of uses." - else src << "That's not a camera." - -/datum/AI_Module/small/upgrade_camera - module_name = "Upgrade Camera" - mod_pick_name = "upgradecam" - description = "Upgrades a camera to have X-Ray vision, Motion and be EMP-Proof. 5 uses." - uses = 5 - cost = 5 - - power_type = /client/proc/upgrade_camera - -/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) - set name = "Upgrade Camera" - set category = "Malfunction" - if(istype(C)) - var/datum/AI_Module/small/upgrade_camera/UC = locate(/datum/AI_Module/small/upgrade_camera) in usr:current_modules - if(UC) - if(UC.uses > 0) - if(C.assembly) - var/upgraded = 0 - - if(!C.isXRay()) - C.upgradeXRay() - upgraded = 1 - - if(!C.isEmpProof()) - C.upgradeEmpProof() - upgraded = 1 - - if(!C.isMotion()) - C.upgradeMotion() - upgraded = 1 - - if(upgraded) - UC.uses -- - C.visible_message("\icon[C] *beep*") - src << "Camera successully upgraded!" - else - src << "This camera is already upgraded!" + C.deactivate(src, 1) //Reactivates the camera based on status. Badly named proc. + fixedcams++ + camera.uses-- + if(C.view_range != initial_range) + C.view_range = initial_range //Fixes cameras with bad focus. + camera.uses-- + fixedcams++ + //If a camera is both deactivated and has bad focus, it will cost two uses to fully fix! else - src << "Out of uses." + src << "Out of uses." + verbs -= /mob/living/silicon/ai/proc/reactivate_cameras //It is useless now, clean it up. + break + src << "Diagnostic complete! Operations completed: [fixedcams]." + malf_cooldown = 1 + spawn(30) //Lag protection + malf_cooldown = 0 + +/datum/AI_Module/small/upgrade_cameras + module_name = "Upgrade Camera Network" + mod_pick_name = "upgradecam" + description = "Install broad-spectrum scanning and electrical redundancy firmware to the camera network, enabling EMP-Proofing and light-amplified X-ray vision." //I <3 pointless technobabble + //This used to have motion sensing as well, but testing quickly revealed that giving it to the whole cameranet is PURE HORROR. + one_time = 1 + cost = 35 //Decent price for omniscience! + + power_type = /mob/living/silicon/ai/proc/upgrade_cameras + +/mob/living/silicon/ai/proc/upgrade_cameras() + set name = "Upgrade Cameranet" + set category = "Malfunction" + + if(stat) + return + + var/upgradedcams = 0 + see_override = SEE_INVISIBLE_MINIMUM //Night-vision, without which X-ray would be very limited in power. + + for(var/obj/machinery/camera/C in cameranet.cameras) + if(C.assembly) + var/upgraded = 0 + + if(!C.isXRay()) + C.upgradeXRay() + //Update what it can see. + cameranet.updateVisibility(C, 0) + upgraded = 1 + + if(!C.isEmpProof()) + C.upgradeEmpProof() + upgraded = 1 + + if(upgraded) + upgradedcams++ + + src << "OTA firmware distribution complete! Cameras upgraded: [upgradedcams]. Light amplification system online." + verbs -= /mob/living/silicon/ai/proc/upgrade_cameras /datum/module_picker var/temp = null @@ -411,9 +467,9 @@ rcd light flash thingy on matter drain Install Module:
The number afterwards is the amount of processing time it consumes.
"} for(var/datum/AI_Module/large/module in src.possible_modules) - dat += "[module.module_name] ([module.cost])
" + dat += "[module.module_name]\[?\] ([module.cost])
" for(var/datum/AI_Module/small/module in src.possible_modules) - dat += "[module.module_name] ([module.cost])
" + dat += "[module.module_name]\[?\] ([module.cost])
" dat += "
" if (src.temp) dat += "[src.temp]" @@ -455,5 +511,9 @@ rcd light flash thingy on matter drain temp = AM.description src.processing_time -= AM.cost + if(href_list["showdesc"]) + if(AM.mod_pick_name == href_list["showdesc"]) + temp = AM.description + src.use(usr) return diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm index fdca56bd5cc..e3fb3809c39 100644 --- a/code/game/gamemodes/malfunction/malfunction.dm +++ b/code/game/gamemodes/malfunction/malfunction.dm @@ -127,7 +127,7 @@ /datum/game_mode/malfunction/proc/capture_the_station() - world << "The AI has won!" + world << "The AI has accessed the station's core files!" world << "It has fully taken control of all of [station_name()]'s systems." to_nuke_or_not_to_nuke = 1 @@ -328,7 +328,8 @@ /datum/game_mode/proc/auto_declare_completion_malfunction() if( malf_ai.len || istype(ticker.mode,/datum/game_mode/malfunction) ) var/text = "The malfunctioning AI were:" - + var/module_text_temp = "
Purchased modules:
" //Added at the end + for(var/datum/mind/malf in malf_ai) text += "
[malf.key] was [malf.name] (" @@ -339,9 +340,13 @@ text += "operational" if(malf.current.real_name != malf.name) text += " as [malf.current.real_name]" + var/mob/living/silicon/ai/AI = malf.current + for(var/datum/AI_Module/mod in AI.current_modules) + module_text_temp += mod.module_name + "
" else text += "hardware destroyed" text += ")" - + text += module_text_temp + world << text return 1 \ No newline at end of file diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index faf3f353c16..0850f6ad46b 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -6,26 +6,23 @@ var/bomb_set icon = 'icons/obj/stationobjs.dmi' icon_state = "nuclearbomb0" density = 1 - var/deployable = 0.0 - var/extended = 0.0 + var/deployable = 0 + var/extended = 0 var/lighthack = 0 - var/opened = 0.0 - var/timeleft = 120.0 - var/timing = 0.0 + var/timeleft = 120 + var/timing = 0 var/r_code = "ADMIN" var/code = "" - var/yes_code = 0.0 - var/safety = 1.0 + var/yes_code = 0 + var/safety = 1 var/obj/item/weapon/disk/nuclear/auth = null - var/list/wires = list() - var/light_wire - var/safety_wire - var/timing_wire var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, 3 is sealant open, 4 is unwrenched, 5 is removed from bolts. var/lastentered var/is_syndicate = 0 use_power = 0 unacidable = 1 + var/previous_level = "" + var/datum/wires/nuclearbomb/wires = null /obj/machinery/nuclearbomb/syndicate is_syndicate = 1 @@ -33,23 +30,15 @@ var/bomb_set /obj/machinery/nuclearbomb/New() ..() r_code = "[rand(10000, 99999.0)]"//Creates a random code upon object spawn. - src.wires["Red"] = 0 - src.wires["Blue"] = 0 - src.wires["Green"] = 0 - src.wires["Marigold"] = 0 - src.wires["Fuschia"] = 0 - src.wires["Black"] = 0 - src.wires["Pearl"] = 0 - var/list/w = list("Red","Blue","Green","Marigold","Black","Fuschia","Pearl") - src.light_wire = pick(w) - w -= src.light_wire - src.timing_wire = pick(w) - w -= src.timing_wire - src.safety_wire = pick(w) - w -= src.safety_wire - + wires = new/datum/wires/nuclearbomb(src) + previous_level = get_security_level() + +/obj/machinery/nuclearbomb/Destroy() + qdel(wires) + return ..() + /obj/machinery/nuclearbomb/process() - if (src.timing) + if (timing) bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. timeleft = max(timeleft - 2, 0) // 2 seconds per process() if (timeleft <= 0) @@ -60,40 +49,41 @@ var/bomb_set /obj/machinery/nuclearbomb/attackby(obj/item/weapon/O as obj, mob/user as mob, params) if (istype(O, /obj/item/weapon/screwdriver)) - src.add_fingerprint(user) - if (src.auth) - if (src.opened == 0) - src.opened = 1 + add_fingerprint(user) + if (auth) + if (panel_open == 0) + panel_open = 1 overlays += image(icon, "npanel_open") user << "You unscrew the control panel of [src]." + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) else - src.opened = 0 + panel_open = 0 overlays -= image(icon, "npanel_open") user << "You screw the control panel of [src] back on." + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) else - if (src.opened == 0) + if (panel_open == 0) user << "[src] emits a buzzing noise, the panel staying locked in." - if (src.opened == 1) - src.opened = 0 + if (panel_open == 1) + panel_open = 0 overlays -= image(icon, "npanel_open") user << "You screw the control panel of [src] back on." + playsound(src, 'sound/items/Screwdriver.ogg', 50, 1) flick("nuclearbombc", src) - ui_interact(user) return - if (istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters)) - ui_interact(user) + if (panel_open && (istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters))) + return attack_hand(user) - if (src.extended) + if (extended) if (istype(O, /obj/item/weapon/disk/nuclear)) usr.drop_item() O.loc = src - src.auth = O - src.add_fingerprint(user) - ui_interact(user) - return + auth = O + add_fingerprint(user) + return attack_hand(user) - if (src.anchored) + if (anchored) switch(removal_stage) if(0) if(istype(O,/obj/item/weapon/weldingtool)) @@ -163,73 +153,56 @@ var/bomb_set ..() /obj/machinery/nuclearbomb/attack_ghost(mob/user as mob) - ui_interact(user) + attack_hand(user) /obj/machinery/nuclearbomb/attack_hand(mob/user as mob) - if (src.extended) - if (src.opened) + if (extended) + if (panel_open) + wires.Interact(user) + else ui_interact(user) - else if (src.deployable) + else if (deployable) if(removal_stage < 5) - src.anchored = 1 + anchored = 1 visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring!") else visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") - if(!src.lighthack) + if(!lighthack) flick("nuclearbombc", src) - src.icon_state = "nuclearbomb1" - src.extended = 1 + icon_state = "nuclearbomb1" + extended = 1 return /obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) var/data[0] - var/uiwidth - var/uiheight - var/uititle data["is_syndicate"] = is_syndicate - if(!src.opened) - data["hacking"] = 0 - data["auth"] = is_auth(user) - if (is_auth(user)) - if (src.yes_code) - data["authstatus"] = src.timing ? "Functional/Set" : "Functional" - else - data["authstatus"] = "Auth. S2" + data["hacking"] = 0 + data["auth"] = is_auth(user) + if (is_auth(user)) + if (yes_code) + data["authstatus"] = timing ? "Functional/Set" : "Functional" else - if (src.timing) - data["authstatus"] = "Set" - else - data["authstatus"] = "Auth. S1" - data["safe"] = src.safety ? "Safe" : "Engaged" - data["time"] = src.timeleft - data["timer"] = src.timing - data["safety"] = src.safety - data["anchored"] = src.anchored - data["yescode"] = src.yes_code - data["message"] = "AUTH" - if (is_auth(user)) - data["message"] = src.code - if (src.yes_code) - data["message"] = "*****" - uiwidth = 300 - uiheight = 510 - uititle = "Nuke Control Panel" + data["authstatus"] = "Auth. S2" else - data["hacking"] = 1 - var/list/tempwires[0] - for(var/wire in src.wires) - tempwires.Add(list(list("name" = wire, "cut" = src.wires[wire]))) - data["wires"] = tempwires - data["timing"] = src.timing - data["safety"] = src.safety - data["lighthack"] = src.lighthack - uiwidth = 420 - uiheight = 440 - uititle = "Nuclear Bomb Defusion" + if (timing) + data["authstatus"] = "Set" + else + data["authstatus"] = "Auth. S1" + data["safe"] = safety ? "Safe" : "Engaged" + data["time"] = timeleft + data["timer"] = timing + data["safety"] = safety + data["anchored"] = anchored + data["yescode"] = yes_code + data["message"] = "AUTH" + if (is_auth(user)) + data["message"] = code + if (yes_code) + data["message"] = "*****" ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) - ui = new(user, src, ui_key, "nuclear_bomb.tmpl", uititle, uiwidth, uiheight) + ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 300, 510) ui.set_initial_data(data) ui.open() ui.set_auto_update(1) @@ -242,12 +215,12 @@ var/bomb_set if(usr.stat || !usr.canmove || usr.restrained()) return - if (src.deployable) + if (deployable) usr << "\red You close several panels to make [src] undeployable." - src.deployable = 0 + deployable = 0 else usr << "\red You adjust some panels to make [src] deployable." - src.deployable = 1 + deployable = 1 return /obj/machinery/nuclearbomb/proc/is_auth(user as mob) @@ -262,73 +235,29 @@ var/bomb_set if(..()) return 1 - if(href_list["act"]) - var/temp_wire = href_list["wire"] - if(href_list["act"] == "pulse") - if (!istype(usr.get_active_hand(), /obj/item/device/multitool)) - usr << "You need a multitool!" - else - if(src.wires[temp_wire]) - usr << "You can't pulse a cut wire." - else - if(src.light_wire == temp_wire) - src.lighthack = !src.lighthack - spawn(100) src.lighthack = !src.lighthack - if(src.timing_wire == temp_wire) - if(src.timing) - spawn - explode() - if(src.safety_wire == temp_wire) - src.safety = !src.safety - spawn(100) src.safety = !src.safety - if(src.safety == 1) - visible_message("\blue The [src] quiets down.") - if(!src.lighthack) - if (src.icon_state == "nuclearbomb2") - src.icon_state = "nuclearbomb1" - else - visible_message("\blue The [src] emits a quiet whirling noise!") - if(href_list["act"] == "wire") - if (!istype(usr.get_active_hand(), /obj/item/weapon/wirecutters)) - usr << "You need wirecutters!" - else - wires[temp_wire] = !wires[temp_wire] - if(src.safety_wire == temp_wire) - if(src.timing) - spawn - explode() - if(src.timing_wire == temp_wire) - if(!src.lighthack) - if (src.icon_state == "nuclearbomb2") - src.icon_state = "nuclearbomb1" - src.timing = 0 - bomb_set = 0 - if(src.light_wire == temp_wire) - src.lighthack = !src.lighthack - if (href_list["auth"]) - if (src.auth) - src.auth.loc = src.loc - src.yes_code = 0 - src.auth = null + if (auth) + auth.loc = loc + yes_code = 0 + auth = null else var/obj/item/I = usr.get_active_hand() if (istype(I, /obj/item/weapon/disk/nuclear)) usr.drop_item() I.loc = src - src.auth = I + auth = I if (is_auth(usr)) if (href_list["type"]) if (href_list["type"] == "E") - if (src.code == src.r_code) - src.yes_code = 1 - src.code = null + if (code == r_code) + yes_code = 1 + code = null else - src.code = "ERROR" + code = "ERROR" else if (href_list["type"] == "R") - src.yes_code = 0 - src.code = null + yes_code = 0 + code = null else lastentered = text("[]", href_list["type"]) if (text2num(lastentered) == null) @@ -336,51 +265,61 @@ var/bomb_set message_admins("[key_name_admin(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]! ([LOC ? "JMP" : "null"])", 0) log_admin("EXPLOIT: [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered]!") else - src.code += lastentered - if (length(src.code) > 5) - src.code = "ERROR" - if (src.yes_code) + code += lastentered + if (length(code) > 5) + code = "ERROR" + if (yes_code) if (href_list["time"]) var/time = text2num(href_list["time"]) - src.timeleft += time - src.timeleft = min(max(round(src.timeleft), 120), 600) + timeleft += time + timeleft = min(max(round(src.timeleft), 120), 600) if (href_list["timer"]) - if (src.timing == -1.0) + if (timing == -1.0) nanomanager.update_uis(src) return - if (src.safety) + if (safety) usr << "\red The safety is still on." nanomanager.update_uis(src) return - src.timing = !( src.timing ) - if (src.timing) - if(!src.lighthack) - src.icon_state = "nuclearbomb2" - if(!src.safety) - bomb_set = 1//There can still be issues with this reseting when there are multiple bombs. Not a big deal tho for Nuke/N + timing = !(timing) + if (timing) + if(!lighthack) + icon_state = "nuclearbomb2" + if(!safety) + message_admins("[key_name_admin(usr)] engaged a nuclear bomb (JMP)") + if(!is_syndicate) + set_security_level("delta") + bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N else bomb_set = 0 else + if(!is_syndicate) + set_security_level(previous_level) bomb_set = 0 - if(!src.lighthack) - src.icon_state = "nuclearbomb1" + if(!lighthack) + icon_state = "nuclearbomb1" if (href_list["safety"]) - src.safety = !( src.safety ) + safety = !(safety) if(safety) - src.timing = 0 + if(!is_syndicate) + set_security_level(previous_level) + timing = 0 bomb_set = 0 if (href_list["anchor"]) if(removal_stage == 5) - src.anchored = 0 + anchored = 0 visible_message("\red \The [src] makes a highly unpleasant crunching noise. It looks like the anchoring bolts have been cut.") nanomanager.update_uis(src) return - - src.anchored = !( src.anchored ) - if(src.anchored) - visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.") + + if(!isinspace()) + anchored = !(anchored) + if(anchored) + visible_message("\red With a steely snap, bolts slide out of [src] and anchor it to the flooring.") + else + visible_message("\red The anchoring bolts slide back into the depths of [src].") else - visible_message("\red The anchoring bolts slide back into the depths of [src].") + usr << "There is nothing to anchor to!" nanomanager.update_uis(src) @@ -388,7 +327,7 @@ var/bomb_set return /obj/machinery/nuclearbomb/blob_act() - if (src.timing == -1.0) + if (timing == -1.0) return else return ..() @@ -396,14 +335,14 @@ var/bomb_set #define NUKERANGE 80 /obj/machinery/nuclearbomb/proc/explode() - if (src.safety) - src.timing = 0 + if (safety) + timing = 0 return - src.timing = -1.0 - src.yes_code = 0 - src.safety = 1 - if(!src.lighthack) - src.icon_state = "nuclearbomb3" + timing = -1.0 + yes_code = 0 + safety = 1 + if(!lighthack) + icon_state = "nuclearbomb3" playsound(src,'sound/machines/Alarm.ogg',100,0,5) if (ticker && ticker.mode) ticker.mode.explosion_in_progress = 1 diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index 8ce55e77526..421582d26a1 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -152,9 +152,9 @@ Made by Xhuis update_shadow_icons_added(new_thrall_mind) new_thrall_mind.current.attack_log += "\[[time_stamp()]\] Became a thrall" new_thrall_mind.current.add_language("Shadowling Hivemind") - new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_glare) - new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) - //new_thrall_mind.current.AddSpell(new /obj/effect/proc_holder/spell/targeted/thrall_vision) //Uncomment when vision code is unfucked. + new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_glare) + new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) + //new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/thrall_vision) //Uncomment when vision code is unfucked. new_thrall_mind.current << "You see the truth. Reality has been torn away and you realize what a fool you've been." new_thrall_mind.current << "The shadowlings are your masters. Serve them above all else and ensure they complete their goals." new_thrall_mind.current << "You may not harm other thralls or the shadowlings. However, you do not need to obey other thralls." diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm index 46d05fa38a9..1566e3b254b 100644 --- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm @@ -91,11 +91,11 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N sleep(10) H << "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies." H.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/shadowling_hatch) - H.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare) - H.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil) - H.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk) - H.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze) - H.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze) + H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind) /obj/effect/proc_holder/spell/targeted/shadowling_ascend name = "Ascend" @@ -156,11 +156,11 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.mind.transfer_to(A) A.name = H.real_name A.languages = H.languages - A.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate) - A.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis) - A.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift) - A.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm) - A.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit) + A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/annihilate) + A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/hypnosis) + A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift) + A.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm) + A.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit) if(A.real_name) A.real_name = H.real_name H.invisibility = 60 //This is pretty bad, but is also necessary for the shuttle call to function properly diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 8aa64e18b6b..76fd8cf7ea5 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -233,201 +233,28 @@ This is a good place for AI-related object verbs so I'm sticking it here. If adding stuff to this, don't forget that an AI need to cancel_camera() whenever it physically moves to a different location. That prevents a few funky behaviors. */ -//What operation to perform based on target, what ineraction to perform based on object used, target itself, user. The object used is src and calls this proc. -/obj/item/proc/transfer_ai(var/choice as text, var/interaction as text, var/target, var/mob/U as mob) - if(!src:flush) - switch(choice) - if("AICORE")//AI mob. - var/mob/living/silicon/ai/T = target - switch(interaction) - if("AICARD") - var/obj/item/device/aicard/C = src - if(C.contents.len)//If there is an AI on card. - U << "\red Transfer failed: \black Existing AI found on this terminal. Remove existing AI to install a new one." - else - if (ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if (T.mind == malfai) - U << "\red ERROR: \black Remote transfer interface disabled."//Do ho ho ho~ - return - new /obj/structure/AIcore/deactivated(T.loc)//Spawns a deactivated terminal at AI location. - T.aiRestorePowerRoutine = 0//So the AI initially has power. - T.control_disabled = 1//Can't control things remotely if you're stuck in a card! - T.loc = C//Throw AI into the card. - C.name = "inteliCard - [T.name]" - if (T.stat == 2) - C.icon_state = "aicard-404" - else - C.icon_state = "aicard-full" - T.cancel_camera() - T << "You have been downloaded to a mobile storage device. Remote device connection severed." - U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." - /*if("NINJASUIT") - var/obj/item/clothing/suit/space/space_ninja/C = src - if(C.AI)//If there is an AI on card. - U << "\red Transfer failed: \black Existing AI found on this terminal. Remove existing AI to install a new one." - else - if (ticker.mode.name == "AI malfunction") - var/datum/game_mode/malfunction/malf = ticker.mode - for (var/datum/mind/malfai in malf.malf_ai) - if (T.mind == malfai) - U << "\red ERROR: \black Remote transfer interface disabled." - return - if(T.stat)//If the ai is dead/dying. - U << "\red ERROR: \black [T.name] data core is corrupted. Unable to install." - else - new /obj/structure/AIcore/deactivated(T.loc) - T.aiRestorePowerRoutine = 0 - T.control_disabled = 1 - T.loc = C - C.AI = T - T.cancel_camera() - T << "You have been downloaded to a mobile storage device. Remote device connection severed." - U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."*/ +//The type of interaction, the player performing the operation, the AI itself, and the card object, if any. - if("INACTIVE")//Inactive AI object. - var/obj/structure/AIcore/deactivated/T = target - switch(interaction) - if("AICARD") - var/obj/item/device/aicard/C = src - var/mob/living/silicon/ai/A = locate() in C//I love locate(). Best proc ever. - if(A)//If AI exists on the card. Else nothing since both are empty. - A.control_disabled = 0 - A.loc = T.loc//To replace the terminal. - C.icon_state = "aicard" - C.name = "inteliCard" - C.overlays.Cut() - A.cancel_camera() - A << "You have been uploaded to a stationary terminal. Remote device connection restored." - U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed." - qdel(T) - /*if("NINJASUIT") - var/obj/item/clothing/suit/space/space_ninja/C = src - var/mob/living/silicon/ai/A = C.AI - if(A) - A.control_disabled = 0 - C.AI = null - A.loc = T.loc - A.cancel_camera() - A << "You have been uploaded to a stationary terminal. Remote device connection restored." - U << "\blue Transfer succesful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed." - del(T)*/ - if("AIFIXER")//AI Fixer terminal. - var/obj/machinery/computer/aifixer/T = target - switch(interaction) - if("AICARD") - var/obj/item/device/aicard/C = src - if(!T.contents.len) - if (!C.contents.len) - U << "No AI to copy over!"//Well duh - else for(var/mob/living/silicon/ai/A in C) - C.icon_state = "aicard" - C.name = "inteliCard" - C.overlays.Cut() - A.loc = T - T.occupant = A - A.control_disabled = 1 - if (A.stat == 2) - T.overlays += image('icons/obj/computer.dmi', "ai-fixer-404") - else - T.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-empty") - A.cancel_camera() - A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here." - U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed." - else - if(!C.contents.len && T.occupant && !T.active) - C.name = "inteliCard - [T.occupant.name]" - T.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") - if (T.occupant.stat == 2) - C.icon_state = "aicard-404" - T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") - else - C.icon_state = "aicard-full" - T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-full") - T.occupant << "You have been downloaded to a mobile storage device. Still no remote access." - U << "\blue Transfer succesful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." - T.occupant.loc = C - T.occupant.cancel_camera() - T.occupant = null - else if (C.contents.len) - U << "\red ERROR: \black Artificial intelligence detected on terminal." - else if (T.active) - U << "\red ERROR: \black Reconstruction in progress." - else if (!T.occupant) - U << "\red ERROR: \black Unable to locate artificial intelligence." - /*if("NINJASUIT") - var/obj/item/clothing/suit/space/space_ninja/C = src - if(!T.contents.len) - if (!C.AI) - U << "No AI to copy over!" - else - var/mob/living/silicon/ai/A = C.AI - A.loc = T - T.occupant = A - C.AI = null - A.control_disabled = 1 - T.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-empty") - A.cancel_camera() - A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here." - U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed." - else - if(!C.AI && T.occupant && !T.active) - if (T.occupant.stat) - U << "\red ERROR: \black [T.occupant.name] data core is corrupted. Unable to install." - else - T.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") - T.overlays -= image('icons/obj/computer.dmi', "ai-fixer-full") - T.occupant << "You have been downloaded to a mobile storage device. Still no remote access." - U << "\blue Transfer successful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." - T.occupant.loc = C - T.occupant.cancel_camera() - T.occupant = null - else if (C.AI) - U << "\red ERROR: \black Artificial intelligence detected on terminal." - else if (T.active) - U << "\red ERROR: \black Reconstruction in progress." - else if (!T.occupant) - U << "\red ERROR: \black Unable to locate artificial intelligence."*/ - /*if("NINJASUIT")//Ninjasuit - var/obj/item/clothing/suit/space/space_ninja/T = target - switch(interaction) - if("AICARD") - var/obj/item/device/aicard/C = src - if(T.s_initialized&&U==T.affecting)//If the suit is initialized and the actor is the user. - var/mob/living/silicon/ai/A_T = locate() in C//Determine if there is an AI on target card. Saves time when checking later. - var/mob/living/silicon/ai/A = T.AI//Deterine if there is an AI in suit. +atom/proc/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card) + if(istype(card)) + if(card.flush) + user << "ERROR: AI flush is in progress, cannot execute transfer protocol." + return 0 + return 1 - if(A)//If the host AI card is not empty. - if(A_T)//If there is an AI on the target card. - U << "\red ERROR: \black [A_T.name] already installed. Remove [A_T.name] to install a new one." - else - A.loc = C//Throw them into the target card. Since they are already on a card, transfer is easy. - C.name = "inteliCard - [A.name]" - C.icon_state = "aicard-full" - T.AI = null - A.cancel_camera() - A << "You have been uploaded to a mobile storage device." - U << "\blue SUCCESS: \black [A.name] ([rand(1000,9999)].exe) removed from host and stored within local memory." - else//If host AI is empty. - if(C.flush)//If the other card is flushing. - U << "\red ERROR: \black AI flush is in progress, cannot execute transfer protocol." - else - if(A_T&&!A_T.stat)//If there is an AI on the target card and it's not inactive. - A_T.loc = T//Throw them into suit. - C.icon_state = "aicard" - C.name = "inteliCard" - C.overlays.Cut() - T.AI = A_T - A_T.cancel_camera() - A_T << "You have been uploaded to a mobile storage device." - U << "\blue SUCCESS: \black [A_T.name] ([rand(1000,9999)].exe) removed from local memory and installed to host." - else if(A_T)//If the target AI is dead. Else just go to return since nothing would happen if both are empty. - U << "\red ERROR: \black [A_T.name] data core is corrupted. Unable to install."*/ - else - U << "\red ERROR: \black AI flush is in progress, cannot execute transfer protocol." - return \ No newline at end of file +/obj/structure/AIcore/deactivated/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card) + if(!..()) + return + //Transferring a carded AI to a core. + if(interaction == AI_TRANS_FROM_CARD) + AI.control_disabled = 0 + AI.aiRadio.disabledAi = 0 + AI.loc = loc//To replace the terminal. + AI << "You have been uploaded to a stationary terminal. Remote device connection restored." + user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed." + qdel(src) + else //If for some reason you use an empty card on an empty AI terminal. + user << "There is no AI loaded on this terminal!" + \ No newline at end of file diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index d291c65ac78..a7dd1874424 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -10,77 +10,64 @@ light_color = LIGHT_COLOR_PURPLE -/obj/machinery/computer/aifixer/New() - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") - - /obj/machinery/computer/aifixer/attackby(I as obj, user as mob, params) - if(istype(I, /obj/item/device/aicard)) + if(occupant && istype(I, /obj/item/weapon/screwdriver)) if(stat & (NOPOWER|BROKEN)) - user << "This terminal isn't functioning right now, get it working!" - return - I:transfer_ai("AIFIXER","AICARD",src,user) - - ..() - return - + user << "The screws on [name]'s screen won't budge." + else + user << "The screws on [name]'s screen won't budge and it emits a warning beep." + return + else + ..() + /obj/machinery/computer/aifixer/attack_ai(var/mob/user as mob) - return attack_hand(user) + ui_interact(user) /obj/machinery/computer/aifixer/attack_hand(var/mob/user as mob) - if(..()) - return - - user.set_machine(src) - var/dat = "

AI System Integrity Restorer



" - - if (src.occupant) - var/laws - dat += "Stored AI: [src.occupant.name]
System integrity: [(src.occupant.health+100)/2]%
" - - if (src.occupant.laws.zeroth) - laws += "0: [src.occupant.laws.zeroth]
" + ui_interact(user) +/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + if(occupant) + data["occupant"] = occupant.name + data["reference"] = "\ref[occupant]" + data["integrity"] = (occupant.health+100)/2 + data["stat"] = occupant.stat + data["active"] = active + data["wireless"] = occupant.control_disabled + data["radio"] = occupant.aiRadio.disabledAi + data["zeroth"] = occupant.laws.zeroth + + var/laws[0] var/number = 1 - for (var/index = 1, index <= src.occupant.laws.inherent.len, index++) - var/law = src.occupant.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
" + for (var/index = 1, index <= occupant.laws.inherent.len, index++) + var/law = occupant.laws.inherent[index] + if(length(law) > 0) + laws.Add(list(list("law" = law, "number" = number))) number++ - for (var/index = 1, index <= src.occupant.laws.supplied.len, index++) - var/law = src.occupant.laws.supplied[index] + for (var/index = 1, index <= occupant.laws.supplied.len, index++) + var/law = occupant.laws.supplied[index] if (length(law) > 0) - laws += "[number]: [law]
" - number++ + laws += "[number]: [law]
" + number++ + + data["laws"] = laws + + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - dat += "Laws:
[laws]
" - - if (src.occupant.stat == 2) - dat += "AI nonfunctional" - else - dat += "AI functional" - if (!src.active) - dat += {"

Begin Reconstruction"} - else - dat += "

Reconstruction in process, please wait.
" - dat += {" Close"} - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - -/obj/machinery/computer/aifixer/process() - if(..()) - src.updateDialog() - return + if (!ui) + ui = new(user, src, ui_key, "ai_fixer.tmpl", "AI System Integrity Restorer", 550, 500) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) /obj/machinery/computer/aifixer/Topic(href, href_list) if(..()) return 1 - if (href_list["fix"]) + + if(href_list["fix"]) src.active = 1 - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-on") while (src.occupant.health < 100) src.occupant.adjustOxyLoss(-1) src.occupant.adjustFireLoss(-1) @@ -92,32 +79,66 @@ src.occupant.lying = 0 dead_mob_list -= src.occupant living_mob_list += src.occupant - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") - src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") - src.updateUsrDialog() sleep(10) src.active = 0 - src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on") - - src.add_fingerprint(usr) - src.updateUsrDialog() - return + + if(href_list["wireless"]) + var/wireless = text2num(href_list["wireless"]) + if(wireless == 0 || wireless == 1) + occupant.control_disabled = wireless + + if(href_list["radio"]) + var/radio = text2num(href_list["radio"]) + if(radio == 0 || radio == 1) + occupant.aiRadio.disabledAi = radio + nanomanager.update_uis(src) + update_icon() + return /obj/machinery/computer/aifixer/update_icon() ..() - // Broken / Unpowered - if((stat & BROKEN) || (stat & NOPOWER)) - overlays.Cut() - - // Working / Powered + if(stat & (NOPOWER|BROKEN)) + return else + var/overlay_layer = LIGHTING_LAYER+0.2 // +0.1 from the default computer overlays + if(active) + overlays += image(icon,"ai-fixer-on",overlay_layer) if (occupant) switch (occupant.stat) if (0) - overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + overlays += image(icon,"ai-fixer-full",overlay_layer) if (2) - overlays += image('icons/obj/computer.dmi', "ai-fixer-404") + overlays += image(icon,"ai-fixer-404",overlay_layer) else - overlays += image('icons/obj/computer.dmi', "ai-fixer-empty") + overlays += image(icon,"ai-fixer-empty",overlay_layer) + +/obj/machinery/computer/aifixer/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card) + if(!..()) + return + //Downloading AI from card to terminal. + if(interaction == AI_TRANS_FROM_CARD) + if(stat & (NOPOWER|BROKEN)) + user << "[src] is offline and cannot take an AI at this time!" + return + AI.loc = src + occupant = AI + AI.control_disabled = 1 + AI.aiRadio.disabledAi = 1 + AI << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here." + user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed." + update_icon() + + else //Uploading AI from terminal to card + if(occupant && !active) + occupant << "You have been downloaded to a mobile storage device. Still no remote access." + user << "Transfer successful: [occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." + occupant.loc = card + occupant = null + update_icon() + else if (active) + user << "ERROR: Reconstruction in progress." + else if (!occupant) + user << "ERROR: Unable to locate artificial intelligence." + \ No newline at end of file diff --git a/code/game/machinery/computer/pod_tracking_console.dm b/code/game/machinery/computer/pod_tracking_console.dm index 5c40d9a11f8..060b58eda90 100644 --- a/code/game/machinery/computer/pod_tracking_console.dm +++ b/code/game/machinery/computer/pod_tracking_console.dm @@ -5,39 +5,43 @@ icon_screen = "rdcomp" light_color = LIGHT_COLOR_PURPLE req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/pod_locater" + circuit = /obj/item/weapon/circuitboard/pod_locater /obj/machinery/computer/podtracker/attack_ai(var/mob/user as mob) - return src.attack_hand(user) - -/obj/machinery/computer/podtracker/attack_hand(var/mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat = "[src.name]" - dat += "

Pod beacons data

" + return attack_hand(user) + +/obj/machinery/computer/podtracker/attack_hand(user as mob) + ui_interact(user) + +/obj/machinery/computer/podtracker/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + var/list/pods[0] for(var/obj/item/device/spacepod_equipment/misc/tracker/TR in world) var/obj/spacepod/myPod = TR.my_atom var/enabled = TR.enabled if(myPod && enabled) - dat += {"
[capitalize(myPod.name)]
-  Pod SPS X: [myPod.x]
-  Pod SPS Y: [myPod.y]
-  Pod SPS Z: [myPod.z]
"} + var/podname = capitalize(sanitize(myPod.name)) + var/occupant = "None" + var/occupant2 = "None" if(myPod.occupant) - dat += {" Pod Pilot: [myPod.occupant.name]
"} + occupant = myPod.occupant.name if(myPod.occupant2) - dat += {" Pod Passenger: [myPod.occupant2.name]
"} + occupant2 = myPod.occupant2.name + pods.Add(list(list("pod" = "\ref[myPod]", "name" = podname, "occupant" = occupant, "occupant2" = occupant2, "x" = myPod.x, "y" = myPod.y, "z" = myPod.z))) + + data["pods"] = pods - dat += "(Refresh)
" - dat += "" + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return + if (!ui) + ui = new(user, src, ui_key, "pod_tracking.tmpl", "Pod Tracking Console", 400, 500) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) /obj/machinery/computer/podtracker/Topic(href, href_list) if(..()) - return - src.updateUsrDialog() - return + return 1 + + if(href_list["refresh"]) + nanomanager.update_uis(src) diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm index db49facd824..7c08f2ebd07 100644 --- a/code/game/machinery/kitchen/gibber.dm +++ b/code/game/machinery/kitchen/gibber.dm @@ -374,11 +374,11 @@ new /obj/effect/decal/cleanable/blood/gibs(src) if(!UserOverride) - src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [user]/[user.ckey]" //One shall not simply gib a mob unnoticed! - user.attack_log += "\[[time_stamp()]\] Gibbed [src.occupant]/[src.occupant.ckey]" + src.occupant.attack_log += "\[[time_stamp()]\] Was gibbed by [key_name(user)]" //One shall not simply gib a mob unnoticed! + user.attack_log += "\[[time_stamp()]\] Gibbed [key_name(occupant)]" if(src.occupant.ckey) - msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] gibbed [src.occupant] ([src.occupant.ckey]) (JMP)") + msg_admin_attack("[key_name_admin(user)] gibbed [key_name_admin(occupant)]") if(!iscarbon(user)) src.occupant.LAssailant = null diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index 458c8a369cb..9882151bb21 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -282,17 +282,22 @@ construction_time = 1200 construction_cost = list("metal"=30000,"plasma"=25000,"silver"=20000,"gold"=20000) var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. - var/disabled = 0 //malf var/canRwall = 0 + + New() + rcd_list += src + ..() + + Destroy() + rcd_list -= src + ..() action(atom/target) - if(istype(target,/area/shuttle)||istype(target, /turf/space/transit))//>implying these are ever made -Sieve - disabled = 1 - else - disabled = 0 + if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve + return if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) target = get_turf(target) - if(!action_checks(target) || disabled || get_dist(chassis, target)>3) return + if(!action_checks(target) || get_dist(chassis, target)>3) return playsound(chassis, 'sound/machines/click.ogg', 50, 1) //meh switch(mode) @@ -303,7 +308,6 @@ occupant_message("Deconstructing [target]...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return chassis.spark_system.start() target:ChangeTurf(/turf/simulated/floor/plating) playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) @@ -312,7 +316,6 @@ occupant_message("Deconstructing [target]...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return chassis.spark_system.start() target:ChangeTurf(/turf/space) playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) @@ -321,7 +324,6 @@ occupant_message("Deconstructing [target]...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return chassis.spark_system.start() qdel(target) playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) @@ -331,7 +333,6 @@ occupant_message("Building Floor...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return target:ChangeTurf(/turf/simulated/floor/plating) playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) chassis.spark_system.start() @@ -340,7 +341,6 @@ occupant_message("Building Wall...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return target:ChangeTurf(/turf/simulated/wall) playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) chassis.spark_system.start() @@ -350,7 +350,6 @@ occupant_message("Building Airlock...") set_ready_state(0) if(do_after_cooldown(target)) - if(disabled) return chassis.spark_system.start() var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) T.autoclose = 1 diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 27fe49e746d..b812cab95bd 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -96,11 +96,6 @@ mechas_list += src //global mech list return -/obj/mecha/Destroy() - src.go_out() - mechas_list -= src //global mech list - return ..() - //////////////////////// ////// Helpers ///////// //////////////////////// @@ -615,50 +610,65 @@ return /obj/mecha/proc/destroy() - spawn() - go_out() - var/turf/T = get_turf(src) - tag = "\ref[src]" //better safe then sorry - if(loc) - loc.Exited(src) - loc = null - if(T) - if(istype(src, /obj/mecha/working/ripley/)) - var/obj/mecha/working/ripley/R = src - if(R.cargo) - for(var/obj/O in R.cargo) //Dump contents of stored cargo - O.loc = T - R.cargo -= O - T.Entered(O) + go_out() + for(var/mob/M in src) //Let's just be ultra sure + if(isAI(M)) + M.gib() //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. Forever. + else + M.Move(loc) + + if(prob(30)) + explosion(get_turf(loc), 0, 0, 1, 3) + + if(istype(src, /obj/mecha/working/ripley/)) + var/obj/mecha/working/ripley/R = src + if(R.cargo) + for(var/obj/O in R.cargo) //Dump contents of stored cargo + O.loc = loc + R.cargo -= O + loc.Entered(O) - if(prob(30)) - explosion(get_turf(loc), 0, 0, 1, 3) - spawn(0) - if(wreckage) - var/obj/effect/decal/mecha_wreckage/WR = new wreckage(T) - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - if(E.salvageable && prob(30)) - WR.crowbar_salvage += E - E.forceMove(WR) - E.equip_ready = 1 - E.reliability = round(rand(E.reliability/3,E.reliability)) - else - E.forceMove(T) - E.destroy() - if(cell) - WR.crowbar_salvage += cell - cell.forceMove(WR) - cell.charge = rand(0, cell.charge) - if(internal_tank) - WR.crowbar_salvage += internal_tank - internal_tank.forceMove(WR) - else - for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) - E.forceMove(T) - E.destroy() - spawn(0) - qdel(src) - return + if(wreckage) + var/obj/effect/decal/mecha_wreckage/WR = new wreckage(loc) + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + if(E.salvageable && prob(30)) + WR.crowbar_salvage += E + E.forceMove(WR) + E.equip_ready = 1 + E.reliability = round(rand(E.reliability/3,E.reliability)) + else + E.forceMove(loc) + E.destroy() + if(cell) + WR.crowbar_salvage += cell + cell.forceMove(WR) + cell.charge = rand(0, cell.charge) + if(internal_tank) + WR.crowbar_salvage += internal_tank + internal_tank.forceMove(WR) + else + for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) + E.forceMove(loc) + E.destroy() + if(cell) + qdel(cell) + if(internal_tank) + qdel(internal_tank) + equipment.Cut() + cell = null + internal_tank = null + + qdel(pr_int_temp_processor) + qdel(pr_give_air) + qdel(pr_internal_damage) + qdel(spark_system) + pr_int_temp_processor = null + pr_give_air = null + pr_internal_damage = null + spark_system = null + + mechas_list -= src //global mech list + return ..() /obj/mecha/ex_act(severity) src.log_message("Affected by explosion of severity: [severity].",1) @@ -916,16 +926,92 @@ return -/* +///////////////////////////////////// +//////////// AI piloting //////////// +///////////////////////////////////// + /obj/mecha/attack_ai(var/mob/living/silicon/ai/user as mob) - if(!istype(user, /mob/living/silicon/ai)) + if(!isAI(user)) return - var/output = {"Assume direct control over [src]? - Yes
- "} - user << browse(output, "window=mecha_attack_ai") - return -*/ + //Allows the Malf to scan a mech's status and loadout, helping it to decide if it is a worthy chariot. + if(user.can_dominate_mechs) + examine(user) //Get diagnostic information! + var/obj/item/mecha_parts/mecha_tracking/B = locate(/obj/item/mecha_parts/mecha_tracking) in src + if(B) //Beacons give the AI more detailed mech information. + user << "Warning: Tracking Beacon detected. Enter at your own risk. Beacon Data:" + user << "[B.get_mecha_info()]" + //Nothing like a big, red link to make the player feel powerful! + user << "ASSUME DIRECT CONTROL?
" + +/obj/mecha/transfer_ai(var/interaction, mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card) + if(!..()) + return + + //Transfer from core or card to mech. Proc is called by mech. + switch(interaction) + if(AI_TRANS_TO_CARD) //Upload AI from mech to AI card. + if(!maint_access) //Mech must be in maint mode to allow carding. + user << "[name] must have maintenance protocols active in order to allow a transfer." + return + AI = occupant + if(!AI || !isAI(occupant)) //Mech does not have an AI for a pilot + user << "No AI detected in the [name] onboard computer." + return + if (AI.mind.special_role == "malfunction") //Malf AIs cannot leave mechs. Except through death. + user << "ACCESS DENIED." + return + AI.aiRestorePowerRoutine = 0//So the AI initially has power. + AI.control_disabled = 1 + AI.aiRadio.disabledAi = 1 + AI.loc = card + occupant = null + AI.controlled_mech = null + AI.remote_control = null + icon_state = initial(icon_state)+"-open" + AI << "You have been downloaded to a mobile storage device. Wireless connection offline." + user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) removed from [name] and stored within local memory." + + if(AI_MECH_HACK) //Called by Malf AI mob on the mech. + new /obj/structure/AIcore/deactivated(AI.loc) + if(occupant) //Oh, I am sorry, were you using that? + AI << "Pilot detected! Forced ejection initiated!" + occupant << "You have been forcibly ejected!" + go_out(1) //IT IS MINE, NOW. SUCK IT, RD! + ai_enter_mech(AI, interaction) + + if(AI_TRANS_FROM_CARD) //Using an AI card to upload to a mech. + AI = locate(/mob/living/silicon/ai) in card + if(!AI) + user << "There is no AI currently installed on this device." + return + else if(AI.stat || !AI.client) + user << "[AI.name] is currently unresponsive, and cannot be uploaded." + return + else if(occupant || dna) //Normal AIs cannot steal mechs! + user << "Access denied. [name] is [occupant ? "currently occupied" : "secured with a DNA lock"]." + return + AI.control_disabled = 0 + AI.aiRadio.disabledAi = 0 + user << "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed." + ai_enter_mech(AI, interaction) + +//Hack and From Card interactions share some code, so leave that here for both to use. +/obj/mecha/proc/ai_enter_mech(var/mob/living/silicon/ai/AI, var/interaction) + AI.aiRestorePowerRoutine = 0 + AI.loc = src + occupant = AI + icon_state = initial(icon_state) + playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) + if(!hasInternalDamage()) + occupant << sound('sound/mecha/nominal.ogg',volume=50) + AI.cancel_camera() + AI.controlled_mech = src + AI.remote_control = src + AI.canmove = 1 //Much easier than adding AI checks! Be sure to set this back to 0 if you decide to allow an AI to leave a mech somehow. + AI.can_shunt = 0 //ONE AI ENTERS. NO AI LEAVES. + AI << "[interaction == AI_MECH_HACK ? "Takeover of [name] complete! You are now permanently loaded onto the onboard computer. Do not attempt to leave the station sector!" \ + : "You have been uploaded to a mech's onboard computer."]" + AI << "Use Middle-Mouse to activate mech functions and equipment. Click normally for AI interactions." ///////////////////////////////////// //////// Atmospheric stuff //////// @@ -1228,7 +1314,7 @@ return -/obj/mecha/proc/go_out() +/obj/mecha/proc/go_out(var/forced) if(!src.occupant) return var/atom/movable/mob_container if(ishuman(occupant)) @@ -1236,6 +1322,10 @@ else if(istype(occupant, /mob/living/carbon/brain)) var/mob/living/carbon/brain/brain = occupant mob_container = brain.container + else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf. + occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced. + occupant = null + return else return if(mob_container.forceMove(src.loc))//ejecting mob container @@ -1677,13 +1767,13 @@ user << browse(null,"window=exosuit_add_access") return if(href_list["dna_lock"]) - if(usr != src.occupant) return - if(istype(occupant, /mob/living/carbon/brain)) - occupant_message("You are a brain. No.") + if(usr != src.occupant) return - if(src.occupant) - src.dna = src.occupant.dna.unique_enzymes - src.occupant_message("You feel a prick as the needle takes your DNA sample.") + if(src.occupant && !iscarbon(src.occupant)) + src.occupant << "You do not have any DNA!" + return + src.dna = src.occupant.dna.unique_enzymes + src.occupant_message("You feel a prick as the needle takes your DNA sample.") return if(href_list["reset_dna"]) if(usr != src.occupant) return @@ -1712,54 +1802,6 @@ return */ - - -/* - - if (href_list["ai_take_control"]) - var/mob/living/silicon/ai/AI = locate(href_list["ai_take_control"]) - var/duration = text2num(href_list["duration"]) - var/mob/living/silicon/ai/O = new /mob/living/silicon/ai(src) - var/cur_occupant = src.occupant - O.invisibility = 0 - O.canmove = 1 - O.name = AI.name - O.real_name = AI.real_name - O.anchored = 1 - O.aiRestorePowerRoutine = 0 - O.control_disabled = 1 // Can't control things remotely if you're stuck in a card! - O.laws = AI.laws - O.stat = AI.stat - O.oxyloss = AI.getOxyLoss() - O.fireloss = AI.getFireLoss() - O.bruteloss = AI.getBruteLoss() - O.toxloss = AI.toxloss - O.updatehealth() - src.occupant = O - if(AI.mind) - AI.mind.transfer_to(O) - AI.name = "Inactive AI" - AI.real_name = "Inactive AI" - AI.icon_state = "ai-empty" - spawn(duration) - AI.name = O.name - AI.real_name = O.real_name - if(O.mind) - O.mind.transfer_to(AI) - AI.control_disabled = 0 - AI.laws = O.laws - AI.oxyloss = O.getOxyLoss() - AI.fireloss = O.getFireLoss() - AI.bruteloss = O.getBruteLoss() - AI.toxloss = O.toxloss - AI.updatehealth() - del(O) - if (!AI.stat) - AI.icon_state = "ai" - else - AI.icon_state = "ai-crash" - src.occupant = cur_occupant -*/ return /////////////////////// diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 036872780b2..ce44f2e59b1 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -5,64 +5,66 @@ icon_screen = "mecha" light_color = LIGHT_COLOR_FADEDPURPLE req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/mecha_control" + circuit = /obj/item/weapon/circuitboard/mecha_control var/list/located = list() var/screen = 0 var/stored_data - attack_ai(var/mob/user as mob) - return src.attack_hand(user) +/obj/machinery/computer/mecha/attack_ai(var/mob/user as mob) + return attack_hand(user) - attack_hand(var/mob/user as mob) - if(..()) - return - user.set_machine(src) - var/dat = "[src.name]" - if(screen == 0) - dat += "

Tracking beacons data

" - for(var/obj/item/mecha_parts/mecha_tracking/TR in world) - var/answer = TR.get_mecha_info() - if(answer) - dat += {"
[answer]
- Send message
- Show exosuit log | (EMP pulse)
"} +/obj/machinery/computer/mecha/attack_hand(var/mob/user as mob) + ui_interact(user) + +/obj/machinery/computer/mecha/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + data["screen"] = screen + if(screen == 0) + var/list/mechas[0] + for(var/obj/item/mecha_parts/mecha_tracking/TR in world) + var/answer = TR.get_mecha_info() + if(answer) + mechas[++mechas.len] = answer + data["mechas"] = mechas + if(screen == 1) + data["log"] = stored_data - if(screen==1) - dat += "

Log contents

" - dat += "Return
" - dat += "[stored_data]" - - dat += "(Refresh)
" - dat += "" - - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") - return - - Topic(href, href_list) - if(..()) - return - var/datum/topic_input/filter = new /datum/topic_input(href,href_list) - if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message") - var/message = strip_html_simple(input(usr,"Input message","Transmit message") as text) - var/obj/mecha/M = MT.in_mecha() - if(trim(message) && M) - M.occupant_message(message) - return - if(href_list["shock"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock") - MT.shock() - if(href_list["get_log"]) - var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log") - stored_data = MT.get_mecha_log() - screen = 1 - if(href_list["return"]) - screen = 0 - src.updateUsrDialog() - return + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "exosuit_control.tmpl", "Exosuit Control Console", 420, 500) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) +/obj/machinery/computer/mecha/Topic(href, href_list) + if(..()) + return 1 + + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(href_list["send_message"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("send_message") + var/message = strip_html_simple(input(usr,"Input message","Transmit message") as text) + if(!trim(message) || ..()) + return 1 + var/obj/mecha/M = MT.in_mecha() + if(M) + M.occupant_message(message) + + if(href_list["shock"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("shock") + MT.shock() + + if(href_list["get_log"]) + var/obj/item/mecha_parts/mecha_tracking/MT = filter.getObj("get_log") + stored_data = MT.get_mecha_log() + screen = 1 + + if(href_list["return"]) + screen = 0 + + nanomanager.update_uis(src) + return /obj/item/mecha_parts/mecha_tracking name = "Exosuit tracking beacon" @@ -73,49 +75,57 @@ construction_time = 50 construction_cost = list("metal"=500) - proc/get_mecha_info() - if(!in_mecha()) - return 0 - var/obj/mecha/M = src.loc - var/cell_charge = M.get_charge() - var/answer = {"Name: [M.name]
- Integrity: [M.health/initial(M.health)*100]%
- Cell charge: [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]
- Airtank: [M.return_pressure()]kPa
- Pilot: [M.occupant||"None"]
- Location: [get_area(M)||"Unknown"]
- Active equipment: [M.selected||"None"]"} - if(istype(M, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/RM = M - answer += "Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
" - - return answer - - emp_act() - qdel(src) - return - - ex_act() - qdel(src) - return - - proc/in_mecha() - if(istype(src.loc, /obj/mecha)) - return src.loc +/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info() + if(!in_mecha()) return 0 + var/obj/mecha/M = src.loc + var/list/answer[0] + answer["reference"] = "\ref[src]" + answer["name"] = sanitize(replacetext(M.name,"\"","'")) // Double apostrophes break JSON + if(M.cell) + answer["cell"] = 1 + answer["cell_capacity"] = M.cell.maxcharge + answer["cell_current"] = M.get_charge() + answer["cell_percentage"] = round(M.cell.percent()) + else + answer["cell"] = 0 + answer["integrity"] = M.health/initial(M.health)*100 + answer["airtank"] = M.return_pressure() + answer["pilot"] = "[M.occupant||"None"]" + var/area/area = get_area(M) + answer["location"] = "[sanitize(area.name)||"Unknown"]" + answer["equipment"] = "[M.selected||"None"]" + if(istype(M, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/RM = M + answer["hascargo"] = 1 + answer["cargo"] = RM.cargo.len/RM.cargo_capacity*100 + + return answer - proc/shock() - var/obj/mecha/M = in_mecha() - if(M) - M.emp_act(2) - qdel(src) +/obj/item/mecha_parts/mecha_tracking/emp_act() + qdel(src) + return - proc/get_mecha_log() - if(!src.in_mecha()) - return 0 - var/obj/mecha/M = src.loc - return M.get_log_html() +/obj/item/mecha_parts/mecha_tracking/ex_act() + qdel(src) + return +/obj/item/mecha_parts/mecha_tracking/proc/in_mecha() + if(istype(src.loc, /obj/mecha)) + return src.loc + return 0 + +/obj/item/mecha_parts/mecha_tracking/proc/shock() + var/obj/mecha/M = in_mecha() + if(M) + M.emp_act(2) + qdel(src) + +/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log() + if(!src.in_mecha()) + return 0 + var/obj/mecha/M = src.loc + return M.get_log_html() /obj/item/weapon/storage/box/mechabeacons name = "Exosuit Tracking Beacons" diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 2e6a91b6909..e2c0ddf1df0 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -5,129 +5,138 @@ item_state = "electronic" w_class = 2.0 slot_flags = SLOT_BELT + flags = NOBLUDGEON var/flush = null origin_tech = "programming=4;materials=4" - attack(mob/living/silicon/ai/M as mob, mob/user as mob) - if(!istype(M, /mob/living/silicon/ai))//If target is not an AI. - return ..() - - M.attack_log += text("\[[time_stamp()]\] Has been carded with [src.name] by [key_name(user)]") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to card [key_name(M)]") - msg_admin_attack("[key_name_admin(user)] used the [src.name] to card [M.name] ([M.ckey])") - - transfer_ai("AICORE", "AICARD", M, user) +/obj/item/device/aicard/afterattack(atom/target, mob/user, proximity) + ..() + if(!proximity || !target) return + var/mob/living/silicon/ai/AI = locate(/mob/living/silicon/ai) in src + if(AI) //AI is on the card, implies user wants to upload it. + target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src) + add_logs(AI,user, "carded", object="[name]") + else //No AI on the card, therefore the user wants to download one. + target.transfer_ai(AI_TRANS_TO_CARD, user, null, src) + update_state() //Whatever happened, update the card's state (icon, name) to match. - attack(mob/living/silicon/decoy/M as mob, mob/user as mob) - if (!istype (M, /mob/living/silicon/decoy)) - return ..() +/obj/item/device/aicard/proc/update_state() + var/mob/living/silicon/ai/AI = locate(/mob/living/silicon/ai) in src //AI is inside. + if(AI) + name = "intelliCard - [AI.name]" + if (AI.stat == DEAD) + icon_state = "aicard-404" else - M.death() - user << "ERROR ERROR ERROR" + icon_state = "aicard-full" + AI.cancel_camera() //AI are forced to move when transferred, so do this whenver one is downloaded. + else + icon_state = "aicard" + name = "intelliCard" + overlays.Cut() + +/obj/item/device/aicard/attack_self(mob/user) + if (!in_range(src, user)) + return + user.set_machine(src) + var/dat = "Intelicard
" + var/laws + for(var/mob/living/silicon/ai/A in src) + dat += "Stored AI: [A.name]
System integrity: [(A.health+100)/2]%
" - attack_self(mob/user) - if (!in_range(src, user)) - return - user.set_machine(src) - var/dat = "Intelicard
" - var/laws - for(var/mob/living/silicon/ai/A in src) - dat += "Stored AI: [A.name]
System integrity: [(A.health+100)/2]%
" + for (var/index = 1, index <= A.laws.ion.len, index++) + var/law = A.laws.ion[index] + if (length(law) > 0) + var/num = ionnum() + laws += "[num]. [law]" - for (var/index = 1, index <= A.laws.ion.len, index++) - var/law = A.laws.ion[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]. [law]" + if (A.laws.zeroth) + laws += "0: [A.laws.zeroth]
" - if (A.laws.zeroth) - laws += "0: [A.laws.zeroth]
" + var/number = 1 + for (var/index = 1, index <= A.laws.inherent.len, index++) + var/law = A.laws.inherent[index] + if (length(law) > 0) + laws += "[number]: [law]
" + number++ - var/number = 1 - for (var/index = 1, index <= A.laws.inherent.len, index++) - var/law = A.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
" - number++ + for (var/index = 1, index <= A.laws.supplied.len, index++) + var/law = A.laws.supplied[index] + if (length(law) > 0) + laws += "[number]: [law]
" + number++ - for (var/index = 1, index <= A.laws.supplied.len, index++) - var/law = A.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
" - number++ + dat += "Laws:
[laws]
" - dat += "Laws:
[laws]
" - - if (A.stat == 2) - dat += "AI nonfunctional" + if (A.stat == 2) + dat += "AI nonfunctional" + else + if (!src.flush) + dat += {"Wipe AI"} else - if (!src.flush) - dat += {"Wipe AI"} - else - dat += "Wipe in progress" - dat += "
" - dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"} - dat += "
" - dat += "Subspace Transceiver is: [A.aiRadio.disabledAi ? "Disabled" : "Enabled"]" - dat += "
" - dat += {"[A.aiRadio.disabledAi ? "Enable" : "Disable"] Subspace Transceiver"} - dat += "
" - dat += {" Close"} - user << browse(dat, "window=aicard") - onclose(user, "aicard") + dat += "Wipe in progress" + dat += "
" + dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"} + dat += "
" + dat += "Subspace Transceiver is: [A.aiRadio.disabledAi ? "Disabled" : "Enabled"]" + dat += "
" + dat += {"[A.aiRadio.disabledAi ? "Enable" : "Disable"] Subspace Transceiver"} + dat += "
" + dat += {" Close"} + user << browse(dat, "window=aicard") + onclose(user, "aicard") + return + +/obj/item/device/aicard/Topic(href, href_list) + var/mob/U = usr + if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else). + U << browse(null, "window=aicard") + U.unset_machine() return - Topic(href, href_list) - var/mob/U = usr - if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else). + add_fingerprint(U) + U.set_machine(src) + + switch(href_list["choice"])//Now we switch based on choice. + if ("Close") U << browse(null, "window=aicard") U.unset_machine() return - add_fingerprint(U) - U.set_machine(src) + if ("Wipe") + var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") + if(confirm == "Yes") + if(isnull(src)||!in_range(src, U)||U.machine!=src) + U << browse(null, "window=aicard") + U.unset_machine() + return + else + flush = 1 + for(var/mob/living/silicon/ai/A in src) + A.suiciding = 1 + A << "Your core files are being wiped!" + while (A.stat != 2) + A.adjustOxyLoss(2) + A.updatehealth() + sleep(10) + flush = 0 - switch(href_list["choice"])//Now we switch based on choice. - if ("Close") - U << browse(null, "window=aicard") - U.unset_machine() - return + if ("Radio") + for(var/mob/living/silicon/ai/A in src) + A.aiRadio.disabledAi = !A.aiRadio.disabledAi + A << "Your Subspace Transceiver has been: [A.aiRadio.disabledAi ? "disabled" : "enabled"]" + U << "You [A.aiRadio.disabledAi ? "Disable" : "Enable"] the AI's Subspace Transceiver" - if ("Wipe") - var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No") - if(confirm == "Yes") - if(isnull(src)||!in_range(src, U)||U.machine!=src) - U << browse(null, "window=aicard") - U.unset_machine() - return - else - flush = 1 - for(var/mob/living/silicon/ai/A in src) - A.suiciding = 1 - A << "Your core files are being wiped!" - while (A.stat != 2) - A.adjustOxyLoss(2) - A.updatehealth() - sleep(10) - flush = 0 - - if ("Radio") - for(var/mob/living/silicon/ai/A in src) - A.aiRadio.disabledAi = !A.aiRadio.disabledAi - A << "Your Subspace Transceiver has been: [A.aiRadio.disabledAi ? "disabled" : "enabled"]" - U << "You [A.aiRadio.disabledAi ? "Disable" : "Enable"] the AI's Subspace Transceiver" - - if ("Wireless") - for(var/mob/living/silicon/ai/A in src) - A.control_disabled = !A.control_disabled - A << "The intelicard's wireless port has been [A.control_disabled ? "disabled" : "enabled"]!" - if (A.control_disabled) - overlays -= image('icons/obj/aicards.dmi', "aicard-on") - else - overlays += image('icons/obj/aicards.dmi', "aicard-on") - attack_self(U) + if ("Wireless") + for(var/mob/living/silicon/ai/A in src) + A.control_disabled = !A.control_disabled + A << "The intelicard's wireless port has been [A.control_disabled ? "disabled" : "enabled"]!" + if (A.control_disabled) + overlays -= image('icons/obj/aicards.dmi', "aicard-on") + else + overlays += image('icons/obj/aicards.dmi', "aicard-on") + attack_self(U) /obj/item/device/aicard/ex_act(severity) switch(severity) diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index 4efc8bdc2ee..28c573be0bb 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -50,10 +50,10 @@ var/list/world_uplinks = list() job = user.mind.assigned_role var/dat = "[src.welcome]
" - dat += "Tele-Crystals left: [src.uses]
" + dat += "Telecrystals left: [src.uses]
" dat += "
" dat += "Request item:
" - dat += "Each item costs a number of tele-crystals as indicated by the number following their name.
" + dat += "Each item costs a number of telecrystals as indicated by the number following their name.
" var/category_items = 1 for(var/category in ItemsCategory) @@ -262,10 +262,6 @@ var/list/world_uplinks = list() for(var/datum/data/record/L in data_core.general) if(L.fields["id"] == id) nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value. - // We trade off being able to automatically add shit for more control over what gets passed to json - // and if it's sanitized for html. - nanoui_data["exploit"]["nanoui_exploit_record"] = html_encode(L.fields["exploit_record"]) // Change stuff into html - nanoui_data["exploit"]["nanoui_exploit_record"] = replacetext(nanoui_data["exploit"]["nanoui_exploit_record"], "\n", "
") // change line breaks into
nanoui_data["exploit"]["name"] = html_encode(L.fields["name"]) nanoui_data["exploit"]["sex"] = html_encode(L.fields["sex"]) nanoui_data["exploit"]["age"] = html_encode(L.fields["age"]) diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index 24788c42a0e..2d788e219a4 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -26,16 +26,20 @@ RCD var/working = 0 var/mode = 1 var/canRwall = 0 - var/disabled = 0 - New() desc = "A RCD. It currently holds [matter]/[max_matter] matter-units." src.spark_system = new /datum/effect/effect/system/spark_spread spark_system.set_up(5, 0, src) spark_system.attach(src) + rcd_list += src return - + + Destroy() + qdel(spark_system) + spark_system = null + rcd_list -= src + return ..() attackby(obj/item/weapon/W, mob/user, params) ..() @@ -82,8 +86,6 @@ RCD afterattack(atom/A, mob/user, proximity) if(!proximity) return - if(disabled && !isrobot(user)) - return 0 if(istype(A,/area/shuttle)||istype(A,/turf/space/transit)) return 0 if(!(istype(A, /turf) || istype(A, /obj/machinery/door/airlock))) diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index a71b1c76df4..b94337a118c 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -258,7 +258,7 @@ playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6) return else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding) - msg_admin_attack("[key_name_admin(user)][isAntag(user) ? "(ANTAG)" : ""] triggered a fueltank explosion.") + msg_admin_attack("[key_name_admin(user)] triggered a fueltank explosion.") log_game("[key_name(user)] triggered a fueltank explosion.") user << "\red That was stupid of you." var/obj/structure/reagent_dispensers/fueltank/tank = O diff --git a/code/game/response_team.dm b/code/game/response_team.dm index 03efff51ffe..09871374089 100644 --- a/code/game/response_team.dm +++ b/code/game/response_team.dm @@ -251,7 +251,7 @@ var/send_emergency_team if("Engineer") engineer_slots -= 1 M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/engineer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/industrial(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert/engineer(M), slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/responseteam(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full/multitool(M), slot_belt) @@ -275,7 +275,7 @@ var/send_emergency_team if("Security") security_slots -= 1 M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/security(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/security(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert/security(M), slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/responseteam(M), slot_in_backpack) M.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/security/response_team(M), slot_belt) @@ -299,7 +299,7 @@ var/send_emergency_team if("Medic") medical_slots -= 1 M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/medical(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/medic(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert/medical(M), slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/responseteam(M), slot_in_backpack) var/obj/item/weapon/card/id/W = new(src) @@ -321,7 +321,7 @@ var/send_emergency_team if("Commander") command_slots = 0 M.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(M), slot_w_uniform) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/captain(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert/commander(M), slot_back) M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/responseteam(M), slot_in_backpack) var/obj/item/weapon/card/id/W = new(src) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index d40539cdbf7..847c4179d8f 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -676,11 +676,10 @@ var/list/mechtoys = list( supply_controller.points -= P.cost supply_controller.shoppinglist += O temp = "Thanks for your order.
" - temp += "
Back Main Menu" else temp = "Not enough supply points.
" - temp += "
Back Main Menu" break + temp += "
Back Main Menu" else if (href_list["vieworders"]) temp = "Current approved orders:

" diff --git a/code/modules/DetectiveWork/scanner.dm b/code/modules/DetectiveWork/scanner.dm index d694e4c1645..5aec21ac94e 100644 --- a/code/modules/DetectiveWork/scanner.dm +++ b/code/modules/DetectiveWork/scanner.dm @@ -10,6 +10,7 @@ item_state = "electronic" flags = CONDUCT | NOBLUDGEON slot_flags = SLOT_BELT + origin_tech = "magnets=4;biotech=2" var/scanning = 0 var/list/log = list() diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index eb6b02cc626..1673171ceec 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -922,7 +922,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert/alt(M), slot_l_ear) M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert(M), slot_back) var/obj/item/weapon/card/id/W = new(M) W.name = "[M.real_name]'s ID Card (Emergency Response Team - Member)" @@ -944,7 +944,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that M.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert/alt(M), slot_l_ear) M.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/gun(M), slot_belt) M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses) - M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back) + M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/ert/commander(M), slot_back) var/obj/item/weapon/card/id/W = new(M) W.name = "[M.real_name]'s ID Card (Emergency Response Team - Leader)" diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 8085fefd999..ec2277c22dd 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -44,12 +44,12 @@ if((istype(W, /obj/item/weapon/weldingtool) && W:welding)) if(!status) status = 1 - bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" - msg_admin_attack("[key_name_admin(user)][isAntag(user) ? "(ANTAG)" : ""] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]") + bombers += "[key_name(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]" + msg_admin_attack("[key_name_admin(user)] welded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]") user << "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited." else status = 0 - bombers += "[key_name(user)] unwelded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" + bombers += "[key_name(user)] unwelded a single tank bomb. Temperature: [bombtank.air_contents.temperature-T0C]" user << "The hole has been closed." add_fingerprint(user) ..() diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm index b3fbea5343c..c1778e060bc 100644 --- a/code/modules/events/mass_hallucination.dm +++ b/code/modules/events/mass_hallucination.dm @@ -3,4 +3,4 @@ if(!(C.species.flags & IS_SYNTHETIC)) C.hallucination += rand(50, 100) /datum/event/mass_hallucination/announce() - command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucination, but no further damage") \ No newline at end of file + command_announcement.Announce("It seems that station [station_name()] is passing through a minor radiation field, this may cause some hallucinations, but no further damage") diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 17417104463..f494d7336db 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -302,9 +302,9 @@ user.lastattacked = M M.lastattacker = user - user.attack_log += "\[[time_stamp()]\] Attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - M.attack_log += "\[[time_stamp()]\] Attacked by [user.name] ([user.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" - msg_admin_attack("[user.name] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] attacked [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) + user.attack_log += "\[[time_stamp()]\] Attacked [key_name(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + M.attack_log += "\[[time_stamp()]\] Attacked by [key_name(user)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" + msg_admin_attack("[key_name_admin(user)] attacked [key_name_admin(M)] with [name] (INTENT: [uppertext(user.a_intent)]) (DAMTYE: [uppertext(damtype)])" ) if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/H = M diff --git a/code/modules/karma/karma.dm b/code/modules/karma/karma.dm index 6c3a5d35046..4144c4ef5cc 100644 --- a/code/modules/karma/karma.dm +++ b/code/modules/karma/karma.dm @@ -63,7 +63,7 @@ var/list/karma_spenders = list() var/list/karma_list = list("Cancel") for(var/mob/M in player_list) if(M.client && M.mind) - if(isAntag(M)) // Don't include special roles, because players use it to meta + if(isNonCrewAntag(M)) // Don't include special roles, because players use it to meta continue karma_list += M diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 5a0028bb952..82f09f0f489 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1225,6 +1225,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc else if(!seer) see_in_dark = species.darksight see_invisible = SEE_INVISIBLE_LIVING + + if(see_override) //Override all + see_invisible = see_override if(ticker && ticker.mode.name == "nations") process_nations() diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2415bdb5be3..d64dc143ec2 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -55,6 +55,7 @@ var/list/ai_verbs_default = list( var/ioncheck[1] var/lawchannel = "Common" // Default channel on which to state laws var/icon/holo_icon//Default is assigned when AI is created. + var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye. var/obj/item/device/pda/ai/aiPDA = null var/obj/item/device/multitool/aiMulti = null var/custom_sprite = 0 //For our custom sprites @@ -66,7 +67,7 @@ var/list/ai_verbs_default = list( var/processing_time = 100 var/list/datum/AI_Module/current_modules = list() var/fire_res_on_core = 0 - + var/can_dominate_mechs = 0 var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite var/malf_cooldown = 0 //Cooldown var for malf modules @@ -536,6 +537,14 @@ var/list/ai_verbs_default = list( botcall() return + if (href_list["ai_take_control"]) //Mech domination + var/obj/mecha/M = locate(href_list["ai_take_control"]) + if(controlled_mech) + src << "You are already loaded into an onboard computer!" + return + if(M) + M.transfer_ai(AI_MECH_HACK,src, usr) //Called om the mech itself. + else if (href_list["faketrack"]) var/mob/target = locate(href_list["track"]) in mob_list var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list @@ -981,6 +990,24 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/is_in_chassis() return istype(loc, /turf) + +/mob/living/silicon/ai/transfer_ai(var/interaction, var/mob/user, var/mob/living/silicon/ai/AI, var/obj/item/device/aicard/card) + if(!..()) + return + if(interaction == AI_TRANS_TO_CARD)//The only possible interaction. Upload AI mob to a card. + if(!mind) + user << "No intelligence patterns detected." //No more magical carding of empty cores, AI RETURN TO BODY!!!11 + return + if (mind.special_role == "malfunction") //AI MALF!! + user << "ERROR: Remote transfer interface disabled."//Do ho ho ho~ + return + new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location. + aiRestorePowerRoutine = 0//So the AI initially has power. + control_disabled = 1//Can't control things remotely if you're stuck in a card! + aiRadio.disabledAi = 1 //No talking on the built-in radio for you either! + loc = card//Throw AI into the card. + src << "You have been downloaded to a mobile storage device. Remote device connection severed." + user << "Transfer successful: [name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory." #undef AI_CHECK_WIRELESS #undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 5be1da223a9..40facde6f9c 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -44,7 +44,7 @@ loc = T.loc if (istype(loc, /area)) //stage = 4 - if (!loc.power_equip && !istype(src.loc,/obj/item)) + if (!loc.power_equip && !is_type_in_list(src.loc,list(/obj/item, /obj/mecha))) //stage = 5 blind = 1 @@ -56,7 +56,8 @@ src.sight |= SEE_OBJS src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_LEVEL_TWO - + if(see_override) + see_invisible = see_override //Congratulations! You've found a way for AI's to run without using power! //Todo: Without snowflaking up master_controller procs find a way to make AI use_power but only when APC's clear the area usage the tick prior @@ -97,7 +98,7 @@ src.see_in_dark = 0 src.see_invisible = SEE_INVISIBLE_LIVING - if (((!loc.power_equip) || istype(T, /turf/space)) && !istype(src.loc,/obj/item)) + if (((!loc.power_equip) || istype(T, /turf/space)) && !is_type_in_list(src.loc,list(/obj/item, /obj/mecha))) if (src:aiRestorePowerRoutine==0) src:aiRestorePowerRoutine = 1 diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a67a2eed0d9..e64ec58e553 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -174,6 +174,18 @@ proc/isAntag(A) if(C.mind && C.mind.special_role) return 1 return 0 + +proc/isNonCrewAntag(A) + if(!isAntag(A)) + return 0 + + var/mob/living/carbon/C = A + var/special_role = C.mind.special_role + var/list/crew_roles = list("traitor", "Changeling", "Vampire", "Cultist", "Head Revolutionary", "Revolutionary", "malfunctioning AI", "Shadowling", "loyalist", "mutineer", "Response Team") + if((special_role in crew_roles)) + return 0 + + return 1 proc/isnewplayer(A) if(istype(A, /mob/new_player)) @@ -480,7 +492,7 @@ var/list/intents = list("help","disarm","grab","harm") name = realname for(var/mob/M in player_list) - if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_MOD,0)) && (M.client.prefs.toggles & CHAT_DEAD)) + if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_MOD,0,M)) && (M.client.prefs.toggles & CHAT_DEAD)) var/follow var/lname if(subject) @@ -491,7 +503,7 @@ var/list/intents = list("help","disarm","grab","harm") var/mob/dead/observer/DM if(istype(subject, /mob/dead/observer)) DM = subject - if(check_rights(R_MOD,0)) // What admins see + if(check_rights(R_MOD,0,M)) // What admins see lname = "[keyname][(DM && DM.anonsay) ? "*" : (DM ? "" : "^")] ([name])" else if(DM && DM.anonsay) // If the person is actually observer they have the option to be anonymous diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index df5727e4315..1201c95b74c 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -191,8 +191,6 @@ if(world.time < move_delay) return - if(isAI(mob)) return AIMove(n,direct,mob) - if(!isliving(mob)) return mob.Move(n,direct) if(moving) return 0 @@ -211,10 +209,6 @@ var/mob/spirit/currentSpirit = mob return currentSpirit.Spirit_Move(direct) - // handle possible AI movement - if(isAI(mob)) - return AIMove(n,direct,mob) - if(mob.notransform) return//This is sota the goto stop mobs from moving var if(isliving(mob)) @@ -235,6 +229,9 @@ if(mob.remote_control) //we're controlling something, our movement is relayed to it return mob.remote_control.relaymove(mob, direct) + if(isAI(mob)) + return AIMove(n,direct,mob) + if(!mob.canmove) return diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index eb13ba91b21..b0d3a7e4a85 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -135,8 +135,8 @@ var/obj/item/device/assembly_holder/H = W if (istype(H.a_left,/obj/item/device/assembly/igniter) || istype(H.a_right,/obj/item/device/assembly/igniter)) - msg_admin_attack("[key_name_admin(user)][isAntag(user) ? "(ANTAG)" : ""] rigged fueltank at ([loc.x],[loc.y],[loc.z]) for explosion.") - log_game("[key_name(user)] rigged fueltank at ([loc.x],[loc.y],[loc.z]) for explosion.") + msg_admin_attack("[key_name_admin(user)] rigged a fueltank for explosion (JMP)") + log_game("[key_name(user)] rigged fueltank a fueltank for explosion at [loc.x], [loc.y], [loc.z]") rig = W user.drop_item() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 21cbcd5c49d..e6a16f00765 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -169,10 +169,10 @@ msg = "[user.name] stuffs [target.name] into the [src]!" user << "You stuff [target.name] into the [src]!" - user.attack_log += text("\[[time_stamp()]\] Has placed [target.name] ([target.ckey]) in disposals.") - target.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Has placed [key_name(target)] in disposals.") + target.attack_log += text("\[[time_stamp()]\] Has been placed in disposals by [key_name(user)]") if(target.ckey) - msg_admin_attack("[user] ([user.ckey])[isAntag(user) ? "(ANTAG)" : ""] placed [target] ([target.ckey]) in a disposals unit. (JMP)") + msg_admin_attack("[key_name_admin(user)] placed [key_name_admin(target)] in a disposals unit") else return if (target.client) diff --git a/code/modules/research/designs/equipment_designs.dm b/code/modules/research/designs/equipment_designs.dm index 10a6a18ee31..ab78834a877 100644 --- a/code/modules/research/designs/equipment_designs.dm +++ b/code/modules/research/designs/equipment_designs.dm @@ -99,4 +99,15 @@ build_type = PROTOLATHE materials = list("$metal" = 4000, "$glass" = 1000) build_path = /obj/item/clothing/mask/gas/welding + category = list("Equipment") + +/datum/design/detective_scanner + name = "Forensic Scanner" + desc = "A high tech scanner designed for forensic evidence collection, DNA recovery, and fiber analysis." + id = "detectivescanner" + req_tech = list("biotech" = 2, "magnets" = 4) + build_type = PROTOLATHE + materials = list("$metal" = 6000, "$glass" = 2000) + build_path = /obj/item/device/detective_scanner + locked = 1 //no validhunting scientists. category = list("Equipment") \ No newline at end of file diff --git a/code/modules/research/xenoarchaeology/tools/ano_device_battery.dm b/code/modules/research/xenoarchaeology/tools/ano_device_battery.dm index bb1d7e30c4f..6df826f3792 100644 --- a/code/modules/research/xenoarchaeology/tools/ano_device_battery.dm +++ b/code/modules/research/xenoarchaeology/tools/ano_device_battery.dm @@ -210,6 +210,6 @@ M.lastattacker = user if(inserted_battery.battery_effect) - user.attack_log += "\[[time_stamp()]\] Tapped [M.name] ([M.ckey]) with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" - M.attack_log += "\[[time_stamp()]\] Tapped by [user.name] ([user.ckey]) with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" - msg_admin_attack("[key_name(user)][isAntag(user) ? "(ANTAG)" : ""] tapped [key_name(M)] with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" ) + user.attack_log += "\[[time_stamp()]\] Tapped [key_name(M)] with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" + M.attack_log += "\[[time_stamp()]\] Tapped by [key_name(user)] with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" + msg_admin_attack("[key_name_admin(user)] tapped [key_name_admin(M)] with [name] (EFFECT: [inserted_battery.battery_effect.effecttype])" ) diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security levels/keycard authentication.dm index 8164fca3f39..87f478938f3 100644 --- a/code/modules/security levels/keycard authentication.dm +++ b/code/modules/security levels/keycard authentication.dm @@ -174,8 +174,7 @@ var/global/maint_all_access = 0 for(var/obj/machinery/door/airlock/D in A) D.emergency = 1 D.update_icon(0) - world << "Attention!" - world << "The maintenance access requirement has been revoked on all airlocks." + minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.") maint_all_access = 1 /proc/revoke_maint_all_access() @@ -183,6 +182,5 @@ var/global/maint_all_access = 0 for(var/obj/machinery/door/airlock/D in A) D.emergency = 0 D.update_icon(0) - world << "Attention!" - world << "The maintenance access requirement has been readded on all maintenance airlocks." + minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.") maint_all_access = 0 \ No newline at end of file diff --git a/code/modules/vehicle/train/trains/cargo/cargo_train.dm b/code/modules/vehicle/train/trains/cargo/cargo_train.dm index 1daee673201..a8f50cd5463 100644 --- a/code/modules/vehicle/train/trains/cargo/cargo_train.dm +++ b/code/modules/vehicle/train/trains/cargo/cargo_train.dm @@ -144,7 +144,7 @@ /obj/vehicle/train/cargo/trolley/RunOver(var/mob/living/carbon/human/H) ..() - attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + attack_log += text("\[[time_stamp()]\] ran over [key_name(H)]") /obj/vehicle/train/cargo/engine/RunOver(var/mob/living/carbon/human/H) ..() @@ -153,10 +153,10 @@ var/mob/living/carbon/human/D = load D << "\red \b You ran over [H]!" visible_message("\red \The [src] ran over [H]!") - attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])") - msg_admin_attack("[D.name] ([D.ckey])[isAntag(D) ? "(ANTAG)" : ""] ran over [H.name] ([H.ckey]). (JMP)") + attack_log += text("\[[time_stamp()]\] ran over [key_name(H)], driven by [key_name(D)]") + msg_admin_attack("[key_name_admin(D)] ran over [key_name_admin(H)]") else - attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + attack_log += text("\[[time_stamp()]\] ran over [key_name(H)]") //------------------------------------------- diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index 8773d255248..a4c6dd0e843 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/nano/templates/ai_fixer.tmpl b/nano/templates/ai_fixer.tmpl new file mode 100644 index 00000000000..4e88dc45c91 --- /dev/null +++ b/nano/templates/ai_fixer.tmpl @@ -0,0 +1,63 @@ + +{{if data.occupant}} +
+

Stored AI: {{:data.occupant}}

+

Information

+
+ Integrity +
+
+ {{:data.integrity}}% +
+
+ Status +
+
+ {{if data.stat == 2}} + Non-functional + {{else}} + Functional + {{/if}} +
+
+ Wireless Activity +
+
+ {{:helper.link('Enabled','check',{'wireless' : 0},data.wireless == 0 ? 'selected' : '')}} + {{:helper.link('Disabled','close',{'wireless' : 1},data.wireless == 1 ? 'selected' : '')}} +
+
+ Subspace Transceiver +
+
+ {{:helper.link('Enabled','check',{'radio' : 0},data.radio == 0 ? 'selected' : '')}} + {{:helper.link('Disabled','close',{'radio' : 1},data.radio == 1 ? 'selected' : '')}} +
+

Laws

+ {{if data.zeroth}} + 0: {{:data.zeroth}}
+ {{/if}} + {{for data.laws}} + {{:value.number}}: {{:value.law}}
+ {{empty}} + {{if !data.zeroth}} + No laws detected! + {{/if}} + {{/for}} + +

Actions

+ {{if data.active}} + Reconstruction in progress, please wait. + {{:helper.displayBar(data.integrity, 0, 100, (data.integrity >= 75) ? 'good' : (data.integrity >= 25) ? 'average' : 'bad')}} + {{:data.integrity}}% + {{/if}} +
+ {{:helper.link('Reconstruct', 'wrench', {'fix' : 1}, data.active || data.integrity >= 100 ? 'disabled' : '')}} +
+
+{{else}} +

No artificial intelligence detected.

+{{/if}} \ No newline at end of file diff --git a/nano/templates/exosuit_control.tmpl b/nano/templates/exosuit_control.tmpl new file mode 100644 index 00000000000..c3b88d50f54 --- /dev/null +++ b/nano/templates/exosuit_control.tmpl @@ -0,0 +1,81 @@ + +{{if data.screen == 0}} + {{for data.mechas}} +
+
+

{{:value.name}}

+

Information

+
+ Pilot: +
+
+ {{:value.pilot}} +
+
+ Integrity: +
+
+ {{:value.integrity}}% +
+
+ Location: +
+
+ {{:value.location}} +
+
+ Airtank: +
+
+ {{:value.airtank}}kPa +
+
+ Active Equipment: +
+
+ {{:value.equipment}} +
+ {{if value.hascargo}} +
+ Cargo Used: +
+
+ {{:value.cargo}}% +
+ {{/if}} + +

Power Cell

+ {{if value.cell}} + + Rating: + + + {{:value.cell_capacity}} + + {{:helper.displayBar(value.cell_percentage, 0, 100, (value.cell_percentage >= 50) ? 'good' : (value.cell_percentage >= 25) ? 'average' : 'bad')}} + {{:value.cell_percentage}}% + {{else}} + Not Installed + {{:helper.displayBar(100, 0, 100, 'bad')}} + {{/if}} + + +

Actions

+ {{:helper.link('Send Message', 'mail-closed', {'send_message' : value.reference})}} + {{:helper.link('Exosuit Log', 'search', {'get_log' : value.reference})}} + {{:helper.link('EMP Pulse', 'alert', {'shock' : value.reference}, null, 'redButton')}} +
+ {{empty}} +
+

No mecha trackers were found.

+
+ {{/for}} +{{else}} +
+ {{:helper.link('Return', 'close', {'return' : 1})}} +
+ {{:data.log}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/nuclear_bomb.tmpl b/nano/templates/nuclear_bomb.tmpl index 087e3efb640..3536d17713f 100644 --- a/nano/templates/nuclear_bomb.tmpl +++ b/nano/templates/nuclear_bomb.tmpl @@ -5,84 +5,67 @@ Used In File(s): \code\game\gamemodes\nuclear\nuclearbomb.dm {{if data.is_syndicate}} {{:helper.syndicateMode()}} {{/if}} -{{if !data.hacking}} +
+ Authorization Disk: {{if data.auth}}{{:helper.link('++++++++++', 'eject', {'auth' : 1})}} {{else}} {{:helper.link('----------', 'disk', {'auth' : 1})}}{{/if}} +
+
+
+
Status: {{:data.authstatus}} - {{:data.safe}}
+
Timer: {{:data.time}}
+
+
- Authorization Disk: {{if data.auth}}{{:helper.link('++++++++++', 'eject', {'auth' : 1})}} {{else}} {{:helper.link('----------', 'disk', {'auth' : 1})}}{{/if}} -
+ {{if data.auth && data.yescode}} +
+ Timer: {{:helper.link('On', 'play', {'timer' : 1}, data.timer ? 'selected' : '')}}{{:helper.link('Off', 'stop', {'timer' : 0}, !data.timer ? 'selected' : '')}} +
+
+ Time: {{:helper.link('--', '', {'time' : -10}, data.time <= 120 ? 'disabled' : '')}}{{:helper.link('-', '', {'time' : -1}, data.time <= 120 ? 'disabled' : '')}} {{:data.time}} {{:helper.link('+', '', {'time' : 1})}}{{:helper.link('++', '', {'time' : 10})}} +
+ {{else}} +
+ Timer: {{:helper.link('On', 'play', null, 'disabled')}}{{:helper.link('Off', 'pause', null, 'disabled')}} +
+
+ Time: {{:helper.link('-', '', null, 'disabled')}}{{:helper.link('-', '', null, 'disabled')}} {{:data.time}} {{:helper.link('+', '', null, 'disabled')}}{{:helper.link('++', '', null, 'disabled')}} +
+ {{/if}} +
+
+ {{if data.auth && data.yescode}} +
+ Safety: {{:helper.link('Engaged', 'info', {'safety' : 1}, data.safety ? 'selected' : '')}}{{:helper.link('Disengaged', 'alert', {'safety' : 0}, data.safety ? '' : 'selected')}} +
+
+ Anchor: {{:helper.link('Engaged', 'locked', {'anchor' : 1}, data.anchored ? 'selected' : '')}}{{:helper.link('Disengaged', 'unlocked', {'anchor' : 0}, data.anchored ? '' : 'selected')}} +
+ {{else}} +
+ Safety: {{:helper.link('Engaged', 'info', null, 'disabled')}}{{:helper.link('Disengaged', 'alert', null, 'disabled')}} +
+
+ Anchor: {{:helper.link('Engaged', 'locked', null, 'disabled')}}{{:helper.link('Disengaged', 'unlocked', null, 'disabled')}} +
+ {{/if}} +

+ +
-
Status: {{:data.authstatus}} - {{:data.safe}}
-
Timer: {{:data.time}}
+ >{{if data.message}} {{:data.message}}{{/if}}
- {{if data.auth && data.yescode}} -
- Timer: {{:helper.link('On', 'play', {'timer' : 1}, data.timer ? 'selected' : '')}}{{:helper.link('Off', 'stop', {'timer' : 0}, !data.timer ? 'selected' : '')}} -
-
- Time: {{:helper.link('--', '', {'time' : -10}, data.time <= 60 ? 'disabled' : '')}}{{:helper.link('-', '', {'time' : -1}, data.time <= 60 ? 'disabled' : '')}} {{:data.time}} {{:helper.link('+', '', {'time' : 1})}}{{:helper.link('++', '', {'time' : 10})}} -
- {{else}} -
- Timer: {{:helper.link('On', 'play', null, 'disabled')}}{{:helper.link('Off', 'pause', null, 'disabled')}} -
-
- Time: {{:helper.link('-', '', null, 'disabled')}}{{:helper.link('-', '', null, 'disabled')}} {{:data.time}} {{:helper.link('+', '', null, 'disabled')}}{{:helper.link('++', '', null, 'disabled')}} -
- {{/if}} + {{:helper.link('1', '', {'type' : 1})}}{{:helper.link('2', '', {'type' : 2})}}{{:helper.link('3', '', {'type' : 3})}}
- {{if data.auth && data.yescode}} -
- Safety: {{:helper.link('Engaged', 'info', {'safety' : 1}, data.safety ? 'selected' : '')}}{{:helper.link('Disengaged', 'alert', {'safety' : 0}, data.safety ? '' : 'selected')}} -
-
- Anchor: {{:helper.link('Engaged', 'locked', {'anchor' : 1}, data.anchored ? 'selected' : '')}}{{:helper.link('Disengaged', 'unlocked', {'anchor' : 0}, data.anchored ? '' : 'selected')}} -
- {{else}} -
- Safety: {{:helper.link('Engaged', 'info', null, 'disabled')}}{{:helper.link('Disengaged', 'alert', null, 'disabled')}} -
-
- Anchor: {{:helper.link('Engaged', 'locked', null, 'disabled')}}{{:helper.link('Disengaged', 'unlocked', null, 'disabled')}} -
- {{/if}} -
-
-
-
-
- >{{if data.message}} {{:data.message}}{{/if}} + {{:helper.link('4', '', {'type' : 4})}}{{:helper.link('5', '', {'type' : 5})}}{{:helper.link('6', '', {'type' : 6})}}
-
- {{:helper.link('1', '', {'type' : 1})}}{{:helper.link('2', '', {'type' : 2})}}{{:helper.link('3', '', {'type' : 3})}} -
-
- {{:helper.link('4', '', {'type' : 4})}}{{:helper.link('5', '', {'type' : 5})}}{{:helper.link('6', '', {'type' : 6})}} -
-
- {{:helper.link('7', '', {'type' : 7})}}{{:helper.link('8', '', {'type' : 8})}}{{:helper.link('9', '', {'type' : 9})}} -
-
- {{:helper.link('R', '', {'type' : 'R'})}}{{:helper.link('0', '', {'type' : 0})}}{{:helper.link('E', '', {'type' : 'E'})}} -
+ {{:helper.link('7', '', {'type' : 7})}}{{:helper.link('8', '', {'type' : 8})}}{{:helper.link('9', '', {'type' : 9})}} +
+
+ {{:helper.link('R', '', {'type' : 'R'})}}{{:helper.link('0', '', {'type' : 0})}}{{:helper.link('E', '', {'type' : 'E'})}}
-{{else}} -
-

Exposed Wires

- {{for data.wires}} -
-
{{:value.name}}
-
{{:helper.link(value.cut ? 'Mend' : 'Cut', '', {'wire' : value.name, 'act' : 'wire'})}} {{:helper.link('Pulse', '', {'wire' : value.name, 'act' : 'pulse'})}}
-
- {{/for}} -
-
- The device is {{if data.timing}}shaking!{{else}}still.{{/if}}
- The device is {{if data.safety}}quiet.{{else}}whirring.{{/if}}
- The lights are {{if data.lighthack}}static.{{else}}functional.{{/if}}
-
-{{/if}} \ No newline at end of file +
\ No newline at end of file diff --git a/nano/templates/pod_tracking.tmpl b/nano/templates/pod_tracking.tmpl new file mode 100644 index 00000000000..4fd68df82f9 --- /dev/null +++ b/nano/templates/pod_tracking.tmpl @@ -0,0 +1,33 @@ + + +
{{:helper.link('Refresh', 'refresh', {'refresh' : 1})}}
+

Pods

+{{for data.pods}} +
+
+

{{:value.name}}

+
Pilot
+
{{:value.occupant}}
+
Passenger
+
{{:value.occupant2}}
+
Coordinates
+
{{:value.x}}, {{:value.y}}, {{:value.z}}
+
+{{empty}} +
+

No pod trackers were found.

+
+{{/for}} \ No newline at end of file diff --git a/nano/templates/robot_control.tmpl b/nano/templates/robot_control.tmpl index 61c5464ad2f..2e5e892e0e8 100644 --- a/nano/templates/robot_control.tmpl +++ b/nano/templates/robot_control.tmpl @@ -64,11 +64,10 @@ {{:value.cell_capacity}}
{{:helper.displayBar(value.cell_percentage, 0, 100, (value.cell_percentage >= 50) ? 'good' : (value.cell_percentage >= 25) ? 'average' : 'bad')}} - {{:value.cell_percentage}} % + {{:value.cell_percentage}}% {{else}} Not Installed {{:helper.displayBar(100, 0, 100, 'bad')}} - N/A % {{/if}}

Actions

{{if value.status == "Operational"}} diff --git a/nano/templates/uplink.tmpl b/nano/templates/uplink.tmpl index a5080f05f36..77550917993 100644 --- a/nano/templates/uplink.tmpl +++ b/nano/templates/uplink.tmpl @@ -12,7 +12,7 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm
{{:helper.link('Request Items', 'gear', {'menu' : 0}, null, 'fixedLeftWider')}} - {{:helper.link(data.descriptions ? 'Hide Descriptions' : 'Show Descriptions', 'gear', {'descriptions' : 1}, null, 'fixedLeftWider')}} + {{:helper.link(data.descriptions ? 'Hide Descriptions' : 'Show Descriptions', 'gear', {'descriptions' : 1}, data.menu == 0 ? '' : 'disabled', 'fixedLeftWider')}} {{:helper.link('Exploitable Information', 'gear', {'menu' : 1}, null, 'fixedLeftWider')}} {{:helper.link('Return', 'arrowreturn-1-w', {'return' : 1}, null, 'fixedLeft')}} {{:helper.link('Close', 'gear', {'lock' : "1"}, null, 'fixedLeft')}} @@ -80,9 +80,6 @@ Used In File(s): \code\game\objects\items\devices\uplinks.dm Age: {{:data.exploit.age}}
Rank: {{:data.exploit.rank}}
Fingerprint: {{:data.exploit.fingerprint}}
- -
Acquired Information:
- Notes:
{{:data.exploit.nanoui_exploit_record}}

{{else}} No exploitative information acquired! diff --git a/paradise.dme b/paradise.dme index 2126b1b0b21..a6a115cd804 100644 --- a/paradise.dme +++ b/paradise.dme @@ -225,6 +225,7 @@ #include "code\datums\wires\camera.dm" #include "code\datums\wires\explosive.dm" #include "code\datums\wires\mulebot.dm" +#include "code\datums\wires\nuclearbomb.dm" #include "code\datums\wires\particle_accelerator.dm" #include "code\datums\wires\radio.dm" #include "code\datums\wires\robot.dm"