Skip to content

Commit

Permalink
[MIRROR] Adds an admin button to send nuke ops reinforcements [MDB IG…
Browse files Browse the repository at this point in the history
…NORE] (#723)

* Adds an admin button to send nuke ops reinforcements (#79695)

---------

Co-authored-by: SkyratBot <[email protected]>
Co-authored-by: MrMelbert <[email protected]>
  • Loading branch information
3 people authored Nov 20, 2023
1 parent cbbc135 commit 5bf3377
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 10 deletions.
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

0 comments on commit 5bf3377

Please sign in to comment.