Skip to content

Commit

Permalink
ERT na zawołanie załogi - mniej więcej (#286)
Browse files Browse the repository at this point in the history
  • Loading branch information
MACIEKBAKI authored Mar 3, 2024
1 parent 1300fc1 commit 9f2fa13
Show file tree
Hide file tree
Showing 8 changed files with 229 additions and 20 deletions.
1 change: 1 addition & 0 deletions aquila/aquila.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "code\game\gamemodes\monkey\monkey.dm"
#include "code\game\machinery\battery.dm"
#include "code\game\machinery\computer\_computer.dm"
#include "code\game\machinery\computer\communications.dm"
#include "code\game\machinery\doors\airlock_types.dm"
#include "code\game\machinery\doors\firedoor.dm"
#include "code\game\machinery\fabricators\modular_fabricator.dm"
Expand Down
28 changes: 28 additions & 0 deletions aquila/code/game/machinery/computer/communications.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/obj/machinery/computer/communications
/// Cooldown before you can call in an ERT or wave of assistants
COOLDOWN_DECLARE(static/reinforcement_action_cooldown)

/obj/machinery/computer/communications/proc/authenticated_as_cap_sec_or_silicon(mob/user)
if (issilicon(user))
return TRUE
return (ACCESS_CAPTAIN in authorize_access) || (ACCESS_HOS in authorize_access)

/obj/machinery/computer/communications/ui_act(action, list/params)
. = ..()
if (.)
return

switch(action)
if("requestERT")
if (!authenticated_as_cap_sec_or_silicon(usr))
return
if (!COOLDOWN_FINISHED(src, reinforcement_action_cooldown))
return
var/reason = trim(html_encode(params["reason"]), MAX_MESSAGE_LEN)
ert_request(reason, usr)
to_chat(usr, "<span class='notice'>Request sent.</span>")
usr.log_message("has requested an emergency response team from Centcom with reason \"[reason]\"", LOG_SAY)
priority_announce("An Emergency Response Team has been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Emergency Response Team Requested", SSstation.announcer.get_rand_report_sound())
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE)
COOLDOWN_START(src, reinforcement_action_cooldown, 15 MINUTES)
. = TRUE
167 changes: 147 additions & 20 deletions aquila/code/modules/requests/request.dm
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
#define NUKE_CODE_AUTOGENERATION_ADMIN_INTERVENTION_TIME 20
#define REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME 20

/datum/request
/// For nuke code requests; auto-fulfillment
var/autogenerate
var/autoaccept

/datum/request/Topic(href, href_list)
. = ..()
if(href_list["cancel_nuke"])
if(req_type != REQUEST_NUKE) // what are you trying to cancel???
to_chat(usr, "<span class='admin'>You can't cancel this type of request.</span>")
return
if(!autoaccept)
to_chat(usr, "<span class='admin'>You are too late to cancel that!</span>")
return
autoaccept = FALSE
message_admins("[key_name_admin(usr)] cancelled nuke code autogeneration requested by [ADMIN_FULLMONTY(owner)].")
log_admin_private("[key_name(usr)] cancelled code autogeneration requested by [ADMIN_FULLMONTY(owner)].")
SSblackbox.record_feedback("tally", "nuke_code_autogeneration_admin_cancelled", 1, message)
if(href_list["cancel_ert"])
if(req_type != REQUEST_ERT) // what are you trying to cancel???
to_chat(usr, "<span class='admin'>You can't cancel this type of request.</span>")
return
if(!autoaccept)
to_chat(usr, "<span class='admin'>You are too late to cancel that!</span>")
return
autoaccept = FALSE
message_admins("[key_name_admin(usr)] rejected the response team request from [ADMIN_FULLMONTY(owner)].")
log_admin_private("[key_name(usr)] rejected the response team request from [ADMIN_FULLMONTY(owner)].")
SSblackbox.record_feedback("tally", "nuke_code_autogeneration_admin_cancelled", 1, message)

/datum/request/proc/auto_generate_nuke_code()
autogenerate = TRUE
message_admins("Automatically generating nuke codes requested by [ADMIN_FULLMONTY(owner)] in [NUKE_CODE_AUTOGENERATION_ADMIN_INTERVENTION_TIME] seconds. (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)")
sleep(NUKE_CODE_AUTOGENERATION_ADMIN_INTERVENTION_TIME SECONDS)
if(autogenerate)
autoaccept = TRUE
message_admins("Automatically generating nuke codes requested by [ADMIN_FULLMONTY(owner)] in [REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME] seconds. (<a href='?src=[REF(src)];cancel_nuke=1'>CANCEL</a>)")
sleep(REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME SECONDS)
if(autoaccept)
var/code = random_code(5)
for(var/obj/machinery/nuclearbomb/selfdestruct/SD in GLOB.nuke_list)
SD.r_code = code
Expand All @@ -19,19 +44,121 @@ System awaryjny automatycznie zatwierdził prośbe.
Kod do ładunku nuklearnego na pokładzie waszego statku to [code]."}
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(priority_announce), message, "Automatyczny System Awaryjny Centrali"), 2 SECONDS)

#define ERT_REQUEST_REJECTED "dont_waste_company_resources"
GLOBAL_VAR_INIT(erts_requested_already, 0)

/datum/request/Topic(href, href_list)
. = ..()
if(href_list["cancel"])
if(req_type != REQUEST_NUKE) // what are you trying to cancel???
to_chat(usr, "<span class='admin'>You can't cancel this type of request.</span>")
return
if(!autogenerate)
to_chat(usr, "<span class='admin'>You are too late to cancel that!</span>")
return
autogenerate = FALSE
message_admins("[key_name_admin(usr)] cancelled nuke code autogeneration requested by [ADMIN_FULLMONTY(owner)].")
log_admin_private("[key_name(usr)] cancelled code autogeneration requested by [ADMIN_FULLMONTY(owner)].")
SSblackbox.record_feedback("tally", "nuke_code_autogeneration_admin_cancelled", 1, message)
/datum/request/proc/pick_ert_team_type()
var/list/picklist = list(
///datum/ert/intern = 40,
ERT_REQUEST_REJECTED = 10
)
if(GLOB.security_level == SEC_LEVEL_DELTA) // not that theyll ever arrive due to time constraints when this goes in
return pickweight(list(
/datum/ert/deathsquad = 25,
/datum/ert/doomguy = 25,
/datum/ert/honk = 20,
/datum/ert/inquisition = 20,
/datum/ert/janitor = 10
))

var/list/all_players = SSticker.mode.current_players[CURRENT_LIVING_PLAYERS] + SSticker.mode.current_players[CURRENT_DEAD_PLAYERS]
var/list/dead_players = SSticker.mode.current_players[CURRENT_DEAD_PLAYERS]
if(!all_players.len)
return pickweight(picklist)
var/ratio = LAZYLEN(dead_players)/LAZYLEN(all_players)

if(ratio >= 0.30)
picklist = list(
/datum/ert/blue = 45,
/datum/ert/amber = 5
)

return pickweight(picklist)

/datum/request/proc/auto_create_response_team()
autoaccept = TRUE
message_admins("Automatically sending response team requested by [ADMIN_FULLMONTY(owner)] in [REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME] seconds. (<a href='?src=[REF(src)];cancel_ert=1'>CANCEL</a>)")
sleep(REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME SECONDS)
if(autoaccept) // pod tym jest kopiuj wklej z one_click_antag.dm
var/message = "Prośba o przesłanie drużyny szybkiej reakcji została zaakceptowana, jednakże wszystkie drużyny są obecnie zajęte. Za niedogodności przepraszamy."
var/datum/ert/ertemplate
var/ert_type = pick_ert_team_type()
if(ert_type == ERT_REQUEST_REJECTED)
message = "Prośba o przesłanie drużyny szybkiej reakcji została odrzucona. Nie marnujcie naszego czasu."
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(priority_announce), message, "Automatyczny System Awaryjny Centrali"), 2 SECONDS)
return FALSE
ertemplate = new ert_type
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for [ertemplate.polldesc] ?", ROLE_ERT, req_hours = 0)
var/teamSpawned = FALSE
if(candidates.len <= 0)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(priority_announce), message, "Automatyczny System Awaryjny Centrali"), 2 SECONDS)
return FALSE
else
//Pick the (un)lucky players
var/numagents = min(ertemplate.teamsize,candidates.len)

//Create team
var/datum/team/ert/ert_team = new ertemplate.team
if(ertemplate.rename_team)
ert_team.name = ertemplate.rename_team

//Asign team objective
var/datum/objective/missionobj = new
missionobj.team = ert_team
missionobj.explanation_text = ertemplate.mission
missionobj.completed = TRUE
ert_team.objectives += missionobj
ert_team.mission = missionobj

var/list/spawnpoints = GLOB.emergencyresponseteamspawn
while(numagents && candidates.len)
if (numagents > spawnpoints.len)
numagents--
continue // This guy's unlucky, not enough spawn points, we skip him.
var/spawnloc = spawnpoints[numagents]
var/mob/dead/observer/chosen_candidate = pick(candidates)
candidates -= chosen_candidate
if(!chosen_candidate.key)
continue

//Spawn the body
var/mob/living/carbon/human/ERTOperative = new ertemplate.mobtype(spawnloc)
chosen_candidate.client.prefs.active_character.copy_to(ERTOperative)
ERTOperative.key = chosen_candidate.key
log_objective(ERTOperative, missionobj.explanation_text)

if(ertemplate.enforce_human || !(ERTOperative.dna.species.changesource_flags & ERT_SPAWN)) // Don't want any exploding plasmemes
ERTOperative.set_species(/datum/species/human)

//Give antag datum
var/datum/antagonist/ert/ert_antag

if(numagents == 1)
ert_antag = new ertemplate.leader_role
else
ert_antag = ertemplate.roles[WRAP(numagents,1,length(ertemplate.roles) + 1)]
ert_antag = new ert_antag

ERTOperative.mind.add_antag_datum(ert_antag,ert_team)
ERTOperative.mind.assigned_role = ert_antag.name

//Logging and cleanup
log_game("[key_name(ERTOperative)] has been selected as an [ert_antag.name]")
numagents--
teamSpawned++

if (teamSpawned)
message_admins("[ertemplate.polldesc] has spawned with the mission: [ertemplate.mission]")

//Open the Armory doors
if(ertemplate.opendoors)
for(var/obj/machinery/door/poddoor/ert/door in GLOB.airlocks)
door.open()
CHECK_TICK
else
message = "Prośba o przesłanie drużyny szybkiej reakcji została odrzucona. Nie marnujcie naszego czasu."
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(priority_announce), message, "Automatyczny System Awaryjny Centrali"), 2 SECONDS)
return FALSE

#undef NUKE_CODE_AUTOGENERATION_ADMIN_INTERVENTION_TIME
#undef REQUEST_AUTOACCEPT_ADMIN_INTERVENTION_TIME
#undef ERT_REQUEST_REJECTED
5 changes: 5 additions & 0 deletions code/game/machinery/computer/communications.dm
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,12 @@
data["canMessageAssociates"] = !issilicon(user) && GLOB.security_level >= SEC_LEVEL_RED
data["canRecallShuttles"] = !issilicon(user)
data["canRequestNuke"] = FALSE
data["canRequestERT"] = FALSE // AQ EDIT
data["canSendToSectors"] = FALSE
data["canSetAlertLevel"] = FALSE
data["canToggleEmergencyAccess"] = FALSE
data["importantActionReady"] = COOLDOWN_FINISHED(src, important_action_cooldown)
data["reinforcementActionReady"] = COOLDOWN_FINISHED(src, reinforcement_action_cooldown) // AQ EDIT
data["shuttleCalled"] = FALSE
data["shuttleLastCalled"] = FALSE

Expand All @@ -388,6 +390,9 @@
data["canMessageAssociates"] = TRUE
data["canRequestNuke"] = TRUE

if (authenticated_as_cap_sec_or_silicon(user)) // AQ EDIT
data["canRequestERT"] = TRUE

if (can_send_messages_to_other_sectors(user))
data["canSendToSectors"] = TRUE

Expand Down
8 changes: 8 additions & 0 deletions code/modules/admin/verbs/pray.dm
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,11 @@
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/console in GLOB.machines)
console.override_cooldown()

/proc/ert_request(text, mob/sender) // AQ EDIT
var/msg = copytext_char(sanitize(text), 1, MAX_MESSAGE_LEN)
GLOB.requests.ert_request(sender.client, msg)
msg = "<span class='adminnotice'><b><font color=orange>RESPONSE TEAM REQUEST:</font>[ADMIN_FULLMONTY(sender)] [ADMIN_CENTCOM_REPLY(sender)]:</b> [msg]</span>"
to_chat(GLOB.admins, msg)
for(var/obj/machinery/computer/communications/console in GLOB.machines)
console.override_cooldown()
6 changes: 6 additions & 0 deletions code/modules/requests/request.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#define REQUEST_SYNDICATE "request_syndicate"
/// Requests for the nuke code
#define REQUEST_NUKE "request_nuke"
// AQ EDIT
/// Requests for an ERT
#define REQUEST_ERT "request_response_team"

/**
* # Request
Expand Down Expand Up @@ -45,3 +48,6 @@
if(req_type == REQUEST_NUKE && CONFIG_GET(flag/allow_nuke_request_auto_accept)) // AQ EDIT
spawn(0)
auto_generate_nuke_code()
if(req_type == REQUEST_ERT && CONFIG_GET(flag/allow_nuke_request_auto_accept)) // AQ EDIT
spawn(0)
auto_create_response_team()
3 changes: 3 additions & 0 deletions code/modules/requests/request_manager.dm
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ GLOBAL_DATUM_INIT(requests, /datum/request_manager, new)
/datum/request_manager/proc/nuke_request(client/C, message)
request_for_client(C, REQUEST_NUKE, message)

/datum/request_manager/proc/ert_request(client/C, message)
request_for_client(C, REQUEST_ERT, message)

/**
* Creates a request and registers the request with all necessary internal tracking lists
*
Expand Down
31 changes: 31 additions & 0 deletions tgui/packages/tgui/interfaces/CommunicationsConsole.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,14 @@ const PageMain = (props, context) => {
canMessageAssociates,
canRecallShuttles,
canRequestNuke,
canRequestERT,
canSendToSectors,
canSetAlertLevel,
canToggleEmergencyAccess,
emagged,
emergencyAccess,
importantActionReady,
reinforcementActionReady,
shuttleCalled,
shuttleCalledPreviously,
shuttleCanEvacOrFailReason,
Expand All @@ -345,6 +347,10 @@ const PageMain = (props, context) => {
context, "messaing_sector", null);
const [requestingNukeCodes, setRequestingNukeCodes] = useLocalState(
context, "requesting_nuke_codes", false);
const [requestingResponseTeam, setRequestingResponseTeam] = useLocalState(
context, "requesting_ert", false);



const [
[showAlertLevelConfirm, confirmingAlertLevelTick],
Expand Down Expand Up @@ -484,6 +490,17 @@ const PageMain = (props, context) => {
</Flex.Item>
)}

{!!canRequestERT && (
<Flex.Item mt={0.3}>
<Button fluid
icon="radiation"
content="Request Emergency Response Team"
disabled={!reinforcementActionReady}
onClick={() => setRequestingResponseTeam(true)}
/>
</Flex.Item>
)}

{!!emagged && (
<Flex.Item mt={0.3}>
<Button fluid
Expand Down Expand Up @@ -535,6 +552,20 @@ const PageMain = (props, context) => {
}}
/>}

{!!canRequestERT && requestingResponseTeam && <MessageModal
label="Reason for requesting emergency response team"
notice="Misuse of the response team requesting system will not be tolerated under any circumstances. Transmission does not guarantee a response."
icon="bomb"
buttonText="Request ERT"
onBack={() => setRequestingResponseTeam(false)}
onSubmit={reason => {
setRequestingResponseTeam(false);
act("requestERT", {
reason,
});
}}
/>}

{!!callingShuttle && <MessageModal
label="Nature of emergency"
icon="space-shuttle"
Expand Down

0 comments on commit 9f2fa13

Please sign in to comment.