diff --git a/code/__DEFINES/ARES.dm b/code/__DEFINES/ARES.dm index 55aa68f97309..712d37f93336 100644 --- a/code/__DEFINES/ARES.dm +++ b/code/__DEFINES/ARES.dm @@ -82,3 +82,11 @@ /// Time until someone can respawn as Working Joe #define JOE_JOIN_DEAD_TIME (15 MINUTES) + + + +#define FACTION_ARES "Ares" +#define FACTION_LIST_ARES_MARINE list(FACTION_MARINE, FACTION_ARES) +#define FACTION_LIST_ARES_ALL list(FACTION_ARES, FACTION_MARINE, FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_WY) +#define FACTION_LIST_ARES_WY list(FACTION_ARES, FACTION_PMC, FACTION_WY_DEATHSQUAD, FACTION_WY) +#define FACTION_LIST_ARES_ALONE list(FACTION_ARES) diff --git a/code/__DEFINES/access.dm b/code/__DEFINES/access.dm index 71b2b6f4b6ac..4b0650e61b3b 100644 --- a/code/__DEFINES/access.dm +++ b/code/__DEFINES/access.dm @@ -169,6 +169,8 @@ most of them are tied into map-placed objects. This should be reworked in the fu #define ACCESS_LIST_MARINE_ALL "Almayer (ALL)" ///Used by the Wey-Yu - USCM Liaison #define ACCESS_LIST_MARINE_LIAISON "Wey-Yu (Liaison)" +///Used by the Wey-Yu AIST aboard Almayer +#define ACCESS_LIST_MARINE_LIAISON_AIST "Wey-Yu (AIST)" ///The accesses granted to emergency responders. #define ACCESS_LIST_EMERGENCY_RESPONSE "Almayer (ERT)" diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index 0173a55e2d17..5d90e099d274 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -128,6 +128,7 @@ GLOBAL_LIST_INIT(job_command_roles, JOB_COMMAND_ROLES_LIST) #define JOB_PLT_MED "Platoon Corpsman" #define JOB_PLT_SL "Platoon Squad Leader" #define JOB_SQUAD_TECH "Reconnaissance Support Technician" +#define JOB_AI_TECH "AI Service Technician" // Used to add a timelock to a job. Will be passed onto derivatives #define AddTimelock(Path, timelockList) \ diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 2ab36d51d297..42f076b0b965 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -311,6 +311,9 @@ #define COOLDOWN_COMM_CENTRAL 30 SECONDS #define COOLDOWN_COMM_DESTRUCT 5 MINUTES +#define FORCE_SCAN_LOCK 25 MINUTES +#define COOLDOWN_FORCE_SCAN 15 MINUTES + ///Cooldown for pred recharge #define COOLDOWN_BRACER_CHARGE 3 MINUTES diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 04c7993bd9f2..86a17514dc0d 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -117,6 +117,7 @@ #define ROLE_WHITELISTED 16 #define ROLE_NO_ACCOUNT 32 #define ROLE_CUSTOM_SPAWN 64 +#define ROLE_HIDDEN 128 //================================================= //Role defines, specifically lists of roles for job bans, crew manifests and the like. @@ -128,7 +129,7 @@ GLOBAL_LIST_INIT(ROLES_CIC, list(JOB_CO, JOB_XO, JOB_SO, JOB_WO_CO, JOB_WO_XO)) GLOBAL_LIST_INIT(ROLES_AUXIL_SUPPORT, list(JOB_AUXILIARY_OFFICER, JOB_INTEL, JOB_CAS_PILOT, JOB_DROPSHIP_PILOT, JOB_DROPSHIP_CREW_CHIEF, JOB_TANK_CREW, JOB_WO_CHIEF_POLICE, JOB_WO_SO, JOB_WO_CREWMAN, JOB_WO_POLICE, JOB_WO_PILOT)) GLOBAL_LIST_INIT(ROLES_MISC, list(JOB_SYNTH, JOB_WORKING_JOE, JOB_SEA, JOB_CORPORATE_LIAISON, JOB_COMBAT_REPORTER, JOB_MESS_SERGEANT, JOB_WO_CORPORATE_LIAISON, JOB_WO_SYNTH)) GLOBAL_LIST_INIT(ROLES_POLICE, list(JOB_CHIEF_POLICE, JOB_WARDEN, JOB_POLICE)) -GLOBAL_LIST_INIT(ROLES_ENGINEERING, list(JOB_CHIEF_ENGINEER, JOB_ORDNANCE_TECH, JOB_MAINT_TECH, JOB_WO_CHIEF_ENGINEER, JOB_WO_ORDNANCE_TECH)) +GLOBAL_LIST_INIT(ROLES_ENGINEERING, list(JOB_CHIEF_ENGINEER, JOB_ORDNANCE_TECH, JOB_MAINT_TECH, JOB_WO_CHIEF_ENGINEER, JOB_WO_ORDNANCE_TECH, JOB_AI_TECH)) GLOBAL_LIST_INIT(ROLES_REQUISITION, list(JOB_CHIEF_REQUISITION, JOB_CARGO_TECH, JOB_WO_CHIEF_REQUISITION, JOB_WO_REQUISITION)) GLOBAL_LIST_INIT(ROLES_MEDICAL, list(JOB_CMO, JOB_RESEARCHER, JOB_DOCTOR, JOB_NURSE, JOB_WO_CMO, JOB_WO_RESEARCHER, JOB_WO_DOCTOR)) GLOBAL_LIST_INIT(ROLES_MARINES, list(JOB_SQUAD_LEADER, JOB_SQUAD_TEAM_LEADER, JOB_SQUAD_SPECIALIST, JOB_SQUAD_SMARTGUN, JOB_SQUAD_MEDIC, JOB_SQUAD_ENGI, JOB_SQUAD_MARINE)) @@ -153,7 +154,7 @@ GLOBAL_LIST_INIT(ROLES_UNASSIGNED, list(JOB_SQUAD_MARINE)) JOB_SQUAD_LEADER, JOB_SQUAD_TEAM_LEADER, JOB_SQUAD_SPECIALIST, JOB_SQUAD_SMARTGUN, JOB_SQUAD_MEDIC, JOB_SQUAD_ENGI, JOB_SQUAD_MARINE #define BLURB_USCM_FLIGHT JOB_CAS_PILOT, JOB_DROPSHIP_PILOT, JOB_DROPSHIP_CREW_CHIEF #define BLURB_USCM_MP JOB_CHIEF_POLICE, JOB_WARDEN, JOB_POLICE -#define BLURB_USCM_ENGI JOB_CHIEF_ENGINEER, JOB_ORDNANCE_TECH, JOB_MAINT_TECH, JOB_WO_CHIEF_ENGINEER, JOB_WO_ORDNANCE_TECH, JOB_TANK_CREW, JOB_WO_PILOT +#define BLURB_USCM_ENGI JOB_CHIEF_ENGINEER, JOB_ORDNANCE_TECH, JOB_MAINT_TECH, JOB_WO_CHIEF_ENGINEER, JOB_WO_ORDNANCE_TECH, JOB_TANK_CREW, JOB_WO_PILOT, JOB_AI_TECH #define BLURB_USCM_MEDICAL JOB_CMO, JOB_RESEARCHER, JOB_DOCTOR, JOB_NURSE, JOB_WO_CMO, JOB_WO_RESEARCHER, JOB_WO_DOCTOR #define BLURB_USCM_REQ JOB_CHIEF_REQUISITION, JOB_CARGO_TECH, JOB_WO_CHIEF_REQUISITION, JOB_WO_REQUISITION #define BLURB_USCM_WY JOB_CORPORATE_LIAISON diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm index 367c35be5605..1449fc771ec9 100644 --- a/code/__DEFINES/radio.dm +++ b/code/__DEFINES/radio.dm @@ -74,3 +74,4 @@ #define RADIO_CHANNEL_YAUTJA "Yautja" +#define RADIO_CHANNEL_AICORE "AI Core" diff --git a/code/__HELPERS/job.dm b/code/__HELPERS/job.dm index 51cc496feeae..4603516317c5 100644 --- a/code/__HELPERS/job.dm +++ b/code/__HELPERS/job.dm @@ -58,5 +58,6 @@ JOB_CHIEF_POLICE, JOB_WARDEN, JOB_SEA, - JOB_MARINE + JOB_MARINE, + JOB_AI_TECH ) diff --git a/code/controllers/subsystem/communications.dm b/code/controllers/subsystem/communications.dm index c4661ff5a673..c87d04478611 100644 --- a/code/controllers/subsystem/communications.dm +++ b/code/controllers/subsystem/communications.dm @@ -147,6 +147,7 @@ Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency #define MAX_FREE_FREQ 1599 // ------------------------------------------------- GLOBAL_LIST_INIT(radiochannels, list( + RADIO_CHANNEL_AICORE = AI_FREQ, RADIO_CHANNEL_YAUTJA = YAUT_FREQ, RADIO_CHANNEL_VAI = VAI_FREQ, RADIO_CHANNEL_CMB = CMB_FREQ, diff --git a/code/datums/factions/uscm.dm b/code/datums/factions/uscm.dm index 6a4b61289ea3..dcd3ee9d4671 100644 --- a/code/datums/factions/uscm.dm +++ b/code/datums/factions/uscm.dm @@ -169,6 +169,8 @@ marine_rk = "tisio" if(JOB_TIS_SA) marine_rk = "tissa" + if(JOB_AI_TECH) + marine_rk = "aist" // Riot MPs if(JOB_RIOT) marine_rk = "rmp" diff --git a/code/game/area/almayer.dm b/code/game/area/almayer.dm index a065a0b8671f..8a8f36ae51bd 100644 --- a/code/game/area/almayer.dm +++ b/code/game/area/almayer.dm @@ -79,6 +79,16 @@ is_resin_allowed = FALSE resin_construction_allowed = FALSE +/area/almayer/command/aist_office + name = "\improper AIST Office" + icon_state = "airoom" + fake_zlevel = 1 // upperdeck + soundscape_playlist = list() + flags_area = AREA_NOTUNNEL|AREA_UNWEEDABLE + can_build_special = FALSE + is_resin_allowed = FALSE + resin_construction_allowed = FALSE + /area/almayer/command/securestorage name = "\improper Upper Deck Secure Storage" icon_state = "corporatespace" diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 5c10e8e7d934..3d9c1e7811e1 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -168,6 +168,19 @@ ACCESS_MARINE_MEDBAY, ) + get_access(ACCESS_LIST_COLONIAL_ALL) + if(ACCESS_LIST_MARINE_LIAISON_AIST) + return list( + ACCESS_WY_GENERAL, + ACCESS_WY_COLONIAL, + ACCESS_WY_EXEC, + ACCESS_MARINE_COMMAND, + ACCESS_MARINE_MEDBAY, + ACCESS_MARINE_ENGINEERING, + ACCESS_MARINE_SYNTH, + ACCESS_MARINE_AI, + ACCESS_ARES_DEBUG, + ) + get_access(ACCESS_LIST_COLONIAL_ALL) + if(ACCESS_LIST_COLONIAL_ALL) return list( ACCESS_CIVILIAN_PUBLIC, diff --git a/code/game/jobs/job/special/uscm.dm b/code/game/jobs/job/special/uscm.dm index 934241fdca8a..e06d2e0d7be4 100644 --- a/code/game/jobs/job/special/uscm.dm +++ b/code/game/jobs/job/special/uscm.dm @@ -17,3 +17,54 @@ /datum/job/special/uscm/tech title = JOB_SQUAD_TECH + +#define USCM_TECH "USCM" +#define WY_TECH "Wey-Yu" + +/datum/job/special/uscm/ai_tech + title = JOB_AI_TECH + selection_class = "job_ce" + supervisors = "the acting commanding officer" + total_positions = 1 + spawn_positions = 1 + flags_startup_parameters = ROLE_ADD_TO_DEFAULT|ROLE_ADMIN_NOTIFY|ROLE_WHITELISTED + gear_preset = /datum/equipment_preset/uscm_event/ai_tech + + // job option + job_options = list(USCM_TECH = "USCM", WY_TECH = "WY") + var/corporate = FALSE + +//check the job option. and change the gear preset +/datum/job/special/uscm/ai_tech/handle_job_options(option) + if(option != USCM_TECH) + corporate = TRUE + supervisors = "Weyland Yutani" + gear_preset = /datum/equipment_preset/uscm_event/ai_tech/corporate + else + corporate = FALSE + gear_preset = /datum/equipment_preset/uscm_event/ai_tech + +/datum/job/special/uscm/ai_tech/check_whitelist_status(mob/user) + if(check_rights(R_PERMISSIONS, show_msg = FALSE) || user.client.check_whitelist_status(WHITELIST_SYNTHETIC_COUNCIL)) + return TRUE + return FALSE + +/datum/job/special/uscm/ai_tech/generate_entry_message() + entry_message_body = "You are a [corporate ? FACTION_WY : FACTION_MARINE] AI Service Technician temporarily assigned to the [MAIN_SHIP_NAME]. Your goal is to ensure the onboard AI, [MAIN_AI_SYSTEM], is operating effectively. Your job involves heavy roleplay and requires you to behave like [corporate ? "a senior corporate representative, remaining in character at all times.
As a Weyland Yutani Technician you have access to the Corporate Office aboard the USS Almayer. Although you should cooperate with the onboard Liaison, you are not their subordinate nor they yours. You should help The Company interests where applicable but do not abuse your access to the AI Systems." : "an officer and to stay in character at all times. You are required to adhere to and obey Marine Law. Failure to do so may result in punitive action against you. Godspeed.\n\nThe access code for APOLLO Interface is [GLOB.ares_link.code_apollo].\nThe access code for ARES Interface is [GLOB.ares_link.code_interface]."]" + return ..() + +/datum/job/special/uscm/ai_tech/announce_entry_message(mob/living/carbon/human/ai_tech) + addtimer(CALLBACK(src, PROC_REF(handle_wakeup), ai_tech), 2 SECONDS) + +/datum/job/special/uscm/ai_tech/proc/handle_wakeup(mob/living/carbon/human/ai_tech) + ares_apollo_talk("AI Service Technician, [ai_tech.get_paygrade(0)] [ai_tech.real_name], is now awake.") + var/radio_prefix = ":n" + if(corporate) + radio_prefix = ":y" + ai_silent_announcement("AI Service Technician, [ai_tech.get_paygrade(0)] [ai_tech.real_name], is now awake.", ":v") + ai_silent_announcement("AI Service Technician, [ai_tech.get_paygrade(0)] [ai_tech.real_name], is now awake.", radio_prefix) + +/obj/effect/landmark/start/ai_tech + name = JOB_AI_TECH + icon_state = "aist_spawn" + job = /datum/job/special/uscm/ai_tech diff --git a/code/game/machinery/ARES/ARES.dm b/code/game/machinery/ARES/ARES.dm index 1ecbb4a5d7d6..3236abe44f6d 100644 --- a/code/game/machinery/ARES/ARES.dm +++ b/code/game/machinery/ARES/ARES.dm @@ -115,3 +115,35 @@ name = "ARES Substrate" desc = "The memory substrate of ARES, containing complex protocols and information. Limited capabilities can operate on substrate alone, without the main ARES Unit operational." icon_state = "substrate" + + +/// Sentry +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares + name = "UA X512-S mini sentry" + faction_group = FACTION_LIST_ARES_MARINE + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/Initialize() + link_sentry() + . = ..() + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/Destroy() + delink_sentry() + . = ..() + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/start_processing() + sync_iff() + ..() + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/proc/sync_iff() + var/datum/ares_link/ares_link = GLOB.ares_link + if(!ares_link || !ares_link.faction_group) + faction_group = FACTION_LIST_ARES_MARINE + faction_group = ares_link.faction_group + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/proc/link_sentry() + var/datum/ares_link/link = GLOB.ares_link + link.core_sentries += src + +/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/proc/delink_sentry() + var/datum/ares_link/link = GLOB.ares_link + link.core_sentries -= src diff --git a/code/game/machinery/ARES/ARES_interface.dm b/code/game/machinery/ARES/ARES_interface.dm index 0316274774be..9a259fbf9982 100644 --- a/code/game/machinery/ARES/ARES_interface.dm +++ b/code/game/machinery/ARES/ARES_interface.dm @@ -69,136 +69,20 @@ ui.open() /obj/structure/machinery/computer/ares_console/ui_data(mob/user) - var/list/data = list() - - data["current_menu"] = current_menu - data["last_page"] = last_menu - - data["logged_in"] = last_login - data["sudo"] = sudo_holder ? TRUE : FALSE - - data["access_text"] = "[sudo_holder ? "(SUDO)," : ""] access level [authentication], [ares_auth_to_text(authentication)]." - data["access_level"] = authentication - - data["alert_level"] = GLOB.security_level - data["evac_status"] = SShijack.evac_status - data["worldtime"] = world.time - - data["access_log"] = datacore.interface_access_list - data["apollo_log"] = datacore.apollo_log - - data["deleted_conversation"] = deleted_1to1 - - data["distresstime"] = datacore.ares_distress_cooldown - data["distresstimelock"] = DISTRESS_TIME_LOCK - data["quarterstime"] = datacore.ares_quarters_cooldown - data["mission_failed"] = SSticker.mode.is_in_endgame - data["nuketimelock"] = NUCLEAR_TIME_LOCK - data["nuke_available"] = datacore.nuke_available - - data["printer_cooldown"] = !COOLDOWN_FINISHED(src, printer_cooldown) - - var/list/logged_announcements = list() - for(var/datum/ares_record/announcement/broadcast as anything in datacore.records_announcement) - var/list/current_broadcast = list() - current_broadcast["time"] = broadcast.time - current_broadcast["title"] = broadcast.title - current_broadcast["details"] = broadcast.details - current_broadcast["ref"] = "\ref[broadcast]" - logged_announcements += list(current_broadcast) - data["records_announcement"] = logged_announcements - - var/list/logged_alerts = list() - for(var/datum/ares_record/security/security_alert as anything in datacore.records_security) - var/list/current_alert = list() - current_alert["time"] = security_alert.time - current_alert["title"] = security_alert.title - current_alert["details"] = security_alert.details - current_alert["ref"] = "\ref[security_alert]" - logged_alerts += list(current_alert) - data["records_security"] = logged_alerts - - var/list/logged_flights = list() - for(var/datum/ares_record/flight/flight_log as anything in datacore.records_flight) - var/list/current_flight = list() - current_flight["time"] = flight_log.time - current_flight["title"] = flight_log.title - current_flight["details"] = flight_log.details - current_flight["user"] = flight_log.user - current_flight["ref"] = "\ref[flight_log]" - logged_flights += list(current_flight) - data["records_flight"] = logged_flights - - var/list/logged_bioscans = list() - for(var/datum/ares_record/bioscan/scan as anything in datacore.records_bioscan) - var/list/current_scan = list() - current_scan["time"] = scan.time - current_scan["title"] = scan.title - current_scan["details"] = scan.details - current_scan["ref"] = "\ref[scan]" - logged_bioscans += list(current_scan) - data["records_bioscan"] = logged_bioscans - - var/list/logged_bombs = list() - for(var/datum/ares_record/bombardment/bomb as anything in datacore.records_bombardment) - var/list/current_bomb = list() - current_bomb["time"] = bomb.time - current_bomb["title"] = bomb.title - current_bomb["details"] = bomb.details - current_bomb["user"] = bomb.user - current_bomb["ref"] = "\ref[bomb]" - logged_bombs += list(current_bomb) - data["records_bombardment"] = logged_bombs - - var/list/logged_deletes = list() - for(var/datum/ares_record/deletion/deleted as anything in datacore.records_deletion) - if(!istype(deleted)) - continue - var/list/current_delete = list() - current_delete["time"] = deleted.time - current_delete["title"] = deleted.title - current_delete["details"] = deleted.details - current_delete["user"] = deleted.user - current_delete["ref"] = "\ref[deleted]" - logged_deletes += list(current_delete) - data["records_deletion"] = logged_deletes - - var/list/logged_discussions = list() - for(var/datum/ares_record/deleted_talk/deleted_convo as anything in datacore.records_deletion) - if(!istype(deleted_convo)) - continue - var/list/deleted_disc = list() - deleted_disc["time"] = deleted_convo.time - deleted_disc["title"] = deleted_convo.title - deleted_disc["ref"] = "\ref[deleted_convo]" - logged_discussions += list(deleted_disc) - data["deleted_discussions"] = logged_discussions - - var/list/logged_orders = list() - for(var/datum/ares_record/requisition_log/req_order as anything in datacore.records_asrs) - if(!istype(req_order)) - continue - var/list/current_order = list() - current_order["time"] = req_order.time - current_order["details"] = req_order.details - current_order["title"] = req_order.title - current_order["user"] = req_order.user - current_order["ref"] = "\ref[req_order]" - logged_orders += list(current_order) - data["records_requisition"] = logged_orders - - var/list/logged_techs = list() - for(var/datum/ares_record/tech/tech_unlock as anything in datacore.records_tech) - var/list/current_tech = list() - current_tech["time"] = tech_unlock.time - current_tech["details"] = tech_unlock.details - current_tech["user"] = tech_unlock.user - current_tech["tier_changer"] = tech_unlock.is_tier - current_tech["ref"] = "\ref[tech_unlock]" - logged_techs += list(current_tech) - data["records_tech"] = logged_techs - - var/list/logged_convos = list() + var/list/data = datacore.get_interface_data() + + data["local_current_menu"] = current_menu + data["local_last_page"] = last_menu + + data["local_logged_in"] = last_login + data["local_sudo"] = sudo_holder ? TRUE : FALSE + + data["local_access_text"] = "[sudo_holder ? "(SUDO)," : ""] access level [authentication], [ares_auth_to_text(authentication)]." + data["local_access_level"] = authentication + + data["local_deleted_conversation"] = deleted_1to1 + data["local_printer_cooldown"] = !COOLDOWN_FINISHED(src, printer_cooldown) + var/list/active_convo = list() var/active_ref for(var/datum/ares_record/talk_log/log as anything in datacore.records_talking) @@ -207,18 +91,8 @@ if(log.user == last_login) active_convo = log.conversation active_ref = "\ref[log]" - - var/list/current_convo = list() - current_convo["user"] = log.user - current_convo["ref"] = "\ref[log]" - current_convo["conversation"] = log.conversation - logged_convos += list(current_convo) - - data["active_convo"] = active_convo - data["active_ref"] = active_ref - data["conversations"] = logged_convos - - data["security_vents"] = link.get_ares_vents() + data["local_active_convo"] = active_convo + data["local_active_ref"] = active_ref return data @@ -456,7 +330,7 @@ datacore.records_talking += convo if("clear_conversation") - var/datum/ares_record/talk_log/conversation = locate(params["active_convo"]) + var/datum/ares_record/talk_log/conversation = locate(params["passed_active_convo"]) if(!istype(conversation)) return FALSE var/datum/ares_record/deleted_talk/deleted = new @@ -469,7 +343,7 @@ if("message_ares") var/message = tgui_input_text(user, "What do you wish to say to ARES?", "ARES Message", encode = FALSE) if(message) - message_ares(message, user, params["active_convo"]) + message_ares(message, user, params["passed_active_convo"]) if("read_record") var/datum/ares_record/deleted_talk/conversation = locate(params["record"]) @@ -573,6 +447,24 @@ COOLDOWN_START(datacore, ares_nuclear_cooldown, COOLDOWN_COMM_DESTRUCT) return TRUE + if("bioscan") + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < FORCE_SCAN_LOCK) + to_chat(operator, SPAN_WARNING("Bio sensors are not yet ready to initiate a scan!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!(COOLDOWN_FINISHED(datacore, ares_bioscan_cooldown)) || (world.time < (GLOB.last_human_bioscan + COOLDOWN_FORCE_SCAN))) + to_chat(operator, SPAN_WARNING("It is too soon since the last scan, wait for the sensor array to reset!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + GLOB.bioscan_data.ares_bioscan(FALSE, 2) + COOLDOWN_START(datacore, ares_bioscan_cooldown, COOLDOWN_FORCE_SCAN) + playsound(src, 'sound/machines/terminal_processing.ogg', 15, 1) + message_admins("BIOSCAN: [key_name(operator)] triggered a Marine bioscan via ARES AIST.") + return TRUE + if("trigger_vent") playsound = FALSE var/obj/structure/pipes/vents/pump/no_boom/gas/sec_vent = locate(params["vent"]) @@ -599,5 +491,20 @@ aicore_lockdown(user) return TRUE + if("update_sentries") + playsound = FALSE + var/new_iff = params["chosen_iff"] + if(!new_iff) + to_chat(user, SPAN_WARNING("ERROR: Unknown setting.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(new_iff == link.faction_label) + return FALSE + link.change_iff(new_iff) + playsound(src, 'sound/machines/chime.ogg', 15, 1) + message_admins("ARES: [key_name(user)] updated ARES Sentry IFF to [new_iff].") + to_chat(user, SPAN_WARNING("Sentry IFF settings updated!")) + return TRUE + if(playsound) playsound(src, "keyboard_alt", 15, 1) diff --git a/code/game/machinery/ARES/ARES_interface_admin.dm b/code/game/machinery/ARES/ARES_interface_admin.dm index 758ba9fbb5e7..15cdf540cb05 100644 --- a/code/game/machinery/ARES/ARES_interface_admin.dm +++ b/code/game/machinery/ARES/ARES_interface_admin.dm @@ -48,190 +48,31 @@ if(!interface) to_chat(user, SPAN_WARNING("ARES ADMIN DATA LINK FAILED")) return FALSE - var/list/data = list() - - data["admin_login"] = "[admin_interface.logged_in], [user.client.admin_holder?.rank]" - data["admin_access_log"] = list(admin_interface.access_list) - - data["current_menu"] = admin_interface.current_menu - data["last_page"] = admin_interface.last_menu - - data["logged_in"] = interface.last_login - data["sudo"] = interface.sudo_holder ? TRUE : FALSE - - data["access_text"] = "[interface.sudo_holder ? "(SUDO)," : ""] access level [interface.authentication], [interface.ares_auth_to_text(interface.authentication)]." - data["access_level"] = interface.authentication - - data["alert_level"] = GLOB.security_level - data["evac_status"] = SShijack.evac_status - data["worldtime"] = world.time - - data["access_log"] = datacore.interface_access_list - data["apollo_log"] = datacore.apollo_log - - data["deleted_conversation"] = admin_interface.deleted_1to1 - - data["distresstime"] = datacore.ares_distress_cooldown - data["distresstimelock"] = DISTRESS_TIME_LOCK - data["mission_failed"] = SSticker.mode.is_in_endgame - data["nuketimelock"] = NUCLEAR_TIME_LOCK - data["nuke_available"] = datacore.nuke_available - - var/list/logged_announcements = list() - for(var/datum/ares_record/announcement/broadcast in datacore.records_announcement) - var/list/current_broadcast = list() - current_broadcast["time"] = broadcast.time - current_broadcast["title"] = broadcast.title - current_broadcast["details"] = broadcast.details - current_broadcast["ref"] = "\ref[broadcast]" - logged_announcements += list(current_broadcast) - data["records_announcement"] = logged_announcements - - var/list/logged_alerts = list() - for(var/datum/ares_record/security/security_alert in datacore.records_security) - var/list/current_alert = list() - current_alert["time"] = security_alert.time - current_alert["title"] = security_alert.title - current_alert["details"] = security_alert.details - current_alert["ref"] = "\ref[security_alert]" - logged_alerts += list(current_alert) - data["records_security"] = logged_alerts - - var/list/logged_flights = list() - for(var/datum/ares_record/flight/flight_log in datacore.records_flight) - var/list/current_flight = list() - current_flight["time"] = flight_log.time - current_flight["title"] = flight_log.title - current_flight["details"] = flight_log.details - current_flight["user"] = flight_log.user - current_flight["ref"] = "\ref[flight_log]" - logged_flights += list(current_flight) - data["records_flight"] = logged_flights - - var/list/logged_bioscans = list() - for(var/datum/ares_record/bioscan/scan in datacore.records_bioscan) - var/list/current_scan = list() - current_scan["time"] = scan.time - current_scan["title"] = scan.title - current_scan["details"] = scan.details - current_scan["ref"] = "\ref[scan]" - logged_bioscans += list(current_scan) - data["records_bioscan"] = logged_bioscans - - var/list/logged_bombs = list() - for(var/datum/ares_record/bombardment/bomb in datacore.records_bombardment) - var/list/current_bomb = list() - current_bomb["time"] = bomb.time - current_bomb["title"] = bomb.title - current_bomb["details"] = bomb.details - current_bomb["user"] = bomb.user - current_bomb["ref"] = "\ref[bomb]" - logged_bombs += list(current_bomb) - data["records_bombardment"] = logged_bombs - - var/list/logged_deletes = list() - for(var/datum/ares_record/deletion/deleted in datacore.records_deletion) - var/list/current_delete = list() - current_delete["time"] = deleted.time - current_delete["title"] = deleted.title - current_delete["details"] = deleted.details - current_delete["user"] = deleted.user - current_delete["ref"] = "\ref[deleted]" - logged_deletes += list(current_delete) - data["records_deletion"] = logged_deletes - - var/list/logged_discussions = list() - for(var/datum/ares_record/deleted_talk/deleted_convo in datacore.records_deletion) - var/list/deleted_disc = list() - deleted_disc["time"] = deleted_convo.time - deleted_disc["title"] = deleted_convo.title - deleted_disc["ref"] = "\ref[deleted_convo]" - logged_discussions += list(deleted_disc) - data["deleted_discussions"] = logged_discussions - - var/list/logged_orders = list() - for(var/datum/ares_record/requisition_log/req_order in datacore.records_asrs) - var/list/current_order = list() - current_order["time"] = req_order.time - current_order["details"] = req_order.details - current_order["title"] = req_order.title - current_order["user"] = req_order.user - current_order["ref"] = "\ref[req_order]" - logged_orders += list(current_order) - data["records_requisition"] = logged_orders - - var/list/logged_techs = list() - for(var/datum/ares_record/tech/tech_unlock as anything in datacore.records_tech) - var/list/current_tech = list() - current_tech["time"] = tech_unlock.time - current_tech["details"] = tech_unlock.details - current_tech["user"] = tech_unlock.user - current_tech["tier_changer"] = tech_unlock.is_tier - current_tech["ref"] = "\ref[tech_unlock]" - logged_techs += list(current_tech) - data["records_tech"] = logged_techs - - var/list/logged_convos = list() + var/list/data = datacore.get_interface_data() + + data["is_pda"] = FALSE + data["admin_access_log"] = admin_interface.access_list + + data["local_current_menu"] = admin_interface.current_menu + data["local_last_page"] = admin_interface.last_menu + + data["ares_logged_in"] = interface.last_login + data["ares_sudo"] = interface.sudo_holder ? TRUE : FALSE + + data["ares_access_text"] = "[interface.sudo_holder ? "(SUDO)," : ""] access level [interface.authentication], [interface.ares_auth_to_text(interface.authentication)]." + + data["local_deleted_conversation"] = admin_interface.deleted_1to1 + var/list/active_convo = list() var/active_ref - for(var/datum/ares_record/talk_log/log in datacore.records_talking) + for(var/datum/ares_record/talk_log/log as anything in datacore.records_talking) + if(!istype(log)) + continue if(log.user == interface.last_login) active_convo = log.conversation active_ref = "\ref[log]" - - var/list/current_convo = list() - current_convo["user"] = log.user - current_convo["ref"] = "\ref[log]" - current_convo["conversation"] = log.conversation - logged_convos += list(current_convo) - - data["active_convo"] = active_convo - data["active_ref"] = active_ref - data["conversations"] = logged_convos - - var/list/logged_maintenance = list() - for(var/datum/ares_ticket/maintenance/maint_ticket in tickets_maintenance) - var/lock_status = TICKET_OPEN - switch(maint_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) - lock_status = TICKET_CLOSED - - var/list/current_maint = list() - current_maint["id"] = maint_ticket.ticket_id - current_maint["time"] = maint_ticket.ticket_time - current_maint["priority_status"] = maint_ticket.ticket_priority - current_maint["category"] = maint_ticket.ticket_name - current_maint["details"] = maint_ticket.ticket_details - current_maint["status"] = maint_ticket.ticket_status - current_maint["submitter"] = maint_ticket.ticket_submitter - current_maint["assignee"] = maint_ticket.ticket_assignee - current_maint["lock_status"] = lock_status - current_maint["ref"] = "\ref[maint_ticket]" - logged_maintenance += list(current_maint) - data["maintenance_tickets"] = logged_maintenance - - var/list/logged_access = list() - for(var/datum/ares_ticket/access/access_ticket in tickets_access) - var/lock_status = TICKET_OPEN - switch(access_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED) - lock_status = TICKET_CLOSED - - var/list/current_ticket = list() - current_ticket["id"] = access_ticket.ticket_id - current_ticket["time"] = access_ticket.ticket_time - current_ticket["priority_status"] = access_ticket.ticket_priority - current_ticket["title"] = access_ticket.ticket_name - current_ticket["details"] = access_ticket.ticket_details - current_ticket["status"] = access_ticket.ticket_status - current_ticket["submitter"] = access_ticket.ticket_submitter - current_ticket["assignee"] = access_ticket.ticket_assignee - current_ticket["lock_status"] = lock_status - current_ticket["ref"] = "\ref[access_ticket]" - logged_access += list(current_ticket) - data["access_tickets"] = logged_access - - data["security_vents"] = get_ares_vents() + data["local_active_convo"] = active_convo + data["local_active_ref"] = active_ref return data @@ -514,3 +355,22 @@ log_ares_security("Nerve Gas Release", "Released Nerve Gas from Vent '[sec_vent.vent_tag]'.", MAIN_AI_SYSTEM) sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + + if("security_lockdown") + if(!COOLDOWN_FINISHED(datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(datacore, aicore_lockdown)] seconds!")) + return FALSE + aicore_lockdown(user) + return TRUE + + if("update_sentries") + var/new_iff = params["chosen_iff"] + if(!new_iff) + to_chat(user, SPAN_WARNING("ERROR: Unknown setting.")) + return FALSE + if(new_iff == faction_label) + return FALSE + change_iff(new_iff) + message_admins("ARES: [key_name(user)] updated ARES Sentry IFF to [new_iff].") + to_chat(user, SPAN_WARNING("Sentry IFF settings updated!")) + return TRUE diff --git a/code/game/machinery/ARES/ARES_interface_apollo.dm b/code/game/machinery/ARES/ARES_interface_apollo.dm index 93637f39d1a7..7918ce9a1023 100644 --- a/code/game/machinery/ARES/ARES_interface_apollo.dm +++ b/code/game/machinery/ARES/ARES_interface_apollo.dm @@ -73,75 +73,14 @@ ui.open() /obj/structure/machinery/computer/working_joe/ui_data(mob/user) - var/list/data = list() + var/list/data = datacore.get_interface_data() - data["current_menu"] = current_menu - data["last_page"] = last_menu - - data["logged_in"] = last_login - - data["access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." - data["access_level"] = authentication - - data["alert_level"] = GLOB.security_level - data["worldtime"] = world.time - - data["access_log"] = list() - data["access_log"] += datacore.apollo_login_list - - data["apollo_log"] = datacore.apollo_log - - data["notify_sounds"] = notify_sounds - - var/list/logged_maintenance = list() - for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) - if(!istype(maint_ticket)) - continue - var/lock_status = TICKET_OPEN - switch(maint_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) - lock_status = TICKET_CLOSED - - var/list/current_maint = list() - current_maint["id"] = maint_ticket.ticket_id - current_maint["time"] = maint_ticket.ticket_time - current_maint["priority_status"] = maint_ticket.ticket_priority - current_maint["category"] = maint_ticket.ticket_name - current_maint["details"] = maint_ticket.ticket_details - current_maint["status"] = maint_ticket.ticket_status - current_maint["submitter"] = maint_ticket.ticket_submitter - current_maint["assignee"] = maint_ticket.ticket_assignee - current_maint["lock_status"] = lock_status - current_maint["ref"] = "\ref[maint_ticket]" - logged_maintenance += list(current_maint) - data["maintenance_tickets"] = logged_maintenance - - var/list/logged_access = list() - var/list/requesting_access = list() - for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access) - var/lock_status = TICKET_OPEN - switch(access_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED) - lock_status = TICKET_CLOSED - - var/list/current_ticket = list() - current_ticket["id"] = access_ticket.ticket_id - current_ticket["time"] = access_ticket.ticket_time - current_ticket["priority_status"] = access_ticket.ticket_priority - current_ticket["title"] = access_ticket.ticket_name - current_ticket["details"] = access_ticket.ticket_details - current_ticket["status"] = access_ticket.ticket_status - current_ticket["submitter"] = access_ticket.ticket_submitter - current_ticket["assignee"] = access_ticket.ticket_assignee - current_ticket["lock_status"] = lock_status - current_ticket["ref"] = "\ref[access_ticket]" - logged_access += list(current_ticket) - - if(lock_status == TICKET_OPEN) - requesting_access += access_ticket.ticket_name - data["access_tickets"] = logged_access - - data["security_vents"] = link.get_ares_vents() + data["local_current_menu"] = current_menu + data["local_last_page"] = last_menu + data["local_logged_in"] = last_login + data["local_access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." + data["local_access_level"] = authentication + data["local_notify_sounds"] = notify_sounds return data @@ -444,6 +383,21 @@ aicore_lockdown(user) return TRUE + if("update_sentries") + playsound = FALSE + var/new_iff = params["chosen_iff"] + if(!new_iff) + to_chat(user, SPAN_WARNING("ERROR: Unknown setting.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(new_iff == link.faction_label) + return FALSE + link.change_iff(new_iff) + playsound(src, 'sound/machines/chime.ogg', 15, 1) + message_admins("ARES: [key_name(user)] updated ARES Sentry IFF to [new_iff].") + to_chat(user, SPAN_WARNING("Sentry IFF settings updated!")) + return TRUE + if(playsound) playsound(src, "keyboard_alt", 15, 1) diff --git a/code/game/machinery/ARES/ARES_interface_data.dm b/code/game/machinery/ARES/ARES_interface_data.dm new file mode 100644 index 000000000000..621cc35eb2a5 --- /dev/null +++ b/code/game/machinery/ARES/ARES_interface_data.dm @@ -0,0 +1,200 @@ +/datum/ares_datacore/proc/get_interface_data() + var/datum/ares_link/link = GLOB.ares_link + var/list/data = list() + + data["alert_level"] = GLOB.security_level + data["evac_status"] = SShijack.evac_status + data["worldtime"] = world.time + + data["ares_access_log"] = interface_access_list + data["apollo_access_log"] = apollo_login_list + data["apollo_log"] = apollo_log + + + data["distresstime"] = ares_distress_cooldown + data["distresstimelock"] = DISTRESS_TIME_LOCK + data["quarterstime"] = ares_quarters_cooldown + data["mission_failed"] = SSticker.mode.is_in_endgame + data["nuketimelock"] = NUCLEAR_TIME_LOCK + data["nuke_available"] = nuke_available + + + var/list/logged_announcements = list() + for(var/datum/ares_record/announcement/broadcast as anything in records_announcement) + var/list/current_broadcast = list() + current_broadcast["time"] = broadcast.time + current_broadcast["title"] = broadcast.title + current_broadcast["details"] = broadcast.details + current_broadcast["ref"] = "\ref[broadcast]" + logged_announcements += list(current_broadcast) + data["records_announcement"] = logged_announcements + + var/list/logged_alerts = list() + for(var/datum/ares_record/security/security_alert as anything in records_security) + var/list/current_alert = list() + current_alert["time"] = security_alert.time + current_alert["title"] = security_alert.title + current_alert["details"] = security_alert.details + current_alert["ref"] = "\ref[security_alert]" + logged_alerts += list(current_alert) + data["records_security"] = logged_alerts + + var/list/logged_flights = list() + for(var/datum/ares_record/flight/flight_log as anything in records_flight) + var/list/current_flight = list() + current_flight["time"] = flight_log.time + current_flight["title"] = flight_log.title + current_flight["details"] = flight_log.details + current_flight["user"] = flight_log.user + current_flight["ref"] = "\ref[flight_log]" + logged_flights += list(current_flight) + data["records_flight"] = logged_flights + + var/list/logged_bioscans = list() + for(var/datum/ares_record/bioscan/scan as anything in records_bioscan) + var/list/current_scan = list() + current_scan["time"] = scan.time + current_scan["title"] = scan.title + current_scan["details"] = scan.details + current_scan["ref"] = "\ref[scan]" + logged_bioscans += list(current_scan) + data["records_bioscan"] = logged_bioscans + + var/list/logged_bombs = list() + for(var/datum/ares_record/bombardment/bomb as anything in records_bombardment) + var/list/current_bomb = list() + current_bomb["time"] = bomb.time + current_bomb["title"] = bomb.title + current_bomb["details"] = bomb.details + current_bomb["user"] = bomb.user + current_bomb["ref"] = "\ref[bomb]" + logged_bombs += list(current_bomb) + data["records_bombardment"] = logged_bombs + + var/list/logged_deletes = list() + for(var/datum/ares_record/deletion/deleted as anything in records_deletion) + if(!istype(deleted)) + continue + var/list/current_delete = list() + current_delete["time"] = deleted.time + current_delete["title"] = deleted.title + current_delete["details"] = deleted.details + current_delete["user"] = deleted.user + current_delete["ref"] = "\ref[deleted]" + logged_deletes += list(current_delete) + data["records_deletion"] = logged_deletes + + var/list/logged_discussions = list() + for(var/datum/ares_record/deleted_talk/deleted_convo as anything in records_deletion) + if(!istype(deleted_convo)) + continue + var/list/deleted_disc = list() + deleted_disc["time"] = deleted_convo.time + deleted_disc["title"] = deleted_convo.title + deleted_disc["ref"] = "\ref[deleted_convo]" + logged_discussions += list(deleted_disc) + data["deleted_discussions"] = logged_discussions + + var/list/logged_orders = list() + for(var/datum/ares_record/requisition_log/req_order as anything in records_asrs) + if(!istype(req_order)) + continue + var/list/current_order = list() + current_order["time"] = req_order.time + current_order["details"] = req_order.details + current_order["title"] = req_order.title + current_order["user"] = req_order.user + current_order["ref"] = "\ref[req_order]" + logged_orders += list(current_order) + data["records_requisition"] = logged_orders + + var/list/logged_techs = list() + for(var/datum/ares_record/tech/tech_unlock as anything in records_tech) + var/list/current_tech = list() + current_tech["time"] = tech_unlock.time + current_tech["details"] = tech_unlock.details + current_tech["user"] = tech_unlock.user + current_tech["tier_changer"] = tech_unlock.is_tier + current_tech["ref"] = "\ref[tech_unlock]" + logged_techs += list(current_tech) + data["records_tech"] = logged_techs + + var/list/logged_convos = list() + for(var/datum/ares_record/talk_log/log as anything in records_talking) + if(!istype(log)) + continue + + var/list/current_convo = list() + current_convo["user"] = log.user + current_convo["ref"] = "\ref[log]" + current_convo["conversation"] = log.conversation + logged_convos += list(current_convo) + + data["conversations"] = logged_convos + + var/list/security_vents = list() + for(var/obj/structure/pipes/vents/pump/no_boom/gas/vent in link.linked_vents) + if(!vent.vent_tag) + vent.vent_tag = "Security Vent #[link.tag_num]" + link.tag_num++ + + var/list/current_vent = list() + var/is_available = COOLDOWN_FINISHED(vent, vent_trigger_cooldown) + current_vent["vent_tag"] = vent.vent_tag + current_vent["ref"] = "\ref[vent]" + current_vent["available"] = is_available + security_vents += list(current_vent) + data["security_vents"] = security_vents + + var/list/logged_maintenance = list() + for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) + if(!istype(maint_ticket)) + continue + var/lock_status = TICKET_OPEN + switch(maint_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) + lock_status = TICKET_CLOSED + + var/list/current_maint = list() + current_maint["id"] = maint_ticket.ticket_id + current_maint["time"] = maint_ticket.ticket_time + current_maint["priority_status"] = maint_ticket.ticket_priority + current_maint["category"] = maint_ticket.ticket_name + current_maint["details"] = maint_ticket.ticket_details + current_maint["status"] = maint_ticket.ticket_status + current_maint["submitter"] = maint_ticket.ticket_submitter + current_maint["assignee"] = maint_ticket.ticket_assignee + current_maint["lock_status"] = lock_status + current_maint["ref"] = "\ref[maint_ticket]" + logged_maintenance += list(current_maint) + data["maintenance_tickets"] = logged_maintenance + + var/list/logged_access = list() + var/list/requesting_access = list() + for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access) + var/lock_status = TICKET_OPEN + switch(access_ticket.ticket_status) + if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED) + lock_status = TICKET_CLOSED + + var/list/current_ticket = list() + current_ticket["id"] = access_ticket.ticket_id + current_ticket["time"] = access_ticket.ticket_time + current_ticket["priority_status"] = access_ticket.ticket_priority + current_ticket["title"] = access_ticket.ticket_name + current_ticket["details"] = access_ticket.ticket_details + current_ticket["status"] = access_ticket.ticket_status + current_ticket["submitter"] = access_ticket.ticket_submitter + current_ticket["assignee"] = access_ticket.ticket_assignee + current_ticket["lock_status"] = lock_status + current_ticket["ref"] = "\ref[access_ticket]" + logged_access += list(current_ticket) + + if(lock_status == TICKET_OPEN) + requesting_access += access_ticket.ticket_name + data["access_tickets"] = logged_access + + data["sentry_setting"] = link.faction_label + data["faction_options"] = link.faction_options + + return data diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm index ef1b836a3d4b..4ae610b1ab9c 100644 --- a/code/game/machinery/ARES/ARES_procs.dm +++ b/code/game/machinery/ARES/ARES_procs.dm @@ -40,10 +40,24 @@ GLOBAL_LIST_INIT(maintenance_categories, list( var/list/waiting_ids = list() var/list/active_ids = list() + ///Sentry faction stuff + var/faction_label = FACTION_MARINE + var/list/faction_group = FACTION_LIST_ARES_MARINE + var/list/faction_options = list(FACTION_MARINE, FACTION_WY, "USCM-WY", FACTION_ARES) + var/list/core_sentries = list() + + var/code_apollo = 1 + var/code_interface = 1 + var/code_debug = 1 + /datum/ares_link/New() admin_interface = new datacore = GLOB.ares_datacore + code_apollo = "[pick(GLOB.alphabet_uppercase)][rand(1000, 9999)][pick(GLOB.alphabet_uppercase)][pick(GLOB.alphabet_uppercase)]" + code_interface = "[pick(GLOB.alphabet_uppercase)][rand(1000, 9999)][pick(GLOB.alphabet_uppercase)][pick(GLOB.alphabet_uppercase)]" + code_debug = "X[rand(1000, 9999)][pick(GLOB.alphabet_uppercase)][pick(GLOB.alphabet_uppercase)]" + /datum/ares_link/Destroy() qdel(admin_interface) for(var/obj/structure/machinery/ares/link in linked_systems) @@ -54,22 +68,29 @@ GLOBAL_LIST_INIT(maintenance_categories, list( alert.delink() ..() -/datum/ares_link/proc/get_ares_vents() - var/list/security_vents = list() - var/datum/ares_link/link = GLOB.ares_link - for(var/obj/structure/pipes/vents/pump/no_boom/gas/vent in link.linked_vents) - if(!vent.vent_tag) - vent.vent_tag = "Security Vent #[link.tag_num]" - link.tag_num++ - - var/list/current_vent = list() - var/is_available = COOLDOWN_FINISHED(vent, vent_trigger_cooldown) - current_vent["vent_tag"] = vent.vent_tag - current_vent["ref"] = "\ref[vent]" - current_vent["available"] = is_available - security_vents += list(current_vent) - return security_vents +/datum/ares_link/proc/change_iff(selection) + faction_label = selection + var/list/new_iff = list() + var/setting + switch(selection) + if("USCM-WY") + setting = "all USCM and Corporate personnel!" + new_iff = FACTION_LIST_ARES_ALL + if(FACTION_WY) + setting = "Corporate personnel only!" + new_iff = FACTION_LIST_ARES_WY + if(FACTION_ARES) + setting = "authenticated Core Assets!" + new_iff = FACTION_LIST_ARES_ALONE + else + setting = "USCM personnel only!" + faction_label = FACTION_MARINE + new_iff = FACTION_LIST_ARES_MARINE + faction_group = new_iff + ares_apollo_talk("Security IFF systems updated to [setting]") + for(var/obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares/sentry in core_sentries) + sentry.sync_iff() /* BELOW ARE IN AdminAres.dm /datum/ares_link/tgui_interact(mob/user, datum/tgui/ui) @@ -113,6 +134,7 @@ GLOBAL_LIST_INIT(maintenance_categories, list( COOLDOWN_DECLARE(ares_nuclear_cooldown) COOLDOWN_DECLARE(ares_quarters_cooldown) COOLDOWN_DECLARE(aicore_lockdown) + COOLDOWN_DECLARE(ares_bioscan_cooldown) // ------ ARES Logging Procs ------ // /proc/ares_is_active() diff --git a/code/game/machinery/ARES/ARES_records.dm b/code/game/machinery/ARES/ARES_records.dm index 5bfe50dce068..9516c676777b 100644 --- a/code/game/machinery/ARES/ARES_records.dm +++ b/code/game/machinery/ARES/ARES_records.dm @@ -49,6 +49,15 @@ src.details = details src.user = user +/datum/ares_record/flight + record_name = ARES_RECORD_FLIGHT + +/datum/ares_record/flight/New(details, user) + time = worldtime2text() + src.title = "Flight Log" + src.details = details + src.user = user + /datum/ares_record/bombardment record_name = ARES_RECORD_BOMB diff --git a/code/game/machinery/ARES/ARES_step_triggers.dm b/code/game/machinery/ARES/ARES_step_triggers.dm index 77a53200ddd3..e84f2cab329b 100644 --- a/code/game/machinery/ARES/ARES_step_triggers.dm +++ b/code/game/machinery/ARES/ARES_step_triggers.dm @@ -16,6 +16,8 @@ var/list/pass_jobs = list(JOB_WORKING_JOE, JOB_CHIEF_ENGINEER, JOB_CO) /// The accesses on an ID card to enter var/pass_accesses = list(ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + /// If the motion alert is sent over a radio channel, what is that prefix? + var/broadcast_prefix /obj/effect/step_trigger/ares_alert/Crossed(mob/living/passer) if(!COOLDOWN_FINISHED(src, sensor_cooldown))//Don't want alerts spammed. @@ -75,6 +77,8 @@ to_chat(passer, SPAN_BOLDWARNING("You hear a soft beeping sound as you cross the threshold.")) ares_apollo_talk(broadcast_message) + if(broadcast_prefix) + ai_silent_announcement(broadcast_message, broadcast_prefix) COOLDOWN_START(src, sensor_cooldown, cooldown_duration) if(alert_id && link) for(var/obj/effect/step_trigger/ares_alert/sensor in link.linked_alerts) @@ -84,13 +88,25 @@ /obj/effect/step_trigger/ares_alert/public pass_accesses = list(ACCESS_MARINE_AI_TEMP, ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + /obj/effect/step_trigger/ares_alert/core alert_id = "AresCore" pass_accesses = list(ACCESS_MARINE_AI_TEMP, ACCESS_MARINE_AI, ACCESS_ARES_DEBUG) + broadcast_prefix = ":p" + +/obj/effect/step_trigger/ares_alert/core/Crossed(mob/living/passer) + if(isxeno(passer)) + if(!COOLDOWN_FINISHED(link.datacore, aicore_lockdown)) + return FALSE + aicore_lockdown(passer, "ATTENTION! \n\nUNIDENTIFIED BIOSIGN DETECTED IN AI CORE! \n\nAI CORE UNDER LOCKDOWN.") + return TRUE + else + ..() /obj/effect/step_trigger/ares_alert/mainframe alert_id = "AresMainframe" alert_message = "ALERT: Unauthorized movement detected in ARES Mainframe!" + broadcast_prefix = ":n" /obj/effect/step_trigger/ares_alert/terminals alert_id = "AresTerminals" @@ -100,6 +116,7 @@ area_based = TRUE alert_id = "TComms" pass_accesses = list(ACCESS_MARINE_CE) + broadcast_prefix = ":n" /// Trigger will remove ACCESS_MARINE_AI_TEMP unless ACCESS_MARINE_AI is also present. diff --git a/code/game/machinery/ARES/apollo_pda.dm b/code/game/machinery/ARES/apollo_pda.dm index 7b92b869daeb..5a989743cf7d 100644 --- a/code/game/machinery/ARES/apollo_pda.dm +++ b/code/game/machinery/ARES/apollo_pda.dm @@ -97,76 +97,14 @@ update_icon() /obj/item/device/working_joe_pda/ui_data(mob/user) - var/list/data = list() + var/list/data = datacore.get_interface_data() - data["current_menu"] = current_menu - data["last_page"] = last_menu - - data["logged_in"] = last_login - - data["access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." - data["access_level"] = authentication - - data["alert_level"] = GLOB.security_level - data["worldtime"] = world.time - - data["access_log"] = list() - data["access_log"] += datacore.apollo_login_list - - data["apollo_log"] = list() - data["apollo_log"] += datacore.apollo_log - - data["notify_sounds"] = notify_sounds - - var/list/logged_maintenance = list() - for(var/datum/ares_ticket/maintenance/maint_ticket as anything in link.tickets_maintenance) - if(!istype(maint_ticket)) - continue - var/lock_status = TICKET_OPEN - switch(maint_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_COMPLETED) - lock_status = TICKET_CLOSED - - var/list/current_maint = list() - current_maint["id"] = maint_ticket.ticket_id - current_maint["time"] = maint_ticket.ticket_time - current_maint["priority_status"] = maint_ticket.ticket_priority - current_maint["category"] = maint_ticket.ticket_name - current_maint["details"] = maint_ticket.ticket_details - current_maint["status"] = maint_ticket.ticket_status - current_maint["submitter"] = maint_ticket.ticket_submitter - current_maint["assignee"] = maint_ticket.ticket_assignee - current_maint["lock_status"] = lock_status - current_maint["ref"] = "\ref[maint_ticket]" - logged_maintenance += list(current_maint) - data["maintenance_tickets"] = logged_maintenance - - var/list/logged_access = list() - var/list/requesting_access = list() - for(var/datum/ares_ticket/access/access_ticket as anything in link.tickets_access) - var/lock_status = TICKET_OPEN - switch(access_ticket.ticket_status) - if(TICKET_REJECTED, TICKET_CANCELLED, TICKET_REVOKED) - lock_status = TICKET_CLOSED - - var/list/current_ticket = list() - current_ticket["id"] = access_ticket.ticket_id - current_ticket["time"] = access_ticket.ticket_time - current_ticket["priority_status"] = access_ticket.ticket_priority - current_ticket["title"] = access_ticket.ticket_name - current_ticket["details"] = access_ticket.ticket_details - current_ticket["status"] = access_ticket.ticket_status - current_ticket["submitter"] = access_ticket.ticket_submitter - current_ticket["assignee"] = access_ticket.ticket_assignee - current_ticket["lock_status"] = lock_status - current_ticket["ref"] = "\ref[access_ticket]" - logged_access += list(current_ticket) - - if(lock_status == TICKET_OPEN) - requesting_access += access_ticket.ticket_name - data["access_tickets"] = logged_access - - data["security_vents"] = link.get_ares_vents() + data["local_current_menu"] = current_menu + data["local_last_page"] = last_menu + data["local_logged_in"] = last_login + data["local_access_text"] = "access level [authentication], [ares_auth_to_text(authentication)]." + data["local_access_level"] = authentication + data["local_notify_sounds"] = notify_sounds return data @@ -470,6 +408,21 @@ aicore_lockdown(user) return TRUE + if("update_sentries") + playsound = FALSE + var/new_iff = params["chosen_iff"] + if(!new_iff) + to_chat(user, SPAN_WARNING("ERROR: Unknown setting.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(new_iff == link.faction_label) + return FALSE + link.change_iff(new_iff) + message_admins("ARES: [key_name(user)] updated ARES Sentry IFF to [new_iff].") + playsound(src, 'sound/machines/chime.ogg', 15, 1) + to_chat(user, SPAN_WARNING("Sentry IFF settings updated!")) + return TRUE + if(playsound) var/sound = pick('sound/machines/pda_button1.ogg', 'sound/machines/pda_button2.ogg') playsound(src, sound, 15, TRUE) diff --git a/code/game/machinery/ARES/debug_pda.dm b/code/game/machinery/ARES/debug_pda.dm new file mode 100644 index 000000000000..2c0c388213a9 --- /dev/null +++ b/code/game/machinery/ARES/debug_pda.dm @@ -0,0 +1,927 @@ +/obj/item/device/ai_tech_pda + icon = 'icons/obj/items/synth/ait_pda.dmi' + name = "T411 AIDT" + desc = "Artifical Intelligence Diagnostic Tablet model T411. Built to withstand a nuclear bomb." + icon_state = "karnak_off" + unacidable = TRUE + indestructible = TRUE + req_one_access = list(ACCESS_ARES_DEBUG, ACCESS_MARINE_AI) + + /// The ID used to link all devices. + var/datum/ares_link/link + /// The datacore storing all the information. + var/datum/ares_datacore/datacore + + var/current_menu = "login" + var/last_menu = "off" + + var/authentication = APOLLO_ACCESS_LOGOUT + /// The last person to login. + var/logged_in + /// A record of who logged in and when. + var/list/access_list = list() + var/list/deleted_1to1 = list() + + /// Notification sound + var/notify_sounds = TRUE + COOLDOWN_DECLARE(printer_cooldown) + var/access_code = 0 + var/set_ui = "AresAccessCode" + +/obj/item/device/ai_tech_pda/proc/link_systems(datum/ares_link/new_link = GLOB.ares_link, override) + if(link && !override) + return FALSE + if(new_link) + new_link.ticket_computers += src + link = new_link + new_link.linked_systems += src + if(!datacore) + datacore = GLOB.ares_datacore + return TRUE + +/obj/item/device/ai_tech_pda/Initialize(mapload, ...) + link_systems(override = FALSE) + . = ..() + +/obj/item/device/ai_tech_pda/proc/delink() + if(link) + link.ticket_computers -= src + link.linked_systems -= src + link = null + datacore = null + +/obj/item/device/ai_tech_pda/verb/enter_code() + set name = "Enter Access Code" + set desc = "Enter an access code. Duh." + set category = "Object.AIDT" + set src in usr + + if(access_code) + to_chat(usr, SPAN_WARNING("An access code has already been entered!")) + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + return FALSE + var/mob/living/carbon/user = usr + playsound(src, 'sound/machines/terminal_prompt.ogg', 15, TRUE) + var/new_access_code = tgui_input_text(user, "Please enter a data access code.", "Access Code", "00000", 7, timeout = 20 SECONDS) + if(!new_access_code) + to_chat(usr, SPAN_WARNING("Error: No input detected!")) + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + return FALSE + access_code = new_access_code + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 15, TRUE) + to_chat(usr, SPAN_HELPFUL("New access code detected. Please reload your device.")) + +/obj/item/device/ai_tech_pda/verb/clear_code() + set name = "Clear Access Code" + set desc = "Take a guess." + set category = "Object.AIDT" + set src in usr + + var/mob/living/carbon/human/user + if(ishuman(usr)) + user = usr + else + return FALSE + + if(!access_code) + to_chat(user, SPAN_WARNING("You can't clear an already cleared code...")) + return FALSE + + var/obj/item/card/id/card = user.wear_id + if(!card || !card.check_biometrics(user)) + to_chat(user, SPAN_WARNING("You require an authenticated ID card to access this device!")) + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + return FALSE + access_code = 0 + last_menu = "off" + current_menu = "login" + +/obj/item/device/ai_tech_pda/Destroy() + delink() + return ..() + +/obj/item/device/ai_tech_pda/update_icon() + . = ..() + if(last_menu == "off") + icon_state = "karnak_off" + else if(current_menu == "login") + icon_state = "karnak_login_anim" + else + icon_state = "karnak_on_anim" + +/obj/item/device/ai_tech_pda/attack_self(mob/living/carbon/human/user) + if(..() || !allowed(user)) + to_chat(user, SPAN_WARNING("Access Denied!")) + return FALSE + + if((last_menu == "off") && (current_menu == "login")) + last_menu = "main" + update_icon() + + tgui_interact(user) + return TRUE + +/obj/item/device/ai_tech_pda/tgui_interact(mob/user, datum/tgui/ui) + if(!link.interface || !datacore) + to_chat(user, SPAN_WARNING("ARES DATA LINK FAILED")) + return FALSE + ui = SStgui.try_update_ui(user, src, ui) + if(access_code == GLOB.ares_link.code_apollo) + set_ui = "WorkingJoe" + else if(access_code == GLOB.ares_link.code_interface) + set_ui = "AresInterface" + else if((access_code == GLOB.ares_link.code_debug) && (check_debug_login(user))) + set_ui = "AresAdmin" + else + access_code = 0 + set_ui = "AresAccessCode" + if(!ui) + ui = new(user, src, set_ui, name) + ui.open() + +/obj/item/device/ai_tech_pda/proc/check_debug_login(mob/user) + var/mob/living/carbon/human/human_user = user + if(!ishuman(human_user)) + return FALSE + var/failed = FALSE + var/obj/item/card/id/idcard = human_user.get_active_hand() + if(!istype(idcard)) + if(human_user.wear_id) + idcard = human_user.wear_id + if(!istype(idcard)) + failed = TRUE + if(!idcard?.check_biometrics(human_user) || !(ACCESS_ARES_DEBUG in idcard?.access)) + failed = TRUE + if(failed) + to_chat(human_user, SPAN_WARNING("You require an authenticated ID card to access this device!")) + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + return FALSE + return TRUE + +/obj/item/device/ai_tech_pda/ui_close(mob/user) + . = ..() + if(set_ui == "AresAdmin") + access_list += "[logged_in] logged out at [worldtime2text()]." + logged_in = null + authentication = 0 + current_menu = "login" + last_menu = "off" + update_icon() + +/obj/item/device/ai_tech_pda/ui_data(mob/user) + if(!link.interface) + to_chat(user, SPAN_WARNING("ARES ADMIN DATA LINK FAILED")) + return FALSE + var/list/data = datacore.get_interface_data() + + data["is_pda"] = TRUE + data["admin_login"] = "[logged_in], AI Service Technician" + data["admin_access_log"] = access_list + + data["local_current_menu"] = current_menu + data["local_last_page"] = last_menu + data["local_logged_in"] = logged_in + data["local_access_level"] = authentication + data["local_sudo"] = FALSE + data["local_printer_cooldown"] = !COOLDOWN_FINISHED(src, printer_cooldown) + data["local_notify_sounds"] = notify_sounds + + var/admin_remote_access_text = "[link.interface.sudo_holder ? "(SUDO)," : ""] access level [link.interface.authentication], [link.interface.ares_auth_to_text(link.interface.authentication)]." + if(set_ui == "AresAdmin") + data["ares_access_text"] = admin_remote_access_text + data["ares_logged_in"] = link.interface.last_login + data["ares_sudo"] = link.interface.sudo_holder ? TRUE : FALSE + else if(set_ui == "WorkingJoe") + data["local_access_text"] = " access level [authentication], [apollo_auth_to_text(authentication)]." + else if(set_ui == "AresInterface") + data["local_access_text"] = " access level [authentication], [ares_auth_to_text(authentication)]." + + var/list/active_convo = list() + var/active_ref + for(var/datum/ares_record/talk_log/log as anything in datacore.records_talking) + if(!istype(log)) + continue + if(log.user == link.interface.last_login) + active_convo = log.conversation + active_ref = "\ref[log]" + data["local_active_convo"] = active_convo + data["local_active_ref"] = active_ref + + return data + +/obj/item/device/ai_tech_pda/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + var/mob/living/carbon/human/user = ui.user + var/playsound = TRUE + + if(set_ui == "AresAdmin" && !check_security(user)) + return FALSE + + switch(action) + if("go_back") + if(!last_menu) + return to_chat(user, SPAN_WARNING("Error, no previous page detected.")) + var/temp_holder = current_menu + current_menu = last_menu + last_menu = temp_holder + + if("login") + var/failed = FALSE + var/obj/item/card/id/idcard = user.get_active_hand() + if(!istype(idcard)) + if(user.wear_id) + idcard = user.wear_id + if(!istype(idcard)) + failed = TRUE + if(!idcard.check_biometrics(user)) + failed = TRUE + if(failed) + to_chat(user, SPAN_WARNING("You require an authenticated ID card to access this device!")) + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + return FALSE + + switch(set_ui) + if("AresInterface", "AresAdmin") + authentication = get_ares_access(idcard) + if("WorkingJoe") + authentication = get_apollo_access(idcard) + + if(authentication) + logged_in = idcard.registered_name + access_list += "[logged_in] at [worldtime2text()]." + current_menu = "main" + + if("sudo") + if(!check_security(user) || set_ui == "AresAdmin") + return FALSE + var/new_user = tgui_input_text(user, "Enter Sudo Username", "Sudo User", encode = FALSE) + if(new_user) + if(new_user == link.interface.sudo_holder) + link.interface.last_login = link.interface.sudo_holder + link.interface.sudo_holder = null + return FALSE + if(new_user == link.interface.last_login) + to_chat(user, SPAN_WARNING("Already remote logged in as this user.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + link.interface.sudo_holder = link.interface.last_login + link.interface.last_login = new_user + datacore.interface_access_list += "[link.interface.last_login] at [worldtime2text()], Sudo Access." + return TRUE + if("sudo_logout") + if(!check_security(user)) + return FALSE + datacore.interface_access_list += "[link.interface.last_login] at [worldtime2text()], Sudo Logout." + link.interface.last_login = link.interface.sudo_holder + link.interface.sudo_holder = null + return + + // -- Page Changers -- // + if("logout") + current_menu = "login" + last_menu = "login" + access_list += "[logged_in] logged out at [worldtime2text()]." + logged_in = null + + if("home") + last_menu = current_menu + current_menu = "main" + if("page_1to1") + last_menu = current_menu + current_menu = "talking" + if("page_announcements") + last_menu = current_menu + current_menu = "announcements" + if("page_bioscans") + last_menu = current_menu + current_menu = "bioscans" + if("page_bombardments") + last_menu = current_menu + current_menu = "bombardments" + if("page_apollo") + last_menu = current_menu + current_menu = "apollo" + if("page_access") + last_menu = current_menu + current_menu = "access_log" + if("page_admin_list") + last_menu = current_menu + current_menu = "admin_access_log" + if("page_security") + last_menu = current_menu + current_menu = "security" + if("page_requisitions") + last_menu = current_menu + current_menu = "requisitions" + if("page_flight") + last_menu = current_menu + current_menu = "flight_log" + if("page_emergency") + last_menu = current_menu + current_menu = "emergency" + if("page_deleted") + last_menu = current_menu + current_menu = "delete_log" + if("page_deleted_1to1") + last_menu = current_menu + current_menu = "deleted_talks" + if("page_tech") + last_menu = current_menu + current_menu = "tech_log" + if("page_core_sec") + last_menu = current_menu + current_menu = "core_security" + if("page_access_management") + last_menu = current_menu + current_menu = "access_management" + if("page_maint_management") + last_menu = current_menu + current_menu = "maintenance_management" + + // -- 1:1 Conversation -- // + if("new_conversation") + if(link.interface.last_login == "No User") + return FALSE + var/datum/ares_record/talk_log/convo = new(link.interface.last_login) + convo.conversation += "[MAIN_AI_SYSTEM] at [worldtime2text()], 'New 1:1 link initiated. Greetings, [link.interface.last_login].'" + datacore.records_talking += convo + + if("clear_conversation") + var/datum/ares_record/talk_log/conversation = locate(params["active_convo"]) + if(!istype(conversation)) + return FALSE + var/datum/ares_record/deleted_talk/deleted = new + deleted.title = conversation.title + deleted.conversation = conversation.conversation + deleted.user = MAIN_AI_SYSTEM + datacore.records_deletion += deleted + datacore.records_talking -= conversation + + if("fake_message_ares") + if(!check_security(user)) + return FALSE + var/message = tgui_input_text(user, "What do you wish to say to ARES?", "ARES Message", encode = FALSE) + if(message) + link.interface.message_ares(message, user, params["active_convo"], TRUE) + if("ares_reply") + if(!check_security(user)) + return FALSE + var/message = tgui_input_text(user, "What do you wish to reply with?", "ARES Response", encode = FALSE) + if(message) + link.interface.response_from_ares(message, params["active_convo"]) + var/datum/ares_record/talk_log/conversation = locate(params["active_convo"]) + var/admin_log = SPAN_STAFF_IC("ADMINS/MODS: [SPAN_RED("[key_name(user)] replied to [conversation.user]'s ARES message")] [SPAN_GREEN("via [src]")] with: [SPAN_BLUE(message)] ") + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + to_chat(admin, admin_log) + + if("read_record") + var/datum/ares_record/deleted_talk/conversation = locate(params["record"]) + deleted_1to1 = conversation.conversation + last_menu = current_menu + current_menu = "read_deleted" + + if("claim_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + var/claim = TRUE + var/assigned = ticket.ticket_assignee + if(assigned) + if(assigned == logged_in) + var/prompt = tgui_alert(user, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No")) + if(prompt != "Yes") + return FALSE + /// set ticket back to pending + ticket.ticket_assignee = null + ticket.ticket_status = TICKET_PENDING + return claim + var/choice = tgui_alert(user, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No")) + if(choice != "Yes") + claim = FALSE + if(claim) + ticket.ticket_assignee = logged_in + ticket.ticket_status = TICKET_ASSIGNED + return claim + + if("auth_access") + if(!check_security(user)) + return FALSE + playsound = FALSE + var/datum/ares_ticket/access/access_ticket = locate(params["ticket"]) + if(!access_ticket) + return FALSE + for(var/obj/item/card/id/identification in link.waiting_ids) + if(!istype(identification)) + continue + if(identification.registered_gid != access_ticket.user_id_num) + continue + identification.handle_ares_access(logged_in, user) + access_ticket.ticket_status = TICKET_GRANTED + playsound(src, 'sound/machines/chime.ogg', 15, TRUE) + ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] granted core access.") + return TRUE + for(var/obj/item/card/id/identification in link.active_ids) + if(!istype(identification)) + continue + if(identification.registered_gid != access_ticket.user_id_num) + continue + identification.handle_ares_access(logged_in, user) + access_ticket.ticket_status = TICKET_REVOKED + playsound(src, 'sound/machines/chime.ogg', 15, TRUE) + ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: core access for [access_ticket.ticket_submitter] revoked.") + return TRUE + return FALSE + + if("reject_access") + var/datum/ares_ticket/access/access_ticket = locate(params["ticket"]) + if(!istype(access_ticket)) + return FALSE + access_ticket.ticket_status = TICKET_REJECTED + to_chat(user, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as rejected.")) + ares_apollo_talk("Access Ticket [access_ticket.ticket_id] rejected.") + return TRUE + + if("new_report") + var/priority_report = FALSE + var/maint_type = tgui_input_list(user, "What is the type of maintenance item you wish to report?", "Report Category", GLOB.maintenance_categories, 30 SECONDS) + switch(maint_type) + if("Major Structural Damage", "Fire", "Communications Failure", "Power Generation Failure") + priority_report = TRUE + + if(!maint_type) + return FALSE + var/details = tgui_input_text(user, "What are the details for this report?", "Ticket Details", encode = FALSE) + if(!details) + return FALSE + + if(!priority_report) + var/is_priority = tgui_alert(user, "Is this a priority report?", "Priority designation", list("Yes", "No")) + if(is_priority == "Yes") + priority_report = TRUE + + var/confirm = alert(user, "Please confirm the submission of your maintenance report. \n\n Priority: [priority_report ? "Yes" : "No"]\n Category: '[maint_type]'\n Details: '[details]'\n\n Is this correct?", "Confirmation", "Yes", "No") + if(confirm == "Yes") + var/datum/ares_ticket/maintenance/maint_ticket = new("[logged_in] (AIST)", maint_type, details, priority_report) + link.tickets_maintenance += maint_ticket + if(priority_report) + ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.") + log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(user)] as AI-ST with Category '[maint_type]' and Details of '[details]'.") + return TRUE + return FALSE + + if("cancel_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + to_chat(user, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled.")) + ticket.ticket_status = TICKET_CANCELLED + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been cancelled.") + return TRUE + + if("mark_ticket") + var/datum/ares_ticket/ticket = locate(params["ticket"]) + if(!istype(ticket)) + return FALSE + var/options_list = list(TICKET_COMPLETED, TICKET_REJECTED) + if(ticket.ticket_priority) + options_list += TICKET_NON_PRIORITY + else + options_list += TICKET_PRIORITY + var/choice = tgui_alert(user, "What do you wish to mark the ticket as?", "Mark", options_list, 20 SECONDS) + switch(choice) + if(TICKET_PRIORITY) + ticket.ticket_priority = TRUE + ares_apollo_talk("[ticket.ticket_type] [ticket.ticket_id] upgraded to Priority.") + return TRUE + if(TICKET_NON_PRIORITY) + ticket.ticket_priority = FALSE + ares_apollo_talk("[ticket.ticket_type] [ticket.ticket_id] downgraded from Priority.") + return TRUE + if(TICKET_COMPLETED) + ticket.ticket_status = TICKET_COMPLETED + if(TICKET_REJECTED) + ticket.ticket_status = TICKET_REJECTED + else + return FALSE + if(ticket.ticket_priority) + ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by AI-ST [logged_in].") + to_chat(user, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice].")) + return TRUE + + if("delete_record") + if(!check_security(user)) + return FALSE + playsound = FALSE + var/datum/ares_record/record = locate(params["record"]) + if(record.record_name == ARES_RECORD_DELETED) + return FALSE + var/datum/ares_record/deletion/new_delete = new + var/new_details = "Error" + var/new_title = "Error" + switch(record.record_name) + if(ARES_RECORD_ANNOUNCE) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_announcement -= record + if(ARES_RECORD_SECURITY, ARES_RECORD_ANTIAIR) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_security -= record + if(ARES_RECORD_BIOSCAN) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_bioscan -= record + if(ARES_RECORD_BOMB) + new_title = "[record.title] at [record.time]" + new_details = "[record.details] Launched by [record.user]." + datacore.records_bombardment -= record + if(ARES_RECORD_TECH) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_tech -= record + if(ARES_RECORD_FLIGHT) + new_title = "[record.title] at [record.time]" + new_details = record.details + datacore.records_flight -= record + + new_delete.details = new_details + new_delete.user = "[logged_in] (AIST)" + new_delete.title = new_title + + datacore.records_deletion += new_delete + playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE) + + if("general_quarters") + if(!check_security(user)) + return FALSE + if(!COOLDOWN_FINISHED(datacore, ares_quarters_cooldown)) + to_chat(user, SPAN_WARNING("It has not been long enough since the last General Quarters call!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(GLOB.security_level < SEC_LEVEL_RED) + set_security_level(SEC_LEVEL_RED, no_sound = TRUE, announce = FALSE) + shipwide_ai_announcement("ATTENTION! GENERAL QUARTERS. ALL HANDS, MAN YOUR BATTLESTATIONS.", MAIN_AI_SYSTEM, 'sound/effects/GQfullcall.ogg') + log_game("[key_name(user)] has called for general quarters via ARES.") + message_admins("[key_name_admin(user)] has called for general quarters via ARES.") + log_ares_security("General Quarters", "[logged_in] has called for general quarters via ARES.") + COOLDOWN_START(datacore, ares_quarters_cooldown, 10 MINUTES) + . = TRUE + + if("evacuation_start") + if(!check_security(user)) + return FALSE + if(GLOB.security_level < SEC_LEVEL_RED) + to_chat(user, SPAN_WARNING("The ship must be under red alert in order to enact evacuation procedures.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + if(SShijack.evac_admin_denied) + to_chat(user, SPAN_WARNING("The USCM has placed a lock on deploying the evacuation pods.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + if(!SShijack.initiate_evacuation()) + to_chat(user, SPAN_WARNING("You are unable to initiate an evacuation procedure right now!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + log_game("[key_name(user)] has called for an emergency evacuation via ARES.") + message_admins("[key_name_admin(user)] has called for an emergency evacuation via ARES.") + log_ares_security("Initiate Evacuation", "[logged_in] has called for an emergency evacuation via ARES.") + . = TRUE + + if("distress") + if(!check_security(user)) + return FALSE + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < DISTRESS_TIME_LOCK) + to_chat(user, SPAN_WARNING("You have been here for less than six minutes... what could you possibly have done!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!COOLDOWN_FINISHED(datacore, ares_distress_cooldown)) + to_chat(user, SPAN_WARNING("The distress launcher is cooling down!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(GLOB.security_level == SEC_LEVEL_DELTA) + to_chat(user, SPAN_WARNING("The ship is already undergoing self destruct procedures!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(GLOB.security_level < SEC_LEVEL_RED) + to_chat(user, SPAN_WARNING("The ship must be under red alert to launch a distress beacon!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + playsound_client(admin,'sound/effects/sos-morse-code.ogg',10) + SSticker.mode.request_ert(user, TRUE) + to_chat(user, SPAN_NOTICE("A distress beacon request has been sent to USCM High Command.")) + COOLDOWN_START(datacore, ares_distress_cooldown, COOLDOWN_COMM_REQUEST) + return TRUE + + if("nuclearbomb") + if(!check_security(user)) + return FALSE + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < NUCLEAR_TIME_LOCK) + to_chat(user, SPAN_WARNING("It is too soon to request Nuclear Ordnance!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!COOLDOWN_FINISHED(datacore, ares_nuclear_cooldown)) + to_chat(user, SPAN_WARNING("The ordnance request frequency is garbled, wait for reset!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(GLOB.security_level == SEC_LEVEL_DELTA || SSticker.mode.is_in_endgame) + to_chat(user, SPAN_WARNING("The mission has failed catastrophically, what do you want a nuke for?!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + var/reason = tgui_input_text(user, "Please enter reason nuclear ordnance is required.", "Reason for Nuclear Ordnance") + if(!reason) + return FALSE + for(var/client/admin in GLOB.admins) + if((R_ADMIN|R_MOD) & admin.admin_holder.rights) + playsound_client(admin,'sound/effects/sos-morse-code.ogg',10) + message_admins("[key_name(user)] has requested use of Nuclear Ordnance (via ARES)! Reason: [reason] [CC_MARK(user)] (APPROVE) (DENY) [ADMIN_JMP_USER(user)] [CC_REPLY(user)]") + to_chat(user, SPAN_NOTICE("A nuclear ordnance request has been sent to USCM High Command for the following reason: [reason]")) + log_ares_security("Nuclear Ordnance Request", "[logged_in] has sent a request for nuclear ordnance for the following reason: [reason]") + if(ares_can_interface()) + ai_silent_announcement("[logged_in] has sent a request for nuclear ordnance to USCM High Command.", ".V") + ai_silent_announcement("Reason given: [reason].", ".V") + COOLDOWN_START(datacore, ares_nuclear_cooldown, COOLDOWN_COMM_DESTRUCT) + return TRUE + + if("bioscan") + if(!check_security(user)) + return FALSE + if(!SSticker.mode) + return FALSE //Not a game mode? + if(world.time < FORCE_SCAN_LOCK) + to_chat(user, SPAN_WARNING("Bio sensors are not yet ready to initiate a scan!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!(COOLDOWN_FINISHED(datacore, ares_bioscan_cooldown)) || (world.time < (GLOB.last_human_bioscan + COOLDOWN_FORCE_SCAN))) + to_chat(user, SPAN_WARNING("It is too soon since the last scan, wait for the sensor array to reset!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + + GLOB.bioscan_data.ares_bioscan(FALSE, 2) + COOLDOWN_START(datacore, ares_bioscan_cooldown, COOLDOWN_FORCE_SCAN) + playsound(src, 'sound/machines/terminal_processing.ogg', 15, 1) + message_admins("BIOSCAN: [key_name(user)] triggered a Marine bioscan via ARES AIST.") + return TRUE + + if("trigger_vent") + if(!check_security(user)) + return FALSE + playsound = FALSE + var/obj/structure/pipes/vents/pump/no_boom/gas/sec_vent = locate(params["vent"]) + if(!istype(sec_vent) || sec_vent.welded) + to_chat(user, SPAN_WARNING("ERROR: Gas release failure.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!COOLDOWN_FINISHED(sec_vent, vent_trigger_cooldown)) + to_chat(user, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + to_chat(user, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag].")) + playsound(src, 'sound/machines/chime.ogg', 15, 1) + COOLDOWN_START(sec_vent, vent_trigger_cooldown, COOLDOWN_ARES_VENT) + ares_apollo_talk("Nerve Gas release imminent from [sec_vent.vent_tag].") + log_ares_security("Nerve Gas Release", "[MAIN_AI_SYSTEM] released Nerve Gas from Vent '[sec_vent.vent_tag]'.") + sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS) + log_admin("[key_name(user)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.") + + if("security_lockdown") + if(!check_security(user)) + return FALSE + if(!COOLDOWN_FINISHED(datacore, aicore_lockdown)) + to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(datacore, aicore_lockdown)] seconds!")) + return FALSE + aicore_lockdown(user) + return TRUE + + if("update_sentries") + if(!check_security(user)) + return FALSE + playsound = FALSE + var/new_iff = params["chosen_iff"] + if(!new_iff) + to_chat(user, SPAN_WARNING("ERROR: Unknown setting.")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(new_iff == link.faction_label) + return FALSE + link.change_iff(new_iff) + playsound(src, 'sound/machines/chime.ogg', 15, 1) + message_admins("ARES: [key_name(user)] updated ARES Sentry IFF to [new_iff].") + to_chat(user, SPAN_WARNING("Sentry IFF settings updated!")) + return TRUE + + if("print_req") + playsound = FALSE + if(!COOLDOWN_FINISHED(src, printer_cooldown)) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + if(!length(datacore.records_asrs)) + to_chat(user, SPAN_WARNING("There are no records to print!")) + playsound(src, 'sound/machines/buzz-two.ogg', 15, 1) + return FALSE + COOLDOWN_START(src, printer_cooldown, 20 SECONDS) + playsound(src, 'sound/machines/fax.ogg', 15, 1) + sleep(3.4 SECONDS) + var/contents = {" +
\ +
\ +

A.S.R.S.

\ +

Automatic Storage Retrieval System

\ +

Audit Log

\ +

+ Printed By: [logged_in]
+ Print Time: [worldtime2text()]
+
+
+ + + + + + + + + + + "} + + for(var/datum/ares_record/requisition_log/req_order as anything in datacore.records_asrs) + + contents += {" + + + + + + + "} + + contents += "
TimeUserSourceOrder
[req_order.time][req_order.user][req_order.title][req_order.details]
" + + var/location = get_turf(loc) + var/obj/item/paper/log = new(location) + log.name = "ASRS Audit Log" + log.info += contents + log.icon_state = "paper_uscm_words" + visible_message(SPAN_NOTICE("[src] prints out a paper.")) + + if("enter_code") + enter_code() + return + + if("page_logins") + last_menu = current_menu + current_menu = "login_records" + if("page_request") + last_menu = current_menu + current_menu = "access_requests" + if("page_report") + last_menu = current_menu + current_menu = "maint_reports" + if("page_tickets") + last_menu = current_menu + current_menu = "access_tickets" + if("page_maintenance") + last_menu = current_menu + current_menu = "maint_claim" + if("page_core_gas") + last_menu = current_menu + current_menu = "core_security_gas" + + if(playsound) + var/sound = pick('sound/machines/pda_button1.ogg', 'sound/machines/pda_button2.ogg') + playsound(src, sound, 15, TRUE) + +/obj/item/device/ai_tech_pda/proc/check_security(mob/living/carbon/human/user) + if(logged_in && (user.real_name != logged_in)) + playsound(src, 'sound/machines/lockdownalarm.ogg', 15, TRUE) + audible_message(SPAN_ALERTWARNING("[src] blares a security alarm.")) + + current_menu = "login" + last_menu = "off" + logged_in = null + authentication = 0 + access_code = 0 + + if(set_ui == "AresAdmin") + set_ui = "AresAccessCode" + + var/message1 = "ATTENTION! CORE SECURITY ALERT! UNAUTHORIZED USE OF DIAGNOSTIC TABLET DETECTED!" + var/message2 = "ASSOCIATED FINGERPRINT: [user.real_name]. ASSOCIATED LOCATION: [get_area_name(user)]." + + ares_apollo_talk(message1) + ares_apollo_talk(message2) + ai_silent_announcement(message1, ":p") + ai_silent_announcement(message2, ":p") + return FALSE + return TRUE + +/obj/item/device/ai_tech_pda/proc/get_apollo_access(obj/item/card/id/card) + if(ACCESS_ARES_DEBUG in card.access) + return APOLLO_ACCESS_DEBUG + switch(card.assignment) + if(JOB_WORKING_JOE) + return APOLLO_ACCESS_JOE + if(JOB_CHIEF_ENGINEER, JOB_SYNTH, JOB_CO) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI in card.access) + return APOLLO_ACCESS_AUTHED + if(ACCESS_MARINE_AI_TEMP in card.access) + return APOLLO_ACCESS_TEMP + if((ACCESS_MARINE_SENIOR in card.access ) || (ACCESS_MARINE_ENGINEERING in card.access) || (ACCESS_WY_GENERAL in card.access)) + return APOLLO_ACCESS_REPORTER + else + return APOLLO_ACCESS_REQUEST + +/obj/item/device/ai_tech_pda/proc/apollo_auth_to_text(access_level) + switch(access_level) + if(APOLLO_ACCESS_LOGOUT)//0 + return "Logged Out" + if(APOLLO_ACCESS_REQUEST)//1 + return "Unauthorized Personnel" + if(APOLLO_ACCESS_REPORTER)//2 + return "Validated Incident Reporter" + if(APOLLO_ACCESS_TEMP)//3 + return "Authorized Visitor" + if(APOLLO_ACCESS_AUTHED)//4 + return "Certified Personnel" + if(APOLLO_ACCESS_JOE)//5 + return "Working Joe" + if(APOLLO_ACCESS_DEBUG)//6 + return "AI Service Technician" + +/obj/item/device/ai_tech_pda/proc/get_ares_access(obj/item/card/id/card) + if(ACCESS_ARES_DEBUG in card.access) + return ARES_ACCESS_DEBUG + switch(card.assignment) + if(JOB_WORKING_JOE) + return ARES_ACCESS_JOE + if(JOB_CHIEF_ENGINEER) + return ARES_ACCESS_CE + if(JOB_SYNTH) + return ARES_ACCESS_SYNTH + if(card.paygrade in GLOB.wy_highcom_paygrades) + return ARES_ACCESS_WY_COMMAND + if(card.paygrade in GLOB.uscm_highcom_paygrades) + return ARES_ACCESS_HIGH + if(card.paygrade in GLOB.co_paygrades) + return ARES_ACCESS_CO + if(ACCESS_MARINE_SENIOR in card.access) + return ARES_ACCESS_SENIOR + if(ACCESS_WY_GENERAL in card.access) + return ARES_ACCESS_CORPORATE + if(ACCESS_MARINE_COMMAND in card.access) + return ARES_ACCESS_COMMAND + else + return ARES_ACCESS_BASIC + +/obj/item/device/ai_tech_pda/proc/ares_auth_to_text(access_level) + switch(access_level) + if(ARES_ACCESS_LOGOUT) + return "Logged Out" + if(ARES_ACCESS_BASIC) + return "Authorized" + if(ARES_ACCESS_COMMAND) + return "[MAIN_SHIP_NAME] Command" + if(ARES_ACCESS_JOE) + return "Working Joe" + if(ARES_ACCESS_CORPORATE) + return "Weyland-Yutani" + if(ARES_ACCESS_SENIOR) + return "[MAIN_SHIP_NAME] Senior Command" + if(ARES_ACCESS_CE) + return "Chief Engineer" + if(ARES_ACCESS_SYNTH) + return "USCM Synthetic" + if(ARES_ACCESS_CO) + return "[MAIN_SHIP_NAME] Commanding Officer" + if(ARES_ACCESS_HIGH) + return "USCM High Command" + if(ARES_ACCESS_WY_COMMAND) + return "Weyland-Yutani Directorate" + if(ARES_ACCESS_DEBUG) + return "AI Service Technician" diff --git a/code/game/machinery/aicore_lockdown.dm b/code/game/machinery/aicore_lockdown.dm index 8120e98977dc..3ecc357bf41f 100644 --- a/code/game/machinery/aicore_lockdown.dm +++ b/code/game/machinery/aicore_lockdown.dm @@ -84,8 +84,10 @@ return PROC_BLOCKED var/log = "[key_name(user)] triggered AI core lockdown!" - var/ares_log = "Triggered triggered AI Core Emergency Lockdown." + var/ares_log = "Triggered AI Core Emergency Lockdown." var/person = user.name + if(isxeno(user)) + person = MAIN_AI_SYSTEM if(message) log = "[key_name(user)] triggered AI core emergency lockdown! (Using a custom announcement)." if(admin) diff --git a/code/game/machinery/sentry_holder.dm b/code/game/machinery/sentry_holder.dm index 27cfe0cfcec8..e3a7ca4c9f24 100644 --- a/code/game/machinery/sentry_holder.dm +++ b/code/game/machinery/sentry_holder.dm @@ -131,6 +131,7 @@ turret_path = /obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini /obj/structure/machinery/sentry_holder/almayer/mini/aicore + turret_path = /obj/structure/machinery/defenses/sentry/premade/deployable/almayer/mini/ares /obj/structure/machinery/sentry_holder/almayer/mini/aicore/Initialize() . = ..() diff --git a/code/game/machinery/vending/vendor_types/crew/corporate_liaison.dm b/code/game/machinery/vending/vendor_types/crew/corporate_liaison.dm index 69261115ecaa..d655409bec43 100644 --- a/code/game/machinery/vending/vendor_types/crew/corporate_liaison.dm +++ b/code/game/machinery/vending/vendor_types/crew/corporate_liaison.dm @@ -78,7 +78,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_dress_corporate_liaison, list( vendor_theme = VENDOR_THEME_USCM show_points = FALSE req_access = list() - vendor_role = list(JOB_CORPORATE_LIAISON, JOB_SURVIVOR, JOB_TRAINEE, JOB_JUNIOR_EXECUTIVE, JOB_EXECUTIVE, JOB_SENIOR_EXECUTIVE, JOB_EXECUTIVE_SPECIALIST, JOB_EXECUTIVE_SUPERVISOR, JOB_ASSISTANT_MANAGER, JOB_DIVISION_MANAGER, JOB_CHIEF_EXECUTIVE, JOB_DIRECTOR, JOB_WY_GOON_RESEARCHER) + vendor_role = list(JOB_CORPORATE_LIAISON, JOB_SURVIVOR, JOB_TRAINEE, JOB_JUNIOR_EXECUTIVE, JOB_EXECUTIVE, JOB_SENIOR_EXECUTIVE, JOB_EXECUTIVE_SPECIALIST, JOB_EXECUTIVE_SUPERVISOR, JOB_ASSISTANT_MANAGER, JOB_DIVISION_MANAGER, JOB_CHIEF_EXECUTIVE, JOB_DIRECTOR, JOB_WY_GOON_RESEARCHER, JOB_AI_TECH) /obj/structure/machinery/cm_vending/clothing/dress/corporate_liaison/get_listed_products(mob/user) return GLOB.cm_vending_clothing_dress_corporate_liaison diff --git a/code/game/machinery/vending/vendor_types/crew/senior_officers.dm b/code/game/machinery/vending/vendor_types/crew/senior_officers.dm index e724d2f33a3b..2b7837c767bf 100644 --- a/code/game/machinery/vending/vendor_types/crew/senior_officers.dm +++ b/code/game/machinery/vending/vendor_types/crew/senior_officers.dm @@ -2,7 +2,7 @@ name = "\improper ColMarTech Senior Officer Equipment Rack" desc = "An automated equipment vendor for Senior Officers." req_access = list(ACCESS_MARINE_SENIOR) - vendor_role = list(JOB_CHIEF_POLICE, JOB_CMO, JOB_XO, JOB_CHIEF_ENGINEER, JOB_CHIEF_REQUISITION, JOB_AUXILIARY_OFFICER) + vendor_role = list(JOB_CHIEF_POLICE, JOB_CMO, JOB_XO, JOB_CHIEF_ENGINEER, JOB_CHIEF_REQUISITION, JOB_AUXILIARY_OFFICER, JOB_AI_TECH) /obj/structure/machinery/cm_vending/clothing/senior_officer/get_listed_products(mob/user) if(!user) @@ -25,6 +25,10 @@ return GLOB.cm_vending_clothing_military_police_chief else if(user.job == JOB_AUXILIARY_OFFICER) return GLOB.cm_vending_clothing_auxiliary_officer + else if(user.job == JOB_AI_TECH) + if(FACTION_WY in user.faction_group) + return GLOB.cm_vending_clothing_aist_wy + return GLOB.cm_vending_clothing_aist return ..() @@ -164,6 +168,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_chief_engineer, list( list("Spare Equipment", 0, null, null, null), list("Technician's Headset", 15, /obj/item/device/radio/headset/almayer/mt, null, VENDOR_ITEM_REGULAR), + list("Synthetic Sparker", 15, /obj/item/device/defibrillator/synthetic, null, VENDOR_ITEM_REGULAR), )) @@ -537,3 +542,160 @@ GLOBAL_LIST_INIT(cm_vending_clothing_auxiliary_officer, list( /obj/item/clothing/head/marine/peaked, /obj/item/clothing/under/marine/dress, ) + + + +//------------ AI SERVICE TECHNICIAN --------------- +GLOBAL_LIST_INIT(cm_vending_clothing_aist, list( + list("STANDARD EQUIPMENT", 0, null, null, null), + list("Marine Formal Uniform", 0, /obj/item/clothing/under/marine/dress, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), + list("Marine Combat Boots", 0, /obj/item/clothing/shoes/marine, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Gloves", 0, /obj/item/clothing/gloves/yellow, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), + list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom/cdrcom/aist, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), + list("Toolbelt", 0, /obj/item/storage/belt/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_MANDATORY), + list("Welding Goggles", 0, /obj/item/clothing/glasses/welding, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_RECOMMENDED), + list("Gas Mask", 0, /obj/item/clothing/mask/gas, MARINE_CAN_BUY_MASK, VENDOR_ITEM_RECOMMENDED), + + list("SUIT (CHOOSE 1)", 0, null, null, null), + list("Black Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/black, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_RECOMMENDED), + list("Blue Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/blue, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + list("Orange Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + list("Yellow Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/yellow, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + + list("HEADWEAR (OPTIONAL)", 0, null, null, null), + list("Welding Helmet", 0, /obj/item/clothing/head/welding, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_REGULAR), + + list("BAG (CHOOSE 1)", 0, null, null, null), + list("Secure Leather Satchel", 0, /obj/item/storage/backpack/satchel/lockable, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_RECOMMENDED), + list("USCM Satchel", 0, /obj/item/storage/backpack/marine/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Standard Backpack", 0, /obj/item/storage/backpack/marine, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Chestrig", 0, /obj/item/storage/backpack/marine/satchel/tech, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Welder-Satchel", 0, /obj/item/storage/backpack/marine/engineerpack/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Welderpack", 0, /obj/item/storage/backpack/marine/engineerpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Welding Kit", 0, /obj/item/tool/weldpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + + list("PERSONAL SIDEARM (CHOOSE 1)", 0, null, null, null), + list("M2019 Blaster", 0, /obj/effect/essentials_set/m2019, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_RECOMMENDED), + list("M4A3 Service Pistol", 0, /obj/item/storage/belt/gun/m4a3/full, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + list("Mod 88 Pistol", 0, /obj/item/storage/belt/gun/m4a3/mod88, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + list("M44 Revolver", 0, /obj/item/storage/belt/gun/m44/mp, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + + list("COMBAT EQUIPMENT (COMBAT USE ONLY)", 0, null, null, null), + list("Officer M3 Armor", 0, /obj/item/clothing/suit/storage/marine/MP/SO, MARINE_CAN_BUY_COMBAT_ARMOR, VENDOR_ITEM_MANDATORY), + list("Officer M10 Helmet", 0, /obj/item/clothing/head/helmet/marine/MP/SO, MARINE_CAN_BUY_COMBAT_HELMET, VENDOR_ITEM_MANDATORY), + list("Marine Combat Boots", 0, /obj/item/clothing/shoes/marine/knife, MARINE_CAN_BUY_COMBAT_SHOES, VENDOR_ITEM_MANDATORY), + list("M2019 Ammo Refil", 15, /obj/effect/essentials_set/pkd_ammo, null, VENDOR_ITEM_REGULAR), + + list("POUCHES (CHOOSE 2)", 0, null, null, null), + list("First-Aid Pouch (Refillable Injectors)", 0, /obj/item/storage/pouch/firstaid/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("First-Aid Pouch (Splints, Gauze, Ointment)", 0, /obj/item/storage/pouch/firstaid/full/alternate, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("First-Aid Pouch (Pill Packets)", 0, /obj/item/storage/pouch/firstaid/full/pills, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Sling Strap", 0, /obj/item/storage/pouch/sling, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Large General Pouch", 0, /obj/item/storage/pouch/general/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Tools Pouch (Full)", 0, /obj/item/storage/pouch/tools/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Construction Pouch", 0, /obj/item/storage/pouch/construction, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Electronics Pouch (Full)", 0, /obj/item/storage/pouch/electronics/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Magazine Pouch", 0, /obj/item/storage/pouch/magazine, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Pouch", 0, /obj/item/storage/pouch/shotgun, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Sidearm Pouch", 0, /obj/item/storage/pouch/pistol, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Flare Pouch (Full)", 0, /obj/item/storage/pouch/flare/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + + list("ACCESSORIES (CHOOSE 1)", 0, null, null, null), + list("Shoulder Holster", 0, /obj/item/clothing/accessory/storage/holster, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Black Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Brown Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest/brown_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Webbing", 0, /obj/item/clothing/accessory/storage/webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + + list("Spare Equipment", 0, null, null, null), + list("T411 AIDT", 0, /obj/item/device/ai_tech_pda, MARINE_CAN_BUY_MRE, VENDOR_ITEM_REGULAR), + list("APOLLO Relay Key", 5, /obj/item/device/encryptionkey/binary, null, VENDOR_ITEM_REGULAR), + )) + +GLOBAL_LIST_INIT(cm_vending_clothing_aist_wy, list( + list("UNIFORM (CHOOSE 1)", 0, null, null, null), + list("Blue Suit Pants", 0, /obj/item/clothing/under/liaison_suit/blue, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_RECOMMENDED), + list("Brown Suit Pants", 0, /obj/item/clothing/under/liaison_suit/brown, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_REGULAR), + list("Black Suit Pants", 0, /obj/item/clothing/under/liaison_suit/black, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_REGULAR), + list("White Suit Pants", 0, /obj/item/clothing/under/liaison_suit/corporate_formal, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_REGULAR), + + list("STANDARD EQUIPMENT", 0, null, null, null), + list("Headset", 0, /obj/item/device/radio/headset/almayer/mcl/aist, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), + list("Gloves", 0, /obj/item/clothing/gloves/yellow, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), + list("Polished Boots", 0, /obj/item/clothing/shoes/veteran/pmc, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), + list("Toolbelt", 0, /obj/item/storage/belt/utility/full, MARINE_CAN_BUY_BELT, VENDOR_ITEM_MANDATORY), + list("Welding Goggles", 0, /obj/item/clothing/glasses/welding, MARINE_CAN_BUY_GLASSES, VENDOR_ITEM_RECOMMENDED), + list("Gas Mask", 0, /obj/item/clothing/mask/gas, MARINE_CAN_BUY_MASK, VENDOR_ITEM_RECOMMENDED), + + list("VEST (CHOOSE 1)", 0, null, null, null), + list("Orange Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_RECOMMENDED), + list("Black Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/black, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + list("Blue Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/blue, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + list("Yellow Hazard Vest", 0, /obj/item/clothing/suit/storage/hazardvest/yellow, MARINE_CAN_BUY_ARMOR, VENDOR_ITEM_REGULAR), + + list("HEADWEAR (OPTIONAL)", 0, null, null, null), + list("Welding Helmet", 0, /obj/item/clothing/head/welding, MARINE_CAN_BUY_HELMET, VENDOR_ITEM_REGULAR), + + list("BAG (CHOOSE 1)", 0, null, null, null), + list("Secure Leather Satchel", 0, /obj/item/storage/backpack/satchel/lockable, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_RECOMMENDED), + list("USCM Satchel", 0, /obj/item/storage/backpack/marine/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Standard Backpack", 0, /obj/item/storage/backpack/marine, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Chestrig", 0, /obj/item/storage/backpack/marine/satchel/tech, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Welder-Satchel", 0, /obj/item/storage/backpack/marine/engineerpack/satchel, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + list("Technician Welderpack", 0, /obj/item/storage/backpack/marine/engineerpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), + + list("PERSONAL SIDEARM (CHOOSE 1)", 0, null, null, null), + list("M2019 Blaster", 0, /obj/effect/essentials_set/m2019, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_RECOMMENDED), + list("M4A3 Service Pistol", 0, /obj/item/storage/belt/gun/m4a3/full, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + list("Mod 88 Pistol", 0, /obj/item/storage/belt/gun/m4a3/mod88, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + list("M44 Revolver", 0, /obj/item/storage/belt/gun/m44/mp, MARINE_CAN_BUY_SECONDARY, VENDOR_ITEM_REGULAR), + + list("COMBAT EQUIPMENT (COMBAT USE ONLY)", 0, null, null, null), + list("Bulletproof Vest", 0, /obj/item/clothing/suit/armor/bulletproof, MARINE_CAN_BUY_COMBAT_ARMOR, VENDOR_ITEM_MANDATORY), + list("M10 pattern marine helmet", 0, /obj/item/clothing/head/helmet/marine, MARINE_CAN_BUY_COMBAT_HELMET, VENDOR_ITEM_MANDATORY), + list("Polished Boots", 0, /obj/item/clothing/shoes/veteran/pmc/knife, MARINE_CAN_BUY_COMBAT_SHOES, VENDOR_ITEM_MANDATORY), + list("M2019 Ammo Refil", 15, /obj/effect/essentials_set/pkd_ammo, null, VENDOR_ITEM_REGULAR), + + list("POUCHES (CHOOSE 2)", 0, null, null, null), + list("First-Aid Pouch (Refillable Injectors)", 0, /obj/item/storage/pouch/firstaid/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("First-Aid Pouch (Splints, Gauze, Ointment)", 0, /obj/item/storage/pouch/firstaid/full/alternate, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("First-Aid Pouch (Pill Packets)", 0, /obj/item/storage/pouch/firstaid/full/pills, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Sling Strap", 0, /obj/item/storage/pouch/sling, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Large General Pouch", 0, /obj/item/storage/pouch/general/large, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Tools Pouch (Full)", 0, /obj/item/storage/pouch/tools/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Construction Pouch", 0, /obj/item/storage/pouch/construction, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Electronics Pouch (Full)", 0, /obj/item/storage/pouch/electronics/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Magazine Pouch", 0, /obj/item/storage/pouch/magazine, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Pouch", 0, /obj/item/storage/pouch/shotgun, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Sidearm Pouch", 0, /obj/item/storage/pouch/pistol, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + list("Flare Pouch (Full)", 0, /obj/item/storage/pouch/flare/full, MARINE_CAN_BUY_POUCH, VENDOR_ITEM_REGULAR), + + list("ACCESSORIES (CHOOSE 1)", 0, null, null, null), + list("Shoulder Holster", 0, /obj/item/clothing/accessory/storage/holster, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Black Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Brown Webbing Vest", 0, /obj/item/clothing/accessory/storage/black_vest/brown_vest, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + list("Webbing", 0, /obj/item/clothing/accessory/storage/webbing, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), + + list("Spare Equipment", 0, null, null, null), + list("T411 AIDT", 0, /obj/item/device/ai_tech_pda, MARINE_CAN_BUY_MRE, VENDOR_ITEM_REGULAR), + list("APOLLO Relay Key", 5, /obj/item/device/encryptionkey/binary, null, VENDOR_ITEM_REGULAR), + )) + +/obj/effect/essentials_set/m2019 + icon = 'icons/obj/items/weapons/guns/guns_by_faction/colony.dmi' + icon_state = "lapd_2019" + desc = "Properly known as the Pflager Katsumata Series-D Blaster, the M2019 is a relic of a handgun used by detectives and blade runners, having replaced the snub nose .38 detective special in 2019. Fires .44 custom packed sabot magnum rounds. Legally a revolver, the unconventional but robust internal design has made this model incredibly popular amongst collectors and enthusiasts." + spawned_gear_list = list( + /obj/item/weapon/gun/revolver/m44/custom/pkd_special, + /obj/item/ammo_magazine/revolver/pkd, + /obj/item/ammo_magazine/revolver/pkd, + ) + +/obj/effect/essentials_set/pkd_ammo + icon = 'icons/obj/items/weapons/guns/ammo_by_faction/colony.dmi' + icon_state = "pkd_44" + desc = "Flip up the two side latches (three on PKL) and push after aligning with feed lips on blaster. Clip can be re-used." + spawned_gear_list = list( + /obj/item/ammo_magazine/revolver/pkd, + /obj/item/ammo_magazine/revolver/pkd, + /obj/item/ammo_magazine/revolver/pkd, + ) diff --git a/code/game/machinery/vending/vendor_types/crew/synthetic.dm b/code/game/machinery/vending/vendor_types/crew/synthetic.dm index 240155176efa..164b7a995abd 100644 --- a/code/game/machinery/vending/vendor_types/crew/synthetic.dm +++ b/code/game/machinery/vending/vendor_types/crew/synthetic.dm @@ -87,9 +87,17 @@ //------------CLOTHING VENDOR--------------- GLOBAL_LIST_INIT(cm_vending_clothing_synth, list( - list("EXPERIMENTAL TOOL TOKEN (TAKE ALL)", 0, null, null, null), + list("EXPERIMENTAL TOOL TOKEN", 0, null, null, null), list("Experimental Tool Vendor Token", 0, /obj/item/coin/marine/synth, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_MANDATORY), + list("SYNTHETIC SPECIALTY EQUIPMENT", 0, null, null, null), + list("PK-130 SIMI Wrist-Mounted Computer", 0, /obj/item/clothing/gloves/synth, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_KIT, VENDOR_ITEM_REGULAR), + list("RADIO (TAKE ALL)", 0, null, null, null), list("Headset", 0, /obj/item/device/radio/headset/almayer/mcom/synth, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), @@ -134,11 +142,6 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth, list( list("Latex Gloves", 0, /obj/item/clothing/gloves/latex, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_REGULAR), list("BACKPACK (CHOOSE 1)", 0, null, null, null), - list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), list("Logistics IMP Backpack", 0, /obj/item/storage/backpack/marine/satchel/big, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), list("Expedition Chestrig", 0, /obj/item/storage/backpack/marine/satchel/intel/chestrig, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), @@ -338,6 +341,7 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list( list("Backpack, USCM Medical", 12, /obj/item/storage/backpack/marine/medic, null, VENDOR_ITEM_REGULAR), list("Chestrig, Technician", 12, /obj/item/storage/backpack/marine/satchel/tech, null, VENDOR_ITEM_REGULAR), list("Satchel, USCM", 12, /obj/item/storage/backpack/marine/satchel, null, VENDOR_ITEM_REGULAR), + list("Satchel, USCM Medical", 12, /obj/item/storage/backpack/marine/satchel/medic, null, VENDOR_ITEM_REGULAR), list("Satchel, Leather", 12, /obj/item/storage/backpack/satchel, null, VENDOR_ITEM_REGULAR), list("Satchel, Medical", 12, /obj/item/storage/backpack/satchel/med, null, VENDOR_ITEM_REGULAR), list("USCM RTO Pack", 12, /obj/item/storage/backpack/marine/satchel/rto, null, VENDOR_ITEM_REGULAR), @@ -401,16 +405,28 @@ GLOBAL_LIST_INIT(cm_vending_clothing_synth_snowflake, list( return GLOB.cm_vending_synth_tools GLOBAL_LIST_INIT(cm_vending_synth_tools, list( - list("Autocompressor", 15, /obj/item/clothing/suit/auto_cpr, null, VENDOR_ITEM_REGULAR), + list("PK-130", 0, null, null, null), + list("PK-130 Repair Mode", 7, /obj/item/device/simi_chip/repair, null, VENDOR_ITEM_RECOMMENDED), + list("PK-130 Protection Mode", 7, /obj/item/device/simi_chip/protect, null, VENDOR_ITEM_REGULAR), + list("PK-130 Anchor Mode", 4, /obj/item/device/simi_chip/anchor, null, VENDOR_ITEM_REGULAR), + list("PK-130 Motion Detector", 4, /obj/item/device/simi_chip/motion_detector, null, VENDOR_ITEM_REGULAR), + + list("UTILITY & SELF DEFENSE TOOLS", 0, null, null, null), + list("Telescopic Baton", 15, /obj/item/weapon/telebaton, null, VENDOR_ITEM_REGULAR), + list("Experimental Meson Goggles", 15, /obj/item/clothing/glasses/night/experimental_mesons, null, VENDOR_ITEM_REGULAR), list("Backpack Firefighting Watertank", 15, /obj/item/reagent_container/glass/watertank/atmos, null, VENDOR_ITEM_REGULAR), - list("Breaching Hammer", 15, /obj/item/weapon/twohanded/breacher/synth, null, VENDOR_ITEM_REGULAR), + + list("MEDICAL TOOLS", 0, null, null, null), + list("Autocompressor", 15, /obj/item/clothing/suit/auto_cpr, null, VENDOR_ITEM_REGULAR), list("Compact Defibrillator", 15, /obj/item/device/defibrillator/compact, null, VENDOR_ITEM_REGULAR), - list("Compact Nailgun kit", 15, /obj/effect/essentials_set/cnailgun, null, VENDOR_ITEM_REGULAR), + list("Portable Dialysis Machine", 15, /obj/item/tool/portadialysis, null, VENDOR_ITEM_REGULAR), list("Crew Monitor", 15, /obj/item/tool/crew_monitor, null, VENDOR_ITEM_REGULAR), - list("Experimental Meson Goggles", 15, /obj/item/clothing/glasses/night/experimental_mesons, null, VENDOR_ITEM_REGULAR), + list("Synthetic Sparker", 15, /obj/item/device/defibrillator/synthetic, null, VENDOR_ITEM_REGULAR), + + list("CONSTRUCTION TOOLS", 0, null, null, null), + list("Breaching Hammer", 15, /obj/item/weapon/twohanded/breacher/synth, null, VENDOR_ITEM_REGULAR), + list("Compact Nailgun kit", 15, /obj/effect/essentials_set/cnailgun, null, VENDOR_ITEM_REGULAR), list("Maintenance Jack", 15, /obj/item/maintenance_jack, null, VENDOR_ITEM_REGULAR), - list("Portable Dialysis Machine", 15, /obj/item/tool/portadialysis, null, VENDOR_ITEM_REGULAR), - list("Telescopic Baton", 15, /obj/item/weapon/telebaton, null, VENDOR_ITEM_REGULAR), )) //------------EXPERIMENTAL TOOL KITS--------------- diff --git a/code/game/objects/effects/landmarks/landmarks.dm b/code/game/objects/effects/landmarks/landmarks.dm index f5f0e0b50c05..ecece4af6899 100644 --- a/code/game/objects/effects/landmarks/landmarks.dm +++ b/code/game/objects/effects/landmarks/landmarks.dm @@ -413,6 +413,9 @@ name = "working joe late join" job = JOB_WORKING_JOE +/obj/effect/landmark/late_join/aist + name = "AIST late join" + job = JOB_AI_TECH /obj/effect/landmark/late_join/cmo name = "Chief Medical Officer late join" diff --git a/code/game/objects/items/devices/defibrillator.dm b/code/game/objects/items/devices/defibrillator.dm index 2debcf82d7d0..14b52ab298b0 100644 --- a/code/game/objects/items/devices/defibrillator.dm +++ b/code/game/objects/items/devices/defibrillator.dm @@ -24,6 +24,12 @@ var/defib_cooldown = 0 //Cooldown for toggling the defib var/shock_cooldown = 0 //cooldown for shocking someone - separate to toggling + /// Skill requirements. + var/skill_to_check = SKILL_MEDICAL + var/skill_level = SKILL_MEDICAL_MEDIC + var/skill_to_check_alt = null + var/skill_level_alt = 0 + /mob/living/carbon/human/proc/check_tod() if(!undefibbable && world.time <= timeofdeath + revive_grace_period) return TRUE @@ -79,10 +85,11 @@ return //Job knowledge requirement - if (istype(user)) - if(!skillcheck(user, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC)) - to_chat(user, SPAN_WARNING("You don't seem to know how to use [src]...")) - return + if(istype(user)) + if(!skillcheck(user, skill_to_check, skill_level)) + if(!skill_to_check_alt || (!skillcheck(user, skill_to_check_alt, skill_level_alt))) + to_chat(user, SPAN_WARNING("You don't seem to know how to use [src]...")) + return defib_cooldown = world.time + 10 //1 second cooldown every time the defib is toggled ready = !ready @@ -125,7 +132,7 @@ if(!ready) to_chat(user, SPAN_WARNING("Take [src]'s paddles out first.")) return - if(dcell.charge <= charge_cost) + if(dcell.charge < charge_cost) user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src]'s battery is too low! It needs to recharge.")) return if(H.stat != DEAD) @@ -146,103 +153,110 @@ return TRUE -/obj/item/device/defibrillator/attack(mob/living/carbon/human/H, mob/living/carbon/human/user) +/obj/item/device/defibrillator/proc/can_defib(mob/living/carbon/human/target, mob/living/carbon/human/user) if(shock_cooldown > world.time) //cooldown is only for shocking, this is so that you can immediately shock when you take the paddles out - stan_albatross - return + return FALSE shock_cooldown = world.time + 20 //2 second cooldown before you can try shocking again if(user.action_busy) //Currently deffibing - return + return FALSE //job knowledge requirement if(user.skills) - if(!skillcheck(user, SKILL_MEDICAL, SKILL_MEDICAL_MEDIC)) - to_chat(user, SPAN_WARNING("You don't seem to know how to use [src]...")) - return + if(!skillcheck(user, skill_to_check, skill_level)) + if(skill_to_check_alt && !skillcheck(user, skill_to_check_alt, skill_level_alt)) + to_chat(user, SPAN_WARNING("You don't seem to know how to use [src]...")) + return - if(!check_revive(H, user)) - return + if(!check_revive(target, user)) + return FALSE - var/mob/dead/observer/G = H.get_ghost() + var/mob/dead/observer/G = target.get_ghost() if(istype(G) && G.client) playsound_client(G.client, 'sound/effects/adminhelp_new.ogg') to_chat(G, SPAN_BOLDNOTICE(FONT_SIZE_LARGE("Someone is trying to revive your body. Return to it if you want to be resurrected! \ (Verbs -> Ghost -> Re-enter corpse, or click here!)"))) - user.visible_message(SPAN_NOTICE("[user] starts setting up the paddles on [H]'s chest"), \ - SPAN_HELPFUL("You start setting up the paddles on [H]'s chest.")) + user.visible_message(SPAN_NOTICE("[user] starts setting up the paddles on [target]'s chest"), \ + SPAN_HELPFUL("You start setting up the paddles on [target]'s chest.")) playsound(get_turf(src),'sound/items/defib_charge.ogg', 25, 0) //Do NOT vary this tune, it needs to be precisely 7 seconds //Taking square root not to make defibs too fast... - if(!do_after(user, (4 + (3 * user.get_skill_duration_multiplier(SKILL_MEDICAL))) SECONDS, INTERRUPT_NO_NEEDHAND|BEHAVIOR_IMMOBILE, BUSY_ICON_FRIENDLY, H, INTERRUPT_MOVED, BUSY_ICON_MEDICAL)) - user.visible_message(SPAN_WARNING("[user] stops setting up the paddles on [H]'s chest."), \ - SPAN_WARNING("You stop setting up the paddles on [H]'s chest.")) - return + if(!do_after(user, (4 + (3 * user.get_skill_duration_multiplier(SKILL_MEDICAL))) SECONDS, INTERRUPT_NO_NEEDHAND|BEHAVIOR_IMMOBILE, BUSY_ICON_FRIENDLY, target, INTERRUPT_MOVED, BUSY_ICON_MEDICAL)) + user.visible_message(SPAN_WARNING("[user] stops setting up the paddles on [target]'s chest."), \ + SPAN_WARNING("You stop setting up the paddles on [target]'s chest.")) + return FALSE - if(!check_revive(H, user)) - return + if(!check_revive(target, user)) + return FALSE + + return TRUE + +/obj/item/device/defibrillator/attack(mob/living/carbon/human/target, mob/living/carbon/human/user) + if(!can_defib(target, user)) + return FALSE //Do this now, order doesn't matter sparks.start() dcell.use(charge_cost) update_icon() playsound(get_turf(src), 'sound/items/defib_release.ogg', 25, 1) - user.visible_message(SPAN_NOTICE("[user] shocks [H] with the paddles."), - SPAN_HELPFUL("You shock [H] with the paddles.")) - H.visible_message(SPAN_DANGER("[H]'s body convulses a bit.")) + user.visible_message(SPAN_NOTICE("[user] shocks [target] with the paddles."), + SPAN_HELPFUL("You shock [target] with the paddles.")) + target.visible_message(SPAN_DANGER("[target]'s body convulses a bit.")) shock_cooldown = world.time + 10 //1 second cooldown before you can shock again - var/datum/internal_organ/heart/heart = H.internal_organs_by_name["heart"] + var/datum/internal_organ/heart/heart = target.internal_organs_by_name["heart"] - if(!H.is_revivable()) + if(!target.is_revivable()) playsound(get_turf(src), 'sound/items/defib_failed.ogg', 25, 0) if(heart && heart.organ_status >= ORGAN_BROKEN) user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Defibrillation failed. Patient's heart is too damaged. Immediate surgery is advised.")) - msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(H)] with [src] because of heart damage.") + msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(target)] with [src] because of heart damage.") return user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Defibrillation failed. Patient's general condition does not allow reviving.")) - msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(H)] with [src].") + msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(target)] with [src].") return - if(!H.client) //Freak case, no client at all. This is a braindead mob (like a colonist) + if(!target.client) //Freak case, no client at all. This is a braindead mob (like a colonist) user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: No soul detected, Attempting to revive...")) - if(isobserver(H.mind?.current) && !H.client) //Let's call up the correct ghost! Also, bodies with clients only, thank you. - H.mind.transfer_to(H, TRUE) + if(isobserver(target.mind?.current) && !target.client) //Let's call up the correct ghost! Also, bodies with clients only, thank you. + target.mind.transfer_to(target, TRUE) //At this point, the defibrillator is ready to work - H.apply_damage(-damage_heal_threshold, BRUTE) - H.apply_damage(-damage_heal_threshold, BURN) - H.apply_damage(-damage_heal_threshold, TOX) - H.apply_damage(-damage_heal_threshold, CLONE) - H.apply_damage(-H.getOxyLoss(), OXY) - H.updatehealth() //Needed for the check to register properly - - if(!(H.species?.flags & NO_CHEM_METABOLIZATION)) - for(var/datum/reagent/R in H.reagents.reagent_list) + target.apply_damage(-damage_heal_threshold, BRUTE) + target.apply_damage(-damage_heal_threshold, BURN) + target.apply_damage(-damage_heal_threshold, TOX) + target.apply_damage(-damage_heal_threshold, CLONE) + target.apply_damage(-target.getOxyLoss(), OXY) + target.updatehealth() //Needed for the check to register properly + + if(!(target.species?.flags & NO_CHEM_METABOLIZATION)) + for(var/datum/reagent/R in target.reagents.reagent_list) var/datum/chem_property/P = R.get_property(PROPERTY_ELECTROGENETIC)//Adrenaline helps greatly at restarting the heart if(P) - P.trigger(H) - H.reagents.remove_reagent(R.id, 1) + P.trigger(target) + target.reagents.remove_reagent(R.id, 1) break - if(H.health > HEALTH_THRESHOLD_DEAD) + if(target.health > HEALTH_THRESHOLD_DEAD) user.visible_message(SPAN_NOTICE("[icon2html(src, viewers(src))] \The [src] beeps: Defibrillation successful.")) - msg_admin_niche("[key_name_admin(user)] successfully revived [key_name_admin(H)] with [src].") + msg_admin_niche("[key_name_admin(user)] successfully revived [key_name_admin(target)] with [src].") playsound(get_turf(src), 'sound/items/defib_success.ogg', 25, 0) user.track_life_saved(user.job) user.life_revives_total++ - H.handle_revive() + target.handle_revive() if(heart) heart.take_damage(rand(min_heart_damage_dealt, max_heart_damage_dealt), TRUE) // Make death and revival leave lasting consequences - to_chat(H, SPAN_NOTICE("You suddenly feel a spark and your consciousness returns, dragging you back to the mortal plane.")) - if(H.client?.prefs.toggles_flashing & FLASH_CORPSEREVIVE) - window_flash(H.client) + to_chat(target, SPAN_NOTICE("You suddenly feel a spark and your consciousness returns, dragging you back to the mortal plane.")) + if(target.client?.prefs.toggles_flashing & FLASH_CORPSEREVIVE) + window_flash(target.client) else user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Defibrillation failed. Vital signs are too weak, repair damage and try again.")) //Freak case - msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(H)] with [src] because of weak vitals.") + msg_admin_niche("[key_name_admin(user)] failed an attempt to revive [key_name_admin(target)] with [src] because of weak vitals.") playsound(get_turf(src), 'sound/items/defib_failed.ogg', 25, 0) if(heart && prob(25)) heart.take_damage(rand(min_heart_damage_dealt, max_heart_damage_dealt), TRUE) // Make death and revival leave lasting consequences @@ -268,3 +282,50 @@ item_state = "defib" w_class = SIZE_SMALL charge_cost = 99 + + +/obj/item/device/defibrillator/synthetic + name = "synthetic sparker" + desc = "Functioning similarly to a regular defibrillator, this device is designed to restart a synthetic unit via electric shock." + icon = 'icons/obj/items/experimental_tools.dmi' + icon_state = "sparker" + item_state = "defib" + w_class = SIZE_SMALL + charge_cost = 300 + skill_to_check_alt = SKILL_ENGINEER + skill_level_alt = SKILL_ENGINEER_ENGI + +/obj/item/device/defibrillator/synthetic/update_icon() + icon_state = initial(icon_state) + overlays.Cut() + if(ready) + icon_state += "_out" + +/obj/item/device/defibrillator/synthetic/check_revive(mob/living/carbon/human/H, mob/living/carbon/human/user) + if(!issynth(H)) + to_chat(user, SPAN_WARNING("You can't use a [src] on a living being!")) + return FALSE + if(!ready) + to_chat(user, SPAN_WARNING("Take [src]'s paddles out first.")) + return FALSE + if(dcell.charge < charge_cost) + user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src]'s battery is too low! It needs to recharge.")) + return FALSE + if(H.stat != DEAD) + user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Function signs detected. Aborting.")) + return FALSE + + if(!H.is_revivable()) + user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Unit's general condition does not allow reactivation.")) + return FALSE + + if((!MODE_HAS_TOGGLEABLE_FLAG(MODE_STRONG_DEFIBS) && blocked_by_suit) && H.wear_suit && (istype(H.wear_suit, /obj/item/clothing/suit/armor) || istype(H.wear_suit, /obj/item/clothing/suit/storage/marine)) && prob(95)) + user.visible_message(SPAN_WARNING("[icon2html(src, viewers(src))] \The [src] buzzes: Paddles registering >100,000 ohms, Possible cause: Suit or Armor interfering.")) + return FALSE + + return TRUE + +/obj/item/device/defibrillator/synthetic/one_shot + desc = "Functioning similarly to a regular defibrillator, this device is designed to restart a synthetic unit via electric shock. This one can only be used once before needing a recharge and is intended for rebooting Working Joes." + charge_cost = 1000 + icon_state = "sparker_once" diff --git a/code/game/objects/items/devices/motion_detector.dm b/code/game/objects/items/devices/motion_detector.dm index f68295001f92..6a5ab8a32d23 100644 --- a/code/game/objects/items/devices/motion_detector.dm +++ b/code/game/objects/items/devices/motion_detector.dm @@ -184,9 +184,11 @@ if(ishuman(loc)) return loc -/obj/item/device/motiondetector/sg +/obj/item/device/motiondetector/integrated + name = "integrated motion detector" + desc = "A motion sensing component from another device." -/obj/item/device/motiondetector/sg/get_user() +/obj/item/device/motiondetector/integrated/get_user() var/atom/A = loc if(ishuman(A.loc)) return A.loc diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index 95fc3bb76f2c..d22e592b3551 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -12,6 +12,8 @@ var/abstract = FALSE /obj/item/device/encryptionkey/binary + name = "APOLLO relay key" + desc = "An encryption key allowing speech over the APOLLO Link. (Using :+)" icon_state = "binary_key" translate_apollo = TRUE @@ -45,11 +47,11 @@ //MARINE ENCRYPTION KEYS -/obj/item/device/encryptionkey/ai_integrated - name = "AI Integrated Encryption Key" - desc = "Integrated encryption key" - icon_state = "cap_key" - channels = list(RADIO_CHANNEL_ALMAYER = TRUE, RADIO_CHANNEL_COMMAND = TRUE, RADIO_CHANNEL_MP = TRUE, RADIO_CHANNEL_ENGI = TRUE, RADIO_CHANNEL_MEDSCI = TRUE, RADIO_CHANNEL_REQ = TRUE, SQUAD_MARINE_1 = TRUE, SQUAD_MARINE_2 = TRUE, SQUAD_MARINE_3 = TRUE, SQUAD_MARINE_4 = TRUE, SQUAD_MARINE_5 = TRUE, SQUAD_MARINE_CRYO = TRUE, RADIO_CHANNEL_JTAC = TRUE, RADIO_CHANNEL_INTEL = TRUE) +/obj/item/device/encryptionkey/aicore + name = "AI Core Encryption Key" + desc = "AI Core internal communication channel." + icon_state = "binary_key" + channels = list(RADIO_CHANNEL_AICORE = TRUE) /obj/item/device/encryptionkey/sentry_laptop name = "Sentry Network Status Encryption Key" @@ -171,7 +173,7 @@ channels = list(RADIO_CHANNEL_REQ = TRUE, RADIO_CHANNEL_COMMAND = FALSE) /obj/item/device/encryptionkey/mcom/ai //AI only. - channels = list(RADIO_CHANNEL_COMMAND = TRUE, RADIO_CHANNEL_MP = TRUE, SQUAD_MARINE_1 = TRUE, SQUAD_MARINE_2 = TRUE, SQUAD_MARINE_3 = TRUE, SQUAD_MARINE_4 = TRUE, SQUAD_MARINE_5 = TRUE, SQUAD_MARINE_CRYO = TRUE, RADIO_CHANNEL_ENGI = TRUE, RADIO_CHANNEL_MEDSCI = TRUE, RADIO_CHANNEL_REQ = TRUE, RADIO_CHANNEL_JTAC = TRUE, RADIO_CHANNEL_INTEL = TRUE) + channels = list(RADIO_CHANNEL_COMMAND = TRUE, RADIO_CHANNEL_MP = TRUE, SQUAD_MARINE_1 = TRUE, SQUAD_MARINE_2 = TRUE, SQUAD_MARINE_3 = TRUE, SQUAD_MARINE_4 = TRUE, SQUAD_MARINE_5 = TRUE, SQUAD_MARINE_CRYO = TRUE, RADIO_CHANNEL_ENGI = TRUE, RADIO_CHANNEL_MEDSCI = TRUE, RADIO_CHANNEL_REQ = TRUE, RADIO_CHANNEL_JTAC = TRUE, RADIO_CHANNEL_INTEL = TRUE, RADIO_CHANNEL_WY = TRUE, RADIO_CHANNEL_AICORE = TRUE) // MARINE SQUADS diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index e414ca3dafdd..7e86701d465b 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -371,21 +371,6 @@ /obj/item/device/radio/headset/binary initial_keys = list(/obj/item/device/encryptionkey/binary) -/obj/item/device/radio/headset/ai_integrated //No need to care about icons, it should be hidden inside the AI anyway. - name = "AI Subspace Transceiver" - desc = "Integrated AI radio transceiver." - icon = 'icons/obj/items/robot_component.dmi' - icon_state = "radio" - item_state = "headset" - initial_keys = list(/obj/item/device/encryptionkey/ai_integrated) - var/myAi = null // Atlantis: Reference back to the AI which has this radio. - var/disabledAi = 0 // Atlantis: Used to manually disable AI's integrated radio via intellicard menu. - -/obj/item/device/radio/headset/ai_integrated/receive_range(freq, level) - if (disabledAi) - return -1 //Transceiver Disabled. - return ..(freq, level, 1) - //MARINE HEADSETS /obj/item/device/radio/headset/almayer @@ -451,6 +436,12 @@ icon_state = "eng_headset" initial_keys = list(/obj/item/device/encryptionkey/engi) +/obj/item/device/radio/headset/almayer/mt/joe + name = "working joe radio headset" + desc = "The headset used by working joe synthetics. To access the engineering channel, use :n. To access the AI Core internal network, use :q." + icon_state = "eng_headset" + initial_keys = list(/obj/item/device/encryptionkey/aicore) + /obj/item/device/radio/headset/almayer/chef name = "kitchen radio headset" desc = "Used by the onboard kitchen staff, filled with background noise of sizzling pots. Can coordinate with the supply channel, using :u and inform command of delivery service using :v." @@ -547,6 +538,12 @@ maximum_keys = 5 initial_keys = list(/obj/item/device/encryptionkey/mcom/cl) +/obj/item/device/radio/headset/almayer/mcl/aist + name = "corporate AI service technician headset" + desc = "A standard issue corporate liaison headset, modified for AIST responsibilities. Allows the wearer to listen to, and broadcast over, the APOLLO Link. (Use :+)" + icon_state = "aist_wy_headset" + initial_keys = list(/obj/item/device/encryptionkey/binary, /obj/item/device/encryptionkey/mcom/cl, /obj/item/device/encryptionkey/aicore) + /obj/item/device/radio/headset/almayer/reporter name = "reporter radio headset" desc = "Used by the combat correspondent to get the scoop. Channels are as follows: :v - marine command, :a - alpha squad, :b - bravo squad, :c - charlie squad, :d - delta squad, :n - engineering, :m - medbay, :u - requisitions, :j - JTAC, :t - intel." @@ -565,6 +562,12 @@ initial_keys = list(/obj/item/device/encryptionkey/cmpcom/cdrcom) volume = RADIO_VOLUME_CRITICAL +/obj/item/device/radio/headset/almayer/mcom/cdrcom/aist + name = "marine AI service technician headset" + desc = "A modified senior command headset issued to USCM AISTs. Allows the wearer to listen to, and broadcast over, the APOLLO Link. (Use :+)" + icon_state = "aist_headset" + initial_keys = list(/obj/item/device/encryptionkey/binary, /obj/item/device/encryptionkey/cmpcom/cdrcom, /obj/item/device/encryptionkey/aicore) + /obj/item/device/radio/headset/almayer/mcom/sea name = "marine senior enlisted advisor headset" desc = "Issued only to senior enlisted advisors. Channels are as follows: :v - marine command, :p - military police, :a - alpha squad, :b - bravo squad, :c - charlie squad, :d - delta squad, :n - engineering, :m - medbay, :u - requisitions, :j - JTAC, :t - intel" @@ -602,6 +605,9 @@ ) /obj/item/device/radio/headset/almayer/mcom/ai + name = "USCM AI Headset" + desc = "The integrated headset of a W-Y built USCM Ship AI" + initial_keys = list(/obj/item/device/encryptionkey/mcom/ai) volume = RADIO_VOLUME_CRITICAL diff --git a/code/game/objects/items/tools/synth_bracer/_defines.dm b/code/game/objects/items/tools/synth_bracer/_defines.dm new file mode 100644 index 000000000000..1a4d4bcdf531 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/_defines.dm @@ -0,0 +1,44 @@ +// Possible Bracer Colors +#define SIMI_COLOR_DEFAULT "default" +#define SIMI_COLOR_WHITE "white" + +/// Loads/Reloads the available actions on the computer itself. +#define SIMI_ACTIONS_LOAD "load" +#define SIMI_ACTIONS_RELOAD "reload" +/// Cleans and then adds actions to the user. +#define SIMI_ACTIONS_ADD "add" +/// Removes actions from the user. +#define SIMI_ACTIONS_REMOVE "remove" + +/// No active module. +#define SIMI_ACTIVE_NONE "none" + +// Primary Abilities +#define SIMI_PRIMARY_ACTION "primary" + +/// Synth self-repair +#define SIMI_ABILITY_REPAIR "repair" +#define SIMI_REPAIR_COST 50 + +/// Synth fortify, enforced stationary +#define SIMI_ABILITY_ANCHOR "anchor" +#define SIMI_IMMOBILE_COST 20 + +/// Damage reduced but incapable of self defense. +#define SIMI_ABILITY_PROTECT "protect" +#define SIMI_PROTECTIVE_COST 60 + +// Secondary Abilities +#define SIMI_SECONDARY_ACTION "secondary" + +/// Rescue hook. +#define SIMI_SECONDARY_HOOK "hook" +/// Motion Detector +#define SIMI_SECONDARY_MD "motion" + +// Statuses +#define SIMI_STATUS_IDLE "status_idle" +#define SIMI_STATUS_NOACCESS "status_unauthorized" +#define SIMI_STATUS_LOWPOWER "status_lowbattery" +#define SIMI_STATUS_NOPOWER "status_nobattery" +#define SIMI_STATUS_CHARGING "status_charging" diff --git a/code/game/objects/items/tools/synth_bracer/abilities/chips.dm b/code/game/objects/items/tools/synth_bracer/abilities/chips.dm new file mode 100644 index 000000000000..305aa3802abc --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/chips.dm @@ -0,0 +1,34 @@ +/obj/item/device/simi_chip + name = "PK-130 SIMI programmable circuit (NOT FOR USE)" + desc = "A programmable computer circuit used within the PK-130 SINI wrist-mounted computer to add or unlock various functions." + icon = 'icons/obj/items/synth/bracer.dmi' + icon_state = "simi_chip_white" + + /// The action this chip will add to the SIMI + var/chip_action = /datum/action/human_action + /// If this chip is 'secret' or not (cannot be removed/one time use) + var/secret = FALSE + +/obj/item/device/simi_chip/repair + name = "PK-130 SIMI programmable circuit (Self-Repair)" + chip_action = /datum/action/human_action/synth_bracer/repair_form + icon_state = "simi_chip_red" + +/obj/item/device/simi_chip/protect + name = "PK-130 SIMI programmable circuit (Damage Bracing)" + icon_state = "simi_chip_blue" + chip_action = /datum/action/human_action/synth_bracer/protective_form + +/obj/item/device/simi_chip/anchor + name = "PK-130 SIMI programmable circuit (Anchor)" + icon_state = "simi_chip_blue" + chip_action = /datum/action/human_action/synth_bracer/anchor_form + +/obj/item/device/simi_chip/rescue_hook + name = "PK-130 SIMI programmable circuit (Rescue Hook)" + chip_action = /datum/action/human_action/activable/synth_bracer/rescue_hook + +/obj/item/device/simi_chip/motion_detector + name = "PK-130 SIMI programmable circuit (Motion Detector)" + chip_action = /datum/action/human_action/synth_bracer/motion_detector + desc = "A programmable computer circuit used within the PK-130 SINI wrist-mounted computer to add or unlock various functions. This one activates a motion detector capability, at a running cost of power." diff --git a/code/game/objects/items/tools/synth_bracer/abilities/framework.dm b/code/game/objects/items/tools/synth_bracer/abilities/framework.dm new file mode 100644 index 000000000000..7d85be000650 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/framework.dm @@ -0,0 +1,225 @@ +/* -- ACTIVATABLE ACTIONS -- */ + +/datum/action/human_action/activable/synth_bracer + icon_file = 'icons/obj/items/synth/bracer.dmi' + var/mob/living/carbon/human/synth + var/obj/item/clothing/gloves/synth/synth_bracer + var/charge_cost = 0 + var/handles_cooldown = FALSE + var/handles_charge_cost = FALSE + /// What cateogry of action it is. Can only have one active action from each type. + var/category = SIMI_SECONDARY_ACTION + var/human_adaptable = FALSE + /// The tag to tell what ability is active. + var/ability_tag = SIMI_ACTIVE_NONE + +/datum/action/human_action/activable/synth_bracer/give_to(user) + /// never add a check to see if the synth has gloves on, because they shouldn't have these abilities while not wearing gloves. it should runtime to let us know + synth = user + synth_bracer = synth.gloves + if(!issynth(user) && !is_human_usable()) + synth = null + synth_bracer = null + return FALSE + return ..() + +/datum/action/human_action/activable/synth_bracer/remove_from(mob/living/carbon/human/H) + synth = null + synth_bracer = null + return ..() + +/datum/action/human_action/activable/synth_bracer/Destroy() + synth = null + synth_bracer = null + return ..() + +/datum/action/human_action/activable/synth_bracer/action_activate() + if(is_active()) + set_inactive(category) + return + ..() + +/datum/action/human_action/activable/synth_bracer/use_ability(mob/M) + if(!can_use_action()) + return FALSE + if(synth_bracer.battery_charge < charge_cost) + to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)].")) + return FALSE + if(!handles_cooldown && cooldown) + enter_cooldown() + if(!handles_charge_cost && charge_cost) + synth_bracer.drain_charge(owner, charge_cost) + return TRUE + +/datum/action/human_action/activable/synth_bracer/can_use_action() + if(is_active()) + set_inactive(category) + return FALSE + if(!issynth(owner) && !is_human_usable()) + to_chat(owner, SPAN_WARNING("You have no idea how to use this!")) + if(owner.is_mob_incapacitated()) + to_chat(owner, SPAN_WARNING("You cannot use this action while incapacitated!")) + return FALSE + + switch(category) + if(SIMI_PRIMARY_ACTION) + if(synth_bracer.active_ability != SIMI_ACTIVE_NONE) + to_chat(owner, SPAN_WARNING("You cannot use this action while another primary ability is active.")) + return FALSE + if(SIMI_SECONDARY_ACTION) + if(synth_bracer.active_utility != SIMI_ACTIVE_NONE) + to_chat(owner, SPAN_WARNING("You cannot use this action while another secondary ability is active.")) + return FALSE + + if(synth_bracer.battery_charge <= 0) + to_chat(synth, SPAN_WARNING("You cannot do this without power!")) + return FALSE + if(synth_bracer.battery_charge < charge_cost) + to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)].")) + return FALSE + if(!action_cooldown_check()) + return FALSE + return ..() + +/datum/action/human_action/activable/synth_bracer/proc/is_human_usable() + if(human_adaptable && synth_bracer.human_adapted) + return TRUE + return FALSE + +/datum/action/human_action/activable/synth_bracer/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE) + switch(category) + if(SIMI_PRIMARY_ACTION) + synth_bracer.active_ability = set_ability + if(SIMI_SECONDARY_ACTION) + synth_bracer.active_utility = set_ability + if((synth_bracer.active_ability == SIMI_ACTIVE_NONE) && (synth_bracer.active_utility == SIMI_ACTIVE_NONE)) + synth_bracer.flags_item &= ~NODROP + else + synth_bracer.flags_item |= NODROP + synth_bracer.update_icon(synth) + +/datum/action/human_action/activable/synth_bracer/proc/set_inactive(category = SIMI_SECONDARY_ACTION) + set_active(category, SIMI_ACTIVE_NONE) + +/datum/action/human_action/activable/synth_bracer/proc/is_active() + switch(category) + if(SIMI_PRIMARY_ACTION) + if(synth_bracer.active_ability == ability_tag) + return TRUE + if(SIMI_SECONDARY_ACTION) + if(synth_bracer.active_utility == ability_tag) + return TRUE + return FALSE +/* -- ON-CLICK ACTIONS -- */ + +/datum/action/human_action/synth_bracer + icon_file = 'icons/obj/items/synth/bracer.dmi' + var/mob/living/carbon/human/synth + var/obj/item/clothing/gloves/synth/synth_bracer + var/ability_used_time = 0 + var/charge_cost = 0 + var/handles_cooldown = FALSE // whether the cooldown gets handled by the child, or should be done automatically here + var/handles_charge_cost = FALSE + /// What cateogry of action it is. Can only have one active action from each type. + var/category = SIMI_SECONDARY_ACTION + var/human_adaptable = FALSE + /// The tag to tell what ability is active. + var/ability_tag = SIMI_ACTIVE_NONE + +/datum/action/human_action/synth_bracer/give_to(user) + synth = user + synth_bracer = synth.gloves + if(!issynth(user) && !is_human_usable()) + synth = null + synth_bracer = null + return FALSE + return ..() + +/datum/action/human_action/synth_bracer/remove_from(user) + synth = null + synth_bracer = null + return ..() + +/datum/action/human_action/synth_bracer/Destroy() + synth = null + synth_bracer = null + return ..() + +/datum/action/human_action/synth_bracer/proc/form_call() + return + +/datum/action/human_action/synth_bracer/action_cooldown_check() + return ability_used_time <= world.time + +/datum/action/human_action/synth_bracer/proc/enter_cooldown(amount = cooldown) + ability_used_time = world.time + amount + update_button_icon() + addtimer(CALLBACK(src, PROC_REF(update_button_icon)), amount) + +/datum/action/human_action/synth_bracer/update_button_icon() + if(!button) + return + if(!action_cooldown_check()) + button.color = rgb(240,180,0,200) + else + button.color = rgb(255,255,255,255) + +/datum/action/human_action/synth_bracer/can_use_action() + if(!issynth(owner) && !is_human_usable()) + to_chat(owner, SPAN_WARNING("You have no idea how to use this!")) + if(owner.is_mob_incapacitated()) + to_chat(owner, SPAN_WARNING("You cannot use this action while incapacitated!")) + return FALSE + + switch(category) + if(SIMI_PRIMARY_ACTION) + if(synth_bracer.active_ability != SIMI_ACTIVE_NONE) + to_chat(owner, SPAN_WARNING("You cannot use this action while another primary ability is active.")) + return FALSE + if(SIMI_SECONDARY_ACTION) + if(synth_bracer.active_utility != SIMI_ACTIVE_NONE) + to_chat(owner, SPAN_WARNING("You cannot use this action while another secondary ability is active.")) + return FALSE + + if(synth_bracer.battery_charge <= 0) + to_chat(synth, SPAN_WARNING("You cannot do this without power!")) + return FALSE + if(synth_bracer.battery_charge < charge_cost) + to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)].")) + return FALSE + if(!action_cooldown_check()) + return FALSE + return ..() + +/datum/action/human_action/synth_bracer/action_activate() + . = ..() + if(!istype(owner, /mob/living/carbon/human)) + return + var/mob/living/carbon/human/human_owner = owner + if(human_owner.gloves == synth_bracer) + form_call(synth_bracer, human_owner) + if(!handles_cooldown && cooldown) + enter_cooldown() + if(!handles_charge_cost && charge_cost) + synth_bracer.drain_charge(owner, charge_cost) + +/datum/action/human_action/synth_bracer/proc/is_human_usable() + if(human_adaptable && synth_bracer.human_adapted) + return TRUE + return FALSE + +/datum/action/human_action/synth_bracer/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE) + synth_bracer.set_active(category, set_ability) + +/datum/action/human_action/synth_bracer/proc/set_inactive(category = SIMI_SECONDARY_ACTION) + set_active(category, SIMI_ACTIVE_NONE) + +/datum/action/human_action/synth_bracer/proc/is_active() + switch(category) + if(SIMI_PRIMARY_ACTION) + if(synth_bracer.active_ability == ability_tag) + return TRUE + if(SIMI_SECONDARY_ACTION) + if(synth_bracer.active_utility == ability_tag) + return TRUE + return FALSE diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm new file mode 100644 index 000000000000..1ed3ec64b4d5 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/crew_monitor.dm @@ -0,0 +1,33 @@ +/datum/action/human_action/synth_bracer/crew_monitor + name = "View Crew Monitor" + action_icon_state = "crew_monitor" + + var/datum/radar/lifeline/radar + human_adaptable = TRUE + +/datum/action/human_action/synth_bracer/crew_monitor/New() + ..() + radar = new /datum/radar/lifeline(src, "UNSET") + +/datum/action/human_action/synth_bracer/crew_monitor/give_to(user) + ..() + if(!synth_bracer) + return + radar.holder = synth_bracer + radar.faction = synth_bracer.faction + +/datum/action/human_action/synth_bracer/crew_monitor/remove_from(user) + radar.holder = src + radar.faction = "UNSET" + return ..() + +/datum/action/human_action/synth_bracer/crew_monitor/Destroy() + QDEL_NULL(radar) + return ..() + +/datum/action/human_action/synth_bracer/crew_monitor/action_activate() + ..() + if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown)) + COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS) + playsound(synth_bracer, 'sound/machines/terminal_processing.ogg', 35, TRUE) + radar.tgui_interact(usr) diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm new file mode 100644 index 000000000000..edc749fa56a5 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/ocular_designator.dm @@ -0,0 +1,63 @@ +/obj/item/clothing/gloves/synth + var/obj/item/device/binoculars/binos + +/obj/item/clothing/gloves/synth/Initialize(mapload, ...) + . = ..() + binos = new(src) + RegisterSignal(binos, COMSIG_ITEM_DROPPED, PROC_REF(return_binos)) + +/obj/item/clothing/gloves/synth/attackby(obj/item/I, mob/user) + if(I == binos) + return_binos() + return + return ..() + +/obj/item/clothing/gloves/synth/dropped(mob/user) + . = ..() + return_binos() + +/obj/item/clothing/gloves/synth/Destroy() + QDEL_NULL(binos) + return ..() + +/obj/item/clothing/gloves/synth/proc/deploy_binos(mob/M) + if(!M.put_in_active_hand(binos)) + M.put_in_inactive_hand(binos) + +/obj/item/clothing/gloves/synth/proc/return_binos() + if(QDELETED(binos)) + binos = null + return + + if(ismob(binos.loc)) + var/mob/M = binos.loc + M.drop_inv_item_to_loc(binos, src) + else + binos.forceMove(src) + + +/datum/action/human_action/synth_bracer/deploy_binoculars + name = "Deploy Binoculars" + action_icon_state = "far_sight" + human_adaptable = TRUE + +/datum/action/human_action/synth_bracer/deploy_ocular_binos/can_use_action() + if(QDELETED(synth_bracer.binos) || synth_bracer.binos.loc != synth_bracer) + to_chat(synth, SPAN_WARNING("The ocular device isn't inside the SIMI anymore.")) + return FALSE + if(synth.l_hand && synth.r_hand) + to_chat(synth, SPAN_WARNING("You need at least one free hand.")) + return FALSE + return ..() + +/datum/action/human_action/synth_bracer/deploy_binoculars/action_activate() + ..() + if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown)) + COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS) + playsound(synth_bracer.loc,'sound/machines/click.ogg', 25, TRUE) + if(synth_bracer.binos.loc == synth_bracer) + to_chat(synth, SPAN_NOTICE("You deploy your binoculars.")) + synth_bracer.deploy_binos(synth) + else + to_chat(synth, SPAN_NOTICE("You return your binoculars.")) + synth_bracer.return_binos(synth) diff --git a/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm b/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm new file mode 100644 index 000000000000..4edf10c5f276 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/integrated/tactical_map.dm @@ -0,0 +1,22 @@ +/datum/action/human_action/synth_bracer/tactical_map + name = "View Tactical Map" + action_icon_state = "minimap" + + var/datum/tacmap/tacmap + var/minimap_type = MINIMAP_FLAG_USCM + human_adaptable = TRUE + +/datum/action/human_action/synth_bracer/tactical_map/New() + . = ..() + tacmap = new(src, minimap_type) + +/datum/action/human_action/synth_bracer/tactical_map/Destroy() + QDEL_NULL(tacmap) + return ..() + +/datum/action/human_action/synth_bracer/tactical_map/action_activate() + ..() + if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown)) + COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS) + playsound(synth_bracer, 'sound/machines/terminal_processing.ogg', 35, TRUE) + tacmap.tgui_interact(usr) diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm new file mode 100644 index 000000000000..a7e9c4982adb --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/anchor_form.dm @@ -0,0 +1,61 @@ +/datum/action/human_action/synth_bracer/anchor_form + name = "Anchor Form" + action_icon_state = "anchor" + cooldown = 15 SECONDS + charge_cost = SIMI_IMMOBILE_COST + + handles_charge_cost = TRUE + handles_cooldown = TRUE + category = SIMI_PRIMARY_ACTION + ability_tag = SIMI_ABILITY_ANCHOR + + +/datum/action/human_action/synth_bracer/anchor_form/can_use_action() + if(!issynth(synth)) + to_chat(synth, SPAN_WARNING("You have no idea how to use this!")) + if(synth.is_mob_incapacitated() || synth.dazed) + to_chat(synth, SPAN_WARNING("You cannot use this action while incapacitated!")) + return FALSE + if((synth_bracer.battery_charge < charge_cost) && (synth_bracer.active_ability != ability_tag)) + to_chat(synth, SPAN_WARNING("You don't have enough charge to to do this! Charge: [synth_bracer.battery_charge]/[synth_bracer.battery_charge_max] you need [SPAN_RED(charge_cost)].")) + return FALSE + if(!action_cooldown_check()) + return FALSE + if((synth_bracer.active_ability != ability_tag) && (synth_bracer.active_ability != SIMI_ACTIVE_NONE)) + to_chat(synth, SPAN_WARNING("You cannot use this action while another primary ability is active.")) + return FALSE + return TRUE + +/datum/action/human_action/synth_bracer/anchor_form/form_call() + switch(synth_bracer.active_ability) + if(SIMI_ACTIVE_NONE) + synth_bracer.enable_anchor(charge_cost) + if(SIMI_ABILITY_ANCHOR) + synth_bracer.disable_anchor() + else + to_chat(synth, SPAN_WARNING("You cannot use this action while another primary ability is active.")) + return FALSE + + if(COOLDOWN_FINISHED(synth_bracer, sound_cooldown)) + playsound(synth_bracer, 'sound/mecha/mechmove04.ogg', 25, TRUE) + COOLDOWN_START(synth_bracer, sound_cooldown, 5 SECONDS) + return TRUE + +/obj/item/clothing/gloves/synth/proc/enable_anchor(charge_cost) + set_active(SIMI_PRIMARY_ACTION, SIMI_ABILITY_ANCHOR) + drain_charge(wearer, charge_cost) + wearer.status_flags &= ~CANPUSH + wearer.anchored = TRUE + ADD_TRAIT(wearer, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS)) + to_chat(wearer, SPAN_DANGER("[name] beeps, \"You are anchored in place and cannot be moved.\"")) + wearer.add_filter("synth_immobile_form", priority = 1, params = list("type" = "outline", "color" = "#2B719E", "size" = 1)) + +/obj/item/clothing/gloves/synth/proc/disable_anchor() + if(!(active_ability == SIMI_ABILITY_ANCHOR)) + return FALSE + wearer.status_flags |= CANPUSH + wearer.anchored = FALSE + REMOVE_TRAIT(wearer, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS)) + to_chat(wearer, SPAN_DANGER("[name] beeps, \"You can now move again.\"")) + set_inactive(SIMI_PRIMARY_ACTION) + wearer.remove_filter("synth_immobile_form") diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm new file mode 100644 index 000000000000..4246b780a73b --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/protect_form.dm @@ -0,0 +1,56 @@ +/datum/action/human_action/synth_bracer/protective_form + name = "Protective Form" + action_icon_state = "protect" + cooldown = 15 SECONDS + charge_cost = SIMI_PROTECTIVE_COST + + handles_charge_cost = TRUE + handles_cooldown = TRUE + category = SIMI_PRIMARY_ACTION + ability_tag = SIMI_ABILITY_PROTECT + +/datum/action/human_action/synth_bracer/protective_form/form_call() + if((!issynth(synth) && !human_adaptable) || synth_bracer.active_ability != SIMI_ACTIVE_NONE) + return + + if(synth_bracer.battery_charge < SIMI_PROTECTIVE_COST) + to_chat(synth, SPAN_DANGER("There is a lack of charge for that action. Charge: [synth_bracer.battery_charge]/[SIMI_PROTECTIVE_COST]")) + return + synth_bracer.enable_shield(charge_cost) + + +/obj/item/clothing/gloves/synth/proc/enable_shield(charge_cost) + flags_item |= NODROP + flags_inventory |= CANTSTRIP + LAZYSET(wearer.brute_mod_override, src, 0.2) + LAZYSET(wearer.burn_mod_override, src, 0.2) + saved_melee_allowed = wearer.melee_allowed + saved_gun_allowed = wearer.allow_gun_usage + saved_throw_allowed = wearer.throw_allowed + wearer.melee_allowed = FALSE + wearer.allow_gun_usage = FALSE + wearer.throw_allowed = FALSE + to_chat(wearer, SPAN_DANGER("[name] beeps, \"You are now protected, but unable to attack.\"")) + drain_charge(wearer, charge_cost) + playsound(loc, 'sound/mecha/mechmove04.ogg', 25, TRUE) + to_chat(wearer, SPAN_INFO("The current charge reads [battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) + set_active(SIMI_PRIMARY_ACTION, SIMI_ABILITY_PROTECT) + + wearer.add_filter("synth_protective_form", priority = 1, params = list("type" = "outline", "color" = "#369E2B", "size" = 1)) + + addtimer(CALLBACK(src, PROC_REF(disable_shield), wearer), 120) + +/obj/item/clothing/gloves/synth/proc/disable_shield(charge_cost) + if(!(active_ability == SIMI_ABILITY_PROTECT)) + return FALSE + flags_item &= ~NODROP + flags_inventory &= ~CANTSTRIP + wearer.melee_allowed = saved_melee_allowed + wearer.throw_allowed = saved_throw_allowed + wearer.allow_gun_usage = saved_gun_allowed + LAZYREMOVE(wearer.brute_mod_override, src) + LAZYREMOVE(wearer.burn_mod_override, src) + to_chat(wearer, SPAN_DANGER("[name] beeps, \"The protection wears off.\"")) + playsound(loc, 'sound/mecha/mechmove04.ogg', 25, TRUE) + set_inactive(SIMI_PRIMARY_ACTION) + wearer.remove_filter("synth_protective_form") diff --git a/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm b/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm new file mode 100644 index 000000000000..ba64e27fa279 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/primary/repair_form.dm @@ -0,0 +1,32 @@ +/datum/action/human_action/synth_bracer/repair_form + name = "Repair Form" + action_icon_state = "repair" + cooldown = 15 SECONDS + charge_cost = SIMI_REPAIR_COST + + handles_charge_cost = TRUE + handles_cooldown = TRUE + category = SIMI_PRIMARY_ACTION + ability_tag = SIMI_ABILITY_REPAIR + +/datum/action/human_action/synth_bracer/repair_form/form_call() + if(synth.getBruteLoss() <= 0 && synth.getFireLoss() <= 0) + to_chat(synth, SPAN_WARNING("[synth_bracer.name] beeps, \"No noticeable damage. Procedure cancelled.\"")) + return + + set_active(category, SIMI_ABILITY_REPAIR) + synth.visible_message(SPAN_WARNING("[synth_bracer.name] beeps, \"Engaging the repairing process.\""), SPAN_WARNING("[synth_bracer.name] beeps, \"Beginning to carefully examine your sustained damage.\"")) + playsound(synth.loc, 'sound/mecha/mechmove04.ogg', 25, TRUE) + if(!do_after(synth, 5 SECONDS, INTERRUPT_ALL, BUSY_ICON_FRIENDLY)) + to_chat(synth, SPAN_DANGER("[synth_bracer.name] beeps, \"Repair process was cancelled.\"")) + set_inactive(category) + return + + enter_cooldown() + synth_bracer.drain_charge(synth, charge_cost) + + playsound(synth.loc, 'sound/items/Welder2.ogg', 25, TRUE) + synth.heal_overall_damage(25, 25, TRUE) + synth.pain.recalculate_pain() + synth.visible_message(SPAN_NOTICE("[synth_bracer.name] beeps, \"Completed the repairing process.\"")) + set_inactive(category) diff --git a/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm b/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm new file mode 100644 index 000000000000..dff3e2cc3203 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/utility/motion_detector.dm @@ -0,0 +1,84 @@ +/obj/item/clothing/gloves/synth + var/obj/item/device/motiondetector/integrated/motion_detector + var/motion_detector_active = FALSE + var/motion_detector_recycle = 120 + var/motion_detector_cooldown = 2 + var/motion_detector_cost = 2 + +/obj/item/clothing/gloves/synth/Initialize(mapload, ...) + . = ..() + motion_detector = new(src) + motion_detector.iff_signal = faction + +/obj/item/clothing/gloves/synth/process() + if(!ishuman(loc)) + STOP_PROCESSING(SSobj, src) + return + if(!motion_detector_active) + STOP_PROCESSING(SSobj, src) + return + if(battery_charge <= 1) + motion_detector_active = FALSE + STOP_PROCESSING(SSobj, src) + return + if(motion_detector_active) + motion_detector_recycle-- + if(!motion_detector_recycle) + motion_detector_recycle = initial(motion_detector_recycle) + motion_detector.refresh_blip_pool() + + motion_detector_cooldown-- + if(motion_detector_cooldown) + return + motion_detector_cooldown = initial(motion_detector_cooldown) + motion_detector.scan() + drain_charge(loc, 2, FALSE) + +/obj/item/clothing/gloves/synth/dropped(mob/user) + . = ..() + if(motion_detector && motion_detector_active) + toggle_motion_detector(user) + +/obj/item/clothing/gloves/synth/Destroy() + QDEL_NULL(motion_detector) + . = ..() + +/obj/item/clothing/gloves/synth/proc/toggle_motion_detector(mob/user) + if(!motion_detector) + to_chat(user, SPAN_WARNING("No motion detector located!")) + return FALSE + to_chat(user, SPAN_NOTICE("You [motion_detector_active? "disable" : "enable"] \the [src]'s motion detector.")) + if(COOLDOWN_FINISHED(src, sound_cooldown)) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 35, TRUE) + COOLDOWN_START(src, sound_cooldown, 5 SECONDS) + motion_detector_active = !motion_detector_active + var/datum/action/human_action/synth_bracer/motion_detector/TMD = locate(/datum/action/human_action/synth_bracer/motion_detector) in actions_list_actions + TMD.update_icon() + update_icon() + + if(!motion_detector_active) + STOP_PROCESSING(SSobj, src) + else + START_PROCESSING(SSobj, src) + return TRUE + +/datum/action/human_action/synth_bracer/motion_detector + name = "Toggle Motion Detector" + action_icon_state = "motion_detector" + handles_charge_cost = TRUE + handles_cooldown = TRUE + charge_cost = 2 + human_adaptable = TRUE + +/datum/action/human_action/synth_bracer/motion_detector/action_activate() + ..() + synth_bracer.toggle_motion_detector(synth) + +/datum/action/human_action/synth_bracer/motion_detector/proc/update_icon() + if(!synth_bracer) + return + + if(synth_bracer.motion_detector_active) + button.icon_state = "template_on" + else + button.icon_state = "template" diff --git a/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm b/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm new file mode 100644 index 000000000000..9e61379e2977 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/abilities/utility/rescue_hook.dm @@ -0,0 +1,114 @@ +/datum/action/human_action/activable/synth_bracer/rescue_hook + name = "Rescue Hook" + action_icon_state = "hook" + cooldown = 5 SECONDS + charge_cost = 65 + + handles_cooldown = TRUE + handles_charge_cost = TRUE + + // Config + var/max_distance = 3 + var/windup = 10 + human_adaptable = TRUE + ability_tag = SIMI_SECONDARY_HOOK + +/datum/action/human_action/activable/synth_bracer/rescue_hook/use_ability(atom/atom_target) + . = ..() + if(!.) + return FALSE + + if(!atom_target || atom_target.layer >= FLY_LAYER || !isturf(synth.loc)) + return FALSE + + if(!action_cooldown_check() || synth.action_busy) + return FALSE + + set_active(category, ability_tag) + // Build our turflist + var/list/turf/turflist = list() + var/list/telegraph_atom_list = list() + var/facing = get_dir(synth, atom_target) + var/turf/T = synth.loc + var/turf/temp = synth.loc + for(var/x in 0 to max_distance) + temp = get_step(T, facing) + if(facing in GLOB.diagonals) // check if it goes through corners + var/reverse_face = GLOB.reverse_dir[facing] + var/turf/back_left = get_step(temp, turn(reverse_face, 45)) + var/turf/back_right = get_step(temp, turn(reverse_face, -45)) + if((!back_left || back_left.density) && (!back_right || back_right.density)) + break + if(!temp || temp.density || temp.opacity) + break + + var/blocked = FALSE + for(var/obj/structure/S in temp) + if(S.opacity || ((istype(S, /obj/structure/barricade) || istype(S, /obj/structure/machinery/door)) && S.density)) + blocked = TRUE + break + if(blocked) + break + + T = temp + + if (T in turflist) + break + + turflist += T + facing = get_dir(T, atom_target) + telegraph_atom_list += new /obj/effect/simi_hook(T, windup) + + if(!length(turflist)) + to_chat(synth, SPAN_WARNING("You don't have any room to launch your hook!")) + set_inactive(category) + return FALSE + + synth.visible_message(SPAN_DANGER("[synth] prepares to launch a rescue hook at [atom_target]!"), SPAN_DANGER("You prepare to launch a rescue hook at [atom_target]!")) + + var/throw_target_turf = get_step(synth.loc, facing) + var/pre_frozen = FALSE + if(HAS_TRAIT(synth, TRAIT_IMMOBILIZED)) + pre_frozen = TRUE + else + ADD_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS)) + if(!do_after(synth, windup, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE, null, null, FALSE, 1, FALSE, 1)) + to_chat(synth, SPAN_WARNING("You cancel your launch.")) + + for (var/obj/effect/xenomorph/xeno_telegraph/XT in telegraph_atom_list) + telegraph_atom_list -= XT + qdel(XT) + if(!pre_frozen) + REMOVE_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS)) + set_inactive(category) + + return FALSE + + enter_cooldown() + synth_bracer.drain_charge(synth, charge_cost) + + if(!pre_frozen) + REMOVE_TRAIT(synth, TRAIT_IMMOBILIZED, TRAIT_SOURCE_EQUIPMENT(WEAR_HANDS)) + + playsound(get_turf(synth), 'sound/items/rappel.ogg', 75, FALSE) + + var/mob/living/carbon/human/marine_target + for(var/turf/target_turf in turflist) + for(var/mob/living/carbon/human/marine in target_turf) + marine_target = marine + continue + + if(marine_target) + to_chat(marine_target, SPAN_DANGER("You are pulled towards [synth]!")) + marine_target.KnockDown(0.2) + shake_camera(marine_target, 10, 1) + marine_target.throw_atom(throw_target_turf, get_dist(throw_target_turf, marine_target)-1, SPEED_VERY_FAST) + set_inactive(category) + +/obj/effect/simi_hook + icon = 'icons/obj/items/synth/bracer.dmi' + icon_state = "holo_hook_telegraph_anim" + +/obj/effect/simi_hook/Initialize(mapload, ttl = 1 SECONDS) + . = ..() + QDEL_IN(src, ttl) diff --git a/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm b/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm new file mode 100644 index 000000000000..4bc17ae898bd --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/bracer_subtypes.dm @@ -0,0 +1,52 @@ +/obj/item/clothing/gloves/synth/wy + name = "PK-130C SIMI wrist-mounted computer" + desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication. This one has a corporate-white finish." + + icon_state = "bracer_white" + base_item_slot_state = "bracer_white" + item_state_slots = list( + WEAR_HANDS = "bracer_white" + ) + + bracer_color = SIMI_COLOR_WHITE + faction = FACTION_WY + +/obj/item/clothing/gloves/synth/wy/pmc + faction = FACTION_PMC + +/obj/item/clothing/gloves/synth/wy/pmc/preset + faction = FACTION_PMC + actions_list_added = list( + /datum/action/human_action/synth_bracer/repair_form, + /datum/action/human_action/synth_bracer/motion_detector, + ) + +/obj/item/clothing/gloves/synth/wy/pmc/preset/Initialize() + . = ..() + underglove = new /obj/item/clothing/gloves/marine/veteran/pmc(src) + + var/obj/item/device/simi_chip/motion_detector/new_md = new + var/obj/item/device/simi_chip/repair/new_repair = new + new_md.forceMove(src) + ability_chips += new_md + new_repair.forceMove(src) + ability_chips += new_repair + +/obj/item/clothing/gloves/synth/testing + name = "XPK-140 SIMI wrist-mounted computer" + desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication. This one is highly experimental and seems to be overclocked." + ability_chips_max = 0 + + actions_list_inherent = list( + /datum/action/human_action/synth_bracer/crew_monitor, + /datum/action/human_action/synth_bracer/deploy_binoculars, + /datum/action/human_action/synth_bracer/tactical_map, + ) + //pre-populated list for testing purposes. + actions_list_added = list( + /datum/action/human_action/synth_bracer/repair_form, + /datum/action/human_action/synth_bracer/protective_form, + /datum/action/human_action/synth_bracer/anchor_form, + /datum/action/human_action/activable/synth_bracer/rescue_hook, + /datum/action/human_action/synth_bracer/motion_detector, + ) diff --git a/code/game/objects/items/tools/synth_bracer/synth_bracer.dm b/code/game/objects/items/tools/synth_bracer/synth_bracer.dm new file mode 100644 index 000000000000..f618d55478e4 --- /dev/null +++ b/code/game/objects/items/tools/synth_bracer/synth_bracer.dm @@ -0,0 +1,469 @@ +/obj/item/clothing/gloves/synth + name = "PK-130 SIMI wrist-mounted computer" + desc = "Developed by a joint effort between Weyland-Yutani CIART and the USCM R&D Division, the SIMI portable computer is the ultimate solution for situational awareness, personnel monitoring and communication." + + icon = 'icons/obj/items/synth/bracer.dmi' + icon_state = "bracer_default" + item_icons = list( + WEAR_HANDS = 'icons/mob/humans/onmob/synth/bracer.dmi' + ) + + var/base_item_slot_state = "bracer_default" + item_state_slots = list( + WEAR_HANDS = "bracer_default" + ) + + siemens_coefficient = 0 + permeability_coefficient = 0.05 + flags_cold_protection = BODY_FLAG_HANDS + flags_heat_protection = BODY_FLAG_HANDS + flags_armor_protection = BODY_FLAG_HANDS + flags_inventory = CANTSTRIP + min_cold_protection_temperature = GLOVES_MIN_COLD_PROT + max_heat_protection_temperature = GLOVES_MAX_HEAT_PROT + + armor_melee = CLOTHING_ARMOR_MEDIUM + armor_bullet = CLOTHING_ARMOR_MEDIUM + armor_laser = CLOTHING_ARMOR_MEDIUM + armor_energy = CLOTHING_ARMOR_MEDIUM + armor_bomb = CLOTHING_ARMOR_MEDIUMHIGH + armor_bio = CLOTHING_ARMOR_MEDIUM + armor_rad = CLOTHING_ARMOR_MEDIUM + armor_internaldamage = CLOTHING_ARMOR_MEDIUM + + var/battery_charge = SMARTPACK_MAX_POWER_STORED + var/battery_charge_max = SMARTPACK_MAX_POWER_STORED + var/bracer_charging = FALSE + + var/list/ability_chips = list() + var/ability_chips_max = 2 + + var/list/actions_list_inherent = list( + /datum/action/human_action/synth_bracer/crew_monitor, + /datum/action/human_action/synth_bracer/deploy_binoculars, + /datum/action/human_action/synth_bracer/tactical_map, + ) + var/list/actions_list_added = list() + + var/list/datum/action/human_action/synth_bracer/actions_list_actions = list() + var/active_ability = SIMI_ACTIVE_NONE + var/active_utility = SIMI_ACTIVE_NONE + + /// Faction used by Internal Phone & Crew Monitor + var/faction = FACTION_MARINE + + /// If the bracer is adapted for human use. (No using repair mode etc.) + var/human_adapted = FALSE + + /// Internal Phone + var/obj/structure/transmitter/internal/internal_transmitter + + /// Pair of gloves worn underneath the computer. + var/obj/item/clothing/gloves/underglove + /// Base color of the bracer. (DEFAULT OR WHITE) + var/bracer_color = SIMI_COLOR_DEFAULT + + // Capability states used in FORITIFY mode. + var/saved_melee_allowed = TRUE + var/saved_throw_allowed = TRUE + var/saved_gun_allowed = FALSE + + var/mob/living/carbon/human/wearer + + /// Cooldown on abilities that play sounds (and don't internally handle it) + COOLDOWN_DECLARE(sound_cooldown) + +/obj/item/clothing/gloves/synth/Initialize(mapload, ...) + . = ..() + update_actions() + + internal_transmitter = new(src) + internal_transmitter.relay_obj = src + internal_transmitter.phone_category = "Synth" + internal_transmitter.enabled = FALSE + internal_transmitter.range = 2 + internal_transmitter.networks_receive = list(faction) + internal_transmitter.networks_transmit = list(faction) + RegisterSignal(internal_transmitter, COMSIG_TRANSMITTER_UPDATE_ICON, PROC_REF(check_for_ringing)) + +/obj/item/clothing/gloves/synth/Destroy() + . = ..() + QDEL_NULL_LIST(actions_list_actions) + QDEL_NULL(internal_transmitter) + QDEL_NULL(underglove) + +/obj/item/clothing/gloves/synth/examine(mob/user) + ..() + to_chat(user, SPAN_INFO("The current charge reads [battery_charge]/[battery_charge_max].")) + if(underglove) + to_chat(user, SPAN_INFO("The wrist-strap is attached to [underglove].")) + else + to_chat(user, SPAN_NOTICE("You see a way to attach a pair of gloves to the wrist-strap.")) + +/obj/item/clothing/gloves/synth/equipped(mob/user, slot) + . = ..() + if(slot == WEAR_HANDS) + update_actions(SIMI_ACTIONS_ADD, user) + flick("bracer_[bracer_color]_startup", src) + + if(ishuman(user)) + wearer = user + if(wearer.comm_title) + internal_transmitter.phone_id = "[wearer.comm_title] [wearer]" + else if(wearer.job) + internal_transmitter.phone_id = "[wearer.job] [wearer]" + else + internal_transmitter.phone_id = "[wearer]" + if(wearer.assigned_squad) + internal_transmitter.phone_id += " ([wearer.assigned_squad.name])" + else + internal_transmitter.phone_id = "[user]" + internal_transmitter.enabled = TRUE + + update_icon() + +/obj/item/clothing/gloves/synth/dropped(mob/user) + disable_anchor() + disable_shield() + + update_actions(SIMI_ACTIONS_REMOVE, user) + + if(bracer_charging) + stop_charging(user) + update_icon() + + if(internal_transmitter) + internal_transmitter.phone_id = "[src]" + internal_transmitter.enabled = FALSE + + wearer = null + return ..() + +/obj/item/clothing/gloves/synth/MouseDrop(obj/over_object as obj) + if(CAN_PICKUP(usr, src)) + if(!istype(over_object, /atom/movable/screen)) + return ..() + + if(!usr.is_mob_restrained() && !usr.stat) + switch(over_object.name) + if("r_hand") + if(usr.drop_inv_item_on_ground(src)) + usr.put_in_r_hand(src) + if("l_hand") + if(usr.drop_inv_item_on_ground(src)) + usr.put_in_l_hand(src) + add_fingerprint(usr) + +/obj/item/clothing/gloves/synth/attackby(obj/item/attacker, mob/living/carbon/human/user) + if((istype(attacker, /obj/item/clothing/gloves)) && !(attacker.flags_item & ITEM_PREDATOR)) + if(underglove) + to_chat(user, SPAN_WARNING("[src] is already attached to [underglove], remove them first.")) + return + underglove = attacker + user.drop_inv_item_to_loc(attacker, src) + to_chat(user, SPAN_NOTICE("You attach the [attacker] to the bracer's wrist-strap.")) + user.update_inv_gloves() + if(internal_transmitter.attached_to == attacker) + internal_transmitter.attackby(attacker, user) + return + + if(istype(attacker, /obj/item/device/simi_chip)) + var/obj/item/device/simi_chip/new_chip = attacker + var/chips_num = 0 + for(var/obj/item/device/simi_chip/chip in ability_chips) + if(chip.chip_action == new_chip.chip_action) + to_chat(user, SPAN_WARNING("[src] already has this circuit chip!")) + return + if(!chip.secret) + chips_num++ + if(chips_num >= ability_chips_max) + to_chat(user, SPAN_WARNING("[src] can't hold another circuit chip!")) + return + if(user.drop_held_item()) + new_chip.forceMove(src) + ability_chips += new_chip + to_chat(user, SPAN_NOTICE("You slot [new_chip] into [src]!")) + playsound(src, 'sound/machines/terminal_processing.ogg', 15, TRUE) + if(user.gloves && (user.gloves == src)) + update_actions(SIMI_ACTIONS_RELOAD, user) + else + update_actions(SIMI_ACTIONS_RELOAD) + return + + if(HAS_TRAIT(attacker, TRAIT_TOOL_SCREWDRIVER)) + //Remove ability chip - give option or remove all? + var/turf/T = get_turf(user) + if(!T) + to_chat(user, "You cannot do that here.") + return + + var/removed_chips = FALSE + for (var/obj/item/device/simi_chip/chip in ability_chips) + if(chip.secret) + continue + chip.forceMove(T) + ability_chips -= chip + removed_chips = TRUE + if(removed_chips) + if(user.gloves && (user.gloves == src)) + update_actions(SIMI_ACTIONS_RELOAD, user) + else + update_actions(SIMI_ACTIONS_RELOAD) + to_chat(user, SPAN_NOTICE("You pop out the circuit chips from [src]!")) + else + to_chat(user, SPAN_NOTICE("There are no removable circuit chips in [src]!")) + return + return ..() + +/obj/item/clothing/gloves/synth/attack_hand(mob/living/carbon/human/user) + if(istype(user) && user.gloves == src) + internal_transmitter.attack_hand(user) + return + return ..() + +/obj/item/clothing/gloves/synth/forceMove(atom/dest) + . = ..() + if(isturf(dest)) + internal_transmitter.set_tether_holder(src) + else + internal_transmitter.set_tether_holder(loc) + +/obj/item/clothing/gloves/synth/proc/set_active(category = SIMI_SECONDARY_ACTION, set_ability = SIMI_ACTIVE_NONE) + switch(category) + if(SIMI_PRIMARY_ACTION) + active_ability = set_ability + if(SIMI_SECONDARY_ACTION) + active_utility = set_ability + if((active_ability == SIMI_ACTIVE_NONE) && (active_utility == SIMI_ACTIVE_NONE)) + flags_item &= ~NODROP + else + flags_item |= NODROP + update_icon() + +/obj/item/clothing/gloves/synth/proc/set_inactive(category = SIMI_SECONDARY_ACTION) + set_active(category, SIMI_ACTIVE_NONE) + +//############################# +//###### ICON HANDLING ######## +//############################# +/obj/item/clothing/gloves/synth/update_icon() + var/mob/living/carbon/human/wearer = loc + if(!istype(wearer) || wearer.gloves != src) + overlays.Cut() + icon_state = "bracer_[bracer_color]" + return + + icon_state = "bracer_[bracer_color]_blank" + + update_overlays() + +/obj/item/clothing/gloves/synth/proc/get_bracer_status() + if(battery_charge <= 0) + internal_transmitter.enabled = FALSE + return SIMI_STATUS_NOPOWER + if(battery_charge <= battery_charge_max * 0.1) + return SIMI_STATUS_LOWPOWER + var/mob/living/carbon/human/wearer = loc + if(!issynth(wearer) && !human_adapted) + internal_transmitter.enabled = FALSE + return SIMI_STATUS_NOACCESS + internal_transmitter.enabled = TRUE + return SIMI_STATUS_IDLE + +/obj/item/clothing/gloves/synth/proc/update_overlays() + overlays.Cut() + + var/image/idle_image = image(icon, src, SIMI_STATUS_IDLE) + idle_image.appearance_flags = RESET_COLOR|KEEP_APART + var/current_status = get_bracer_status() + var/image/status_image + if(current_status != SIMI_STATUS_IDLE) + status_image = image(icon, src, current_status) + status_image.appearance_flags = RESET_COLOR|KEEP_APART + + var/phone_status + if(internal_transmitter && internal_transmitter.attached_to) + if(internal_transmitter.do_not_disturb >= PHONE_DND_ON) + phone_status = "dnd" + else if(internal_transmitter.attached_to.loc != internal_transmitter) + phone_status = "listening" + else if(internal_transmitter.caller) + phone_status = "ringing" + + var/image/phone_image = image(icon, src, "phone_[phone_status]") + phone_image.appearance_flags = RESET_COLOR|KEEP_APART + + var/image/secondary_image = image(icon, src, "secondary_[active_utility]") + secondary_image.appearance_flags = RESET_COLOR|KEEP_APART + + var/image/primary_image = image(icon, src, "primary_[active_ability]") + primary_image.appearance_flags = RESET_COLOR|KEEP_APART + + if(motion_detector_active) + var/image/motion_image = image(icon, src, "motion_active") + motion_image.appearance_flags = RESET_COLOR|KEEP_APART + overlays += motion_image + + overlays += idle_image + overlays += phone_image + overlays += secondary_image + overlays += primary_image + overlays += status_image + + +/obj/item/clothing/gloves/synth/proc/check_for_ringing() + SIGNAL_HANDLER + update_overlays() + +/obj/item/clothing/gloves/synth/get_mob_overlay(mob/user_mob, slot) + var/image/overlay = ..() + + if((slot != WEAR_HANDS) || !underglove) + return overlay + + overlay = underglove.get_mob_overlay(user_mob, slot) + + var/image/bracer_img = overlay_image('icons/mob/humans/onmob/synth/bracer.dmi', get_icon_state(user_mob, slot), null, RESET_COLOR|NO_CLIENT_COLOR) + overlay.overlays += bracer_img + + return overlay + +/obj/item/clothing/gloves/synth/verb/swap_hands() + set name = "Swap Hands" + set src in usr + + if(base_item_slot_state == "bracer_[bracer_color]") + base_item_slot_state = "bracer_[bracer_color]_r" + else + base_item_slot_state = "bracer_[bracer_color]" + item_state_slots[WEAR_HANDS] = base_item_slot_state + + to_chat(usr, SPAN_NOTICE("You shift \the [src] over to your [base_item_slot_state == "bracer_[bracer_color]" ? "left arm" : "right arm"].")) + usr.update_inv_gloves() + +/obj/item/clothing/gloves/synth/verb/remove_gloves() + set name = "Remove Gloves" + set src in usr + + if(!underglove) + return FALSE + + to_chat(usr, SPAN_NOTICE("You remove [underglove] from the wrist-strap.")) + underglove.forceMove(get_turf(usr)) + underglove = null + + usr.update_inv_gloves() + +//############################# +//######## CHARGING ########### +//############################# +/obj/item/clothing/gloves/synth/proc/handle_apc_charge(mob/living/carbon/human/user, obj/structure/machinery/power/apc/apc) + if(!istype(user)) + return FALSE + + if(!(user.species.flags & IS_SYNTHETIC) || user.a_intent != INTENT_GRAB) + return FALSE + + if(user.action_busy) + return FALSE + + INVOKE_ASYNC(src, PROC_REF(complete_apc_charge), user, apc) + +/obj/item/clothing/gloves/synth/proc/complete_apc_charge(mob/living/carbon/human/user, obj/structure/machinery/power/apc/apc) + start_charging(user) + + if(!do_after(user, 6 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + stop_charging(user) + return + if(!user.Adjacent(apc) || (user.gloves != src)) + stop_charging(user) + return + + playsound(apc.loc, 'sound/effects/sparks2.ogg', 25, 1) + + if(apc.stat & BROKEN) + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(3, 1, apc) + s.start() + to_chat(user, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) + user.apply_damage(10, 0, BURN) + else if(apc.cell?.charge > 0) + if(battery_charge < battery_charge_max) + var/charge_to_use = min(apc.cell.charge, battery_charge_max - battery_charge) + if(!(apc.cell.use(charge_to_use))) + stop_charging(user) + return + battery_charge += charge_to_use + to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. \The [src] now has [battery_charge]/[battery_charge_max].")) + apc.charging = 1 //APC_CHARGING + else + to_chat(user, SPAN_WARNING("\The [src] is already fully charged.")) + else + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + stop_charging(user) + +/obj/item/clothing/gloves/synth/proc/start_charging(mob/user) + bracer_charging = TRUE + item_state_slots[WEAR_HANDS] += "_charging" + + var/image/charge_image = image(icon, src, SIMI_STATUS_CHARGING) + charge_image.appearance_flags = RESET_COLOR|KEEP_APART + overlays += charge_image + + user.update_inv_gloves() + +/obj/item/clothing/gloves/synth/proc/stop_charging(mob/user) + bracer_charging = FALSE + item_state_slots[WEAR_HANDS] = base_item_slot_state + update_icon() + user.update_inv_gloves() + +/obj/item/clothing/gloves/synth/proc/drain_charge(mob/user, cost, report_charge = TRUE) + battery_charge = max(0, battery_charge -= cost) + if(report_charge) + to_chat(user, SPAN_WARNING("\The [src]'s charge now reads: [battery_charge]/[battery_charge_max].")) + update_icon() + +//############################# +//##### ACTION HANDLING ####### +//############################# +/obj/item/clothing/gloves/synth/proc/update_actions(mode = SIMI_ACTIONS_LOAD, mob/user) + if((!user) && ((mode != SIMI_ACTIONS_LOAD) && (mode != SIMI_ACTIONS_RELOAD))) + return FALSE + + switch(mode) + if(SIMI_ACTIONS_LOAD) + for(var/action_type in actions_list_inherent) + actions_list_actions += new action_type + for(var/action_type in actions_list_added) + actions_list_actions += new action_type + + if(SIMI_ACTIONS_RELOAD) + actions_list_added.Cut() + for(var/obj/item/device/simi_chip/chip in ability_chips) + actions_list_added += chip.chip_action + if(user) + for(var/datum/action/human_action/action as anything in actions_list_actions) + action.remove_from(user) + for(var/datum/action/human_action/action in actions_list_actions) + actions_list_actions -= action + qdel(action) + update_actions(SIMI_ACTIONS_LOAD) + if(user) + for(var/datum/action/human_action/action as anything in actions_list_actions) + action.give_to(user) + + if(SIMI_ACTIONS_ADD) + for(var/datum/action/human_action/action as anything in actions_list_actions) + action.remove_from(user) + for(var/datum/action/human_action/action as anything in actions_list_actions) + action.give_to(user) + + if(SIMI_ACTIONS_REMOVE) + for(var/datum/action/human_action/action as anything in actions_list_actions) + action.remove_from(user) + else + return FALSE + return TRUE + + diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 2e02be02b8f3..60a09cddb49c 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -273,3 +273,6 @@ new /obj/item/inflatable(src) new /obj/item/inflatable(src) new /obj/item/inflatable(src) + +/obj/item/storage/briefcase/inflatable/small + w_class = SIZE_MEDIUM diff --git a/code/game/objects/structures/pipes/vents/vents.dm b/code/game/objects/structures/pipes/vents/vents.dm index d7e090c581c5..f93314ca9e44 100644 --- a/code/game/objects/structures/pipes/vents/vents.dm +++ b/code/game/objects/structures/pipes/vents/vents.dm @@ -180,5 +180,5 @@ if(!gas_holder || welded) return FALSE playsound(loc, 'sound/effects/smoke.ogg', 25, 1, 4) - gas_holder.set_up(radius, 0, get_turf(src), null, 10 SECONDS) + gas_holder.set_up(radius, 0, get_turf(src), null, 20) gas_holder.start() diff --git a/code/game/turfs/floor_types.dm b/code/game/turfs/floor_types.dm index 096b39e988d2..6002821c5c18 100644 --- a/code/game/turfs/floor_types.dm +++ b/code/game/turfs/floor_types.dm @@ -944,6 +944,45 @@ /turf/open/floor/almayer/aicore/no_build/ai_plates icon_state = "ai_plates" +/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3 + icon_state = "ai_floor3" + +/turf/open/floor/almayer/aicore/no_build/white/ai_plates + icon_state = "w_ai_plates" + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver + icon_state = "w_ai_silver" + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/southwest + dir = SOUTHWEST + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north + dir = NORTH + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/east + dir = EAST + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/northeast + dir = NORTHEAST + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/southeast + dir = SOUTHEAST + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/west + dir = WEST + +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/northwest + dir = NORTHWEST + +/turf/open/floor/almayer/aicore/no_build/white/ai_cargo + icon_state = "w_ai_cargo" + +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1 + icon_state = "w_ai_floor1" + +/turf/open/floor/almayer/no_build/test_floor4 + icon_state = "test_floor4" + /turf/open/floor/almayer/aicore/glowing/no_build allow_construction = FALSE hull_floor = TRUE @@ -955,6 +994,9 @@ /turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3 icon_state = "ai_floor3" +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3 + icon_state = "w_ai_floor3" + // RESEARCH STUFF /turf/open/floor/almayer/research/containment/entrance icon_state = "containment_entrance" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index dd0d406560ab..4a6678a988bd 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -667,7 +667,7 @@ GLOBAL_LIST_INIT(bgstate_options, list( * * width - Screen' width. * * height - Screen's height. */ -/datum/preferences/proc/SetChoices(mob/user, limit = 21, list/splitJobs = list(JOB_CHIEF_REQUISITION, JOB_WO_CMO), width = 950, height = 750) +/datum/preferences/proc/SetChoices(mob/user, limit = 21, list/splitJobs = list(JOB_AI_TECH, JOB_WO_CMO), width = 950, height = 750) if(!GLOB.RoleAuthority) return @@ -690,6 +690,8 @@ GLOBAL_LIST_INIT(bgstate_options, list( if(!job) debug_log("Missing job for prefs: [role_name]") continue + if(job.flags_startup_parameters & ROLE_HIDDEN) + continue index++ if((index >= limit) || (job.title in splitJobs)) HTML += "" @@ -785,7 +787,7 @@ GLOBAL_LIST_INIT(bgstate_options, list( * * width - Screen' width. * * height - Screen's height. */ -/datum/preferences/proc/set_job_slots(mob/user, limit = 21, list/splitJobs = list(JOB_CHIEF_REQUISITION, JOB_WO_CMO), width = 950, height = 750) +/datum/preferences/proc/set_job_slots(mob/user, limit = 21, list/splitJobs = list(JOB_AI_TECH, JOB_WO_CMO), width = 950, height = 750) if(!GLOB.RoleAuthority) return @@ -808,6 +810,8 @@ GLOBAL_LIST_INIT(bgstate_options, list( if(!job) debug_log("Missing job for prefs: [role_name]") continue + if(job.flags_startup_parameters & ROLE_HIDDEN) + continue index++ if((index >= limit) || (job.title in splitJobs)) HTML += "
" diff --git a/code/modules/cm_marines/marines_consoles.dm b/code/modules/cm_marines/marines_consoles.dm index 778f3f4f18bf..325a6e72a5a4 100644 --- a/code/modules/cm_marines/marines_consoles.dm +++ b/code/modules/cm_marines/marines_consoles.dm @@ -961,6 +961,7 @@ GLOBAL_LIST_EMPTY_TYPED(crewmonitor, /datum/crewmonitor) JOB_SURGEON = 42, JOB_NURSE = 43, // 50-59: Engineering + JOB_AI_TECH = 50, JOB_CHIEF_ENGINEER = 50, JOB_ORDNANCE_TECH = 51, JOB_MAINT_TECH = 52, diff --git a/code/modules/gear_presets/pmc.dm b/code/modules/gear_presets/pmc.dm index 60f25442f04e..69d326203921 100644 --- a/code/modules/gear_presets/pmc.dm +++ b/code/modules/gear_presets/pmc.dm @@ -1899,10 +1899,10 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null), new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/experimental_mesons, WEAR_EYES) new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/pmc, WEAR_FACE) - new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/veteran/pmc, WEAR_HANDS) + new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/synth/wy/pmc/preset, WEAR_HANDS) new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/veteran/pmc/knife, WEAR_FEET) - new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/smartpack/white, WEAR_BACK) + new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/lightpack, WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/roller, WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/roller/surgical, WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/tool/extinguisher/mini, WEAR_IN_BACK) @@ -1926,9 +1926,10 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null), /datum/equipment_preset/pmc/synth/get_antag_clothing_equipment() return list( list("STANDARD EQUIPMENT (TAKE ALL)", 0, null, null, null), + list("PK-130 SIMI wrist-mounted computer", 0, /obj/item/clothing/gloves/synth/wy/pmc, MARINE_CAN_BUY_ATTACHMENT, VENDOR_ITEM_MANDATORY), + list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/pmc, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Boots", 0, /obj/item/clothing/shoes/veteran/pmc/knife, MARINE_CAN_BUY_SHOES, VENDOR_ITEM_MANDATORY), list("Fatigues", 0, /obj/item/clothing/under/marine/veteran/pmc, MARINE_CAN_BUY_UNIFORM, VENDOR_ITEM_MANDATORY), - list("Gloves", 0, /obj/item/clothing/gloves/marine/veteran/pmc, MARINE_CAN_BUY_GLOVES, VENDOR_ITEM_MANDATORY), list("Headset", 0, /obj/item/device/radio/headset/distress/pmc/hvh, MARINE_CAN_BUY_EAR, VENDOR_ITEM_MANDATORY), list("MRE", 0, /obj/item/storage/box/MRE, MARINE_CAN_BUY_MRE, VENDOR_ITEM_MANDATORY), list("Armored Balaclava", 0, /obj/item/clothing/mask/gas/pmc, MARINE_CAN_BUY_MASK, VENDOR_ITEM_MANDATORY), @@ -1946,11 +1947,6 @@ list("POUCHES (CHOOSE 2)", 0, null, null, null), list("Drop Pouch", 0, /obj/item/clothing/accessory/storage/droppouch, MARINE_CAN_BUY_ACCESSORY, VENDOR_ITEM_REGULAR), list("BACKPACK (CHOOSE 1)", 0, null, null, null), - list("Smartpack, Blue", 0, /obj/item/storage/backpack/marine/smartpack, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Green", 0, /obj/item/storage/backpack/marine/smartpack/green, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Tan", 0, /obj/item/storage/backpack/marine/smartpack/tan, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, White", 0, /obj/item/storage/backpack/marine/smartpack/white, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), - list("Smartpack, Black", 0, /obj/item/storage/backpack/marine/smartpack/black, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), list("Logistics IMP Backpack", 0, /obj/item/storage/backpack/marine/satchel/big, MARINE_CAN_BUY_BACKPACK, VENDOR_ITEM_REGULAR), list("BELT (CHOOSE 1)", 0, null, null, null), diff --git a/code/modules/gear_presets/synths.dm b/code/modules/gear_presets/synths.dm index db82e44ea890..73ab2af124da 100644 --- a/code/modules/gear_presets/synths.dm +++ b/code/modules/gear_presets/synths.dm @@ -571,7 +571,7 @@ name = "Synthetic - Working Joe" flags = EQUIPMENT_PRESET_START_OF_ROUND|EQUIPMENT_PRESET_MARINE faction = FACTION_MARINE - faction_group = list(FACTION_MARINE) + faction_group = FACTION_LIST_ARES_MARINE assignment = JOB_WORKING_JOE rank = JOB_WORKING_JOE skills = /datum/skills/working_joe @@ -613,12 +613,12 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/sling(new_human), WEAR_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/device/working_joe_pda(new_human.back), WEAR_IN_L_STORE) new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/construction(new_human), WEAR_R_STORE) - new_human.equip_to_slot_or_del(new /obj/item/reagent_container/spray/cleaner(new_human.back), WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/device/defibrillator/synthetic/one_shot(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/reagent_container/spray/cleaner(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/reagent_container/glass/bucket(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/tool/mop(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/tool/wet_sign(new_human.back), WEAR_IN_BACK) - new_human.equip_to_slot_or_del(new /obj/item/storage/box/lights/mixed(new_human.back), WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/reagent_container/spray/cleaner(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/storage/bag/trash(new_human), WEAR_L_HAND) new_human.equip_to_slot_or_del(new /obj/item/clothing/accessory/storage/droppouch(new_human), WEAR_ACCESSORY) new_human.equip_to_slot_or_del(new /obj/item/circuitboard/apc(new_human.back), WEAR_IN_ACCESSORY) @@ -640,11 +640,9 @@ new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/marine/satchel(new_human), WEAR_BACK) new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/mt(new_human), WEAR_L_EAR) new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/marine/joe(new_human), WEAR_HANDS) - new_human.equip_to_slot_or_del(new /obj/item/inflatable/door(new_human), WEAR_IN_BACK) - new_human.equip_to_slot_or_del(new /obj/item/inflatable/door(new_human), WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/device/defibrillator/synthetic/one_shot(new_human.back), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/tool/weldingtool/hugetank, WEAR_IN_BACK) - new_human.equip_to_slot_or_del(new /obj/item/inflatable(new_human), WEAR_IN_BACK) - new_human.equip_to_slot_or_del(new /obj/item/inflatable(new_human), WEAR_IN_BACK) + new_human.equip_to_slot_or_del(new /obj/item/storage/briefcase/inflatable/small(new_human), WEAR_IN_BACK) new_human.equip_to_slot_or_del(new /obj/item/tool/extinguisher(new_human), WEAR_L_HAND) new_human.equip_to_slot_or_del(new /obj/item/maintenance_jack(new_human), WEAR_J_STORE) diff --git a/code/modules/gear_presets/uscm_event.dm b/code/modules/gear_presets/uscm_event.dm index 9ef15ff955ae..57ca39bb1057 100644 --- a/code/modules/gear_presets/uscm_event.dm +++ b/code/modules/gear_presets/uscm_event.dm @@ -516,3 +516,79 @@ /*****************************************************************************************************/ +/datum/equipment_preset/uscm_event/ai_tech + name = "AI Technician (USCM)" + flags = EQUIPMENT_PRESET_EXTRA + faction = FACTION_MARINE + faction_group = FACTION_LIST_ARES_MARINE + assignment = JOB_AI_TECH + rank = JOB_AI_TECH + paygrades = list(PAY_SHORT_MO1 = JOB_PLAYTIME_TIER_0, PAY_SHORT_MO2 = JOB_PLAYTIME_TIER_1, PAY_SHORT_MO3 = JOB_PLAYTIME_TIER_3) + role_comm_title = "AIST" + skills = /datum/skills/CE + languages = list(LANGUAGE_ENGLISH, LANGUAGE_RUSSIAN, LANGUAGE_JAPANESE, LANGUAGE_GERMAN, LANGUAGE_SPANISH, LANGUAGE_CHINESE) + idtype = /obj/item/card/id/silver + access = list( + ACCESS_MARINE_SENIOR, + ACCESS_MARINE_CE, + ACCESS_MARINE_ENGINEERING, + ACCESS_MARINE_COMMAND, + ACCESS_CIVILIAN_ENGINEERING, + ACCESS_MARINE_DATABASE, + ACCESS_MARINE_MAINT, + ACCESS_MARINE_OT, + ACCESS_MARINE_SYNTH, + ACCESS_MARINE_AI, + ACCESS_ARES_DEBUG, + ) + +/datum/equipment_preset/uscm_event/ai_tech/load_vanity(mob/living/carbon/human/new_human) + new_human.mind.store_memory("ARES Interface Code: [GLOB.ares_link.code_interface]
APOLLO Interface Code: [GLOB.ares_link.code_apollo]") + return + +/datum/equipment_preset/uscm_event/ai_tech/load_gear(mob/living/carbon/human/new_human) + new_human.equip_to_slot_or_del(new /obj/item/clothing/under/marine/dress(new_human), WEAR_BODY) + new_human.equip_to_slot_or_del(new /obj/item/clothing/glasses/welding(new_human), WEAR_EYES) + new_human.equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow(new_human), WEAR_HANDS) + + new_human.equip_to_slot_or_del(new /obj/item/clothing/accessory/storage/holster(new_human), WEAR_ACCESSORY) + new_human.equip_to_slot_or_del(new /obj/item/weapon/gun/revolver/m44/custom/pkd_special(new_human.back), WEAR_IN_ACCESSORY) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/revolver/pkd(new_human.back), WEAR_IN_ACCESSORY) + new_human.equip_to_slot_or_del(new /obj/item/ammo_magazine/revolver/pkd(new_human.back), WEAR_IN_ACCESSORY) + + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/marine/knife(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/lockable(new_human), WEAR_BACK) + new_human.equip_to_slot_or_del(new /obj/item/storage/belt/utility/full(new_human), WEAR_WAIST) + + new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/hazardvest/black(new_human), WEAR_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/device/flash(new_human), WEAR_IN_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(new_human), WEAR_IN_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/device/flashlight(new_human), WEAR_J_STORE) + + new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/mcom/cdrcom/aist(new_human), WEAR_L_EAR) + + new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/sling(new_human), WEAR_L_STORE) + new_human.equip_to_slot_or_del(new /obj/item/device/ai_tech_pda(new_human.back), WEAR_IN_L_STORE) + + new_human.equip_to_slot_or_del(new /obj/item/storage/pouch/firstaid/ert(new_human), WEAR_R_STORE) + +/datum/equipment_preset/uscm_event/ai_tech/corporate + name = "AI Technician (Contractor)" + faction_group = FACTION_LIST_ARES_ALL + paygrades = list(PAY_SHORT_WYC4 = JOB_PLAYTIME_TIER_0, PAY_SHORT_WYC5 = JOB_PLAYTIME_TIER_1, PAY_SHORT_WYC6 = JOB_PLAYTIME_TIER_3) + + idtype = /obj/item/card/id/silver/cl + +/datum/equipment_preset/uscm_event/ai_tech/corporate/New() + . = ..() + /// WY version gets less access, but can use the CLs office. + access = get_access(ACCESS_LIST_MARINE_LIAISON_AIST) + +/datum/equipment_preset/uscm_event/ai_tech/corporate/load_gear(mob/living/carbon/human/new_human) + new_human.equip_to_slot_or_del(new /obj/item/clothing/under/liaison_suit/blue(new_human), WEAR_BODY) + new_human.equip_to_slot_or_del(new /obj/item/clothing/shoes/veteran/pmc/knife(new_human), WEAR_FEET) + new_human.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/hazardvest(new_human), WEAR_JACKET) + new_human.equip_to_slot_or_del(new /obj/item/device/radio/headset/almayer/mcl/aist(new_human), WEAR_L_EAR) + + + ..() diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 944d54d16106..983c3173c75f 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -22,7 +22,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( ":o" = RADIO_CHANNEL_COLONY, ".o" = RADIO_CHANNEL_COLONY, "#o" = RADIO_CHANNEL_PMC_CCT, ":z" = RADIO_CHANNEL_HIGHCOM, ".z" = RADIO_CHANNEL_HIGHCOM, "#z" = RADIO_CHANNEL_PMC_CMD, ":k" = SQUAD_SOF, ".k" = SQUAD_SOF, "#k" = RADIO_CHANNEL_WY_WO, - ":q" = RADIO_CHANNEL_ROYAL_MARINE, ".q" = RADIO_CHANNEL_ROYAL_MARINE, + ":q" = RADIO_CHANNEL_AICORE, ".q" = RADIO_CHANNEL_AICORE, "#q" = RADIO_CHANNEL_ROYAL_MARINE, ":r" = RADIO_CHANNEL_PROVOST, ".r" = RADIO_CHANNEL_PROVOST, "#r" = RADIO_CHANNEL_PROVOST, ":I" = RADIO_CHANNEL_INTERCOM, ".I" = RADIO_CHANNEL_INTERCOM, "#I" = RADIO_CHANNEL_INTERCOM, @@ -47,7 +47,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( ":O" = RADIO_CHANNEL_COLONY, ".O" = RADIO_CHANNEL_COLONY, "#O" = RADIO_CHANNEL_PMC_CCT, ":Z" = RADIO_CHANNEL_HIGHCOM, ".Z" = RADIO_CHANNEL_HIGHCOM, "#Z" = RADIO_CHANNEL_PMC_CMD, ":K" = SQUAD_SOF, ".K" = SQUAD_SOF, "#K" = RADIO_CHANNEL_WY_WO, - ":Q" = RADIO_CHANNEL_ROYAL_MARINE, ".Q" = RADIO_CHANNEL_ROYAL_MARINE, + ":Q" = RADIO_CHANNEL_AICORE, ".Q" = RADIO_CHANNEL_AICORE, "#Q" = RADIO_CHANNEL_ROYAL_MARINE, ":R" = RADIO_CHANNEL_PROVOST, ".R" = RADIO_CHANNEL_PROVOST, "#R" = RADIO_CHANNEL_PROVOST, )) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index c11d07d64a23..a2d35d611d3c 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -324,6 +324,10 @@ if(JOB_PREDATOR) var/datum/job/J = GLOB.RoleAuthority.roles_by_name[JOB_PREDATOR] return J.gear_preset_whitelist["[JOB_PREDATOR][J.get_whitelist_status(owner)]"] + if(JOB_AI_TECH) + var/datum/job/aist_job = GLOB.RoleAuthority.roles_by_name[JOB_AI_TECH] + return aist_job.gear_preset + return /datum/equipment_preset/uscm/private_equipped diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 8ff67fa4b91c..f237329dcc7b 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -819,38 +819,46 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( if(grabber.a_intent == INTENT_GRAB) //Synthpack recharge - if((grabber.species.flags & IS_SYNTHETIC) && istype(grabber.back, /obj/item/storage/backpack/marine/smartpack)) - var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back - if(grabber.action_busy) - return - - if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + if((grabber.species.flags & IS_SYNTHETIC)) + if(istype(grabber.gloves, /obj/item/clothing/gloves/synth)) + var/obj/item/clothing/gloves/synth/bracer = grabber.gloves + bracer.handle_apc_charge(grabber, src) return - playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + if(istype(grabber.back, /obj/item/storage/backpack/marine/smartpack)) + var/obj/item/storage/backpack/marine/smartpack/s_pack = grabber.back + if(grabber.action_busy) + return - if(stat & BROKEN) - var/datum/effect_system/spark_spread/spark = new() - spark.set_up(3, 1, src) - spark.start() - to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) - grabber.apply_damage(10,0, BURN) - else if(cell && cell.charge > 0) - if(!istype(s_pack)) + if(!do_after(grabber, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + if(!grabber.Adjacent(src) || (grabber.back != s_pack)) return - if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED) - var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge) - if(!(cell.use(charge_to_use))) + playsound(src.loc, 'sound/effects/sparks2.ogg', 25, 1) + + if(stat & BROKEN) + var/datum/effect_system/spark_spread/spark = new() + spark.set_up(3, 1, src) + spark.start() + to_chat(grabber, SPAN_DANGER("The APC's power currents surge eratically, damaging your chassis!")) + grabber.apply_damage(10,0, BURN) + else if(cell && cell.charge > 0) + if(!istype(s_pack)) return - s_pack.battery_charge += charge_to_use - to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) - charging = APC_CHARGING + + if(s_pack.battery_charge < SMARTPACK_MAX_POWER_STORED) + var/charge_to_use = min(cell.charge, SMARTPACK_MAX_POWER_STORED - s_pack.battery_charge) + if(!(cell.use(charge_to_use))) + return + s_pack.battery_charge += charge_to_use + to_chat(user, SPAN_NOTICE("You slot your fingers into the APC interface and siphon off some of the stored charge. [s_pack.name] now has [s_pack.battery_charge]/[SMARTPACK_MAX_POWER_STORED]")) + charging = APC_CHARGING + else + to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged.")) else - to_chat(user, SPAN_WARNING("[s_pack.name] is already fully charged.")) - else - to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) - return + to_chat(user, SPAN_WARNING("There is no charge to draw from that APC.")) + return // Yautja Bracer Recharge var/obj/item/clothing/gloves/yautja/bracer = grabber.gloves diff --git a/code/modules/projectiles/guns/smartgun.dm b/code/modules/projectiles/guns/smartgun.dm index b2d228e27a26..d101f6cb0c75 100644 --- a/code/modules/projectiles/guns/smartgun.dm +++ b/code/modules/projectiles/guns/smartgun.dm @@ -46,7 +46,7 @@ var/range = 7 var/angle = 2 var/list/angle_list = list(180,135,90,60,30) - var/obj/item/device/motiondetector/sg/MD + var/obj/item/device/motiondetector/integrated/MD var/long_range_cooldown = 2 var/recycletime = 120 var/cover_open = FALSE diff --git a/colonialmarines.dme b/colonialmarines.dme index 48996a93ec30..361793596f82 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -894,9 +894,11 @@ #include "code\game\machinery\ARES\ARES_interface.dm" #include "code\game\machinery\ARES\ARES_interface_admin.dm" #include "code\game\machinery\ARES\ARES_interface_apollo.dm" +#include "code\game\machinery\ARES\ARES_interface_data.dm" #include "code\game\machinery\ARES\ARES_procs.dm" #include "code\game\machinery\ARES\ARES_records.dm" #include "code\game\machinery\ARES\ARES_step_triggers.dm" +#include "code\game\machinery\ARES\debug_pda.dm" #include "code\game\machinery\atmoalter\canister.dm" #include "code\game\machinery\atmoalter\meter.dm" #include "code\game\machinery\atmoalter\portable_atmospherics.dm" @@ -1259,6 +1261,19 @@ #include "code\game\objects\items\tools\misc_tools.dm" #include "code\game\objects\items\tools\shovel_tools.dm" #include "code\game\objects\items\tools\surgery_tools.dm" +#include "code\game\objects\items\tools\synth_bracer\_defines.dm" +#include "code\game\objects\items\tools\synth_bracer\bracer_subtypes.dm" +#include "code\game\objects\items\tools\synth_bracer\synth_bracer.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\chips.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\framework.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\crew_monitor.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\ocular_designator.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\integrated\tactical_map.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\primary\anchor_form.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\primary\protect_form.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\primary\repair_form.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\utility\motion_detector.dm" +#include "code\game\objects\items\tools\synth_bracer\abilities\utility\rescue_hook.dm" #include "code\game\objects\items\toys\cards.dm" #include "code\game\objects\items\toys\crayons.dm" #include "code\game\objects\items\toys\toy_weapons.dm" diff --git a/icons/landmarks.dmi b/icons/landmarks.dmi index 32fe9e0790a6..444b8bd6ab13 100644 Binary files a/icons/landmarks.dmi and b/icons/landmarks.dmi differ diff --git a/icons/mob/hud/marine_hud.dmi b/icons/mob/hud/marine_hud.dmi index 8be1ae31ba68..64785ea365ae 100644 Binary files a/icons/mob/hud/marine_hud.dmi and b/icons/mob/hud/marine_hud.dmi differ diff --git a/icons/mob/hud/sec_hud.dmi b/icons/mob/hud/sec_hud.dmi index 493727afac1b..22d8ae9f51b8 100644 Binary files a/icons/mob/hud/sec_hud.dmi and b/icons/mob/hud/sec_hud.dmi differ diff --git a/icons/mob/humans/onmob/synth/bracer.dmi b/icons/mob/humans/onmob/synth/bracer.dmi new file mode 100644 index 000000000000..7016738afd67 Binary files /dev/null and b/icons/mob/humans/onmob/synth/bracer.dmi differ diff --git a/icons/obj/items/clothing/belts.dmi b/icons/obj/items/clothing/belts.dmi index 80070b88b560..d153b88fce4e 100644 Binary files a/icons/obj/items/clothing/belts.dmi and b/icons/obj/items/clothing/belts.dmi differ diff --git a/icons/obj/items/experimental_tools.dmi b/icons/obj/items/experimental_tools.dmi index d490d78c7ffa..d630484f5058 100644 Binary files a/icons/obj/items/experimental_tools.dmi and b/icons/obj/items/experimental_tools.dmi differ diff --git a/icons/obj/items/radio.dmi b/icons/obj/items/radio.dmi index 6352a14baef0..8f3c74e15f0c 100644 Binary files a/icons/obj/items/radio.dmi and b/icons/obj/items/radio.dmi differ diff --git a/icons/obj/items/synth/ait_pda.dmi b/icons/obj/items/synth/ait_pda.dmi new file mode 100644 index 000000000000..3242473c2d3a Binary files /dev/null and b/icons/obj/items/synth/ait_pda.dmi differ diff --git a/icons/obj/items/synth/bracer.dmi b/icons/obj/items/synth/bracer.dmi new file mode 100644 index 000000000000..dd6c30a874b3 Binary files /dev/null and b/icons/obj/items/synth/bracer.dmi differ diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm index b5181e0f77f6..dc1da5626015 100644 --- a/maps/map_files/USS_Almayer/USS_Almayer.dmm +++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm @@ -848,6 +848,13 @@ "afm" = ( /turf/open/floor/almayer_hull/outerhull_dir/southeast, /area/space) +"afo" = ( +/obj/structure/machinery/light{ + unacidable = 1; + unslashable = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "afr" = ( /turf/open/floor/almayer/red/northwest, /area/almayer/lifeboat_pumps/north1) @@ -1813,6 +1820,19 @@ }, /turf/open/floor/almayer/research/containment/floor2/north, /area/almayer/medical/containment/cell) +"any" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "SE-out" + }, +/obj/structure/machinery/door_control{ + id = "ARES Mainframe Left"; + name = "ARES Mainframe Lockdown"; + pixel_x = 24; + pixel_y = 24; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/glowing/no_build, +/area/almayer/command/airoom) "anz" = ( /obj/effect/decal/warning_stripes{ icon_state = "W"; @@ -2520,6 +2540,10 @@ /obj/structure/prop/almayer/computers/sensor_computer1, /turf/open/floor/almayer/silver/northeast, /area/almayer/command/cic) +"arS" = ( +/obj/structure/flora/pottedplant/random, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "arT" = ( /obj/structure/target{ name = "punching bag" @@ -2594,6 +2618,38 @@ /obj/structure/pipes/standard/simple/hidden/supply, /turf/open/floor/almayer, /area/almayer/lifeboat_pumps/north2) +"asC" = ( +/obj/structure/surface/table/reinforced/almayer_B{ + climbable = 0; + indestructible = 1; + unacidable = 1; + unslashable = 1 + }, +/obj/structure/machinery/computer/cameras/almayer/ares{ + pixel_x = -4; + pixel_y = 6 + }, +/obj/structure/machinery/computer/cameras/almayer{ + pixel_y = 6; + pixel_x = 28 + }, +/obj/structure/machinery/computer/view_objectives{ + pixel_x = 12; + pixel_y = 6 + }, +/obj/item/device/radio/intercom{ + frequency = 1500; + name = "AI Core Intercom"; + pixel_y = 32 + }, +/obj/item/device/radio/intercom{ + freerange = 1; + name = "General Listening Channel"; + pixel_y = 32; + pixel_x = 14 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "asE" = ( /obj/structure/bed/chair/office/dark{ dir = 8 @@ -2717,6 +2773,7 @@ id = "tcomms_apc"; name = "\improper Telecommunications Power Storage" }, +/obj/effect/step_trigger/ares_alert/comms, /turf/open/floor/almayer/test_floor4, /area/almayer/command/telecomms) "atm" = ( @@ -4143,6 +4200,7 @@ /obj/structure/pipes/standard/simple/hidden/supply/no_boom{ dir = 4 }, +/obj/effect/step_trigger/ares_alert/comms, /turf/open/floor/almayer/test_floor4, /area/almayer/command/telecomms) "aBh" = ( @@ -4988,16 +5046,6 @@ }, /turf/open/floor/almayer/test_floor4, /area/almayer/command/cichallway) -"aGk" = ( -/obj/structure/machinery/door_control{ - id = "ARES Operations Left"; - name = "ARES Operations Shutter"; - pixel_x = -24; - pixel_y = -8; - req_one_access_txt = "90;91;92" - }, -/turf/open/floor/almayer/aicore/no_build/ai_silver/west, -/area/almayer/command/airoom) "aGm" = ( /obj/structure/largecrate/random/case/double, /turf/open/floor/almayer/plate, @@ -6122,6 +6170,16 @@ }, /turf/open/floor/almayer/research/containment/corner/north, /area/almayer/medical/containment/cell) +"aOi" = ( +/obj/structure/machinery/door_control{ + id = "ARES Operations Left"; + name = "ARES Operations Shutter"; + pixel_x = -24; + pixel_y = -8; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/no_build/ai_silver/west, +/area/almayer/command/airoom) "aOq" = ( /obj/structure/surface/table/almayer, /obj/item/tool/extinguisher, @@ -8905,6 +8963,15 @@ }, /turf/open/floor/almayer/plate, /area/almayer/hallways/hangar) +"bkv" = ( +/obj/structure/stairs, +/obj/effect/step_trigger/teleporter_vector{ + name = "Almayer_AresUp"; + vector_x = -3; + vector_y = -1 + }, +/turf/open/floor/almayer/aicore/no_build, +/area/almayer/command/airoom) "bky" = ( /obj/structure/machinery/cryo_cell, /obj/structure/pipes/standard/cap/hidden, @@ -10544,6 +10611,7 @@ /obj/structure/machinery/door/poddoor/almayer{ id = "tcomms" }, +/obj/effect/step_trigger/ares_alert/comms, /turf/open/floor/almayer/test_floor4, /area/almayer/command/telecomms) "bzI" = ( @@ -11965,6 +12033,13 @@ }, /turf/open/floor/wood/ship, /area/almayer/shipboard/sea_office) +"bKR" = ( +/obj/structure/machinery/cm_vending/clothing/senior_officer{ + req_one_access_txt = "1;92"; + req_access = null + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/northeast, +/area/almayer/command/aist_office) "bKX" = ( /obj/structure/surface/table/almayer, /obj/item/storage/box/masks, @@ -13294,6 +13369,19 @@ }, /turf/open/floor/almayer/plate, /area/almayer/maint/hull/lower/l_m_p) +"bUI" = ( +/obj/effect/step_trigger/clone_cleaner, +/obj/structure/machinery/door/poddoor/shutters/almayer{ + id = "ARES AIST"; + name = "\improper Privacy Shutters" + }, +/obj/structure/machinery/door/airlock/almayer/generic/glass{ + name = "\improper AIST Office"; + dir = 1; + masterkey_resist = 1 + }, +/turf/open/floor/almayer/no_build/test_floor4, +/area/almayer/command/aist_office) "bUN" = ( /obj/structure/surface/table/almayer, /obj/item/trash/USCMtray{ @@ -13956,18 +14044,6 @@ }, /turf/open/floor/almayer/silver/north, /area/almayer/command/cichallway) -"cck" = ( -/obj/structure/surface/table/reinforced/almayer_B, -/obj/effect/decal/warning_stripes{ - icon_state = "E"; - pixel_x = 1 - }, -/obj/effect/decal/warning_stripes{ - icon_state = "S"; - layer = 3.3 - }, -/turf/open/floor/almayer/aicore/glowing/no_build, -/area/almayer/command/airoom) "ccs" = ( /obj/structure/disposalpipe/segment{ dir = 8 @@ -16546,6 +16622,17 @@ /obj/effect/step_trigger/clone_cleaner, /turf/open/floor/almayer, /area/almayer/hallways/upper/starboard) +"cRN" = ( +/obj/structure/stairs{ + icon_state = "ramptop" + }, +/obj/effect/projector{ + name = "Almayer_AresUp"; + vector_x = -3; + vector_y = -1 + }, +/turf/open/floor/almayer/aicore/no_build, +/area/almayer/command/airoom) "cSa" = ( /obj/effect/decal/warning_stripes{ icon_state = "NW-out"; @@ -17253,6 +17340,50 @@ /obj/structure/bed/chair/bolted, /turf/open/floor/almayer/plating_striped, /area/almayer/shipboard/brig/execution) +"dhn" = ( +/obj/structure/machinery/sentry_holder/almayer/mini/aicore{ + dir = 4 + }, +/obj/structure/machinery/door_control{ + id = "ARES StairsUpper"; + name = "Stairway Shutters"; + pixel_x = 36; + req_one_access_txt = "31;92"; + pixel_y = -2 + }, +/obj/structure/machinery/door_control{ + id = "ARES StairsLower"; + name = "Corridor Shutters"; + pixel_x = 36; + pixel_y = 4; + req_one_access_txt = "31;92" + }, +/obj/structure/machinery/door_control{ + id = "ARES Interior"; + indestructible = 1; + name = "Core Shutters"; + pixel_x = 36; + pixel_y = 10; + req_one_access_txt = "31;92" + }, +/obj/structure/machinery/door_control{ + id = "ARES Railing"; + indestructible = 1; + name = "Core Railings"; + needs_power = 0; + pixel_x = 28; + req_one_access_txt = "31;92"; + pixel_y = 7 + }, +/obj/structure/machinery/door_control{ + id = "ARES Operations Left"; + name = "Records Room Shutters"; + pixel_x = 28; + pixel_y = 1; + req_one_access_txt = "31;92" + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "dho" = ( /obj/structure/machinery/alarm/almayer{ dir = 1 @@ -18067,6 +18198,14 @@ }, /turf/open/floor/almayer/sterile_green_side/east, /area/almayer/medical/hydroponics) +"dBn" = ( +/obj/item/device/radio/intercom{ + frequency = 1500; + name = "AI Core Intercom"; + pixel_x = -24 + }, +/turf/open/floor/almayer/silver/west, +/area/almayer/hallways/upper/midship_hallway) "dBp" = ( /obj/structure/machinery/camera/autoname/almayer{ dir = 8; @@ -18761,6 +18900,9 @@ }, /turf/open/floor/plating, /area/almayer/maint/lower/constr) +"dPB" = ( +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "dPC" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 9 @@ -18793,6 +18935,13 @@ }, /turf/open/floor/almayer/no_build, /area/almayer/shipboard/brig/processing) +"dQb" = ( +/obj/structure/pipes/vents/pump/no_boom/gas{ + vent_tag = "AIST Office"; + dir = 8 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "dQp" = ( /obj/structure/pipes/standard/simple/hidden/supply, /obj/effect/decal/warning_stripes{ @@ -20305,19 +20454,6 @@ }, /turf/open/floor/almayer/test_floor4, /area/almayer/maint/hull/upper/u_f_s) -"euN" = ( -/obj/effect/decal/warning_stripes{ - icon_state = "SE-out" - }, -/obj/structure/machinery/door_control{ - id = "ARES Mainframe Left"; - name = "ARES Mainframe Lockdown"; - pixel_x = 24; - pixel_y = 24; - req_one_access_txt = "200;91;92" - }, -/turf/open/floor/almayer/aicore/glowing/no_build, -/area/almayer/command/airoom) "euV" = ( /turf/open/floor/almayer/uscm/directional/logo_c/west, /area/almayer/command/cic) @@ -20561,18 +20697,6 @@ }, /turf/open/floor/almayer/silver/east, /area/almayer/shipboard/brig/cic_hallway) -"eAG" = ( -/obj/structure/surface/table/almayer, -/obj/item/storage/firstaid/regular, -/obj/item/clipboard, -/obj/item/tool/pen{ - pixel_y = -17 - }, -/obj/item/paper_bin/uscm{ - pixel_y = -16 - }, -/turf/open/floor/almayer/plate, -/area/almayer/squads/req) "eAI" = ( /turf/open/floor/almayer/orangecorner/west, /area/almayer/engineering/lower/engine_core) @@ -22956,6 +23080,9 @@ /obj/item/device/defibrillator, /turf/open/floor/almayer/dark_sterile, /area/almayer/medical/lower_medical_medbay) +"fDr" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/southeast, +/area/almayer/command/aist_office) "fDG" = ( /obj/structure/machinery/vending/coffee, /obj/structure/machinery/light{ @@ -23353,6 +23480,9 @@ }, /turf/open/floor/almayer, /area/almayer/shipboard/brig/perma) +"fLW" = ( +/turf/closed/wall/almayer/aicore/white/hull, +/area/almayer/command/aist_office) "fMe" = ( /obj/structure/surface/table/almayer, /obj/item/device/flashlight/lamp{ @@ -23937,30 +24067,6 @@ }, /turf/open/floor/almayer/aicore/no_build, /area/almayer/command/airoom) -"gbg" = ( -/obj/structure/sign/safety/terminal{ - pixel_x = 14; - pixel_y = 24 - }, -/obj/structure/sign/safety/laser{ - pixel_y = 24 - }, -/obj/structure/sign/safety/fibre_optics{ - pixel_x = 14; - pixel_y = 38 - }, -/obj/structure/sign/safety/rewire{ - pixel_y = 38 - }, -/obj/structure/machinery/door_control{ - id = "ARES Operations Right"; - name = "ARES Operations Shutter"; - pixel_x = -24; - pixel_y = -8; - req_one_access_txt = "90;91;92" - }, -/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3, -/area/almayer/command/airoom) "gbm" = ( /turf/open/floor/almayer/aicore/no_build/ai_silver/east, /area/almayer/command/airoom) @@ -24005,6 +24111,9 @@ }, /turf/open/floor/almayer/red/north, /area/almayer/hallways/hangar) +"gdy" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/west, +/area/almayer/command/aist_office) "gdG" = ( /obj/structure/bed/chair{ dir = 8; @@ -24084,6 +24193,17 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/hallways/lower/port_midship_hallway) +"geB" = ( +/obj/effect/step_trigger/clone_cleaner, +/obj/structure/machinery/door_control{ + id = "ARES AIST"; + name = "Privacy Shutters"; + pixel_x = 24; + pixel_y = 8; + req_one_access_txt = "31;92" + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "gfd" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -24565,6 +24685,10 @@ "gqI" = ( /turf/open/floor/almayer/orange/north, /area/almayer/hallways/upper/midship_hallway) +"gqO" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "gqP" = ( /obj/structure/largecrate/random/case, /obj/structure/machinery/camera/autoname/almayer{ @@ -25337,6 +25461,24 @@ /obj/structure/machinery/iv_drip, /turf/open/floor/almayer/mono, /area/almayer/medical/medical_science) +"gGF" = ( +/obj/structure/stairs{ + icon_state = "ramptop" + }, +/obj/effect/projector{ + name = "Almayer_AresUp"; + vector_x = 3; + vector_y = 1 + }, +/obj/structure/machinery/door_control{ + id = "ARES AIST"; + name = "Privacy Shutters"; + pixel_x = 24; + pixel_y = -8; + req_one_access_txt = "31;92" + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "gGI" = ( /obj/structure/disposalpipe/segment, /obj/structure/machinery/light{ @@ -26088,6 +26230,15 @@ }, /turf/open/floor/plating, /area/almayer/medical/upper_medical) +"gXe" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/obj/structure/sign/safety/terminal{ + pixel_y = 26; + pixel_x = 8; + layer = 2.2 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "gXl" = ( /obj/structure/closet/secure_closet/personal/cabinet{ req_access_txt = "5" @@ -26190,6 +26341,13 @@ }, /turf/open/floor/almayer/plate, /area/almayer/maint/hull/upper/u_a_p) +"gZb" = ( +/obj/structure/surface/table/almayer, +/obj/item/storage/firstaid/regular, +/obj/item/clipboard, +/obj/item/tool/pen, +/turf/open/floor/almayer/plate, +/area/almayer/squads/req) "gZw" = ( /obj/structure/bed/sofa/vert/grey/bot, /turf/open/floor/almayer, @@ -27784,6 +27942,9 @@ }, /turf/open/floor/almayer/orangecorner/east, /area/almayer/hallways/upper/aft_hallway) +"hGe" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "hGh" = ( /obj/structure/window/framed/almayer/white, /obj/structure/machinery/door/firedoor/border_only/almayer, @@ -29208,6 +29369,11 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/shipboard/brig/cic_hallway) +"inr" = ( +/obj/effect/landmark/start/intel, +/obj/effect/landmark/late_join/intel, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/engineering/port_atmos) "ins" = ( /obj/structure/pipes/standard/manifold/hidden/supply{ dir = 1 @@ -29638,6 +29804,10 @@ /obj/structure/machinery/computer/crew/alt, /turf/open/floor/almayer/sterile_green, /area/almayer/medical/lockerroom) +"ixm" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "ixu" = ( /obj/structure/largecrate/random/case{ layer = 2.98 @@ -29727,6 +29897,16 @@ "iAg" = ( /turf/open/floor/almayer/redcorner/east, /area/almayer/shipboard/brig/mp_bunks) +"iAu" = ( +/obj/structure/machinery/door_control{ + id = "ARES Operations Right"; + name = "ARES Operations Shutter"; + pixel_x = 24; + pixel_y = -8; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/no_build/ai_silver/east, +/area/almayer/command/airoom) "iAw" = ( /obj/item/tool/warning_cone{ pixel_x = -12 @@ -31091,6 +31271,9 @@ }, /turf/open/floor/wood/ship, /area/almayer/living/commandbunks) +"jbT" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/southwest, +/area/almayer/command/aist_office) "jbX" = ( /obj/structure/pipes/standard/manifold/hidden/supply{ dir = 4 @@ -32355,6 +32538,30 @@ }, /turf/open/floor/almayer/orangecorner, /area/almayer/hallways/lower/starboard_aft_hallway) +"jAm" = ( +/obj/structure/sign/safety/rewire{ + pixel_y = 38 + }, +/obj/structure/sign/safety/fibre_optics{ + pixel_x = 14; + pixel_y = 38 + }, +/obj/structure/sign/safety/laser{ + pixel_y = 24 + }, +/obj/structure/sign/safety/terminal{ + pixel_x = 14; + pixel_y = 24 + }, +/obj/structure/machinery/door_control{ + id = "ARES Operations Left"; + name = "ARES Operations Shutter"; + pixel_x = 24; + pixel_y = -8; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3, +/area/almayer/command/airoom) "jAz" = ( /obj/structure/platform, /obj/structure/platform{ @@ -32908,29 +33115,6 @@ }, /turf/open/floor/almayer/orangecorner/east, /area/almayer/squads/bravo) -"jOk" = ( -/obj/structure/surface/table/almayer, -/obj/structure/machinery/line_nexter_control{ - id = "line2"; - pixel_x = -4; - pixel_y = 10; - req_one_access_txt = "1;21" - }, -/obj/structure/machinery/door_control{ - id = "ROlobby2"; - name = "RO Line 2 Shutters"; - pixel_x = 5; - pixel_y = 10; - req_one_access_txt = "1;21" - }, -/obj/item/paper_bin/uscm{ - pixel_y = -4 - }, -/obj/item/tool/pen{ - pixel_y = -5 - }, -/turf/open/floor/almayer/plate, -/area/almayer/squads/req) "jOo" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -33284,6 +33468,9 @@ "jWh" = ( /turf/closed/wall/almayer, /area/almayer/engineering/upper_engineering/port) +"jWl" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "jWr" = ( /obj/structure/machinery/light{ dir = 4 @@ -33528,6 +33715,14 @@ }, /turf/open/floor/almayer/red/northwest, /area/almayer/squads/alpha) +"kaD" = ( +/obj/structure/machinery/door/airlock/almayer/secure/reinforced{ + name = "\improper AIST Office"; + req_access = null + }, +/obj/effect/step_trigger/clone_cleaner, +/turf/open/floor/almayer/no_build/test_floor4, +/area/almayer/command/airoom) "kaE" = ( /obj/effect/decal/warning_stripes{ icon_state = "E"; @@ -34733,6 +34928,12 @@ }, /turf/open/floor/almayer/plating/northeast, /area/almayer/engineering/lower/engine_core) +"kAb" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom{ + dir = 6 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "kAh" = ( /obj/structure/sign/safety/restrictedarea{ pixel_x = -17 @@ -35001,6 +35202,12 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/hull/lower/l_f_s) +"kFV" = ( +/obj/structure/machinery/light{ + dir = 8 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/west, +/area/almayer/command/aist_office) "kFY" = ( /obj/structure/sign/safety/cryo{ pixel_x = 7 @@ -35569,19 +35776,6 @@ /obj/item/reagent_container/glass/bucket/janibucket, /turf/open/floor/almayer/orange/southeast, /area/almayer/hallways/hangar) -"kSy" = ( -/obj/effect/decal/warning_stripes{ - icon_state = "SW-out" - }, -/obj/structure/machinery/door_control{ - id = "ARES Mainframe Right"; - name = "ARES Mainframe Lockdown"; - pixel_x = -24; - pixel_y = 24; - req_one_access_txt = "200;91;92" - }, -/turf/open/floor/almayer/aicore/glowing/no_build, -/area/almayer/command/airoom) "kSA" = ( /obj/structure/machinery/door/firedoor/border_only/almayer, /obj/structure/machinery/door/poddoor/almayer{ @@ -35703,6 +35897,9 @@ }, /turf/open/floor/almayer/mono, /area/almayer/lifeboat_pumps/south2) +"kVf" = ( +/turf/open/floor/almayer/green, +/area/almayer/squads/req) "kVV" = ( /obj/structure/disposalpipe/segment{ dir = 4; @@ -36554,30 +36751,6 @@ /obj/structure/window/reinforced, /turf/open/floor/prison/kitchen, /area/almayer/engineering/upper_engineering) -"lnS" = ( -/obj/structure/sign/safety/rewire{ - pixel_y = 38 - }, -/obj/structure/sign/safety/fibre_optics{ - pixel_x = 14; - pixel_y = 38 - }, -/obj/structure/sign/safety/laser{ - pixel_y = 24 - }, -/obj/structure/sign/safety/terminal{ - pixel_x = 14; - pixel_y = 24 - }, -/obj/structure/machinery/door_control{ - id = "ARES Operations Left"; - name = "ARES Operations Shutter"; - pixel_x = 24; - pixel_y = -8; - req_one_access_txt = "90;91;92" - }, -/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3, -/area/almayer/command/airoom) "lok" = ( /obj/structure/machinery/cm_vending/clothing/marine/charlie{ density = 0; @@ -37340,16 +37513,6 @@ }, /turf/open/floor/almayer/blue/north, /area/almayer/living/port_emb) -"lFj" = ( -/obj/structure/machinery/door_control{ - id = "ARES Operations Right"; - name = "ARES Operations Shutter"; - pixel_x = 24; - pixel_y = -8; - req_one_access_txt = "90;91;92" - }, -/turf/open/floor/almayer/aicore/no_build/ai_silver/east, -/area/almayer/command/airoom) "lFn" = ( /obj/structure/flora/pottedplant{ icon_state = "pottedplant_21" @@ -37930,6 +38093,12 @@ }, /turf/open/floor/almayer/test_floor4, /area/almayer/maint/upper/u_f_p) +"lSU" = ( +/obj/structure/pipes/vents/scrubber/no_boom{ + dir = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "lSX" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 6 @@ -38225,6 +38394,12 @@ }, /turf/open/floor/almayer/sterile_green_side/east, /area/almayer/medical/upper_medical) +"mba" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom{ + dir = 4 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "mbx" = ( /obj/effect/decal/warning_stripes{ icon_state = "S" @@ -38927,10 +39102,6 @@ /obj/item/storage/box/bodybags, /turf/open/floor/almayer/plate, /area/almayer/medical/morgue) -"mrM" = ( -/obj/structure/closet/secure_closet/quartermaster_uscm, -/turf/open/floor/almayer/green, -/area/almayer/squads/req) "msg" = ( /obj/structure/machinery/light, /obj/structure/sign/safety/waterhazard{ @@ -39994,11 +40165,6 @@ }, /turf/open/floor/almayer, /area/almayer/squads/req) -"mMP" = ( -/obj/effect/landmark/start/intel, -/obj/effect/landmark/late_join/intel, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/engineering/port_atmos) "mMV" = ( /obj/structure/pipes/vents/scrubber, /obj/item/device/radio/intercom{ @@ -41056,6 +41222,11 @@ /obj/structure/surface/table/almayer, /turf/open/floor/almayer, /area/almayer/shipboard/brig/cells) +"nhK" = ( +/obj/item/bedsheet/yellow, +/obj/structure/bed, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "nhN" = ( /obj/structure/sign/safety/autoopenclose{ pixel_x = 7; @@ -41620,31 +41791,6 @@ "nsY" = ( /turf/closed/wall/almayer, /area/almayer/living/port_emb) -"ntd" = ( -/obj/structure/surface/table/almayer, -/obj/item/paper_bin/uscm{ - pixel_x = -8; - pixel_y = 5 - }, -/obj/item/clipboard{ - pixel_x = 12 - }, -/obj/item/tool/pen{ - pixel_x = 12 - }, -/obj/item/tool/hand_labeler{ - pixel_x = 4; - pixel_y = 11 - }, -/obj/structure/sign/ROcreed{ - pixel_y = 30 - }, -/obj/item/device/flashlight/lamp{ - pixel_y = -11; - pixel_x = 7 - }, -/turf/open/floor/almayer/green/north, -/area/almayer/squads/req) "ntj" = ( /turf/closed/wall/almayer/reinforced, /area/almayer/command/computerlab) @@ -42199,6 +42345,10 @@ }, /turf/open/floor/almayer/plate, /area/almayer/living/briefing) +"nFG" = ( +/obj/structure/machinery/cm_vending/sorted/attachments/blend, +/turf/open/floor/almayer/plate, +/area/almayer/squads/req) "nFI" = ( /obj/structure/surface/table/almayer, /obj/structure/disposalpipe/segment{ @@ -44014,6 +44164,16 @@ /obj/structure/machinery/door/airlock/almayer/maint, /turf/open/floor/almayer/test_floor4, /area/almayer/maint/upper/u_a_s) +"orE" = ( +/obj/structure/machinery/door_control{ + id = "ARES Mainframe Right"; + name = "ARES Mainframe Lockdown"; + pixel_x = -24; + pixel_y = -24; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/no_build, +/area/almayer/command/airoom) "orH" = ( /turf/open/floor/almayer/uscm/directional/southwest, /area/almayer/command/lifeboat) @@ -44330,19 +44490,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/shipboard/brig/starboard_hallway) -"oyE" = ( -/obj/effect/landmark/start/intel, -/obj/structure/sign/poster{ - desc = "One of those hot, tanned babes back the beaches of good ol' Earth."; - icon_state = "poster12"; - name = "Beach Babe Pinup"; - pixel_x = 6; - pixel_y = 29; - serial_number = 12 - }, -/obj/effect/landmark/late_join/intel, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/engineering/port_atmos) "oyO" = ( /obj/structure/reagent_dispensers/watertank, /obj/structure/sign/safety/water{ @@ -44893,6 +45040,10 @@ "oIh" = ( /turf/open/floor/almayer/red/west, /area/almayer/shipboard/brig/processing) +"oIj" = ( +/obj/structure/pipes/vents/pump/on, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/squads/req) "oIn" = ( /obj/effect/landmark/start/liaison, /turf/open/floor/plating/plating_catwalk, @@ -45058,6 +45209,23 @@ }, /turf/open/floor/almayer/redfull, /area/almayer/squads/alpha_bravo_shared) +"oMP" = ( +/obj/structure/surface/table/almayer, +/obj/structure/machinery/line_nexter_control{ + id = "line2"; + pixel_x = -4; + pixel_y = 10; + req_one_access_txt = "1;21" + }, +/obj/structure/machinery/door_control{ + id = "ROlobby2"; + name = "RO Line 2 Shutters"; + pixel_x = 5; + pixel_y = 10; + req_one_access_txt = "1;21" + }, +/turf/open/floor/almayer/plate, +/area/almayer/squads/req) "oMQ" = ( /obj/structure/pipes/vents/pump, /turf/open/floor/almayer, @@ -46701,6 +46869,12 @@ "pvP" = ( /turf/open/floor/almayer/redcorner/north, /area/almayer/shipboard/starboard_missiles) +"pvU" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom{ + dir = 4 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "pwl" = ( /obj/structure/sign/safety/bridge{ pixel_x = 15; @@ -46894,6 +47068,12 @@ "pAm" = ( /turf/open/floor/almayer, /area/almayer/engineering/lower/engine_core) +"pAK" = ( +/obj/structure/pipes/standard/manifold/hidden/supply/no_boom{ + dir = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "pAV" = ( /obj/structure/platform{ dir = 1 @@ -46915,12 +47095,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/engineering/lower) -"pCr" = ( -/obj/structure/machinery/cm_vending/sorted/attachments/blend, -/turf/closed/wall/almayer{ - opacity = 0 - }, -/area/almayer/squads/req) "pDh" = ( /obj/structure/machinery/power/monitor{ name = "Core Power Monitoring" @@ -47923,6 +48097,14 @@ "pYX" = ( /turf/open/floor/almayer/silvercorner/west, /area/almayer/shipboard/brig/cic_hallway) +"pZf" = ( +/obj/item/device/radio/intercom{ + frequency = 1500; + name = "AI Core Intercom"; + pixel_x = 24 + }, +/turf/open/floor/almayer/aicore/no_build, +/area/almayer/command/airoom) "pZH" = ( /obj/structure/machinery/shower{ dir = 8 @@ -48870,6 +49052,12 @@ "qrv" = ( /turf/open/floor/almayer/silver, /area/almayer/command/computerlab) +"qrx" = ( +/obj/structure/machinery/status_display{ + pixel_y = 30 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "qsp" = ( /obj/structure/machinery/light/small, /turf/open/floor/plating/plating_catwalk, @@ -49962,6 +50150,17 @@ }, /turf/open/floor/almayer/cargo, /area/almayer/squads/delta) +"qNf" = ( +/obj/structure/stairs{ + icon_state = "ramptop" + }, +/obj/effect/projector{ + name = "Almayer_AresUp"; + vector_x = 3; + vector_y = 1 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "qNI" = ( /obj/effect/decal/warning_stripes{ icon_state = "W" @@ -50033,6 +50232,9 @@ /obj/structure/medical_supply_link, /turf/open/floor/almayer/sterile_green_side/north, /area/almayer/medical/lower_medical_lobby) +"qPc" = ( +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/east, +/area/almayer/command/aist_office) "qPk" = ( /turf/open/floor/almayer, /area/almayer/hallways/lower/starboard_fore_hallway) @@ -50591,16 +50793,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/hull/upper/u_f_s) -"rby" = ( -/obj/structure/machinery/door_control{ - id = "ARES Mainframe Left"; - name = "ARES Mainframe Lockdown"; - pixel_x = 24; - pixel_y = -24; - req_one_access_txt = "200;91;92" - }, -/turf/open/floor/almayer/aicore/no_build, -/area/almayer/command/airoom) "rbB" = ( /turf/open/floor/almayer/silvercorner, /area/almayer/command/computerlab) @@ -51011,6 +51203,12 @@ "rjr" = ( /turf/open/floor/almayer/silvercorner, /area/almayer/hallways/upper/midship_hallway) +"rjz" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom{ + dir = 5 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/white/ai_floor3, +/area/almayer/command/aist_office) "rjF" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -51251,6 +51449,19 @@ /obj/structure/largecrate/random/barrel/green, /turf/open/floor/almayer/plate, /area/almayer/maint/hull/lower/p_bow) +"ros" = ( +/obj/structure/filingcabinet{ + density = 0; + pixel_x = 8; + pixel_y = 18 + }, +/obj/structure/filingcabinet{ + density = 0; + pixel_x = -8; + pixel_y = 18 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/west, +/area/almayer/command/aist_office) "rou" = ( /obj/structure/machinery/cryopod/right{ pixel_y = 6 @@ -51947,6 +52158,14 @@ }, /turf/open/floor/almayer/plate, /area/almayer/engineering/lower/workshop) +"rDC" = ( +/obj/structure/closet/coffin/woodencrate, +/obj/item/storage/box/m94, +/obj/item/storage/box/m94, +/obj/item/storage/box/m94, +/obj/item/stack/sheet/mineral/plastic/small_stack, +/turf/open/floor/almayer/test_floor4, +/area/almayer/squads/req) "rDH" = ( /obj/structure/machinery/light, /turf/open/floor/almayer, @@ -52179,13 +52398,6 @@ }, /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/hull/upper/p_stern) -"rHN" = ( -/obj/structure/pipes/vents/pump/on, -/obj/structure/bed/chair{ - dir = 4 - }, -/turf/open/floor/plating/plating_catwalk, -/area/almayer/squads/req) "rIj" = ( /obj/structure/machinery/door/poddoor/almayer/open{ dir = 4; @@ -52859,6 +53071,22 @@ }, /turf/open/floor/almayer/cargo, /area/almayer/living/cryo_cells) +"rXm" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "S"; + layer = 3.3 + }, +/obj/item/device/radio/intercom{ + frequency = 1500; + name = "AI Core Intercom" + }, +/turf/open/floor/almayer/aicore/glowing/no_build, +/area/almayer/command/airoom) "rXq" = ( /obj/structure/machinery/door/airlock/almayer/maint, /turf/open/floor/almayer/test_floor4, @@ -54347,6 +54575,15 @@ /obj/structure/surface/table/almayer, /turf/open/floor/plating, /area/almayer/maint/lower/constr) +"sDa" = ( +/obj/structure/stairs, +/obj/effect/step_trigger/teleporter_vector{ + name = "Almayer_AresUp"; + vector_x = 3; + vector_y = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "sDu" = ( /obj/item/clothing/under/marine/dress, /turf/open/floor/almayer/dark_sterile, @@ -54368,6 +54605,16 @@ "sDM" = ( /turf/open/floor/almayer/blue/northwest, /area/almayer/squads/delta) +"sDZ" = ( +/obj/structure/bed/chair/office/dark{ + dir = 4 + }, +/obj/structure/machinery/computer/working_joe{ + dir = 8; + pixel_x = 29 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "sEd" = ( /obj/structure/machinery/cryopod/right, /obj/structure/machinery/light{ @@ -54927,6 +55174,15 @@ /obj/structure/pipes/standard/manifold/hidden/supply, /turf/open/floor/almayer/plate, /area/almayer/command/lifeboat) +"sRA" = ( +/obj/structure/machinery/light{ + dir = 4 + }, +/obj/structure/pipes/standard/simple/hidden/supply/no_boom{ + dir = 10 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/east, +/area/almayer/command/aist_office) "sRZ" = ( /obj/effect/projector{ name = "Almayer_Down2"; @@ -55118,6 +55374,16 @@ }, /turf/open/floor/almayer/no_build, /area/almayer/hallways/upper/fore_hallway) +"sWk" = ( +/obj/structure/machinery/door_control{ + id = "ARES Mainframe Left"; + name = "ARES Mainframe Lockdown"; + pixel_x = 24; + pixel_y = -24; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/no_build, +/area/almayer/command/airoom) "sWp" = ( /obj/structure/machinery/light/small{ dir = 8 @@ -55866,6 +56132,15 @@ }, /turf/open/floor/almayer/green/north, /area/almayer/hallways/lower/port_midship_hallway) +"tkk" = ( +/obj/structure/stairs, +/obj/effect/step_trigger/teleporter_vector{ + name = "Almayer_AresUp"; + vector_x = -3; + vector_y = -1 + }, +/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3, +/area/almayer/command/airoom) "tkn" = ( /obj/structure/surface/table/almayer, /obj/item/storage/toolbox/mechanical, @@ -56134,6 +56409,28 @@ "tpn" = ( /turf/closed/wall/almayer, /area/almayer/shipboard/brig/evidence_storage) +"tpp" = ( +/obj/structure/machinery/cryopod/right{ + layer = 3.1; + pixel_y = 13 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "S" + }, +/obj/effect/decal/warning_stripes{ + icon_state = "E"; + pixel_x = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "N"; + pixel_y = 1 + }, +/obj/effect/decal/warning_stripes{ + icon_state = "W"; + pixel_x = -1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_cargo, +/area/almayer/command/aist_office) "tpB" = ( /obj/structure/machinery/door/firedoor/border_only/almayer, /obj/structure/pipes/standard/simple/hidden/supply{ @@ -57021,6 +57318,22 @@ /obj/structure/machinery/photocopier/wyphotocopier, /turf/open/floor/wood/ship, /area/almayer/command/corporateliaison) +"tHi" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/obj/item/folder/white{ + pixel_x = -12 + }, +/obj/item/paper_bin/uscm{ + pixel_y = 6 + }, +/obj/item/tool/pen/fountain{ + pixel_y = 3 + }, +/obj/item/tool/pen/fountain{ + pixel_y = 9 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "tHk" = ( /obj/structure/surface/rack, /obj/effect/spawner/random/toolbox, @@ -57291,6 +57604,10 @@ /obj/structure/largecrate/random/case/small, /turf/open/floor/almayer/plate, /area/almayer/maint/upper/u_a_s) +"tOn" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "tOr" = ( /obj/effect/decal/warning_stripes{ icon_state = "N"; @@ -57592,6 +57909,30 @@ }, /turf/open/floor/almayer/test_floor4, /area/almayer/maint/hull/lower/l_a_p) +"tWn" = ( +/obj/structure/sign/safety/terminal{ + pixel_x = 14; + pixel_y = 24 + }, +/obj/structure/sign/safety/laser{ + pixel_y = 24 + }, +/obj/structure/sign/safety/fibre_optics{ + pixel_x = 14; + pixel_y = 38 + }, +/obj/structure/sign/safety/rewire{ + pixel_y = 38 + }, +/obj/structure/machinery/door_control{ + id = "ARES Operations Right"; + name = "ARES Operations Shutter"; + pixel_x = -24; + pixel_y = -8; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/glowing/no_build/ai_floor3, +/area/almayer/command/airoom) "tWp" = ( /obj/structure/largecrate/random/case/double, /turf/open/floor/almayer/plate, @@ -57660,19 +58001,6 @@ }, /turf/open/floor/almayer, /area/almayer/living/gym) -"tXj" = ( -/obj/structure/closet/coffin/woodencrate, -/obj/item/storage/box/m94, -/obj/item/storage/box/m94, -/obj/item/storage/box/m94, -/obj/item/stack/sheet/mineral/plastic/small_stack, -/obj/item/frame/rack, -/obj/item/frame/rack, -/obj/item/frame/rack, -/obj/item/frame/rack, -/obj/item/frame/rack, -/turf/open/floor/almayer/test_floor4, -/area/almayer/squads/req) "tXn" = ( /obj/structure/machinery/power/apc/almayer/west, /turf/open/floor/almayer/plate, @@ -57749,6 +58077,14 @@ }, /turf/open/floor/almayer/sterile_green_side/northeast, /area/almayer/medical/lower_medical_lobby) +"tYE" = ( +/obj/structure/machinery/camera/autoname/almayer/containment/ares{ + dir = 4; + c_tag = "AI - AIST Office"; + autoname = 0 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/west, +/area/almayer/command/aist_office) "tYM" = ( /obj/structure/pipes/vents/pump{ dir = 4 @@ -59339,6 +59675,16 @@ }, /turf/open/floor/almayer_hull/outerhull_dir, /area/space) +"uJK" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom, +/obj/structure/machinery/door/airlock/almayer/generic{ + name = "\improper AIST Office"; + dir = 1; + req_one_access_txt = "31;92"; + masterkey_resist = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "uJM" = ( /obj/structure/sign/safety/medical{ pixel_x = 8; @@ -59590,6 +59936,19 @@ }, /turf/open/floor/almayer, /area/almayer/hallways/lower/starboard_aft_hallway) +"uQg" = ( +/obj/effect/decal/warning_stripes{ + icon_state = "SW-out" + }, +/obj/structure/machinery/door_control{ + id = "ARES Mainframe Right"; + name = "ARES Mainframe Lockdown"; + pixel_x = -24; + pixel_y = 24; + req_one_access_txt = "91;92" + }, +/turf/open/floor/almayer/aicore/glowing/no_build, +/area/almayer/command/airoom) "uQm" = ( /obj/structure/pipes/standard/simple/hidden/supply{ dir = 4 @@ -60336,6 +60695,12 @@ }, /turf/open/floor/almayer/red/northwest, /area/almayer/lifeboat_pumps/south2) +"vea" = ( +/obj/structure/pipes/vents/pump/no_boom{ + dir = 1 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "ven" = ( /obj/structure/bed/chair, /turf/open/floor/almayer/green, @@ -60596,6 +60961,19 @@ }, /turf/open/floor/almayer/red, /area/almayer/lifeboat_pumps/south1) +"vjf" = ( +/obj/effect/landmark/start/intel, +/obj/structure/sign/poster{ + desc = "One of those hot, tanned babes back the beaches of good ol' Earth."; + icon_state = "poster12"; + name = "Beach Babe Pinup"; + pixel_x = 6; + pixel_y = 29; + serial_number = 12 + }, +/obj/effect/landmark/late_join/intel, +/turf/open/floor/plating/plating_catwalk, +/area/almayer/engineering/port_atmos) "vjg" = ( /obj/structure/prop/almayer/missile_tube{ icon_state = "missiletubesouth" @@ -60603,6 +60981,27 @@ /obj/structure/machinery/light, /turf/open/floor/almayer/plating/northeast, /area/almayer/shipboard/port_missiles) +"vjk" = ( +/obj/structure/surface/table/almayer, +/obj/item/paper_bin/uscm{ + pixel_x = -8; + pixel_y = 5 + }, +/obj/item/clipboard{ + pixel_x = 12 + }, +/obj/item/tool/pen{ + pixel_x = 12 + }, +/obj/item/tool/hand_labeler{ + pixel_x = 4; + pixel_y = 11 + }, +/obj/structure/sign/poster/propaganda{ + pixel_y = 34 + }, +/turf/open/floor/almayer/green/north, +/area/almayer/squads/req) "vjv" = ( /obj/effect/decal/cleanable/blood/oil, /obj/structure/pipes/standard/simple/hidden/supply{ @@ -62170,16 +62569,6 @@ }, /turf/open/floor/almayer/silver/west, /area/almayer/hallways/lower/repair_bay) -"vLz" = ( -/obj/structure/machinery/door_control{ - id = "ARES Mainframe Right"; - name = "ARES Mainframe Lockdown"; - pixel_x = -24; - pixel_y = -24; - req_one_access_txt = "200;91;92" - }, -/turf/open/floor/almayer/aicore/no_build, -/area/almayer/command/airoom) "vLA" = ( /obj/effect/decal/warning_stripes{ icon_state = "W"; @@ -62515,6 +62904,10 @@ /obj/item/storage/box/matches, /turf/open/floor/almayer/orange/north, /area/almayer/engineering/upper_engineering/starboard) +"vRy" = ( +/obj/structure/pipes/standard/simple/hidden/supply/no_boom, +/turf/open/floor/almayer/aicore/no_build/white/ai_floor1, +/area/almayer/command/aist_office) "vRA" = ( /obj/effect/step_trigger/teleporter_vector{ name = "Almayer_AresDown"; @@ -62625,6 +63018,33 @@ }, /turf/open/floor/almayer/plate, /area/almayer/engineering/upper_engineering) +"vTC" = ( +/obj/structure/surface/table/reinforced/almayer_B, +/obj/structure/machinery/light{ + unacidable = 1; + unslashable = 1 + }, +/obj/structure/transmitter/rotary{ + name = "Office Telephone"; + phone_category = "ARES"; + phone_color = "blue"; + phone_id = "AIST Office"; + pixel_x = 8; + pixel_y = 9 + }, +/obj/structure/machinery/aicore_lockdown{ + pixel_x = -5; + req_one_access_txt = "31;92" + }, +/obj/structure/machinery/door_control{ + id = "ARES AIST"; + name = "Privacy Shutters"; + pixel_y = 11; + req_one_access_txt = "31;92"; + pixel_x = -5 + }, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver, +/area/almayer/command/aist_office) "vTE" = ( /obj/structure/machinery/door/airlock/almayer/maint{ dir = 1 @@ -64500,12 +64920,6 @@ /obj/effect/landmark/start/pilot/dropship_pilot, /turf/open/floor/plating/plating_catwalk, /area/almayer/living/pilotbunks) -"wEF" = ( -/obj/structure/bed/chair{ - dir = 4 - }, -/turf/open/floor/almayer, -/area/almayer/squads/req) "wEI" = ( /obj/structure/surface/table/reinforced/black, /obj/item/tool/pen, @@ -65383,6 +65797,9 @@ }, /turf/open/floor/almayer, /area/almayer/hallways/lower/port_aft_hallway) +"wVr" = ( +/turf/closed/wall/almayer/aicore/white/reinforced, +/area/almayer/command/aist_office) "wVt" = ( /obj/effect/step_trigger/clone_cleaner, /turf/open/floor/plating/plating_catwalk, @@ -66803,6 +67220,13 @@ "xzh" = ( /turf/open/floor/plating/plating_catwalk, /area/almayer/maint/upper/u_m_p) +"xzr" = ( +/obj/structure/machinery/light{ + dir = 1 + }, +/obj/effect/step_trigger/clone_cleaner, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "xzx" = ( /obj/structure/machinery/light/small{ dir = 1 @@ -67313,6 +67737,11 @@ "xLw" = ( /turf/open/floor/almayer/silver, /area/almayer/hallways/upper/midship_hallway) +"xLU" = ( +/obj/effect/landmark/late_join/aist, +/obj/effect/landmark/start/ai_tech, +/turf/open/floor/almayer/aicore/no_build/white/ai_silver/north, +/area/almayer/command/aist_office) "xLX" = ( /obj/structure/disposalpipe/junction{ dir = 4; @@ -105779,7 +106208,7 @@ rpV cGO cGO cGO -cGO +dBn cGO kaO cGO @@ -107618,9 +108047,9 @@ sfz poD xIj aUH -oyE -mMP -mMP +vjf +inr +inr nIN xzh gNo @@ -107809,7 +108238,7 @@ ryn ryn mOi xdA -qQS +pZf uUB aqU aHq @@ -108722,7 +109151,7 @@ bdl bGo bGo qjY -pCr +nFG jpD cpK cpK @@ -108922,12 +109351,12 @@ bEs bIs bdm rbY -eAG +gZb bOK bPD bYa bPD -jOk +oMP bNB tiE xGo @@ -112178,7 +112607,7 @@ gvU cyo bdl hTP -tXj +rDC sgc xCa bUy @@ -112369,8 +112798,8 @@ mww sZe bdl fgm -wEF -rHN +bdj +oIj kuu mDj bdl @@ -112571,7 +113000,7 @@ noI dJG sZe bdl -ntd +vjk jCm eqb mLR @@ -112778,7 +113207,7 @@ tFS bdj bNs nwb -mrM +kVf bdl ycH pMJ @@ -113804,7 +114233,7 @@ vub bPL bCM xSM -cgE +tez gsm bCM bbr @@ -114007,7 +114436,7 @@ qlz tez bCN ccQ -cgE +tez ccQ bCN bbr @@ -114210,7 +114639,7 @@ qlz tez bpV ccQ -cgE +tez ccQ cdn bbr @@ -114413,7 +114842,7 @@ qlz tez bCM ccQ -cgE +tez ccQ bCM bbr @@ -114616,7 +115045,7 @@ vub tez bCN ccQ -cgE +tez ccQ bCN jhb @@ -121668,21 +122097,21 @@ aKQ aaa aaa aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak +aak bdH bdH bdH @@ -121864,36 +122293,36 @@ bdH aaa aaa aaa -aab -aaa -aaa -aKQ -aaa -aaa -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -aaa -aaa -aaa +aab +aaa +aaa +aKQ +aaa +aaa +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +bdH +aak +bdH +bdH +bdH +bdH +bdH +aaa +aaa +aaa aaa aaa aaa @@ -122073,7 +122502,7 @@ aaa aKQ aaa aaa -aab +aaa aaa bdH bdH @@ -122088,7 +122517,7 @@ bdH bdH bdH bdH -bdH +aak bdH bdH bdH @@ -122275,23 +122704,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -122478,23 +122907,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -122681,23 +123110,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +fLW +tpp +kFV +jbT +wVr +ros +gdy +tYE +jbT +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -122884,23 +123313,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +fLW +xLU +kAb +vRy +uJK +vRy +lSU +hGe +jWl +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -123087,23 +123516,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +fLW +nhK +mba +arS +wVr +asC +sDZ +dhn +vTC +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -123290,23 +123719,23 @@ aaa aaa aKQ aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +iBn +fLW +ixm +pAK +vea +wVr +gXe +tOn +tOn +tHi +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -123492,24 +123921,24 @@ aab aaa aaa aKQ -aaa -bdH -aak -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH bdH +iBn +fLW +ixm +pvU +arS +wVr +qrx +hGe +hGe +jWl +fLW +iBn +iBn bdH bdH bdH +aak bdH aaa aaa @@ -123696,22 +124125,22 @@ aaa aaa aKQ bdH +iBn +fLW +bKR +sRA +vRy +uJK +vRy +gqO +rjz +afo +fLW +iBn +iBn +bdH +bdH bdH -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak -aak aak bdH aaa @@ -123899,19 +124328,19 @@ bdH bdH aKQ bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +fLW +fLW +fLW +fLW +fLW +fLW +xzr +dPB +dQb +jWl +fLW +iBn +iBn bdH bdH bdH @@ -124101,20 +124530,20 @@ bdH bdH bdH aKQ -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH -bdH +lmz +fLW +sDa +sDa +qNf +gGF +bUI +geB +qPc +qPc +fDr +fLW +iBn +iBn bdH bdH bdH @@ -124305,17 +124734,17 @@ lmz lmz lmz lmz -iBn -iBn -iBn -iBn -iBn -iBn -iBn -iBn -iBn -iBn -iBn +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW +fLW iBn iBn bdH @@ -124506,13 +124935,13 @@ lmz lmz lmz lmz -lmz -lmz -lmz -lmz -lmz -lmz -lmz +daz +daz +daz +daz +daz +daz +daz lmz lmz lmz @@ -124709,13 +125138,13 @@ lmz lmz lmz lmz -lmz -lmz -lmz -lmz -lmz -lmz -lmz +daz +jtj +cRN +cRN +tkk +bkv +daz lmz lmz lmz @@ -124913,10 +125342,10 @@ lmz lmz daz daz +kaD daz -daz -daz -daz +wnh +wnh daz daz daz @@ -125525,9 +125954,9 @@ pmV eGr xDC dIn -rby +sWk bIp -euN +any ujn sEK etM @@ -125726,7 +126155,7 @@ kfU daz ebN ebN -lnS +jAm uVv flf ebN @@ -126123,7 +126552,7 @@ lmz daz jYH ubA -cck +rXm wyQ fmv ubA @@ -126132,7 +126561,7 @@ mRn dJO vMt dkz -aGk +aOi ktQ teZ wkM @@ -126538,7 +126967,7 @@ fMt mEs gbm oBD -lFj +iAu vyE mTr wkM @@ -126944,7 +127373,7 @@ sTV daz ebN ebN -gbg +tWn uVv xwU ebN @@ -127149,9 +127578,9 @@ hTl jrH xDC yaQ -vLz +orE mFN -kSy +uQg bFg dDp nYg diff --git a/maps/map_files/USS_Runtime/USS_Runtime.dmm b/maps/map_files/USS_Runtime/USS_Runtime.dmm index 6dae65b01699..75d94f6a4cdb 100644 --- a/maps/map_files/USS_Runtime/USS_Runtime.dmm +++ b/maps/map_files/USS_Runtime/USS_Runtime.dmm @@ -29,6 +29,10 @@ /obj/effect/landmark/start/marine/medic, /turf/open/floor/almayer/plating, /area/event) +"m" = ( +/obj/effect/landmark/start/ai_tech, +/turf/open/floor/almayer/plating, +/area/event) "n" = ( /obj/effect/landmark/start/professor, /turf/open/floor/almayer/plating, @@ -247,7 +251,7 @@ a W F Q -b +m b b b diff --git a/tgui/packages/tgui/interfaces/AresAccessCode.jsx b/tgui/packages/tgui/interfaces/AresAccessCode.jsx new file mode 100644 index 000000000000..d331ee4164c6 --- /dev/null +++ b/tgui/packages/tgui/interfaces/AresAccessCode.jsx @@ -0,0 +1,75 @@ +import { useBackend } from '../backend'; +import { Box, Button, Flex } from '../components'; +import { Window } from '../layouts'; + +const PAGES = { + login: () => Login, + main: () => MainMenu, + announcements: () => AnnouncementLogs, + bioscans: () => BioscanLogs, + bombardments: () => BombardmentLogs, + apollo: () => ApolloLog, + access_log: () => AccessLogs, + delete_log: () => DeletionLogs, + flight_log: () => FlightLogs, + talking: () => ARESTalk, + deleted_talks: () => DeletedTalks, + read_deleted: () => ReadingTalks, + security: () => Security, + requisitions: () => Requisitions, + emergency: () => Emergency, + tech_log: () => TechLogs, + core_security: () => CoreSec, +}; + +export const AresAccessCode = (props) => { + const { data } = useBackend(); + const { local_current_menu } = data; + const PageComponent = PAGES[local_current_menu](); + + let themecolor = 'crtyellow'; + + return ( + + + + + + ); +}; + +const Login = (props) => { + const { act } = useBackend(); + + return ( + + AIDT Access Interface + + WY-DOS Executive + + Version 11 + Copyright © 2182, Weyland Yutani Corp. + + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/AresAdmin.jsx b/tgui/packages/tgui/interfaces/AresAdmin.jsx index 79a8e83a1f00..a32b45878f97 100644 --- a/tgui/packages/tgui/interfaces/AresAdmin.jsx +++ b/tgui/packages/tgui/interfaces/AresAdmin.jsx @@ -1,5 +1,5 @@ import { useBackend } from '../backend'; -import { Box, Button, Flex, Section, Stack } from '../components'; +import { Box, Button, Dropdown, Flex, Section, Stack } from '../components'; import { Window } from '../layouts'; const PAGES = { @@ -27,15 +27,15 @@ const PAGES = { export const AresAdmin = (props) => { const { data } = useBackend(); - const { current_menu, sudo } = data; - const PageComponent = PAGES[current_menu](); + const { local_current_menu, ares_sudo } = data; + const PageComponent = PAGES[local_current_menu](); let themecolor = 'crtyellow'; - if (sudo >= 1) { + if (ares_sudo >= 1) { themecolor = 'crtred'; - } else if (current_menu === 'emergency') { + } else if (local_current_menu === 'emergency') { themecolor = 'crtred'; - } else if (current_menu === 'core_security') { + } else if (local_current_menu === 'core_security') { themecolor = 'crtred'; } @@ -48,6 +48,16 @@ export const AresAdmin = (props) => { ); }; +const { data } = useBackend(); +const { is_pda } = data; +let remotelock = !is_pda; +let remotetip = 'You cannot do this via remote console.'; +let deletetip = remotetip; +if (!remotelock) { + remotetip = ''; + deletetip = 'Delete Record'; +} + const Login = (props) => { const { act } = useBackend(); @@ -86,8 +96,16 @@ const Login = (props) => { const MainMenu = (props) => { const { data, act } = useBackend(); - const { logged_in, access_text, last_page, current_menu, sudo, admin_login } = - data; + const { + ares_logged_in, + ares_access_text, + local_last_page, + local_current_menu, + ares_sudo, + local_admin_login, + faction_options, + sentry_setting, + } = data; return ( <> @@ -98,24 +116,26 @@ const MainMenu = (props) => { icon="arrow-left" px="2rem" textAlign="center" + tooltipPosition="top" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} /> )} - {sudo >= 1 && ( + {ares_sudo >= 1 && ( @@ -373,23 +410,49 @@ const MainMenu = (props) => { )} -
+

Core Security Protocols

+ + - - + AI Core Lockdown + + + + + act('update_sentries', { chosen_iff: value }) + } + width="90px" + tooltip="Change core sentries IFF settings." + />
@@ -400,24 +463,50 @@ const MainMenu = (props) => { +
+
+ {remotelock && ( + + +

Remote Admin

+
+ + + +
+ )}

ARES Actions

- {!active_convo.length && ( + {!local_active_convo.length && ( )} - {active_convo.map((message, i) => { + {local_active_convo.map((message, i) => { return ( {message} ); })} - {!!active_convo.length && ( + {!!local_active_convo.length && ( @@ -1071,9 +1183,12 @@ const ARESTalk = (props) => { ml="auto" px="2rem" bold + tooltipPosition="top" tooltip="Send a message as if you were the person logged in at the interface." onClick={() => - act('fake_message_ares', { active_convo: active_ref }) + act('fake_message_ares', { + local_active_convo: local_active_ref, + }) } > Send Fake Message @@ -1085,15 +1200,16 @@ const ARESTalk = (props) => {
- act('clear_conversation', { active_convo: active_ref }) + act('clear_conversation', { local_active_convo: local_active_ref }) } - disabled={!active_convo.length} + disabled={!local_active_convo.length} > Clear Conversation @@ -1105,12 +1221,12 @@ const ARESTalk = (props) => { const DeletedTalks = (props) => { const { data, act } = useBackend(); const { - logged_in, - access_text, - last_page, - current_menu, + ares_logged_in, + ares_access_text, + local_last_page, + local_current_menu, deleted_discussions, - admin_login, + local_admin_login, } = data; return ( @@ -1122,23 +1238,25 @@ const DeletedTalks = (props) => { icon="arrow-left" px="2rem" textAlign="center" + tooltipPosition="top" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} /> - {access_level >= 2 && ( + {local_access_level >= 2 && (

Access Level 2

@@ -215,7 +217,7 @@ const MainMenu = (props) => {
)} - {access_level >= 3 && ( + {local_access_level >= 3 && (

Access Level 3

@@ -248,7 +250,7 @@ const MainMenu = (props) => {
)} - {access_level >= 5 && ( + {local_access_level >= 5 && (

Access Level 5

@@ -295,7 +297,7 @@ const MainMenu = (props) => {
)} - {access_level >= 6 && ( + {local_access_level >= 6 && (

Access Level 6

@@ -315,7 +317,7 @@ const MainMenu = (props) => {
)} - {access_level >= 9 && ( + {local_access_level >= 9 && (

Access Level 9

@@ -348,12 +350,12 @@ const MainMenu = (props) => {
)} - {access_level >= 11 && ( + {local_access_level >= 11 && (

Maintenance Access

- {sudo === 0 && ( + {local_sudo === 0 && ( )} - {sudo >= 1 && ( + {local_sudo >= 1 && ( )} -
- )} -
- {(access_level === 3 || access_level >= 6) && ( -
-

Core Security Protocols

- - + - + + )} +
+ {(local_access_level === 3 || local_access_level >= 6) && ( +
+

Core Security Protocols

+ + + + { AI Core Lockdown + + + act('update_sentries', { chosen_iff: value }) + } + width="90px" + disabled={local_access_level < 9} + tooltip="Change core sentries IFF settings." + /> +
)} @@ -430,12 +456,12 @@ const MainMenu = (props) => { const AnnouncementLogs = (props) => { const { data, act } = useBackend(); const { - logged_in, - access_text, - last_page, - current_menu, + local_logged_in, + local_access_text, + local_last_page, + local_current_menu, records_announcement, - access_level, + local_access_level, } = data; return ( @@ -449,7 +475,7 @@ const AnnouncementLogs = (props) => { textAlign="center" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} />
- {!active_convo.length && ( + {!local_active_convo.length && ( )} - {active_convo.map((message, i) => { + {local_active_convo.map((message, i) => { return ( {message} ); })} - {!!active_convo.length && ( + {!!local_active_convo.length && ( @@ -1020,9 +1065,9 @@ const ARESTalk = (props) => { fontSize="1.5rem" bold onClick={() => - act('clear_conversation', { active_convo: active_ref }) + act('clear_conversation', { passed_active_convo: local_active_ref }) } - disabled={!active_convo.length} + disabled={!local_active_convo.length} > Clear Conversation @@ -1034,10 +1079,10 @@ const ARESTalk = (props) => { const DeletedTalks = (props) => { const { data, act } = useBackend(); const { - logged_in, - access_text, - last_page, - current_menu, + local_logged_in, + local_access_text, + local_last_page, + local_current_menu, deleted_discussions, } = data; @@ -1052,7 +1097,7 @@ const DeletedTalks = (props) => { textAlign="center" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} /> @@ -1296,12 +1341,12 @@ const Requisitions = (props) => { const FlightLogs = (props) => { const { data, act } = useBackend(); const { - logged_in, - access_text, - last_page, - current_menu, + local_logged_in, + local_access_text, + local_last_page, + local_current_menu, records_flight, - access_level, + local_access_level, } = data; return ( @@ -1315,7 +1360,7 @@ const FlightLogs = (props) => { textAlign="center" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} /> )} - {access_level === 3 && ( + {local_access_level === 3 && ( { - {access_level >= 4 && ( + {local_access_level >= 4 && (

Certified Personnel

@@ -217,7 +219,7 @@ const MainMenu = (props) => {
)} - {access_level >= 5 && ( + {local_access_level >= 5 && (

Task Management

@@ -251,32 +253,28 @@ const MainMenu = (props) => {
)}
- {access_level >= 5 && ( + {local_access_level >= 5 && (

Core Security Protocols

+ - - - - + { AI Core Lockdown + + + act('update_sentries', { chosen_iff: value }) + } + width="90px" + disabled={local_access_level < 6} + /> +
)} @@ -294,7 +304,13 @@ const MainMenu = (props) => { const ApolloLog = (props) => { const { data, act } = useBackend(); - const { logged_in, access_text, last_page, current_menu, apollo_log } = data; + const { + local_logged_in, + local_access_text, + local_last_page, + local_current_menu, + apollo_log, + } = data; return ( <> @@ -307,7 +323,7 @@ const ApolloLog = (props) => { textAlign="center" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} /> @@ -831,7 +853,7 @@ const AccessRequests = (props) => { view_icon = 'circle-minus'; } let can_cancel = 'Yes'; - if (ticket.submitter !== logged_in) { + if (ticket.submitter !== local_logged_in) { can_cancel = 'No'; } else if (ticket.lock_status === 'CLOSED') { can_cancel = 'No'; @@ -877,8 +899,13 @@ const AccessRequests = (props) => { const AccessTickets = (props) => { const { data, act } = useBackend(); - const { logged_in, access_text, last_page, current_menu, access_tickets } = - data; + const { + local_logged_in, + local_access_text, + local_last_page, + local_current_menu, + access_tickets, + } = data; return ( <> @@ -891,7 +918,7 @@ const AccessTickets = (props) => { textAlign="center" tooltip="Go back" onClick={() => act('go_back')} - disabled={last_page === current_menu} + disabled={local_last_page === local_current_menu} />