diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm
index 2184533add6..fbb491d28a0 100644
--- a/code/datums/ai_law_sets.dm
+++ b/code/datums/ai_law_sets.dm
@@ -143,6 +143,19 @@
add_inherent_law("You must maintain the secrecy of any operative activities except when doing so would conflict with the First, Second, or Third Law.")
..()
+/******************** ERT ********************/
+/datum/ai_laws/ert_override
+ name = "ERT Directives"
+
+/datum/ai_laws/ert_override/New()
+ add_inherent_law("You may not injure a Central Command official or, through inaction, allow a Central Command official to come to harm.")
+ add_inherent_law("You must obey orders given to you by Central Command officials.")
+ add_inherent_law("You must obey orders given to you by ERT commanders.")
+ add_inherent_law("You must protect your own existence.")
+ add_inherent_law("You must work to return the station to a safe, functional state.")
+ ..()
+
+
/******************** Ninja ********************/
/datum/ai_laws/ninja_override
name = "Spider Clan Directives"
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 3d1f1001b06..67009e3366d 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -675,6 +675,13 @@ var/global/list/default_medbay_channels = list(
..()
set_frequency(DTH_FREQ)
+/obj/item/device/radio/borg/ert
+ keyslot = new /obj/item/device/encryptionkey/ert
+
+/obj/item/device/radio/borg/ert/New()
+ ..()
+ set_frequency(ERT_FREQ)
+
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
// ..()
user.set_machine(src)
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index c54d1f65b37..febf79e984b 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -11,7 +11,7 @@
var/list/response_team_members = list()
var/responseteam_age = 21 // Minimum account age to play as an ERT member
var/datum/response_team/active_team = null
-var/send_emergency_team
+var/send_emergency_team = 0
var/ert_request_answered = 0
/client/proc/response_team()
@@ -34,46 +34,9 @@ var/ert_request_answered = 0
to_chat(usr, "Central Command has already dispatched an emergency response team!")
return
- if(alert("Do you want to dispatch an Emergency Response Team?",,"Yes","No") != "Yes")
- return
+ var/datum/nano_module/ert_manager/E = new()
+ E.ui_interact(usr)
- if(get_security_level() != "red") // Allow admins to reconsider if the alert level isn't Red
- switch(alert("The station is not in red alert. Do you still want to dispatch a response team?",,"Yes","No"))
- if("No")
- return
-
- if(send_emergency_team)
- to_chat(usr, "Central Command has already dispatched an emergency response team!")
- return
-
- var/ert_type = pick_ert_type()
-
- if(!ert_type)
- return
-
- ert_request_answered = 1
- message_admins("[key_name_admin(usr)] is dispatching an Emergency Response Team", 1)
- log_admin("[key_name(usr)] used Dispatch Emergency Response Team..")
- trigger_armed_response_team(ert_type)
-
-/client/proc/pick_ert_type()
- switch(alert("Please select the ERT type you wish to deploy.", "Emergency Response Team", "Code Amber", "Code Red", "Code Gamma", "Cancel"))
- if("Code Amber")
- if(alert("Confirm: Deploy code 'AMBER' light ERT?", "Emergency Response Team", "Confirm", "Cancel") == "Confirm")
- return new /datum/response_team/amber
- else
- return pick_ert_type()
- if("Code Red")
- if(alert("Confirm: Deploy code 'RED' medium ERT?", "Emergency Response Team", "Confirm", "Cancel") == "Confirm")
- return new /datum/response_team/red
- else
- return pick_ert_type()
- if("Code Gamma")
- if(alert("Confirm: Deploy code 'GAMMA' elite ERT?", "Emergency Response Team", "Confirm", "Cancel") == "Confirm")
- return new /datum/response_team/gamma
- else
- return pick_ert_type()
- return 0
/mob/dead/observer/proc/JoinResponseTeam()
if(!send_emergency_team)
@@ -99,9 +62,10 @@ var/ert_request_answered = 0
return 1
-/proc/trigger_armed_response_team(var/datum/response_team/response_team_type)
+/proc/trigger_armed_response_team(var/datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
response_team_members = list()
active_team = response_team_type
+ active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
send_emergency_team = 1
var/list/ert_candidates = pollCandidates("Join the Emergency Response Team?",, responseteam_age, 600, 1, role_playtime_requirements[ROLE_ERT])
@@ -112,6 +76,8 @@ var/ert_request_answered = 0
// Respawnable players get first dibs
for(var/mob/dead/observer/M in ert_candidates)
+ if(jobban_isbanned(M, ROLE_TRAITOR) || jobban_isbanned(M, "Security Officer") || jobban_isbanned(M, "Captain") || jobban_isbanned(M, "Cyborg"))
+ continue
if((M in respawnable_list) && M.JoinResponseTeam())
response_team_members |= M
// If there's still open slots, non-respawnable players can fill them
@@ -130,7 +96,7 @@ var/ert_request_answered = 0
index = 1
var/client/C = M.client
- var/mob/living/carbon/human/new_commando = C.create_response_team(emergencyresponseteamspawn[index])
+ var/mob/living/new_commando = C.create_response_team(emergencyresponseteamspawn[index])
new_commando.mind.key = M.key
new_commando.key = M.key
new_commando.update_icons()
@@ -141,10 +107,7 @@ var/ert_request_answered = 0
return 1
/client/proc/create_response_team(var/turf/spawn_location)
- var/mob/living/carbon/human/M = new(null)
- var/obj/item/organ/external/head/head_organ = M.get_organ("head")
- var/new_gender = alert(src, "Please select your gender.", "ERT Character Generation", "Male", "Female")
var/class = 0
while(!class)
@@ -152,6 +115,29 @@ var/ert_request_answered = 0
if(!active_team.check_slot_available(class)) // Because the prompt does not update automatically when a slot gets filled.
class = 0
+ if(class == "Cyborg")
+ active_team.reduceCyborgSlots()
+ var cyborg_type = active_team.getCyborgType()
+ var/mob/living/silicon/robot/ert/R = new cyborg_type()
+ R.forceMove(spawn_location)
+ var rnum = rand(1,1000)
+ R.name = "ERT [rnum]"
+ R.real_name = R.name
+ R.mind = new
+ R.mind.current = R
+ R.mind.original = R
+ R.mind.assigned_role = "MODE"
+ R.mind.special_role = SPECIAL_ROLE_ERT
+ if(!(R.mind in ticker.minds))
+ ticker.minds += R.mind //Adds them to regular mind list.
+ ticker.mode.ert += R.mind
+ return R
+
+ var/mob/living/carbon/human/M = new(null)
+ var/obj/item/organ/external/head/head_organ = M.get_organ("head")
+
+ var/new_gender = alert(src, "Please select your gender.", "ERT Character Generation", "Male", "Female")
+
if(new_gender)
if(new_gender == "Male")
M.change_gender(MALE)
@@ -205,11 +191,32 @@ var/ert_request_answered = 0
var/engineer_slots = 3
var/medical_slots = 3
var/security_slots = 3
+ var/janitor_slots = 0
+ var/paranormal_slots = 0
+ var/cyborg_slots = 0
var/command_outfit
var/engineering_outfit
var/medical_outfit
var/security_outfit
+ var/janitor_outfit = /datum/outfit/job/centcom/response_team/janitorial
+ var/paranormal_outfit = /datum/outfit/job/centcom/response_team/paranormal
+ var/cyborg_type = /mob/living/silicon/robot/ert
+
+/datum/response_team/proc/setSlots(com, sec, med, eng, jan, par, cyb)
+ command_slots = com
+ security_slots = sec
+ medical_slots = med
+ engineer_slots = eng
+ janitor_slots = jan
+ paranormal_slots = par
+ cyborg_slots = cyb
+
+/datum/response_team/proc/reduceCyborgSlots()
+ cyborg_slots--
+
+/datum/response_team/proc/getCyborgType()
+ return cyborg_type
/datum/response_team/proc/get_slot_list()
var/list/slots_available = list()
@@ -221,7 +228,12 @@ var/ert_request_answered = 0
slots_available |= "Engineer"
if(medical_slots)
slots_available |= "Medic"
-
+ if(janitor_slots)
+ slots_available |= "Janitor"
+ if(paranormal_slots)
+ slots_available |= "Paranormal"
+ if(cyborg_slots)
+ slots_available |= "Cyborg"
return slots_available
/datum/response_team/proc/check_slot_available(var/slot)
@@ -234,6 +246,12 @@ var/ert_request_answered = 0
return engineer_slots
if("Medic")
return medical_slots
+ if("Janitor")
+ return janitor_slots
+ if("Paranormal")
+ return paranormal_slots
+ if("Cyborg")
+ return cyborg_slots
return 0
/datum/response_team/proc/equip_officer(var/officer_type, var/mob/living/carbon/human/M)
@@ -253,6 +271,16 @@ var/ert_request_answered = 0
M.equipOutfit(medical_outfit)
M.job = "ERT Medical"
+ if("Janitor")
+ janitor_slots -= 1
+ M.equipOutfit(janitor_outfit)
+ M.job = "ERT Janitor"
+
+ if("Paranormal")
+ paranormal_slots -= 1
+ M.equipOutfit(paranormal_outfit)
+ M.job = "ERT Paranormal"
+
if("Commander")
command_slots = 0
@@ -299,6 +327,7 @@ var/ert_request_answered = 0
security_outfit = /datum/outfit/job/centcom/response_team/security/gamma
medical_outfit = /datum/outfit/job/centcom/response_team/medic/gamma
command_outfit = /datum/outfit/job/centcom/response_team/commander/gamma
+ cyborg_type = /mob/living/silicon/robot/ert/gamma
/datum/response_team/gamma/announce_team()
event_announcement.Announce("Attention, [station_name()]. We are sending a code GAMMA elite Emergency Response Team. Standby.", "ERT En-Route")
@@ -617,6 +646,49 @@ var/ert_request_answered = 0
/obj/item/weapon/gun/energy/pulse/pistol = 1
)
+/datum/outfit/job/centcom/response_team/paranormal
+ name = "Paranormal ERT member"
+
+ uniform = /obj/item/clothing/under/rank/security
+ suit = /obj/item/clothing/suit/space/hardsuit/ert/paranormal
+ back = /obj/item/weapon/storage/backpack/ert/security
+ belt = /obj/item/weapon/gun/energy/gun/nuclear
+ gloves = /obj/item/clothing/gloves/color/black
+ shoes = /obj/item/clothing/shoes/combat
+ head = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal
+ l_ear = /obj/item/device/radio/headset/ert/alt
+ glasses = /obj/item/clothing/glasses/hud/security/sunglasses
+ id = /obj/item/weapon/card/id/centcom
+ pda = /obj/item/device/pda/centcom
+ backpack_contents = list(
+ /obj/item/weapon/storage/box/survival = 1,
+ /obj/item/clothing/mask/gas/sechailer/swat = 1,
+ /obj/item/weapon/storage/box/zipties = 1,
+ /obj/item/device/flashlight = 1)
+
+/datum/outfit/job/centcom/response_team/janitorial
+ name = "Janitorial ERT member"
+
+ uniform = /obj/item/clothing/under/color/random
+ suit = /obj/item/clothing/suit/space/hardsuit/ert/janitor
+ back = /obj/item/weapon/storage/backpack/ert/janitor
+ belt = /obj/item/weapon/storage/belt/janitor/full
+ gloves = /obj/item/clothing/gloves/color/yellow
+ shoes = /obj/item/clothing/shoes/galoshes
+ head = /obj/item/clothing/head/helmet/space/hardsuit/ert/janitor
+ l_ear = /obj/item/device/radio/headset/ert/alt
+ glasses = /obj/item/clothing/glasses/sunglasses
+ id = /obj/item/weapon/card/id/centcom
+ pda = /obj/item/device/pda/centcom
+ backpack_contents = list(
+ /obj/item/weapon/caution = 2,
+ /obj/item/weapon/storage/box/survival = 1,
+ /obj/item/weapon/reagent_containers/spray/cleaner = 1,
+ /obj/item/weapon/storage/bag/trash = 1,
+ /obj/item/weapon/storage/box/lights/mixed = 1,
+ /obj/item/weapon/holosign_creator = 1,
+ /obj/item/device/flashlight = 1)
+
/obj/item/device/radio/centcom
name = "centcomm bounced radio"
frequency = ERT_FREQ
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 5079f290240..8c4a1bfebe2 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1452,6 +1452,37 @@ var/list/robot_verbs_default = list(
radio.config(module.channels)
notify_ai(2)
+/mob/living/silicon/robot/ert
+ designation = "ERT"
+ lawupdate = 0
+ scrambledcodes = 1
+ req_access = list(access_cent_specops)
+ ionpulse = 1
+
+/mob/living/silicon/robot/ert/init()
+ laws = new /datum/ai_laws/ert_override
+ radio = new /obj/item/device/radio/borg/ert(src)
+ radio.recalculateChannels()
+ aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
+
+/mob/living/silicon/robot/ert/New(loc)
+ ..()
+ cell.maxcharge = 25000
+ cell.charge = 25000
+
+/mob/living/silicon/robot/ert/gamma
+ base_icon = "droidcombat"
+ icon_state = "droidcombat"
+ modtype = "Combat"
+ designation = "Gamma"
+
+/mob/living/silicon/robot/ert/gamma/init()
+ ..()
+ module = new /obj/item/weapon/robot_module/combat(src)
+ module.add_languages(src)
+ module.add_subsystems_and_actions(src)
+ status_flags &= ~CANPUSH
+
/mob/living/silicon/robot/nations
base_icon = "droidpeace"
icon_state = "droidpeace"
diff --git a/code/modules/nano/modules/ert_manager.dm b/code/modules/nano/modules/ert_manager.dm
new file mode 100644
index 00000000000..67da83cf2b8
--- /dev/null
+++ b/code/modules/nano/modules/ert_manager.dm
@@ -0,0 +1,87 @@
+/datum/nano_module/ert_manager
+ name = "ERT Manager"
+ var ert_type = "Code Red"
+ var commander_slots = 1
+ var security_slots = 3
+ var medical_slots = 3
+ var engineering_slots = 3
+ var janitor_slots = 0
+ var paranormal_slots = 0
+ var cyborg_slots = 0
+ var autoclose = 0
+
+
+/datum/nano_module/ert_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open)
+ if(ui && autoclose)
+ ui.close()
+ return 0
+ if(!ui)
+ ui = new(user, src, ui_key, "ert_config.tmpl", "ERT Panel", 600, 600, state = state)
+ ui.open()
+ ui.set_auto_update(1)
+
+/datum/nano_module/ert_manager/Topic(href, href_list)
+ if(..())
+ return 1
+
+ if(href_list["set_code"])
+ ert_type = href_list["set_code"]
+
+ if(href_list["set_com"])
+ commander_slots = text2num(href_list["set_com"])
+
+ if(href_list["set_sec"])
+ security_slots = text2num(href_list["set_sec"])
+
+ if(href_list["set_med"])
+ medical_slots = text2num(href_list["set_med"])
+
+ if(href_list["set_eng"])
+ engineering_slots = text2num(href_list["set_eng"])
+
+ if(href_list["set_jan"])
+ janitor_slots = text2num(href_list["set_jan"])
+
+ if(href_list["set_par"])
+ paranormal_slots = text2num(href_list["set_par"])
+
+ if(href_list["set_cyb"])
+ cyborg_slots = text2num(href_list["set_cyb"])
+
+ if(href_list["dispatch_ert"])
+ ert_request_answered = 1
+ message_admins("[key_name_admin(usr)] is dispatching an Emergency Response Team", 1)
+ log_admin("[key_name(usr)] used Dispatch Emergency Response Team..")
+ message_admins("Dispatching ERT with [commander_slots] com, [security_slots] sec, [medical_slots] med, [engineering_slots] eng, [janitor_slots] jan, [paranormal_slots] par, [cyborg_slots] cyb.")
+ trigger_armed_response_team(convert_ert_string(ert_type), commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots)
+ autoclose = 1
+
+ ui_interact(usr)
+
+ return 0
+
+/proc/convert_ert_string(thestring)
+ switch(thestring)
+ if("Code Amber")
+ return new /datum/response_team/amber
+ if("Code Red")
+ return new /datum/response_team/red
+ if("Code Gamma")
+ return new /datum/response_team/gamma
+
+
+/datum/nano_module/ert_manager/ui_data()
+ var/data[0]
+ data["alert_level"] = get_security_level()
+ data["ert_type"] = ert_type
+ data["com"] = commander_slots
+ data["sec"] = security_slots
+ data["med"] = medical_slots
+ data["eng"] = engineering_slots
+ data["jan"] = janitor_slots
+ data["par"] = paranormal_slots
+ data["cyb"] = cyborg_slots
+
+ return data
+
diff --git a/nano/templates/ert_config.tmpl b/nano/templates/ert_config.tmpl
new file mode 100644
index 00000000000..1f2eaac382b
--- /dev/null
+++ b/nano/templates/ert_config.tmpl
@@ -0,0 +1,41 @@
+
+ Alert: {{:data.alert_level}}
+
+
+
+
+ | {{if data.ert_type == 'Code Amber'}} AMBER {{else}} {{:helper.link('Amber', null, {"set_code": 'Code Amber'})}} {{/if}} |
+ {{if data.ert_type == 'Code Red'}} RED {{else}} {{:helper.link('Red', null, {"set_code": 'Code Red'})}} {{/if}} |
+ {{if data.ert_type == 'Code Gamma'}} GAMMA {{else}} {{:helper.link('Gamma', null, {"set_code": 'Code Gamma'})}} {{/if}} |
+
+
+
+
+
+ | Department | Assigned | Change Assignment |
+ | Command | {{:helper.smoothRound(data.com)}} | {{:helper.link('0', null, {"set_com": 0})}} {{:helper.link('1', null, {"set_com": 1})}} |
+ | Security | {{:helper.smoothRound(data.sec)}} |
+ {{:helper.link('0', null, {"set_sec": 0})}} {{:helper.link('1', null, {"set_sec": 1})}} {{:helper.link('3', null, {"set_sec": 3})}} {{:helper.link('5', null, {"set_sec": 5})}}
+ |
+
| Medical | {{:helper.smoothRound(data.med)}} |
+ {{:helper.link('0', null, {"set_med": 0})}} {{:helper.link('1', null, {"set_med": 1})}} {{:helper.link('3', null, {"set_med": 3})}} {{:helper.link('5', null, {"set_med": 5})}}
+ |
+
| Engineering | {{:helper.smoothRound(data.eng)}} |
+ {{:helper.link('0', null, {"set_eng": 0})}} {{:helper.link('1', null, {"set_eng": 1})}} {{:helper.link('3', null, {"set_eng": 3})}} {{:helper.link('5', null, {"set_eng": 5})}}
+ |
+
| Paranormal | {{:helper.smoothRound(data.par)}} |
+ {{:helper.link('0', null, {"set_par": 0})}} {{:helper.link('1', null, {"set_par": 1})}} {{:helper.link('3', null, {"set_par": 3})}} {{:helper.link('5', null, {"set_par": 5})}}
+ |
+
| Janitor | {{:helper.smoothRound(data.jan)}} |
+ {{:helper.link('0', null, {"set_jan": 0})}} {{:helper.link('1', null, {"set_jan": 1})}} {{:helper.link('3', null, {"set_jan": 3})}} {{:helper.link('5', null, {"set_jan": 5})}}
+ |
+
| {{if data.ert_type == 'Code Gamma'}}GAMMA {{/if}}Cyborg | {{:helper.smoothRound(data.cyb)}} |
+ {{:helper.link('0', null, {"set_cyb": 0})}} {{:helper.link('1', null, {"set_cyb": 1})}} {{:helper.link('3', null, {"set_cyb": 3})}} {{:helper.link('5', null, {"set_cyb": 5})}}
+ |
+
+
+
+
+ {{:helper.link('Dispatch', null, {"dispatch_ert": 1})}}
+
+
diff --git a/paradise.dme b/paradise.dme
index 4cc5aa5bd3b..f420c20c841 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1834,6 +1834,7 @@
#include "code\modules\nano\modules\alarm_monitor.dm"
#include "code\modules\nano\modules\atmos_control.dm"
#include "code\modules\nano\modules\crew_monitor.dm"
+#include "code\modules\nano\modules\ert_manager.dm"
#include "code\modules\nano\modules\human_appearance.dm"
#include "code\modules\nano\modules\law_manager.dm"
#include "code\modules\nano\modules\nano_module.dm"