Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] Adds an admin button to send nuke ops reinforcements #723

Merged
merged 1 commit into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions code/__DEFINES/antagonists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#define NUKE_RESULT_HIJACK_DISK 9
#define NUKE_RESULT_HIJACK_NO_DISK 10

/// Min players requireed for nukes to declare war
#define CHALLENGE_MIN_PLAYERS 50

//fugitive end results
#define FUGITIVE_RESULT_BADASS_HUNTER 0
#define FUGITIVE_RESULT_POSTMORTEM_HUNTER 1
Expand Down
4 changes: 4 additions & 0 deletions code/modules/admin/topic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1766,6 +1766,10 @@
var/obj/item/nuclear_challenge/button = locate(href_list["force_war"])
button.force_war()

else if(href_list["give_reinforcement"])
var/datum/team/nuclear/nuketeam = locate(href_list["give_reinforcement"]) in GLOB.antagonist_teams
nuketeam.admin_spawn_reinforcement(usr)

else if (href_list["interview"])
if(!check_rights(R_ADMIN))
return
Expand Down
14 changes: 10 additions & 4 deletions code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#define CHALLENGE_TELECRYSTALS 280
#define CHALLENGE_TIME_LIMIT (5 MINUTES)
#define CHALLENGE_MIN_PLAYERS 50
#define CHALLENGE_SHUTTLE_DELAY (25 MINUTES) // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.

GLOBAL_LIST_EMPTY(jam_on_wardec)
Expand Down Expand Up @@ -54,7 +53,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)

///Admin only proc to bypass checks and force a war declaration. Button on antag panel.
/obj/item/nuclear_challenge/proc/force_war()
var/are_you_sure = tgui_alert(usr, "Are you sure you wish to force a war declaration?", "Declare war?", list("Yes", "No"))
var/are_you_sure = tgui_alert(usr, "Are you sure you wish to force a war declaration?[GLOB.player_list.len < CHALLENGE_MIN_PLAYERS ? " Note, the player count is under the required limit." : ""]", "Declare war?", list("Yes", "No"))

if(are_you_sure != "Yes")
return
Expand All @@ -67,9 +66,14 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
war_declaration = tgui_input_text(usr, "Insert your custom declaration", "Declaration", multiline = TRUE, encode = FALSE)

if(!war_declaration)
to_chat(usr, span_warning("Invalid war declaration."))
tgui_alert(usr, "Invalid war declaration.", "Poor Choice of Words")
return

for(var/obj/item/circuitboard/computer/syndicate_shuttle/board as anything in GLOB.syndicate_shuttle_boards)
if(board.challenge)
tgui_alert(usr, "War has already been declared!", "War Was Declared")
return

war_was_declared(memo = war_declaration)

/obj/item/nuclear_challenge/proc/war_was_declared(mob/living/user, memo)
Expand Down Expand Up @@ -148,6 +152,9 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
if(board.moved)
to_chat(user, span_boldwarning("The shuttle has already been moved! You have forfeit the right to declare war."))
return FALSE
if(board.challenge)
to_chat(user, span_boldwarning("War has already been declared!"))
return FALSE
return TRUE

/obj/item/nuclear_challenge/clownops
Expand Down Expand Up @@ -189,5 +196,4 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)

#undef CHALLENGE_TELECRYSTALS
#undef CHALLENGE_TIME_LIMIT
#undef CHALLENGE_MIN_PLAYERS
#undef CHALLENGE_SHUTTLE_DELAY
116 changes: 110 additions & 6 deletions code/modules/antagonists/nukeop/nukeop.dm
Original file line number Diff line number Diff line change
Expand Up @@ -521,12 +521,116 @@
disk_loc = disk_loc.loc
disk_report += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])</td><td><a href='?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(N)]'>FLW</a></td></tr>"
disk_report += "</table>"
var/common_part = ..()
var/challenge_report
var/obj/item/nuclear_challenge/war_button = war_button_ref?.resolve()
if(war_button)
challenge_report += "<b>War not declared.</b> <a href='?_src_=holder;[HrefToken()];force_war=[REF(war_button)]'>\[Force war\]</a>"
return common_part + disk_report + challenge_report

var/post_report

var/war_declared = FALSE
for(var/obj/item/circuitboard/computer/syndicate_shuttle/board as anything in GLOB.syndicate_shuttle_boards)
if(board.challenge)
war_declared = TRUE

var/force_war_button = ""

if(war_declared)
post_report += "<b>War declared.</b>"
force_war_button = "\[Force war\]"
else
post_report += "<b>War not declared.</b>"
var/obj/item/nuclear_challenge/war_button = war_button_ref?.resolve()
if(war_button)
force_war_button = "<a href='?_src_=holder;[HrefToken()];force_war=[REF(war_button)]'>\[Force war\]</a>"
else
force_war_button = "\[Cannot declare war, challenge button missing!\]"

post_report += "\n[force_war_button]"
post_report += "\n<a href='?_src_=holder;[HrefToken()];give_reinforcement=[REF(src)]'>\[Send Reinforcement\]</a>"

var/final_report = ..()
final_report += disk_report
final_report += post_report
return final_report

#define SPAWN_AT_BASE "Nuke base"
#define SPAWN_AT_INFILTRATOR "Infiltrator"

/datum/team/nuclear/proc/admin_spawn_reinforcement(mob/admin)
if(!check_rights_for(admin.client, R_ADMIN))
return

var/infil_or_nukebase = tgui_alert(
admin,
"Spawn them at the nuke base, or in the Infiltrator?",
"Where to reinforce?",
list(SPAWN_AT_BASE, SPAWN_AT_INFILTRATOR, "Cancel"),
)

if(!infil_or_nukebase || infil_or_nukebase == "Cancel")
return

var/tc_to_spawn = tgui_input_number(admin, "How much TC to spawn with?", "TC", 0, 100)

var/list/nuke_candidates = poll_ghost_candidates(
"Do you want to play as an emergency syndicate reinforcement?",
ROLE_OPERATIVE,
ROLE_OPERATIVE,
30 SECONDS,
POLL_IGNORE_SYNDICATE,
)

nuke_candidates -= admin // may be easy to fat-finger say yes. so just don't

if(!length(nuke_candidates))
tgui_alert(admin, "No candidates found.", "Recruitment Shortage", list("OK"))
return


var/turf/spawn_loc
if(infil_or_nukebase == SPAWN_AT_INFILTRATOR)
var/area/spawn_in
// Prioritize EVA then hallway, if neither can be found default to the first area we can find
for(var/area_type in list(/area/shuttle/syndicate/eva, /area/shuttle/syndicate/hallway, /area/shuttle/syndicate))
spawn_in = locate(area_type) in GLOB.areas // I'd love to use areas_by_type but the Infiltrator is a unique area
if(spawn_in)
break

var/list/turf/options = list()
for(var/turf/open/open_turf in spawn_in?.get_contained_turfs())
if(open_turf.is_blocked_turf())
continue
options += open_turf

if(length(options))
spawn_loc = pick(options)
else
infil_or_nukebase = SPAWN_AT_BASE

if(infil_or_nukebase == SPAWN_AT_BASE)
spawn_loc = pick(GLOB.nukeop_start)

var/mob/dead/observer/picked = pick(nuke_candidates)
var/mob/living/carbon/human/nukie = new(spawn_loc)
picked.client.prefs.safe_transfer_prefs_to(nukie, is_antag = TRUE)
nukie.key = picked.key

var/datum/antagonist/nukeop/antag_datum = new()
antag_datum.send_to_spawnpoint = FALSE
antag_datum.nukeop_outfit = /datum/outfit/syndicate/reinforcement

nukie.mind.add_antag_datum(antag_datum, src)

var/datum/component/uplink/uplink = nukie.mind.find_syndicate_uplink()
uplink?.set_telecrystals(tc_to_spawn)

// add some pizzazz
do_sparks(4, FALSE, spawn_loc)
new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(spawn_loc)
playsound(spawn_loc, SFX_SPARKS, 50, TRUE)
playsound(spawn_loc, 'sound/effects/phasein.ogg', 50, TRUE)

tgui_alert(admin, "Reinforcement spawned at [infil_or_nukebase] with [tc_to_spawn].", "Reinforcements have arrived", list("God speed"))

#undef SPAWN_AT_BASE
#undef SPAWN_AT_INFILTRATOR

/// Returns whether or not syndicate operatives escaped.
/proc/is_infiltrator_docked_at_syndiebase()
Expand Down
Loading