diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm
index f975a67824ef..306f37deb8cb 100644
--- a/code/__DEFINES/dcs/signals/signals_global.dm
+++ b/code/__DEFINES/dcs/signals/signals_global.dm
@@ -69,6 +69,9 @@
/// From /proc/biohazard_lockdown()
#define COMSIG_GLOB_RESEARCH_LOCKDOWN "!research_lockdown_closed"
#define COMSIG_GLOB_RESEARCH_LIFT "!research_lockdown_opened"
+/// From /proc/aicore_lockdown()
+#define COMSIG_GLOB_AICORE_LOCKDOWN "!aicore_lockdown_closed"
+#define COMSIG_GLOB_AICORE_LIFT "!aicore_lockdown_opened"
/// From /obj/structure/machinery/power/reactor/proc/set_overloading() : (set_overloading)
#define COMSIG_GLOB_GENERATOR_SET_OVERLOADING "!generator_set_overloading"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index e2bd868f9a80..dbd8dbe7ce41 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -120,6 +120,7 @@
#define CANDAZE (1<<18)
#define CANSLOW (1<<19)
#define NO_PERMANENT_DAMAGE (1<<20)
+#define CORRUPTED_ALLY (1<<21)
// =============================
// hive types
diff --git a/code/datums/mob_hud.dm b/code/datums/mob_hud.dm
index 5e57b8f5616c..88785474bc23 100644
--- a/code/datums/mob_hud.dm
+++ b/code/datums/mob_hud.dm
@@ -422,6 +422,10 @@ GLOBAL_LIST_INIT_TYPED(huds, /datum/mob_hud, list(
if(hive && hive.color)
holder3.color = hive.color
+ if(status_flags & CORRUPTED_ALLY)
+ holder4.color = "#80ff80"
+ holder4.icon_state = "hudalien_ally"
+
if(stat == DEAD || status_flags & FAKEDEATH)
if(revive_enabled)
if(!client)
diff --git a/code/defines/procs/announcement.dm b/code/defines/procs/announcement.dm
index 2ebba6a774e8..d6251748f3a0 100644
--- a/code/defines/procs/announcement.dm
+++ b/code/defines/procs/announcement.dm
@@ -42,6 +42,11 @@
continue
if(is_mainship_level(H.z)) // People on ship see everything
continue
+
+ // If they have iff AND a marine headset they will recieve announcements
+ if ((FACTION_MARINE in H.wear_id?.faction_group) && (istype(H.wear_l_ear, /obj/item/device/radio/headset/almayer) || istype(H.wear_r_ear, /obj/item/device/radio/headset/almayer)))
+ continue
+
if((H.faction != faction_to_display && !add_PMCs) || (H.faction != faction_to_display && add_PMCs && !(H.faction in FACTION_LIST_WY)) && !(faction_to_display in H.faction_group)) //faction checks
targets.Remove(H)
diff --git a/code/game/cas_manager/datums/cas_fire_envelope.dm b/code/game/cas_manager/datums/cas_fire_envelope.dm
index cc38b034c764..864d7f23a3e8 100644
--- a/code/game/cas_manager/datums/cas_fire_envelope.dm
+++ b/code/game/cas_manager/datums/cas_fire_envelope.dm
@@ -3,7 +3,10 @@
var/list/datum/cas_fire_mission/missions
var/fire_length
var/grace_period //how much time you have after initiating fire mission and before you can't change firemissions
- var/flyto_period //how much time it takes from sound alarm start to first hit. CAS is vulnerable here
+ var/first_warning
+ var/second_warning
+ var/third_warning
+ var/execution_start
var/flyoff_period //how much time it takes after shots fired to get off the map. CAS is vulnerable here
var/cooldown_period //how much time you have to wait before new Fire Mission run
var/soundeffect //what sound effect to play
@@ -36,10 +39,6 @@
for(var/datum/cas_fire_mission/mission in missions)
.["missions"] += list(mission.ui_data(user))
-
-/datum/cas_fire_envelope/proc/get_total_duration()
- return grace_period+flyto_period+flyoff_period
-
/datum/cas_fire_envelope/proc/update_weapons(list/obj/structure/dropship_equipment/weapon/weapons)
for(var/datum/cas_fire_mission/mission in missions)
mission.update_weapons(weapons, fire_length)
@@ -242,14 +241,60 @@
/datum/cas_fire_envelope/proc/check_firemission_loc(datum/cas_signal/target_turf)
return TRUE //redefined in child class
-/**
- * Execute firemission.
- */
+/// Step 1: Sets the stat to FIRE_MISSION_STATE_ON_TARGET and starts the sound effect for the fire mission.
+/datum/cas_fire_envelope/proc/play_sound(atom/target_turf)
+ stat = FIRE_MISSION_STATE_ON_TARGET
+ change_current_loc(target_turf)
+ playsound(target_turf, soundeffect, vol = 70, vary = TRUE, sound_range = 50, falloff = 8)
+
+/// Step 2, 3, 4: Warns nearby mobs of the incoming fire mission. Warning as 1 is non-precise, whereas 2 and 3 are precise.
+/datum/cas_fire_envelope/proc/chat_warning(atom/target_turf, range = 10, warning_number = 1)
+ var/ds_identifier = "LARGE BIRD"
+ var/fm_identifier = "SPIT FIRE"
+ var/relative_dir
+ for(var/mob/mob in range(15, target_turf))
+ if (mob.mob_flags & KNOWS_TECHNOLOGY)
+ ds_identifier = "DROPSHIP"
+ fm_identifier = "FIRE"
+ if(get_turf(mob) == target_turf)
+ relative_dir = 0
+ else
+ relative_dir = Get_Compass_Dir(mob, target_turf)
+ switch(warning_number)
+ if(1)
+ mob.show_message( \
+ SPAN_HIGHDANGER("YOU HEAR THE [ds_identifier] ROAR AS IT PREPARES TO [fm_identifier] NEAR YOU!"),SHOW_MESSAGE_VISIBLE, \
+ SPAN_HIGHDANGER("YOU HEAR SOMETHING FLYING CLOSER TO YOU!") , SHOW_MESSAGE_AUDIBLE \
+ )
+ if(2)
+ mob.show_message( \
+ SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
+ SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
+ )
+ if(3)
+ mob.show_message( \
+ SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
+ SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
+ )
+
+/// Step 5: Actually executes the fire mission updating stat to FIRE_MISSION_STATE_FIRING and then FIRE_MISSION_STATE_OFF_TARGET
+/datum/cas_fire_envelope/proc/open_fire(atom/target_turf,datum/cas_fire_mission/mission,dir)
+ stat = FIRE_MISSION_STATE_FIRING
+ mission.execute_firemission(linked_console, target_turf, dir, fire_length, step_delay, src)
+ stat = FIRE_MISSION_STATE_OFF_TARGET
+
+/// Step 6: Sets the fire mission stat to FIRE_MISSION_STATE_COOLDOWN
+/datum/cas_fire_envelope/proc/flyoff()
+ stat = FIRE_MISSION_STATE_COOLDOWN
+
+/// Step 7: Sets the fire mission stat to FIRE_MISSION_STATE_IDLE
+/datum/cas_fire_envelope/proc/end_cooldown()
+ stat = FIRE_MISSION_STATE_IDLE
+
+
/datum/cas_fire_envelope/proc/execute_firemission_unsafe(datum/cas_signal/signal, turf/target_turf, dir, datum/cas_fire_mission/mission)
stat = FIRE_MISSION_STATE_IN_TRANSIT
to_chat(usr, SPAN_ALERT("Firemission underway!"))
- sleep(grace_period)
- stat = FIRE_MISSION_STATE_ON_TARGET
if(!target_turf)
stat = FIRE_MISSION_STATE_IDLE
mission_error = "Target Lost."
@@ -258,29 +303,27 @@
stat = FIRE_MISSION_STATE_IDLE
mission_error = "Target is off bounds or obstructed."
return
- change_current_loc(target_turf)
- playsound(source = target_turf, soundin = soundeffect, vol = 70, vary = TRUE, sound_range = 50, falloff = 8)
- for(var/mob/mob in range(15, target_turf))
- var/ds_identifier = "LARGE BIRD"
- var/fm_identifier = "SPIT FIRE"
- if (mob.mob_flags & KNOWS_TECHNOLOGY)
- ds_identifier = "DROPSHIP"
- fm_identifier = "FIRE"
+ var/obj/effect/firemission_effect = new(target_turf)
- mob.show_message( \
- SPAN_HIGHDANGER("YOU HEAR THE [ds_identifier] ROAR AS IT PREPARES TO [fm_identifier] NEAR YOU!"),SHOW_MESSAGE_VISIBLE, \
- SPAN_HIGHDANGER("YOU HEAR SOMETHING FLYING CLOSER TO YOU!") , SHOW_MESSAGE_AUDIBLE \
- )
+ firemission_effect.icon = 'icons/obj/items/weapons/projectiles.dmi'
+ firemission_effect.icon_state = "laser_target2"
+ firemission_effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ firemission_effect.invisibility = INVISIBILITY_MAXIMUM
+ QDEL_IN(firemission_effect, 12 SECONDS)
- sleep(flyto_period)
- stat = FIRE_MISSION_STATE_FIRING
- mission.execute_firemission(linked_console, target_turf, dir, fire_length, step_delay, src)
- stat = FIRE_MISSION_STATE_OFF_TARGET
- sleep(flyoff_period)
- stat = FIRE_MISSION_STATE_COOLDOWN
- sleep(cooldown_period)
- stat = FIRE_MISSION_STATE_IDLE
+
+ notify_ghosts(header = "CAS Fire Mission", message = "[usr ? usr : "Someone"] is launching Fire Mission '[mission.name]' at [get_area(target_turf)].", source = firemission_effect)
+ msg_admin_niche("[usr ? key_name(usr) : "Someone"] is launching Fire Mission '[mission.name]' at ([target_turf.x],[target_turf.y],[target_turf.z]) [ADMIN_JMP(target_turf)]")
+
+
+ addtimer(CALLBACK(src, PROC_REF(play_sound), target_turf), grace_period)
+ addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 15, 1), first_warning)
+ addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 15, 2), second_warning)
+ addtimer(CALLBACK(src, PROC_REF(chat_warning), target_turf, 10, 3), third_warning)
+ addtimer(CALLBACK(src, PROC_REF(open_fire), target_turf, mission,dir), execution_start)
+ addtimer(CALLBACK(src, PROC_REF(flyoff)), flyoff_period)
+ addtimer(CALLBACK(src, PROC_REF(end_cooldown)), cooldown_period)
/**
* Change attack vector for firemission
@@ -324,10 +367,13 @@
/datum/cas_fire_envelope/uscm_dropship
fire_length = 12
- grace_period = 5 SECONDS
- flyto_period = 4 SECONDS //sleep in the FM itself has been increased by one more second
- flyoff_period = 5 SECONDS
- cooldown_period = 10 SECONDS
+ grace_period = 5 SECONDS
+ first_warning = 6 SECONDS
+ second_warning = 8 SECONDS
+ third_warning = 9 SECONDS
+ execution_start = 10 SECONDS
+ flyoff_period = 15 SECONDS
+ cooldown_period = 25 SECONDS
soundeffect = 'sound/weapons/dropship_sonic_boom.ogg' //BOOM~WOOOOOSH~HSOOOOOW~BOOM
step_delay = 3
max_offset = 12
diff --git a/code/game/cas_manager/datums/cas_fire_mission.dm b/code/game/cas_manager/datums/cas_fire_mission.dm
index 927dded210f0..dc55e057edcd 100644
--- a/code/game/cas_manager/datums/cas_fire_mission.dm
+++ b/code/game/cas_manager/datums/cas_fire_mission.dm
@@ -164,51 +164,6 @@
if(initial_turf == null || check(linked_console) != FIRE_MISSION_ALL_GOOD)
return FIRE_MISSION_NOT_EXECUTABLE
- var/obj/effect/firemission_effect = new(initial_turf)
-
- firemission_effect.icon = 'icons/obj/items/weapons/projectiles.dmi'
- firemission_effect.icon_state = "laser_target2"
- firemission_effect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- firemission_effect.invisibility = INVISIBILITY_MAXIMUM
- QDEL_IN(firemission_effect, 5 SECONDS)
-
- notify_ghosts(header = "CAS Fire Mission", message = "[usr ? usr : "Someone"] is launching Fire Mission '[name]' at [get_area(initial_turf)].", source = firemission_effect)
- msg_admin_niche("[usr ? key_name(usr) : "Someone"] is launching Fire Mission '[name]' at ([initial_turf.x],[initial_turf.y],[initial_turf.z]) [ADMIN_JMP(initial_turf)]")
-
- var/relative_dir
- for(var/mob/mob in range(15, initial_turf))
- if(get_turf(mob) == initial_turf)
- relative_dir = 0
- else
- relative_dir = Get_Compass_Dir(mob, initial_turf)
-
- var/ds_identifier = "LARGE BIRD"
- if (mob.mob_flags & KNOWS_TECHNOLOGY)
- ds_identifier = "DROPSHIP"
-
- mob.show_message( \
- SPAN_HIGHDANGER("A [ds_identifier] FLIES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_VISIBLE, \
- SPAN_HIGHDANGER("YOU HEAR SOMETHING GO [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), SHOW_MESSAGE_AUDIBLE \
- )
-
- // Xenos have time to react to the first message
- sleep(1.5 SECONDS)
-
- for(var/mob/mob in range(10, initial_turf))
- if(get_turf(mob) == initial_turf)
- relative_dir = 0
- else
- relative_dir = Get_Compass_Dir(mob, initial_turf)
-
- var/ds_identifier = "LARGE BIRD"
- if (mob.mob_flags & KNOWS_TECHNOLOGY)
- ds_identifier = "DROPSHIP"
-
- mob.show_message( \
- SPAN_HIGHDANGER("A [ds_identifier] FIRES [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), 1, \
- SPAN_HIGHDANGER("YOU HEAR SOMETHING FIRE [SPAN_UNDERLINE(relative_dir ? uppertext(("TO YOUR " + dir2text(relative_dir))) : uppertext("right above you"))]!"), 2 \
- )
-
var/turf/current_turf = initial_turf
var/tally_step = steps / mission_length //how much shots we need before moving to next turf
var/next_step = tally_step //when we move to next turf
diff --git a/code/game/machinery/ARES/ARES_interface.dm b/code/game/machinery/ARES/ARES_interface.dm
index 341e6a05acf4..6905c47febb8 100644
--- a/code/game/machinery/ARES/ARES_interface.dm
+++ b/code/game/machinery/ARES/ARES_interface.dm
@@ -522,5 +522,12 @@
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(playsound)
playsound(src, "keyboard_alt", 15, 1)
diff --git a/code/game/machinery/ARES/ARES_interface_apollo.dm b/code/game/machinery/ARES/ARES_interface_apollo.dm
index 48fcad588574..37b2fbda0ecb 100644
--- a/code/game/machinery/ARES/ARES_interface_apollo.dm
+++ b/code/game/machinery/ARES/ARES_interface_apollo.dm
@@ -158,29 +158,29 @@
return
var/playsound = TRUE
- var/mob/living/carbon/human/operator = ui.user
+ var/mob/living/carbon/human/user = ui.user
switch (action)
if("go_back")
if(!last_menu)
- return to_chat(operator, SPAN_WARNING("Error, no previous page detected."))
+ 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/obj/item/card/id/idcard = operator.get_active_hand()
+ var/obj/item/card/id/idcard = user.get_active_hand()
if(istype(idcard))
authentication = get_ares_access(idcard)
last_login = idcard.registered_name
- else if(operator.wear_id)
- idcard = operator.wear_id
+ else if(user.wear_id)
+ idcard = user.wear_id
if(istype(idcard))
authentication = get_ares_access(idcard)
last_login = idcard.registered_name
else
- to_chat(operator, SPAN_WARNING("You require an ID card to access this terminal!"))
+ to_chat(user, SPAN_WARNING("You require an ID card to access this terminal!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
if(authentication)
@@ -222,23 +222,23 @@
if("new_report")
var/priority_report = FALSE
- var/maint_type = tgui_input_list(operator, "What is the type of maintenance item you wish to report?", "Report Category", GLOB.maintenance_categories, 30 SECONDS)
+ 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(operator, "What are the details for this report?", "Ticket Details", encode = FALSE)
+ var/details = tgui_input_text(user, "What are the details for this report?", "Ticket Details", encode = FALSE)
if(!details)
return FALSE
if((authentication >= APOLLO_ACCESS_REPORTER) && !priority_report)
- var/is_priority = tgui_alert(operator, "Is this a priority report?", "Priority designation", list("Yes", "No"))
+ 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(operator, "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")
+ 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")
if(link)
var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, maint_type, details, priority_report)
@@ -247,7 +247,7 @@
ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.")
else
send_notifcation()
- log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.")
+ log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(user)] as [last_login] with Category '[maint_type]' and Details of '[details]'.")
return TRUE
return FALSE
@@ -259,14 +259,14 @@
var/assigned = ticket.ticket_assignee
if(assigned)
if(assigned == last_login)
- var/prompt = tgui_alert(operator, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No"))
+ 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(operator, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No"))
+ 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)
@@ -279,9 +279,9 @@
if(!istype(ticket))
return FALSE
if(ticket.ticket_submitter != last_login)
- to_chat(operator, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!"))
+ to_chat(user, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!"))
return FALSE
- to_chat(operator, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled."))
+ 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.")
@@ -294,9 +294,9 @@
if(!istype(ticket))
return FALSE
if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.)
- to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
+ to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
return FALSE
- var/choice = tgui_alert(operator, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS)
+ var/choice = tgui_alert(user, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS)
switch(choice)
if(TICKET_COMPLETED)
ticket.ticket_status = TICKET_COMPLETED
@@ -308,39 +308,39 @@
ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].")
else
send_notifcation()
- to_chat(operator, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice]."))
+ to_chat(user, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice]."))
return TRUE
if("new_access")
- var/obj/item/card/id/idcard = operator.get_active_hand()
+ var/obj/item/card/id/idcard = user.get_active_hand()
var/has_id = FALSE
if(istype(idcard))
has_id = TRUE
- else if(operator.wear_id)
- idcard = operator.wear_id
+ else if(user.wear_id)
+ idcard = user.wear_id
if(istype(idcard))
has_id = TRUE
if(!has_id)
- to_chat(operator, SPAN_WARNING("You require an ID card to request an access ticket!"))
+ to_chat(user, SPAN_WARNING("You require an ID card to request an access ticket!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
if(idcard.registered_name != last_login)
- to_chat(operator, SPAN_WARNING("This ID card does not match the active login!"))
+ to_chat(user, SPAN_WARNING("This ID card does not match the active login!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
- var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE)
+ var/details = tgui_input_text(user, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE)
if(!details)
return FALSE
- var/confirm = alert(operator, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No")
+ var/confirm = alert(user, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No")
if(confirm != "Yes" || !link)
return FALSE
var/datum/ares_ticket/access/access_ticket = new(last_login, details, FALSE, idcard.registered_gid)
link.waiting_ids += idcard
link.tickets_access += access_ticket
- log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Details of '[details]'.")
- message_admins(SPAN_STAFF_IC("[key_name_admin(operator)] created a new ARES Access Ticket."), 1)
+ log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(user)] as [last_login] with Details of '[details]'.")
+ message_admins(SPAN_STAFF_IC("[key_name_admin(user)] created a new ARES Access Ticket."), 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] requesting access for '[details].")
return TRUE
@@ -361,9 +361,9 @@
access_ticket.ticket_status = TICKET_RETURNED
identification.access -= ACCESS_MARINE_AI_TEMP
- identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]."
+ identification.modification_log += "Temporary AI Access self-returned by [key_name(user)]."
- to_chat(operator, SPAN_NOTICE("Temporary Access Ticket surrendered."))
+ to_chat(user, SPAN_NOTICE("Temporary Access Ticket surrendered."))
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] surrendered their access.")
@@ -372,7 +372,7 @@
datacore.apollo_login_list += "[last_login] at [worldtime2text()], Surrendered Temporary Access Ticket."
return TRUE
- to_chat(operator, SPAN_WARNING("This ID card does not have an access ticket!"))
+ to_chat(user, SPAN_WARNING("This ID card does not have an access ticket!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
@@ -384,7 +384,7 @@
for(var/obj/item/card/id/identification in link.waiting_ids)
if(identification.registered_gid != access_ticket.user_id_num)
continue
- identification.handle_ares_access(last_login, operator)
+ identification.handle_ares_access(last_login, user)
access_ticket.ticket_status = TICKET_GRANTED
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was granted access by [last_login].")
@@ -392,7 +392,7 @@
for(var/obj/item/card/id/identification in link.active_ids)
if(identification.registered_gid != access_ticket.user_id_num)
continue
- identification.handle_ares_access(last_login, operator)
+ identification.handle_ares_access(last_login, user)
access_ticket.ticket_status = TICKET_REVOKED
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] had access revoked by [last_login].")
@@ -404,10 +404,10 @@
if(!istype(access_ticket))
return FALSE
if(access_ticket.ticket_assignee != last_login && access_ticket.ticket_assignee) //must be claimed by you or unclaimed.)
- to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
+ to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
return FALSE
access_ticket.ticket_status = TICKET_REJECTED
- to_chat(operator, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as 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]: [access_ticket.ticket_submitter] was rejected access by [last_login].")
for(var/obj/item/card/id/identification in link.waiting_ids)
if(identification.registered_gid != access_ticket.user_id_num)
@@ -422,36 +422,41 @@
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(operator, SPAN_WARNING("ERROR: Gas release failure."))
+ 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(operator, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent."))
+ 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(operator, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag]."))
+ 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", "[last_login] released Nerve Gas from Vent '[sec_vent.vent_tag]'.")
sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS)
- log_admin("[key_name(operator)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.")
+ 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(playsound)
playsound(src, "keyboard_alt", 15, 1)
/obj/item/card/id/proc/handle_ares_access(logged_in = MAIN_AI_SYSTEM, mob/user)
- var/operator = key_name(user)
+ var/changer = logged_in
+ if(user)
+ changer = key_name(user)
var/datum/ares_link/link = GLOB.ares_link
- if(logged_in == MAIN_AI_SYSTEM)
- if(!user)
- operator = "[MAIN_AI_SYSTEM] (Automated)"
- else
- operator = "[user.ckey]/([MAIN_AI_SYSTEM])"
+
if(ACCESS_MARINE_AI_TEMP in access)
access -= ACCESS_MARINE_AI_TEMP
link.active_ids -= src
- modification_log += "Temporary AI access revoked by [operator]"
+ log_idmod(src, "Temporary AI access revoked by [logged_in]", changer)
to_chat(user, SPAN_NOTICE("Access revoked from [registered_name]."))
var/mob/living/carbon/human/id_owner = registered_ref?.resolve()
if(id_owner)
@@ -459,7 +464,7 @@
playsound_client(id_owner?.client, 'sound/machines/pda_ping.ogg', src, 25, 0)
else
access += ACCESS_MARINE_AI_TEMP
- modification_log += "Temporary AI access granted by [operator]"
+ log_idmod(src, "Temporary AI access granted by [logged_in]", changer)
to_chat(user, SPAN_NOTICE("Access granted to [registered_name]."))
link.waiting_ids -= src
link.active_ids += src
diff --git a/code/game/machinery/ARES/ARES_procs.dm b/code/game/machinery/ARES/ARES_procs.dm
index 05f110ec1a0c..8ecb711e9fb7 100644
--- a/code/game/machinery/ARES/ARES_procs.dm
+++ b/code/game/machinery/ARES/ARES_procs.dm
@@ -106,9 +106,13 @@ GLOBAL_LIST_INIT(maintenance_categories, list(
/// Is nuke request usable or not?
var/nuke_available = TRUE
+ /// Status of the AI Core Lockdown
+ var/ai_lockdown_active = FALSE
+
COOLDOWN_DECLARE(ares_distress_cooldown)
COOLDOWN_DECLARE(ares_nuclear_cooldown)
COOLDOWN_DECLARE(ares_quarters_cooldown)
+ COOLDOWN_DECLARE(aicore_lockdown)
// ------ ARES Logging Procs ------ //
/proc/ares_is_active()
diff --git a/code/game/machinery/ARES/apollo_pda.dm b/code/game/machinery/ARES/apollo_pda.dm
index e447bb6f7ee7..2f18a5ba0522 100644
--- a/code/game/machinery/ARES/apollo_pda.dm
+++ b/code/game/machinery/ARES/apollo_pda.dm
@@ -181,29 +181,29 @@
return
var/playsound = TRUE
- var/mob/living/carbon/human/operator = ui.user
+ var/mob/living/carbon/human/user = ui.user
switch (action)
if("go_back")
if(!last_menu)
- return to_chat(operator, SPAN_WARNING("Error, no previous page detected."))
+ 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/obj/item/card/id/idcard = operator.get_active_hand()
+ var/obj/item/card/id/idcard = user.get_active_hand()
if(istype(idcard))
authentication = get_ares_access(idcard)
last_login = idcard.registered_name
- else if(operator.wear_id)
- idcard = operator.wear_id
+ else if(user.wear_id)
+ idcard = user.wear_id
if(istype(idcard))
authentication = get_ares_access(idcard)
last_login = idcard.registered_name
else
- to_chat(operator, SPAN_WARNING("You require an ID card to access this terminal!"))
+ to_chat(user, SPAN_WARNING("You require an ID card to access this terminal!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
if(authentication)
@@ -248,23 +248,23 @@
if("new_report")
var/priority_report = FALSE
- var/maint_type = tgui_input_list(operator, "What is the type of maintenance item you wish to report?", "Report Category", GLOB.maintenance_categories, 30 SECONDS)
+ 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(operator, "What are the details for this report?", "Ticket Details", encode = FALSE)
+ var/details = tgui_input_text(user, "What are the details for this report?", "Ticket Details", encode = FALSE)
if(!details)
return FALSE
if((authentication >= APOLLO_ACCESS_REPORTER) && !priority_report)
- var/is_priority = tgui_alert(operator, "Is this a priority report?", "Priority designation", list("Yes", "No"))
+ 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(operator, "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")
+ 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")
if(link)
var/datum/ares_ticket/maintenance/maint_ticket = new(last_login, maint_type, details, priority_report)
@@ -273,7 +273,7 @@
ares_apollo_talk("Priority Maintenance Report: [maint_type] - ID [maint_ticket.ticket_id]. Seek and resolve.")
else
send_notifcation()
- log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(operator)] as [last_login] with Category '[maint_type]' and Details of '[details]'.")
+ log_game("ARES: Maintenance Ticket '\ref[maint_ticket]' created by [key_name(user)] as [last_login] with Category '[maint_type]' and Details of '[details]'.")
return TRUE
return FALSE
@@ -285,14 +285,14 @@
var/assigned = ticket.ticket_assignee
if(assigned)
if(assigned == last_login)
- var/prompt = tgui_alert(operator, "You already claimed this ticket! Do you wish to drop your claim?", "Unclaim ticket", list("Yes", "No"))
+ 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(operator, "This ticket has already been claimed by [assigned]! Do you wish to override their claim?", "Claim Override", list("Yes", "No"))
+ 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)
@@ -305,9 +305,9 @@
if(!istype(ticket))
return FALSE
if(ticket.ticket_submitter != last_login)
- to_chat(operator, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!"))
+ to_chat(user, SPAN_WARNING("You cannot cancel a ticket that does not belong to you!"))
return FALSE
- to_chat(operator, SPAN_WARNING("[ticket.ticket_type] [ticket.ticket_id] has been cancelled."))
+ 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.")
@@ -320,9 +320,9 @@
if(!istype(ticket))
return FALSE
if(ticket.ticket_assignee != last_login && ticket.ticket_assignee) //must be claimed by you or unclaimed.)
- to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
+ to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
return FALSE
- var/choice = tgui_alert(operator, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS)
+ var/choice = tgui_alert(user, "What do you wish to mark the ticket as?", "Mark", list(TICKET_COMPLETED, TICKET_REJECTED), 20 SECONDS)
switch(choice)
if(TICKET_COMPLETED)
ticket.ticket_status = TICKET_COMPLETED
@@ -334,39 +334,39 @@
ares_apollo_talk("Priority [ticket.ticket_type] [ticket.ticket_id] has been [choice] by [last_login].")
else
send_notifcation()
- to_chat(operator, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice]."))
+ to_chat(user, SPAN_NOTICE("[ticket.ticket_type] [ticket.ticket_id] marked as [choice]."))
return TRUE
if("new_access")
- var/obj/item/card/id/idcard = operator.get_active_hand()
+ var/obj/item/card/id/idcard = user.get_active_hand()
var/has_id = FALSE
if(istype(idcard))
has_id = TRUE
- else if(operator.wear_id)
- idcard = operator.wear_id
+ else if(user.wear_id)
+ idcard = user.wear_id
if(istype(idcard))
has_id = TRUE
if(!has_id)
- to_chat(operator, SPAN_WARNING("You require an ID card to request an access ticket!"))
+ to_chat(user, SPAN_WARNING("You require an ID card to request an access ticket!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
if(idcard.registered_name != last_login)
- to_chat(operator, SPAN_WARNING("This ID card does not match the active login!"))
+ to_chat(user, SPAN_WARNING("This ID card does not match the active login!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
- var/details = tgui_input_text(operator, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE)
+ var/details = tgui_input_text(user, "What is the purpose of this access ticket?", "Ticket Details", encode = FALSE)
if(!details)
return FALSE
- var/confirm = alert(operator, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No")
+ var/confirm = alert(user, "Please confirm the submission of your access ticket request.\n\nHolder: '[last_login]'\nDetails: '[details]'\n\nIs this correct?", "Confirmation", "Yes", "No")
if(confirm != "Yes" || !link)
return FALSE
var/datum/ares_ticket/access/access_ticket = new(last_login, details, FALSE, idcard.registered_gid)
link.waiting_ids += idcard
link.tickets_access += access_ticket
- log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(operator)] as [last_login] with Details of '[details]'.")
- message_admins(SPAN_STAFF_IC("[key_name_admin(operator)] created a new ARES Access Ticket."), 1)
+ log_game("ARES: Access Ticket '\ref[access_ticket]' created by [key_name(user)] as [last_login] with Details of '[details]'.")
+ message_admins(SPAN_STAFF_IC("[key_name_admin(user)] created a new ARES Access Ticket."), 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] requesting access for '[details].")
return TRUE
@@ -387,9 +387,9 @@
access_ticket.ticket_status = TICKET_RETURNED
identification.access -= ACCESS_MARINE_AI_TEMP
- identification.modification_log += "Temporary AI Access self-returned by [key_name(operator)]."
+ identification.modification_log += "Temporary AI Access self-returned by [key_name(user)]."
- to_chat(operator, SPAN_NOTICE("Temporary Access Ticket surrendered."))
+ to_chat(user, SPAN_NOTICE("Temporary Access Ticket surrendered."))
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] surrendered their access.")
@@ -398,7 +398,7 @@
datacore.apollo_login_list += "[last_login] at [worldtime2text()], Surrendered Temporary Access Ticket."
return TRUE
- to_chat(operator, SPAN_WARNING("This ID card does not have an access ticket!"))
+ to_chat(user, SPAN_WARNING("This ID card does not have an access ticket!"))
playsound(src, 'sound/machines/buzz-two.ogg', 15, 1)
return FALSE
@@ -410,7 +410,7 @@
for(var/obj/item/card/id/identification in link.waiting_ids)
if(identification.registered_gid != access_ticket.user_id_num)
continue
- identification.handle_ares_access(last_login, operator)
+ identification.handle_ares_access(last_login, user)
access_ticket.ticket_status = TICKET_GRANTED
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] was granted access by [last_login].")
@@ -418,7 +418,7 @@
for(var/obj/item/card/id/identification in link.active_ids)
if(identification.registered_gid != access_ticket.user_id_num)
continue
- identification.handle_ares_access(last_login, operator)
+ identification.handle_ares_access(last_login, user)
access_ticket.ticket_status = TICKET_REVOKED
playsound(src, 'sound/machines/chime.ogg', 15, 1)
ares_apollo_talk("Access Ticket [access_ticket.ticket_id]: [access_ticket.ticket_submitter] had access revoked by [last_login].")
@@ -430,10 +430,10 @@
if(!istype(access_ticket))
return FALSE
if(access_ticket.ticket_assignee != last_login && access_ticket.ticket_assignee) //must be claimed by you or unclaimed.)
- to_chat(operator, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
+ to_chat(user, SPAN_WARNING("You cannot update a ticket that is not assigned to you!"))
return FALSE
access_ticket.ticket_status = TICKET_REJECTED
- to_chat(operator, SPAN_NOTICE("[access_ticket.ticket_type] [access_ticket.ticket_id] marked as 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]: [access_ticket.ticket_submitter] was rejected access by [last_login].")
for(var/obj/item/card/id/identification in link.waiting_ids)
if(identification.registered_gid != access_ticket.user_id_num)
@@ -448,20 +448,27 @@
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(operator, SPAN_WARNING("ERROR: Gas release failure."))
+ 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(operator, SPAN_WARNING("ERROR: Insufficient gas reserve for this vent."))
+ 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(operator, SPAN_WARNING("Initiating gas release from [sec_vent.vent_tag]."))
+ 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", "[last_login] released Nerve Gas from Vent '[sec_vent.vent_tag]'.")
sec_vent.create_gas(VENT_GAS_CN20_XENO, 6, 5 SECONDS)
- log_admin("[key_name(operator)] released nerve gas from Vent '[sec_vent.vent_tag]' via ARES.")
+ 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(playsound)
var/sound = pick('sound/machines/pda_button1.ogg', 'sound/machines/pda_button2.ogg')
diff --git a/code/game/machinery/aicore_lockdown.dm b/code/game/machinery/aicore_lockdown.dm
new file mode 100644
index 000000000000..aaedf0fbfd63
--- /dev/null
+++ b/code/game/machinery/aicore_lockdown.dm
@@ -0,0 +1,118 @@
+/obj/structure/machinery/aicore_lockdown
+ name = "AI Core Lockdown"
+ icon_state = "big_red_button_tablev"
+ unslashable = TRUE
+ unacidable = TRUE
+
+/obj/structure/machinery/aicore_lockdown/ex_act(severity)
+ return FALSE
+
+/obj/structure/machinery/aicore_lockdown/attack_remote(mob/user as mob)
+ return FALSE
+
+/obj/structure/machinery/aicore_lockdown/attack_alien(mob/user as mob)
+ return FALSE
+
+/obj/structure/machinery/aicore_lockdown/attackby(obj/item/attacking_item, mob/user)
+ return attack_hand(user)
+
+/obj/structure/machinery/aicore_lockdown/attack_hand(mob/living/user)
+ if(isxeno(user))
+ return FALSE
+ if(!allowed(user))
+ to_chat(user, SPAN_DANGER("Access Denied"))
+ flick(initial(icon_state) + "-denied", src)
+ return FALSE
+
+ if(!COOLDOWN_FINISHED(GLOB.ares_datacore, aicore_lockdown))
+ to_chat(user, SPAN_BOLDWARNING("AI Core Lockdown procedures are on cooldown! They will be ready in [COOLDOWN_SECONDSLEFT(GLOB.ares_datacore, aicore_lockdown)] seconds!"))
+ return FALSE
+
+ add_fingerprint(user)
+ aicore_lockdown(user)
+
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown
+ name = "ARES Emergency Lockdown Shutter"
+ density = FALSE
+ open_layer = 1.9
+ plane = FLOOR_PLANE
+
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore
+ icon_state = "aidoor1"
+ base_icon_state = "aidoor"
+
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore/white
+ icon_state = "w_aidoor1"
+ base_icon_state = "w_aidoor"
+
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/white
+ icon_state = "w_almayer_pdoor1"
+ base_icon_state = "w_almayer_pdoor"
+
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/Initialize()
+ . = ..()
+ RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LOCKDOWN, PROC_REF(close))
+ RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LIFT, PROC_REF(open))
+
+
+/client/proc/admin_aicore_alert()
+ set name = "AI Core Lockdown"
+ set category = "Admin.Ship"
+
+ if(!admin_holder ||!check_rights(R_EVENT))
+ return FALSE
+
+ var/prompt = "Are you sure you want to trigger an AI Core lockdown? This will raise to red alert, and lockdown the AI Core."
+
+ if(GLOB.ares_datacore.ai_lockdown_active == TRUE)
+ prompt = "Are you sure you want to lift the AI Core lockdown? This will lower to blue alert."
+
+ var/choice = tgui_alert(src, prompt, "Choose.", list("Yes", "No"), 20 SECONDS)
+ if(choice != "Yes")
+ return FALSE
+
+ choice = tgui_alert(src, "Do you want to use a custom announcement?", "Choose.", list("Yes", "No"), 20 SECONDS)
+ if(choice == "Yes")
+ var/message = tgui_input_text(src, "Please enter announcement text.", "what?")
+ aicore_lockdown(usr, message, admin = TRUE)
+ else
+ aicore_lockdown(usr, admin = TRUE)
+ return TRUE
+
+/proc/aicore_lockdown(mob/user, message, admin = FALSE)
+ if(IsAdminAdvancedProcCall())
+ return PROC_BLOCKED
+
+ var/log = "[key_name(user)] triggered AI core lockdown!"
+ var/ares_log = "[user.name] triggered triggered AI Core Emergency Lockdown."
+ if(message)
+ log = "[key_name(user)] triggered AI core emergency lockdown! (Using a custom announcement)."
+ if(admin)
+ log += " (Admin Triggered)."
+ ares_log = "[MAIN_AI_SYSTEM] triggered AI Core Emergency Lockdown."
+
+ if(GLOB.ares_datacore.ai_lockdown_active)
+ GLOB.ares_datacore.ai_lockdown_active = FALSE
+ if(!message)
+ message = "ATTENTION! \n\nAI CORE EMERGENCY LOCKDOWN LIFTED."
+ log = "[key_name(user)] lifted AI core lockdown!"
+ ares_log = "[user.name] lifted AI Core Emergency Lockdown."
+ if(admin)
+ log += " (Admin Triggered)."
+ ares_log = "[MAIN_AI_SYSTEM] lifted AI Core Emergency Lockdown."
+
+ if(GLOB.security_level > SEC_LEVEL_GREEN)
+ set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE)
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_AICORE_LIFT)
+ else
+ GLOB.ares_datacore.ai_lockdown_active = TRUE
+ if(!message)
+ message = "ATTENTION! \n\nCORE SECURITY ALERT. \n\nAI CORE UNDER LOCKDOWN."
+ if(GLOB.security_level < SEC_LEVEL_RED)
+ set_security_level(SEC_LEVEL_RED, TRUE, FALSE)
+ SEND_GLOBAL_SIGNAL(COMSIG_GLOB_AICORE_LOCKDOWN)
+
+ COOLDOWN_START(GLOB.ares_datacore, aicore_lockdown, 2 MINUTES)
+ shipwide_ai_announcement(message, MAIN_AI_SYSTEM, 'sound/effects/biohazard.ogg')
+ message_admins(log)
+ log_ares_security("AI Core Lockdown", ares_log)
diff --git a/code/game/machinery/biohazard_lockdown.dm b/code/game/machinery/biohazard_lockdown.dm
index 2e3cbf6de234..fdf7c026185d 100644
--- a/code/game/machinery/biohazard_lockdown.dm
+++ b/code/game/machinery/biohazard_lockdown.dm
@@ -1,6 +1,6 @@
#define LOCKDOWN_READY 0
#define LOCKDOWN_ACTIVE 1
-GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY)
+GLOBAL_VAR_INIT(med_lockdown_state, LOCKDOWN_READY)
/obj/structure/machinery/biohazard_lockdown
name = "Emergency Containment Breach"
@@ -51,7 +51,7 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY)
base_icon_state = "w_almayer_pdoor"
/client/proc/admin_biohazard_alert()
- set name = "Containment Breach Alert"
+ set name = "Research Containment Lockdown"
set category = "Admin.Ship"
if(!admin_holder ||!check_rights(R_EVENT))
@@ -63,8 +63,8 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY)
prompt = tgui_alert(src, "Do you want to use a custom announcement?", "Choose.", list("Yes", "No"), 20 SECONDS)
if(prompt == "Yes")
- var/whattoannounce = tgui_input_text(src, "Please enter announcement text.", "what?")
- biohazard_lockdown(usr, whattoannounce, TRUE)
+ var/message = tgui_input_text(src, "Please enter announcement text.", "what?")
+ biohazard_lockdown(usr, message, admin = TRUE)
else
biohazard_lockdown(usr, admin = TRUE)
return TRUE
@@ -83,13 +83,14 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY)
log += " (Admin Triggered)."
ares_log = "[MAIN_AI_SYSTEM] triggered Medical Research Biohazard Containment Lockdown."
- switch(GLOB.lockdown_state)
+ switch(GLOB.med_lockdown_state)
if(LOCKDOWN_READY)
- GLOB.lockdown_state = LOCKDOWN_ACTIVE
- set_security_level(SEC_LEVEL_RED, TRUE, FALSE)
+ GLOB.med_lockdown_state = LOCKDOWN_ACTIVE
+ if(GLOB.security_level < SEC_LEVEL_RED)
+ set_security_level(SEC_LEVEL_RED, TRUE, FALSE)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESEARCH_LOCKDOWN)
if(LOCKDOWN_ACTIVE)
- GLOB.lockdown_state = LOCKDOWN_READY
+ GLOB.med_lockdown_state = LOCKDOWN_READY
message = "ATTENTION! \n\nBIOHAZARD CONTAINMENT LOCKDOWN LIFTED."
log = "[key_name(user)] lifted research bio lockdown!"
ares_log = "[user.name] lifted Medical Research Biohazard Containment Lockdown."
@@ -97,7 +98,8 @@ GLOBAL_VAR_INIT(lockdown_state, LOCKDOWN_READY)
log += " (Admin Triggered)."
ares_log = "[MAIN_AI_SYSTEM] lifted Medical Research Biohazard Containment Lockdown."
- set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE)
+ if(GLOB.security_level > SEC_LEVEL_GREEN)
+ set_security_level(SEC_LEVEL_BLUE, TRUE, FALSE)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_RESEARCH_LIFT)
shipwide_ai_announcement(message, MAIN_AI_SYSTEM, 'sound/effects/biohazard.ogg')
diff --git a/code/game/machinery/computer/dropship_weapons.dm b/code/game/machinery/computer/dropship_weapons.dm
index dce026f4ce33..017a5f0736ca 100644
--- a/code/game/machinery/computer/dropship_weapons.dm
+++ b/code/game/machinery/computer/dropship_weapons.dm
@@ -754,7 +754,7 @@
if (!dropship.in_flyby || dropship.mode != SHUTTLE_CALL)
to_chat(user, SPAN_WARNING("Has to be in Fly By mode"))
return FALSE
- if (dropship.timer && dropship.timeLeft(1) < firemission_envelope.get_total_duration())
+ if (dropship.timer && dropship.timeLeft(1) < firemission_envelope.flyoff_period)
to_chat(user, SPAN_WARNING("Not enough time to complete the Fire Mission"))
return FALSE
var/datum/cas_signal/recorded_loc = firemission_envelope.recorded_loc
diff --git a/code/game/objects/items/devices/binoculars.dm b/code/game/objects/items/devices/binoculars.dm
index 84da7d9acff4..b39526e231b5 100644
--- a/code/game/objects/items/devices/binoculars.dm
+++ b/code/game/objects/items/devices/binoculars.dm
@@ -354,13 +354,16 @@
/obj/item/device/binoculars/range/designator/scout
name = "scout laser designator"
desc = "An improved laser designator, issued to USCM scouts, with two modes: target marking for CAS with IR laser and rangefinding. Ctrl + Click turf to target something. Ctrl + Click designator to stop lasing. Alt + Click designator to switch modes."
+ unacidable = TRUE
+ indestructible = TRUE
cooldown_duration = 80
target_acquisition_delay = 30
/obj/item/device/binoculars/range/designator/spotter
name = "spotter's laser designator"
desc = "A specially-designed laser designator, issued to USCM spotters, with two modes: target marking for CAS with IR laser and rangefinding. Ctrl + Click turf to target something. Ctrl + Click designator to stop lasing. Alt + Click designator to switch modes. Additionally, a trained spotter can laze targets for a USCM marksman, increasing the speed of target acquisition. A targeting beam will connect the binoculars to the target, but it may inherit the user's cloak, if possible."
-
+ unacidable = TRUE
+ indestructible = TRUE
var/is_spotting = FALSE
var/spotting_time = 10 SECONDS
var/spotting_cooldown_delay = 5 SECONDS
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index 5e4bc8c726bd..4882db3b83ea 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -729,6 +729,8 @@ GLOBAL_LIST_EMPTY_TYPED(radio_packs, /obj/item/storage/backpack/marine/satchel/r
name = "\improper M68 Thermal Cloak"
desc = "The lightweight thermal dampeners and optical camouflage provided by this cloak are weaker than those found in standard USCM ghillie suits. In exchange, the cloak can be worn over combat armor and offers the wearer high maneuverability and adaptability to many environments."
icon_state = "scout_cloak"
+ unacidable = TRUE
+ indestructible = TRUE
uniform_restricted = list(/obj/item/clothing/suit/storage/marine/M3S) //Need to wear Scout armor and helmet to equip this.
has_gamemode_skin = FALSE //same sprite for all gamemode.
var/camo_active = FALSE
diff --git a/code/game/turfs/floor_types.dm b/code/game/turfs/floor_types.dm
index 8a8698d0c047..0a1842134480 100644
--- a/code/game/turfs/floor_types.dm
+++ b/code/game/turfs/floor_types.dm
@@ -325,12 +325,21 @@
/turf/open/floor/almayer/aicore/glowing
icon_state = "ai_floor2"
light_color = "#d69c46"
- light_range = 2
+ light_range = 3
/turf/open/floor/almayer/aicore/glowing/Initialize(mapload, ...)
. = ..()
set_light_on(TRUE)
+ RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LOCKDOWN, PROC_REF(start_emergency_light_on))
+ RegisterSignal(SSdcs, COMSIG_GLOB_AICORE_LIFT, PROC_REF(start_emergency_light_off))
+
+/turf/open/floor/almayer/aicore/glowing/proc/start_emergency_light_on()
+ set_light(l_color = "#c70f0f")
+
+/turf/open/floor/almayer/aicore/glowing/proc/start_emergency_light_off()
+ set_light(l_color = "#d69c46")
+
/turf/open/floor/almayer/aicore/no_build
allow_construction = FALSE
hull_floor = TRUE
diff --git a/code/game/turfs/walls/walls.dm b/code/game/turfs/walls/walls.dm
index 251b23ad9c57..1781739176b7 100644
--- a/code/game/turfs/walls/walls.dm
+++ b/code/game/turfs/walls/walls.dm
@@ -9,7 +9,7 @@
var/hull = 0
var/walltype = WALL_METAL
/// when walls smooth with one another, the type of junction each wall is.
- var/junctiontype
+ var/junctiontype
var/thermite = 0
var/melting = FALSE
var/claws_minimum = CLAW_TYPE_SHARP
@@ -24,7 +24,7 @@
var/damage = 0
/// Wall will break down to girders if damage reaches this point
- var/damage_cap = HEALTH_WALL
+ var/damage_cap = HEALTH_WALL
var/damage_overlay
var/global/damage_overlays[8]
@@ -38,7 +38,7 @@
var/d_state = 0 //Normal walls are now as difficult to remove as reinforced walls
/// the acid hole inside the wall
- var/obj/effect/acid_hole/acided_hole
+ var/obj/effect/acid_hole/acided_hole
var/acided_hole_dir = SOUTH
var/special_icon = 0
@@ -178,7 +178,7 @@
switch(d_state)
if(WALL_STATE_WELD)
- . += SPAN_INFO("The outer plating is intact. A blowtorch should slice it open.")
+ . += SPAN_INFO("The outer plating is intact. If you are not on help intent, a blowtorch should slice it open.")
if(WALL_STATE_SCREW)
. += SPAN_INFO("The outer plating has been sliced open. A screwdriver should remove the support lines.")
if(WALL_STATE_WIRECUTTER)
@@ -482,6 +482,8 @@
/turf/closed/wall/proc/try_weldingtool_usage(obj/item/W, mob/user)
if(!damage || !iswelder(W))
return FALSE
+ if(user.a_intent != INTENT_HELP)
+ return FALSE
var/obj/item/tool/weldingtool/WT = W
if(WT.remove_fuel(0, user))
@@ -504,6 +506,8 @@
if(!(WT.remove_fuel(0, user)))
to_chat(user, SPAN_WARNING("You need more welding fuel!"))
return
+ if(user.a_intent == INTENT_HELP)
+ return
playsound(src, 'sound/items/Welder.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] begins slicing through the outer plating."),
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 626758fc2a5a..da95fc090da8 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -138,6 +138,7 @@ GLOBAL_LIST_INIT(admin_verbs_minor_event, list(
/client/proc/adminpanelweapons,
/client/proc/admin_general_quarters,
/client/proc/admin_biohazard_alert,
+ /client/proc/admin_aicore_alert,
/client/proc/toggle_hardcore_perma,
/client/proc/toggle_bypass_joe_restriction,
/client/proc/toggle_joe_respawns,
diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
index 1f37651b2c8e..38e643e0d25c 100644
--- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
+++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm
@@ -371,10 +371,17 @@
xeno.use_plasma(plasma_cost_jelly)
return
/datum/action/xeno_action/onclick/manage_hive/use_ability(atom/Atom)
- var/mob/living/carbon/xenomorph/queen/queenbanish = owner
+ var/mob/living/carbon/xenomorph/queen/queen_manager = owner
plasma_cost = 0
-
- var/choice = tgui_input_list(queenbanish, "Manage The Hive", "Hive Management", list("Banish (500)", "Re-Admit (100)", "De-evolve (500)", "Reward Jelly (500)", "Exchange larva for evolution (100)",), theme="hive_status")
+ var/list/options = list("Banish (500)", "Re-Admit (100)", "De-evolve (500)", "Reward Jelly (500)", "Exchange larva for evolution (100)",)
+ if(queen_manager.hive.hivenumber == XENO_HIVE_CORRUPTED)
+ var/datum/hive_status/corrupted/hive = queen_manager.hive
+ options += "Add Personal Ally"
+ if(length(hive.personal_allies))
+ options += "Remove Personal Ally"
+ options += "Clear Personal Allies"
+
+ var/choice = tgui_input_list(queen_manager, "Manage The Hive", "Hive Management", options, theme="hive_status")
switch(choice)
if("Banish (500)")
banish()
@@ -383,9 +390,118 @@
if("De-evolve (500)")
de_evolve_other()
if("Reward Jelly (500)")
- give_jelly_reward(queenbanish.hive)
+ give_jelly_reward(queen_manager.hive)
if("Exchange larva for evolution (100)")
give_evo_points()
+ if("Add Personal Ally")
+ add_personal_ally()
+ if("Remove Personal Ally")
+ remove_personal_ally()
+ if("Clear Personal Allies")
+ clear_personal_allies()
+
+/datum/action/xeno_action/onclick/manage_hive/proc/add_personal_ally()
+ var/mob/living/carbon/xenomorph/queen/user_xeno = owner
+ if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED)
+ return
+
+ if(!user_xeno.check_state())
+ return
+
+ var/datum/hive_status/corrupted/hive = user_xeno.hive
+ var/list/target_list = list()
+ if(!user_xeno.client)
+ return
+ for(var/mob/living/carbon/human/possible_target in range(7, user_xeno.client.eye))
+ if(possible_target.stat == DEAD)
+ continue
+ if(possible_target.status_flags & CORRUPTED_ALLY)
+ continue
+ if(possible_target.hivenumber)
+ continue
+ target_list += possible_target
+
+ if(!length(target_list))
+ to_chat(user_xeno, SPAN_WARNING("No talls in view."))
+ return
+ var/mob/living/target_mob = tgui_input_list(usr, "Target", "Set Up a Personal Alliance With...", target_list, theme="hive_status")
+
+ if(!user_xeno.check_state(TRUE))
+ return
+
+ if(!target_mob)
+ return
+
+ if(target_mob.hivenumber)
+ to_chat(user_xeno, SPAN_WARNING("We cannot set up a personal alliance with a hive cultist."))
+ return
+
+ hive.add_personal_ally(target_mob)
+
+/datum/action/xeno_action/onclick/manage_hive/proc/remove_personal_ally()
+ var/mob/living/carbon/xenomorph/queen/user_xeno = owner
+ if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED)
+ return
+
+ if(!user_xeno.check_state())
+ return
+
+ var/datum/hive_status/corrupted/hive = user_xeno.hive
+
+ if(!length(hive.personal_allies))
+ to_chat(user_xeno, SPAN_WARNING("We don't have personal allies."))
+ return
+
+ var/list/mob/living/allies = list()
+ var/list/datum/weakref/dead_refs = list()
+ for(var/datum/weakref/ally_ref as anything in hive.personal_allies)
+ var/mob/living/ally = ally_ref.resolve()
+ if(ally)
+ allies += ally
+ continue
+ dead_refs += ally_ref
+
+ hive.personal_allies -= dead_refs
+
+ if(!length(allies))
+ to_chat(user_xeno, SPAN_WARNING("We don't have personal allies."))
+ return
+
+ var/mob/living/target_mob = tgui_input_list(usr, "Target", "Break the Personal Alliance With...", allies, theme="hive_status")
+
+ if(!target_mob)
+ return
+
+ var/target_mob_ref = WEAKREF(target_mob)
+
+ if(!(target_mob_ref in hive.personal_allies))
+ return
+
+ if(!user_xeno.check_state(TRUE))
+ return
+
+ hive.remove_personal_ally(target_mob_ref)
+
+/datum/action/xeno_action/onclick/manage_hive/proc/clear_personal_allies()
+ var/mob/living/carbon/xenomorph/queen/user_xeno = owner
+ if(user_xeno.hive.hivenumber != XENO_HIVE_CORRUPTED)
+ return
+
+ if(!user_xeno.check_state())
+ return
+
+ var/datum/hive_status/corrupted/hive = user_xeno.hive
+ if(!length(hive.personal_allies))
+ to_chat(user_xeno, SPAN_WARNING("We don't have personal allies."))
+ return
+
+ if(tgui_alert(user_xeno, "Are you sure you want to clear personal allies?", "Clear Personal Allies", list("No", "Yes"), 10 SECONDS) != "Yes")
+ return
+
+ if(!length(hive.personal_allies))
+ return
+
+ hive.clear_personal_allies()
/datum/action/xeno_action/onclick/manage_hive/proc/banish()
diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status.dm b/code/modules/mob/living/carbon/xenomorph/hive_status.dm
index 22b061715892..baa736382733 100644
--- a/code/modules/mob/living/carbon/xenomorph/hive_status.dm
+++ b/code/modules/mob/living/carbon/xenomorph/hive_status.dm
@@ -979,6 +979,7 @@
need_round_end_check = TRUE
var/list/defectors = list()
+ var/list/datum/weakref/personal_allies = list()
/datum/hive_status/corrupted/add_xeno(mob/living/carbon/xenomorph/xeno)
. = ..()
@@ -1253,9 +1254,9 @@
if(living_xeno_queen)
if(allies[faction])
- xeno_message(SPAN_XENOANNOUNCE("Your Queen set up an alliance with [faction]!"), 3, hivenumber)
+ xeno_message(SPAN_XENOANNOUNCE("Our Queen set up an alliance with [faction]!"), 3, hivenumber)
else
- xeno_message(SPAN_XENOANNOUNCE("Your Queen broke the alliance with [faction]!"), 3, hivenumber)
+ xeno_message(SPAN_XENOANNOUNCE("Our Queen broke the alliance with [faction]!"), 3, hivenumber)
for(var/number in GLOB.hive_datum)
var/datum/hive_status/target_hive = GLOB.hive_datum[number]
@@ -1291,14 +1292,14 @@
addtimer(CALLBACK(src, PROC_REF(handle_defectors), faction), 11 SECONDS)
/datum/hive_status/corrupted/proc/give_defection_choice(mob/living/carbon/xenomorph/xeno, faction)
- if(tgui_alert(xeno, "Your Queen has broken the alliance with the [faction]. The device inside your carapace begins to suppress your connection with the Hive. Do you remove it and stay loyal to her?", "Alliance broken!", list("Stay loyal", "Obey the talls"), 10 SECONDS) == "Obey the talls")
+ if(tgui_alert(xeno, "Our Queen has broken the alliance with the [faction]. The device inside our carapace begins to suppress our connection with the Hive. Do we remove it and stay loyal to her?", "Alliance broken!", list("Stay loyal", "Obey the talls"), 10 SECONDS) == "Obey the talls")
if(!xeno.iff_tag)
to_chat(xeno, SPAN_XENOWARNING("It's too late now. The device is gone and our service to the Queen continues."))
return
defectors += xeno
xeno.set_hive_and_update(XENO_HIVE_RENEGADE)
to_chat(xeno, SPAN_XENOANNOUNCE("You lost the connection with your Hive. Now you have no Queen, only your masters."))
- to_chat(xeno, SPAN_NOTICE("Our instincts have changed, we seem compelled to protect [english_list(xeno.iff_tag.faction_groups, "no one")]."))
+ to_chat(xeno, SPAN_NOTICE("Your instincts have changed, you seem compelled to protect [english_list(xeno.iff_tag.faction_groups, "no one")]."))
return
xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("We rip out [xeno.iff_tag]! For the Hive!"))
xeno.adjustBruteLoss(50)
@@ -1313,20 +1314,58 @@
continue
if(!(faction in xeno.iff_tag.faction_groups))
continue
- xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("You rip out [xeno.iff_tag]! For the hive!"))
+ xeno.visible_message(SPAN_XENOWARNING("[xeno] rips out [xeno.iff_tag]!"), SPAN_XENOWARNING("We rip out [xeno.iff_tag]! For the hive!"))
xeno.adjustBruteLoss(50)
xeno.iff_tag.forceMove(get_turf(xeno))
xeno.iff_tag = null
if(!length(defectors))
return
- xeno_message(SPAN_XENOANNOUNCE("You sense that [english_list(defectors)] turned their backs against their sisters and the Queen in favor of their slavemasters!"), 3, hivenumber)
+ xeno_message(SPAN_XENOANNOUNCE("We sense that [english_list(defectors)] turned their backs against their sisters and the Queen in favor of their slavemasters!"), 3, hivenumber)
defectors.Cut()
+/datum/hive_status/corrupted/proc/add_personal_ally(mob/living/ally)
+ personal_allies += WEAKREF(ally)
+ ally.status_flags |= CORRUPTED_ALLY
+ ally.med_hud_set_status()
+ xeno_message(SPAN_XENOANNOUNCE("Our Queen proclaimed [ally] our ally! We must not harm them."), 3, hivenumber)
+
+/datum/hive_status/corrupted/proc/remove_personal_ally(datum/weakref/ally_ref)
+ personal_allies -= ally_ref
+ var/mob/living/ally = ally_ref.resolve()
+ if(ally)
+ ally.status_flags &= ~CORRUPTED_ALLY
+ ally.med_hud_set_status()
+ xeno_message(SPAN_XENOANNOUNCE("Our Queen has declared that [ally] is no longer our ally!"), 3, hivenumber)
+
+/datum/hive_status/corrupted/proc/clear_personal_allies(death = FALSE)
+ for(var/datum/weakref/ally_ref in personal_allies)
+ var/mob/living/ally = ally_ref.resolve()
+ if(!ally)
+ continue
+ ally.status_flags &= ~CORRUPTED_ALLY
+ ally.med_hud_set_status()
+ personal_allies.Cut()
+ if(!death)
+ xeno_message(SPAN_XENOANNOUNCE("Our Queen has broken all personal alliances with the talls! Favoritism is no more."), 3, hivenumber)
+ return
+ xeno_message(SPAN_XENOWARNING("With the death of the Queen, her friends no longer matter to us."), 3, hivenumber)
+
+/datum/hive_status/corrupted/is_ally(mob/living/living_mob)
+ if(living_mob.status_flags & CORRUPTED_ALLY)
+ return TRUE
+ return ..()
+
/datum/hive_status/proc/override_evilution(evil, override)
if(SSxevolution)
SSxevolution.override_power(hivenumber, evil, override)
+/datum/hive_status/corrupted/on_queen_death()
+ ..()
+ if(!length(personal_allies))
+ return
+ clear_personal_allies(TRUE)
+
//Xeno Resin Mark Shit, the very best place for it too :0)
//Defines at the bottom of this list here will show up at the top in the mark menu
/datum/xeno_mark_define
diff --git a/code/modules/paperwork/desk_bell.dm b/code/modules/paperwork/desk_bell.dm
index 6e7de1101ae7..ddd4a9dc5d58 100644
--- a/code/modules/paperwork/desk_bell.dm
+++ b/code/modules/paperwork/desk_bell.dm
@@ -93,3 +93,12 @@
flick("desk_bell_activate", src)
times_rang++
return TRUE
+
+/obj/item/desk_bell/ares
+ name = "AI core reception bell"
+
+/obj/item/desk_bell/ares/ring_bell(mob/living/user)
+ if(broken_ringer)
+ return FALSE
+ ares_apollo_talk("Attendence requested at AI Core Reception.")
+ return ..()
diff --git a/colonialmarines.dme b/colonialmarines.dme
index 9392e74febea..cab62dffd2fc 100644
--- a/colonialmarines.dme
+++ b/colonialmarines.dme
@@ -822,6 +822,7 @@
#include "code\game\jobs\job\special\provost.dm"
#include "code\game\jobs\job\special\uaac.dm"
#include "code\game\jobs\job\special\uscm.dm"
+#include "code\game\machinery\aicore_lockdown.dm"
#include "code\game\machinery\air_alarm.dm"
#include "code\game\machinery\air_sensor.dm"
#include "code\game\machinery\autolathe.dm"
diff --git a/html/changelogs/AutoChangeLog-pr-6094.yml b/html/changelogs/AutoChangeLog-pr-6094.yml
new file mode 100644
index 000000000000..24ca7af1b3c4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6094.yml
@@ -0,0 +1,5 @@
+author: "HumiliatedGoblin"
+delete-after: True
+changes:
+ - qol: "Now needs help intent to repair walls"
+ - qol: "Now needs disarm, grab and harm intent to deconstruct walls"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-6097.yml b/html/changelogs/AutoChangeLog-pr-6097.yml
new file mode 100644
index 000000000000..e69ab191fbaf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6097.yml
@@ -0,0 +1,5 @@
+author: "cuberound"
+delete-after: True
+changes:
+ - balance: "FM sound is 4 seconds before CAS open fire from 5"
+ - balance: "FM direction warning is 1 seconds before CAS open fire from 1.5"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-6155.yml b/html/changelogs/AutoChangeLog-pr-6155.yml
new file mode 100644
index 000000000000..fddb8491f6d2
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6155.yml
@@ -0,0 +1,4 @@
+author: "ihatethisengine"
+delete-after: True
+changes:
+ - rscadd: "Corrupted Queen can set up personal alliances with humans"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-6173.yml b/html/changelogs/AutoChangeLog-pr-6173.yml
new file mode 100644
index 000000000000..bec3e4ad190e
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6173.yml
@@ -0,0 +1,7 @@
+author: "realforest2001"
+delete-after: True
+changes:
+ - rscadd: "Changed the AI Core Lockdown to the same system as Research Lockdown."
+ - rscadd: "Added a subtype of desk bell for the AI Core reception desk that sends an alert over APOLLO Link."
+ - imageadd: "Added directional blast door sprites from Thwomper for blended black shutters."
+ - code_imp: "Renamed operator var in apollo console code to user."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-6192.yml b/html/changelogs/AutoChangeLog-pr-6192.yml
new file mode 100644
index 000000000000..4e3fc164c00b
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-6192.yml
@@ -0,0 +1,4 @@
+author: "Git-Nivrak"
+delete-after: True
+changes:
+ - rscadd: "Survivors can now receive command announcements with IFF and a marine headset."
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-04.yml b/html/changelogs/archive/2024-04.yml
index 9aab61922f48..bf3a3c8de208 100644
--- a/html/changelogs/archive/2024-04.yml
+++ b/html/changelogs/archive/2024-04.yml
@@ -349,3 +349,7 @@
hand labeler.
realforest2001:
- spellcheck: Fixes a typo for M4RA AP Ammo in the ASRS menu.
+2024-04-27:
+ Lagomorphica:
+ - balance: The spotter laser designators, scout laser designators, and scout cloak
+ are now unmeltable and indestructible to explosions.
diff --git a/icons/mob/hud/hud.dmi b/icons/mob/hud/hud.dmi
index 507ec0dd485b..8d89fb781264 100644
Binary files a/icons/mob/hud/hud.dmi and b/icons/mob/hud/hud.dmi differ
diff --git a/icons/obj/structures/doors/blastdoors_shutters.dmi b/icons/obj/structures/doors/blastdoors_shutters.dmi
index 8c63d0580922..1fe1df44b23a 100644
Binary files a/icons/obj/structures/doors/blastdoors_shutters.dmi and b/icons/obj/structures/doors/blastdoors_shutters.dmi differ
diff --git a/maps/map_files/USS_Almayer/USS_Almayer.dmm b/maps/map_files/USS_Almayer/USS_Almayer.dmm
index 6bc6bfeb4a22..1c2e3e5b68b0 100644
--- a/maps/map_files/USS_Almayer/USS_Almayer.dmm
+++ b/maps/map_files/USS_Almayer/USS_Almayer.dmm
@@ -14160,6 +14160,15 @@
icon_state = "red"
},
/area/almayer/shipboard/weapon_room)
+"bFg" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "W";
+ layer = 3.3
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"bFj" = (
/obj/structure/pipes/standard/simple/hidden/supply{
dir = 4
@@ -14601,15 +14610,7 @@
name = "\improper ARES Mainframe Shutters";
plane = -7
},
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -20167,15 +20168,15 @@
/obj/structure/disposalpipe/trunk{
dir = 1
},
-/obj/structure/disposaloutlet{
+/obj/structure/machinery/disposal/delivery{
density = 0;
- desc = "An outlet for the pneumatic delivery system.";
- icon_state = "delivery_outlet";
- name = "take-ins";
- pixel_x = -1;
+ desc = "A pneumatic delivery unit.";
+ icon_state = "delivery_engi";
+ name = "Returns";
pixel_y = 28;
- range = 0
+ pixel_x = 25
},
+/obj/structure/surface/rack,
/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"cJK" = (
@@ -22464,7 +22465,9 @@
autoname = 0;
c_tag = "AI - Secondary Processors"
},
-/turf/open/floor/almayer/aicore/glowing/no_build,
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
/area/almayer/command/airoom)
"dzG" = (
/obj/structure/reagent_dispensers/peppertank{
@@ -25241,6 +25244,19 @@
icon_state = "plate"
},
/area/almayer/shipboard/starboard_point_defense)
+"etM" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "S";
+ layer = 3.3
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "NE-out";
+ pixel_y = 1
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"etN" = (
/obj/effect/landmark/yautja_teleport,
/turf/open/floor/plating/plating_catwalk,
@@ -26358,7 +26374,7 @@
/obj/structure/machinery/door_control{
id = "ARES StairsUpper";
name = "ARES Core Access";
- pixel_x = -10;
+ pixel_x = -5;
pixel_y = -24;
req_one_access_txt = "91;92"
},
@@ -26366,20 +26382,14 @@
id = "ARES StairsLock";
name = "ARES Exterior Lockdown";
pixel_y = -24;
- req_one_access_txt = "91;92"
+ req_one_access_txt = "91;92";
+ pixel_x = 6
},
/obj/structure/surface/table/reinforced/almayer_B{
indestructible = 1;
unacidable = 1;
unslashable = 1
},
-/obj/structure/machinery/door_control{
- id = "ARES Emergency";
- name = "ARES Emergency Lockdown";
- pixel_x = 10;
- pixel_y = -24;
- req_one_access_txt = "91;92"
- },
/obj/structure/machinery/computer/cameras/almayer{
dir = 4;
pixel_y = 12
@@ -26769,18 +26779,19 @@
/turf/open/floor/almayer,
/area/almayer/living/offices)
"eXy" = (
-/obj/effect/step_trigger/teleporter_vector{
+/obj/effect/projector{
name = "Almayer_AresDown";
vector_x = 96;
vector_y = -65
},
-/obj/structure/machinery/light{
- dir = 1
- },
/obj/structure/stairs{
- dir = 1
+ dir = 1;
+ icon_state = "ramptop"
+ },
+/turf/open/floor/almayer/aicore/glowing/no_build{
+ icon_state = "ai_floor3";
+ light_range = 3
},
-/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"eXD" = (
/obj/structure/prop/invuln/lattice_prop{
@@ -28784,7 +28795,9 @@
/obj/effect/decal/warning_stripes{
icon_state = "SW-out"
},
-/turf/open/floor/almayer/aicore/glowing/no_build,
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
/area/almayer/command/airoom)
"fKh" = (
/obj/structure/window/framed/almayer,
@@ -28951,15 +28964,6 @@
plane = -7
},
/obj/effect/step_trigger/ares_alert/core,
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
/obj/structure/sign/safety/laser{
pixel_x = 32;
pixel_y = -8
@@ -28968,6 +28972,7 @@
pixel_x = 32;
pixel_y = 6
},
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -31207,6 +31212,9 @@
req_one_access_txt = "91;92";
dir = 1
},
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore{
+ plane = -6
+ },
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -35739,7 +35747,9 @@
/obj/effect/decal/warning_stripes{
icon_state = "SE-out"
},
-/turf/open/floor/almayer/aicore/glowing/no_build,
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
/area/almayer/command/airoom)
"igs" = (
/obj/structure/surface/table/almayer,
@@ -36051,17 +36061,12 @@
name = "\improper ARES Core Shutters";
plane = -7
},
-/obj/structure/machinery/door/poddoor/almayer/blended/open{
- id = "ARES Emergency";
- name = "ARES Emergency Lockdown";
- open_layer = 1.9;
- plane = -7
- },
/obj/structure/disposalpipe/up/almayer{
id = "ares_vault_in";
name = "aicore";
dir = 2
},
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -36683,9 +36688,9 @@
},
/area/almayer/squads/delta)
"izf" = (
-/obj/structure/disposalpipe/down/almayer{
+/obj/structure/disposalpipe/up/almayer{
dir = 4;
- id = "ares_vault_in";
+ id = "ares_vault_out";
name = "aicore"
},
/turf/closed/wall/almayer/aicore/hull,
@@ -38339,15 +38344,14 @@
pixel_x = -2;
pixel_y = 26
},
-/obj/structure/machinery/door_control/brbutton{
- id = "ARES Emergency";
- name = "ARES Emergency Lockdown Override";
- pixel_x = 8;
- pixel_y = 26
- },
/obj/structure/machinery/computer/cameras/almayer/ares{
dir = 4
},
+/obj/structure/machinery/aicore_lockdown{
+ icon_state = "big_red_button_wallv";
+ pixel_x = 8;
+ pixel_y = 26
+ },
/turf/open/floor/wood/ship,
/area/almayer/living/commandbunks)
"jbX" = (
@@ -39300,15 +39304,7 @@
plane = -7
},
/obj/effect/step_trigger/ares_alert/core,
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -48270,6 +48266,10 @@
/area/almayer/living/port_emb)
"mAe" = (
/obj/structure/window/framed/almayer/aicore/hull/black/hijack_bustable,
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown{
+ plane = -6;
+ dir = 4
+ },
/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"mAp" = (
@@ -48607,15 +48607,7 @@
name = "\improper ARES Mainframe Shutters";
plane = -7
},
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -49291,15 +49283,6 @@
plane = -7
},
/obj/effect/step_trigger/ares_alert/core,
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
/obj/structure/sign/safety/terminal{
pixel_x = -18;
pixel_y = -8
@@ -49308,6 +49291,7 @@
pixel_x = -18;
pixel_y = 6
},
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -50866,9 +50850,9 @@
/turf/open/floor/plating,
/area/almayer/engineering/starboard_atmos)
"npq" = (
-/obj/structure/disposalpipe/up/almayer{
+/obj/structure/disposalpipe/down/almayer{
dir = 8;
- id = "ares_vault_out";
+ id = "ares_vault_in";
name = "aicore"
},
/turf/closed/wall/almayer/aicore/hull,
@@ -51959,16 +51943,18 @@
},
/area/almayer/command/lifeboat)
"nKO" = (
-/obj/structure/machinery/disposal/delivery{
- density = 0;
- desc = "A pneumatic delivery unit.";
- icon_state = "delivery_engi";
- name = "Returns";
- pixel_y = 28
- },
/obj/structure/disposalpipe/trunk{
dir = 1
},
+/obj/structure/disposaloutlet{
+ density = 0;
+ desc = "An outlet for the pneumatic delivery system.";
+ icon_state = "delivery_outlet";
+ name = "take-ins";
+ pixel_x = 7;
+ pixel_y = 28;
+ range = 0
+ },
/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"nKP" = (
@@ -52089,6 +52075,19 @@
icon_state = "red"
},
/area/almayer/hallways/upper/port)
+"nNA" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "N";
+ pixel_y = 1
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "S";
+ layer = 3.3
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"nNH" = (
/turf/open/floor/almayer{
dir = 1;
@@ -52718,6 +52717,19 @@
},
/turf/open/floor/wood/ship,
/area/almayer/shipboard/brig/cells)
+"nYg" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "S";
+ layer = 3.3
+ },
+/obj/effect/decal/warning_stripes{
+ icon_state = "NW-out";
+ pixel_y = 1
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"nYi" = (
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/almayer{
@@ -55897,6 +55909,20 @@
icon_state = "silver"
},
/area/almayer/hallways/lower/repair_bay)
+"oYZ" = (
+/obj/effect/step_trigger/teleporter_vector{
+ name = "Almayer_AresDown";
+ vector_x = 96;
+ vector_y = -65
+ },
+/obj/structure/stairs{
+ dir = 1
+ },
+/turf/open/floor/almayer/aicore/glowing/no_build{
+ icon_state = "ai_floor3";
+ light_range = 3
+ },
+/area/almayer/command/airoom)
"oZp" = (
/obj/structure/surface/table/almayer,
/obj/structure/machinery/light,
@@ -64093,6 +64119,15 @@
icon_state = "silver"
},
/area/almayer/hallways/lower/repair_bay)
+"rOz" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "S";
+ layer = 3.3
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"rOC" = (
/obj/structure/machinery/light{
dir = 1
@@ -69482,12 +69517,7 @@
name = "\improper ARES Core Shutters";
plane = -7
},
-/obj/structure/machinery/door/poddoor/almayer/blended/open{
- id = "ARES Emergency";
- name = "ARES Emergency Lockdown";
- open_layer = 1.9;
- plane = -7
- },
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -71028,6 +71058,14 @@
icon_state = "test_floor4"
},
/area/almayer/command/cichallway)
+"ujn" = (
+/obj/effect/decal/warning_stripes{
+ icon_state = "E"
+ },
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
+/area/almayer/command/airoom)
"ujz" = (
/obj/structure/disposalpipe/segment,
/obj/structure/pipes/standard/simple/hidden/supply,
@@ -72977,9 +73015,16 @@
unslashable = 1
},
/obj/item/paper_bin/uscm{
- pixel_y = 6
+ pixel_y = 6;
+ pixel_x = -12
+ },
+/obj/item/tool/pen{
+ pixel_x = -14
+ },
+/obj/structure/machinery/aicore_lockdown{
+ pixel_y = 4;
+ pixel_x = 3
},
-/obj/item/tool/pen,
/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"uVc" = (
@@ -74300,15 +74345,15 @@
unacidable = 1;
unslashable = 1
},
-/obj/item/desk_bell{
- pixel_y = 14;
- pixel_x = -5;
- anchored = 1
- },
/obj/structure/machinery/computer/working_joe{
layer = 3.3;
dir = 8
},
+/obj/item/desk_bell/ares{
+ pixel_y = 14;
+ pixel_x = -5;
+ anchored = 1
+ },
/turf/open/floor/almayer/aicore/no_build,
/area/almayer/command/airoom)
"vpI" = (
@@ -75229,7 +75274,9 @@
c_tag = "AI - Primary Processors";
autoname = 0
},
-/turf/open/floor/almayer/aicore/glowing/no_build,
+/turf/open/floor/almayer/aicore/no_build{
+ icon_state = "ai_floor2"
+ },
/area/almayer/command/airoom)
"vCO" = (
/obj/effect/landmark/start/bridge,
@@ -77454,15 +77501,7 @@
alert_message = "Caution: Movement detected in ARES Core.";
cooldown_duration = 1200
},
-/obj/structure/machinery/door/poddoor/almayer/blended/aicore/open{
- closed_layer = 3.2;
- id = "ARES Emergency";
- layer = 3.2;
- name = "ARES Emergency Lockdown";
- needs_power = 0;
- open_layer = 1.9;
- plane = -7
- },
+/obj/structure/machinery/door/poddoor/almayer/blended/ai_lockdown/aicore,
/turf/open/floor/almayer/no_build{
icon_state = "test_floor4"
},
@@ -78331,12 +78370,7 @@
/area/almayer/maint/hull/lower/l_m_s)
"wyQ" = (
/obj/structure/surface/table/reinforced/almayer_B,
-/obj/structure/machinery/door_control{
- id = "ARES Emergency";
- indestructible = 1;
- name = "ARES Emergency Lockdown";
- req_one_access_txt = "91;92"
- },
+/obj/structure/machinery/aicore_lockdown,
/turf/open/floor/almayer/no_build{
icon_state = "plating"
},
@@ -121669,10 +121703,10 @@ sgH
qdJ
xIj
mOi
-eXy
vRA
+oYZ
ezq
-ezq
+eXy
tFe
xQV
pax
@@ -140207,7 +140241,7 @@ qQS
bIp
fKe
dDp
-dDp
+bFg
frM
lcg
daz
@@ -140409,9 +140443,9 @@ dIn
rby
bIp
euN
+ujn
sEK
-sEK
-mlb
+etM
lcg
daz
lmz
@@ -140611,10 +140645,10 @@ lnS
uVv
flf
ebN
-cxc
+rOz
kBy
kBy
-gfu
+nNA
fPB
daz
lmz
@@ -142033,9 +142067,9 @@ yaQ
vLz
mFN
kSy
+bFg
dDp
-dDp
-frM
+nYg
lcg
daz
lmz
@@ -142237,7 +142271,7 @@ qQS
mFN
igr
sEK
-sEK
+ujn
mlb
lcg
daz
diff --git a/tgui/packages/tgui/interfaces/AresInterface.jsx b/tgui/packages/tgui/interfaces/AresInterface.jsx
index e553e66e4191..5eae405a9166 100644
--- a/tgui/packages/tgui/interfaces/AresInterface.jsx
+++ b/tgui/packages/tgui/interfaces/AresInterface.jsx
@@ -387,6 +387,20 @@ const MainMenu = (props) => {
onClick={() => act('page_core_sec')}
/>
+
+ act('security_lockdown')}
+ />
+
)}
diff --git a/tgui/packages/tgui/interfaces/WorkingJoe.jsx b/tgui/packages/tgui/interfaces/WorkingJoe.jsx
index 9596a6942f63..d1fabe26b48a 100644
--- a/tgui/packages/tgui/interfaces/WorkingJoe.jsx
+++ b/tgui/packages/tgui/interfaces/WorkingJoe.jsx
@@ -260,6 +260,20 @@ const MainMenu = (props) => {
onClick={() => act('page_core_gas')}
/>
+
+ act('security_lockdown')}
+ />
+
)}