mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
Revolution victories now call the shuttle when enough of the station is revolutionaries (#68630)
When 65% or more of the station is revs, the shuttle will automatically call. This shuttle can be recalled. Approved with majority vote from me and @ninjanomnom Should probably be test merged first, I touched some core shuttle code. Roughly 60% of rev victories I checked called the shuttle shortly after. That's a lot, but there's still a high amount that aren't, either because the population genuinely wants to stay, or the revolutionary victory was a surprise. The latter of which I had happen to me like, recently! Remember that was the core problem revs victories continuing the round was trying to fix. With that in mind, this plays nicely with both some player grievances with post-revs while keeping in line with the core of the feature. Players are still, in part, controlling the end of the round, but with affordance given to the most likely scenario.
This commit is contained in:
@@ -265,10 +265,10 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
/// Check if we can call the evac shuttle.
|
||||
/// Returns TRUE if we can. Otherwise, returns a string detailing the problem.
|
||||
/datum/controller/subsystem/shuttle/proc/canEvac(mob/user)
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
return "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before attempting to call."
|
||||
/datum/controller/subsystem/shuttle/proc/canEvac()
|
||||
var/shuttle_refuel_delay = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < shuttle_refuel_delay)
|
||||
return "The emergency shuttle is refueling. Please wait [DisplayTimeText(shuttle_refuel_delay - (world.time - SSticker.round_start_time))] before attempting to call."
|
||||
|
||||
switch(emergency.mode)
|
||||
if(SHUTTLE_RECALL)
|
||||
@@ -286,58 +286,73 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
|
||||
if(!emergency)
|
||||
WARNING("requestEvac(): There is no emergency shuttle, but the \
|
||||
shuttle was called. Using the backup shuttle instead.")
|
||||
if(!backup_shuttle)
|
||||
CRASH("requestEvac(): There is no emergency shuttle, \
|
||||
or backup shuttle! The game will be unresolvable. This is \
|
||||
possibly a mapping error, more likely a bug with the shuttle \
|
||||
manipulation system, or badminry. It is possible to manually \
|
||||
resolve this problem by loading an emergency shuttle template \
|
||||
manually, and then calling register() on the mobile docking port. \
|
||||
Good luck.")
|
||||
emergency = backup_shuttle
|
||||
/datum/controller/subsystem/shuttle/proc/check_backup_emergency_shuttle()
|
||||
if(emergency)
|
||||
return TRUE
|
||||
|
||||
var/can_evac_or_fail_reason = SSshuttle.canEvac(user)
|
||||
WARNING("check_backup_emergency_shuttle(): There is no emergency shuttle, but the \
|
||||
shuttle was called. Using the backup shuttle instead.")
|
||||
|
||||
if(!backup_shuttle)
|
||||
CRASH("check_backup_emergency_shuttle(): There is no emergency shuttle, \
|
||||
or backup shuttle! The game will be unresolvable. This is \
|
||||
possibly a mapping error, more likely a bug with the shuttle \
|
||||
manipulation system, or badminry. It is possible to manually \
|
||||
resolve this problem by loading an emergency shuttle template \
|
||||
manually, and then calling register() on the mobile docking port. \
|
||||
Good luck.")
|
||||
emergency = backup_shuttle
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason)
|
||||
if (!check_backup_emergency_shuttle())
|
||||
return
|
||||
|
||||
var/can_evac_or_fail_reason = SSshuttle.canEvac()
|
||||
if(can_evac_or_fail_reason != TRUE)
|
||||
to_chat(user, span_alert("[can_evac_or_fail_reason]"))
|
||||
return
|
||||
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && SSsecurity_level.get_current_level_as_number() > SEC_LEVEL_GREEN)
|
||||
if(length(trim(call_reason)) < CALL_SHUTTLE_REASON_LENGTH && SSsecurity_level.get_current_level_as_number() > SEC_LEVEL_GREEN)
|
||||
to_chat(user, span_alert("You must provide a reason."))
|
||||
return
|
||||
|
||||
var/area/signal_origin = get_area(user)
|
||||
var/emergency_reason = "\nNature of emergency:\n\n[call_reason]"
|
||||
var/security_num = SSsecurity_level.get_current_level_as_number()
|
||||
switch(security_num)
|
||||
if(SEC_LEVEL_RED,SEC_LEVEL_DELTA)
|
||||
emergency.request(null, signal_origin, html_decode(emergency_reason), 1) //There is a serious threat we gotta move no time to give them five minutes.
|
||||
else
|
||||
emergency.request(null, signal_origin, html_decode(emergency_reason), 0)
|
||||
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
|
||||
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new(list("command" = "update")) // Start processing shuttle-mode displays to display the timer
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
var/area/A = get_area(user)
|
||||
call_evac_shuttle(call_reason, signal_origin)
|
||||
|
||||
log_shuttle("[key_name(user)] has called the emergency shuttle.")
|
||||
deadchat_broadcast(" has called the shuttle at [span_name("[A.name]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT)
|
||||
deadchat_broadcast(" has called the shuttle at [span_name("[signal_origin.name]")].", span_name("[user.real_name]"), user, message_type=DEADCHAT_ANNOUNCEMENT)
|
||||
if(call_reason)
|
||||
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
|
||||
log_shuttle("Shuttle call reason: [call_reason]")
|
||||
SSticker.emergency_reason = call_reason
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
|
||||
|
||||
/// Call the emergency shuttle.
|
||||
/// If you are doing this on behalf of a player, use requestEvac instead.
|
||||
/// `signal_origin` is fluff occasionally provided to players.
|
||||
/datum/controller/subsystem/shuttle/proc/call_evac_shuttle(call_reason, signal_origin)
|
||||
if (!check_backup_emergency_shuttle())
|
||||
return
|
||||
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
|
||||
var/emergency_reason = "\nNature of emergency:\n\n[call_reason]"
|
||||
|
||||
emergency.request(
|
||||
signal_origin = signal_origin,
|
||||
reason = html_decode(emergency_reason),
|
||||
red_alert = (SSsecurity_level.get_current_level_as_number() >= SEC_LEVEL_RED)
|
||||
)
|
||||
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
|
||||
|
||||
if(frequency)
|
||||
// Start processing shuttle-mode displays to display the timer
|
||||
var/datum/signal/status_signal = new(list("command" = "update"))
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
|
||||
if(emergency.mode != SHUTTLE_CALL || emergency.timer != old_timer)
|
||||
return
|
||||
|
||||
@@ -119,8 +119,6 @@
|
||||
blocking_rules = list(/datum/dynamic_ruleset/roundstart/revs)
|
||||
var/required_heads_of_staff = 3
|
||||
var/finished = FALSE
|
||||
/// How much threat should be injected when the revolution wins?
|
||||
var/revs_win_threat_injection = 20
|
||||
var/datum/team/revolution/revolution
|
||||
|
||||
/datum/dynamic_ruleset/latejoin/provocateur/ready(forced=FALSE)
|
||||
@@ -155,7 +153,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/dynamic_ruleset/latejoin/provocateur/rule_process()
|
||||
var/winner = revolution.process_victory(revs_win_threat_injection)
|
||||
var/winner = revolution.process_victory()
|
||||
if (isnull(winner))
|
||||
return
|
||||
|
||||
|
||||
@@ -495,8 +495,6 @@
|
||||
blocking_rules = list(/datum/dynamic_ruleset/latejoin/provocateur)
|
||||
// I give up, just there should be enough heads with 35 players...
|
||||
minimum_players = 35
|
||||
/// How much threat should be injected when the revolution wins?
|
||||
var/revs_win_threat_injection = 20
|
||||
var/datum/team/revolution/revolution
|
||||
var/finished = FALSE
|
||||
|
||||
@@ -539,7 +537,7 @@
|
||||
..()
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/revs/rule_process()
|
||||
var/winner = revolution.process_victory(revs_win_threat_injection)
|
||||
var/winner = revolution.process_victory()
|
||||
if (isnull(winner))
|
||||
return
|
||||
|
||||
|
||||
@@ -520,7 +520,7 @@
|
||||
data["alertLevel"] = SSsecurity_level.get_current_level_as_text()
|
||||
data["authorizeName"] = authorize_name
|
||||
data["canLogOut"] = !issilicon(user)
|
||||
data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac(user)
|
||||
data["shuttleCanEvacOrFailReason"] = SSshuttle.canEvac()
|
||||
if(syndicate)
|
||||
data["shuttleCanEvacOrFailReason"] = "You cannot summon the shuttle from this console!"
|
||||
|
||||
|
||||
@@ -405,8 +405,7 @@
|
||||
|
||||
/// Updates the state of the world depending on if revs won or loss.
|
||||
/// Returns who won, at which case this method should no longer be called.
|
||||
/// If revs_win_injection_amount is passed, then that amount of threat will be added if the revs win.
|
||||
/datum/team/revolution/proc/process_victory(revs_win_injection_amount)
|
||||
/datum/team/revolution/proc/process_victory()
|
||||
if (check_rev_victory())
|
||||
. = REVOLUTION_VICTORY
|
||||
else if (check_heads_victory())
|
||||
@@ -417,8 +416,6 @@
|
||||
SSshuttle.clearHostileEnvironment(src)
|
||||
save_members()
|
||||
|
||||
var/charter_given = FALSE
|
||||
|
||||
// Remove everyone as a revolutionary
|
||||
for (var/_rev_mind in members)
|
||||
var/datum/mind/rev_mind = _rev_mind
|
||||
@@ -441,56 +438,105 @@
|
||||
priority_announce("It appears the mutiny has been quelled. Please return yourself and your incapacitated colleagues to work. \
|
||||
We have remotely blacklisted the head revolutionaries in your medical records to prevent accidental revival.", null, null, null, "Central Command Loyalty Monitoring Division")
|
||||
else
|
||||
for(var/datum/mind/headrev_mind as anything in ex_headrevs)
|
||||
if(charter_given)
|
||||
break
|
||||
if(!headrev_mind.current || headrev_mind.current.stat != CONSCIOUS)
|
||||
continue
|
||||
charter_given = TRUE
|
||||
podspawn(list(
|
||||
"target" = get_turf(headrev_mind.current),
|
||||
"style" = STYLE_SYNDICATE,
|
||||
"spawn" = /obj/item/station_charter/revolution,
|
||||
))
|
||||
to_chat(headrev_mind.current, span_hear("You hear something crackle in your ears for a moment before a voice speaks. \
|
||||
\"Please stand by for a message from your benefactor. Message as follows, provocateur. \
|
||||
<b>You have been chosen out of your fellow provocateurs to rename the station. Choose wisely.</b> Message ends.\""))
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_REVOLUTION_TAX_REMOVAL)
|
||||
victory_effects()
|
||||
|
||||
for (var/mob/living/player as anything in GLOB.player_list)
|
||||
var/datum/mind/player_mind = player.mind
|
||||
/datum/team/revolution/proc/victory_effects(revs_win_injection_amount)
|
||||
var/charter_given = FALSE
|
||||
|
||||
if (isnull(player_mind))
|
||||
continue
|
||||
for(var/datum/mind/headrev_mind as anything in ex_headrevs)
|
||||
if(charter_given)
|
||||
break
|
||||
if(!headrev_mind.current || headrev_mind.current.stat != CONSCIOUS)
|
||||
continue
|
||||
charter_given = TRUE
|
||||
podspawn(list(
|
||||
"target" = get_turf(headrev_mind.current),
|
||||
"style" = STYLE_SYNDICATE,
|
||||
"spawn" = /obj/item/station_charter/revolution,
|
||||
))
|
||||
to_chat(headrev_mind.current, span_hear("You hear something crackle in your ears for a moment before a voice speaks. \
|
||||
\"Please stand by for a message from your benefactor. Message as follows, provocateur. \
|
||||
<b>You have been chosen out of your fellow provocateurs to rename the station. Choose wisely.</b> Message ends.\""))
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_REVOLUTION_TAX_REMOVAL)
|
||||
|
||||
if (!(player_mind.assigned_role.departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND)))
|
||||
continue
|
||||
for (var/mob/living/player as anything in GLOB.player_list)
|
||||
var/datum/mind/player_mind = player.mind
|
||||
|
||||
if (player_mind in ex_revs + ex_headrevs)
|
||||
continue
|
||||
if (isnull(player_mind))
|
||||
continue
|
||||
|
||||
player_mind.add_antag_datum(/datum/antagonist/enemy_of_the_revolution)
|
||||
if (!(player_mind.assigned_role.departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND)))
|
||||
continue
|
||||
|
||||
if (!istype(player))
|
||||
continue
|
||||
if (player_mind in ex_revs + ex_headrevs)
|
||||
continue
|
||||
|
||||
if(player_mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)
|
||||
ADD_TRAIT(player, TRAIT_DEFIB_BLACKLISTED, REF(src))
|
||||
player.med_hud_set_status()
|
||||
player_mind.add_antag_datum(/datum/antagonist/enemy_of_the_revolution)
|
||||
|
||||
for(var/datum/job/job as anything in SSjob.joinable_occupations)
|
||||
if(!(job.departments_bitflags & (DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND)))
|
||||
continue
|
||||
job.allow_bureaucratic_error = FALSE
|
||||
job.total_positions = 0
|
||||
if (!istype(player))
|
||||
continue
|
||||
|
||||
if (revs_win_injection_amount)
|
||||
var/datum/game_mode/dynamic/dynamic = SSticker.mode
|
||||
dynamic.unfavorable_situation()
|
||||
if(player_mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND)
|
||||
ADD_TRAIT(player, TRAIT_DEFIB_BLACKLISTED, REF(src))
|
||||
player.med_hud_set_status()
|
||||
|
||||
priority_announce("A recent assessment of your station has marked your station as a severe risk area for high ranking Nanotrasen officials. \
|
||||
For the safety of our staff, we have blacklisted your station for new employment of security and command. \
|
||||
[pick(world.file2list("strings/anti_union_propaganda.txt"))]", null, null, null, "Central Command Loyalty Monitoring Division")
|
||||
for(var/datum/job/job as anything in SSjob.joinable_occupations)
|
||||
if(!(job.departments_bitflags & DEPARTMENT_BITFLAG_SECURITY|DEPARTMENT_BITFLAG_COMMAND))
|
||||
continue
|
||||
job.allow_bureaucratic_error = FALSE
|
||||
job.total_positions = 0
|
||||
|
||||
var/datum/game_mode/dynamic/dynamic = SSticker.mode
|
||||
dynamic.unfavorable_situation()
|
||||
|
||||
var/message_header = "A recent assessment of your station has marked your station as a severe risk area for high ranking Nanotrasen officials."
|
||||
var/extra_detail = try_auto_call_shuttle() \
|
||||
? "For the safety of our staff, we are expediting an emergency shuttle for remaining members of security and command." \
|
||||
: "For the safety of our staff, we have blacklisted your station for new employment of security and command."
|
||||
var/propaganda = pick(world.file2list("strings/anti_union_propaganda.txt"))
|
||||
|
||||
priority_announce(
|
||||
"[message_header]\n\n[extra_detail]\n\n[propaganda]",
|
||||
sender_override = "Central Command Loyalty Monitoring Division"
|
||||
)
|
||||
|
||||
/// How much of the station, ignoring sec and command, should be revs before a shuttle will be automatically called?
|
||||
#define REV_AUTO_CALL_THRESHOLD 0.65
|
||||
|
||||
/datum/team/revolution/proc/try_auto_call_shuttle()
|
||||
var/total_revs = ex_revs.len + ex_headrevs.len
|
||||
var/total_candidates = 0
|
||||
|
||||
for (var/mob/player as anything in GLOB.player_list)
|
||||
if (player.mind.has_antag_datum(/datum/antagonist/enemy_of_the_revolution))
|
||||
continue
|
||||
|
||||
total_candidates += 1
|
||||
|
||||
var/display_percent = round(total_revs / total_candidates * 100)
|
||||
|
||||
if (total_revs / total_candidates < REV_AUTO_CALL_THRESHOLD)
|
||||
log_game("REVOLUTION: Not calling the shuttle, [display_percent]% are revs")
|
||||
return FALSE
|
||||
|
||||
// Do it later so everyone has time to see the messages
|
||||
addtimer(CALLBACK(src, .proc/perform_auto_shuttle_call), 20 SECONDS)
|
||||
|
||||
var/log = "REVOLUTION: Auto-calling the shuttle, [display_percent]% are revs"
|
||||
log_game(log)
|
||||
message_admins(log)
|
||||
|
||||
return TRUE
|
||||
|
||||
#undef REV_AUTO_CALL_THRESHOLD
|
||||
|
||||
/datum/team/revolution/proc/perform_auto_shuttle_call()
|
||||
var/can_evac_result = SSshuttle.canEvac()
|
||||
if (can_evac_result != TRUE)
|
||||
log_game("REVOLUTION: Not calling the shuttle, canEvac() returned [can_evac_result]")
|
||||
return
|
||||
|
||||
SSshuttle.call_evac_shuttle("Sending emergency shuttle to rescue command and security staff.")
|
||||
|
||||
/// Mutates the ticker to report that the revs have won
|
||||
/datum/team/revolution/proc/round_result(finished)
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
to_chat(usr, span_warning("Wireless control is disabled!"))
|
||||
return
|
||||
|
||||
var/can_evac_or_fail_reason = SSshuttle.canEvac(src)
|
||||
var/can_evac_or_fail_reason = SSshuttle.canEvac()
|
||||
if(can_evac_or_fail_reason != TRUE)
|
||||
to_chat(usr, span_alert("[can_evac_or_fail_reason]"))
|
||||
return
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
|
||||
. = ..()
|
||||
|
||||
/obj/docking_port/mobile/emergency/request(obj/docking_port/stationary/S, area/signalOrigin, reason, redAlert, set_coefficient=null)
|
||||
/obj/docking_port/mobile/emergency/request(obj/docking_port/stationary/S, area/signal_origin, reason, red_alert, set_coefficient=null)
|
||||
if(!isnum(set_coefficient))
|
||||
var/security_num = SSsecurity_level.get_current_level_as_number()
|
||||
switch(security_num)
|
||||
@@ -342,11 +342,11 @@
|
||||
SSshuttle.emergencyCallAmount++
|
||||
|
||||
if(prob(70))
|
||||
SSshuttle.emergency_last_call_loc = signalOrigin
|
||||
SSshuttle.emergency_last_call_loc = signal_origin
|
||||
else
|
||||
SSshuttle.emergency_last_call_loc = null
|
||||
|
||||
priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergency_last_call_loc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ][SSshuttle.admin_emergency_no_recall ? "\n\nWarning: Shuttle recall subroutines disabled; Recall not possible." : ""]", null, ANNOUNCER_SHUTTLECALLED, "Priority")
|
||||
priority_announce("The emergency shuttle has been called. [red_alert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergency_last_call_loc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ][SSshuttle.admin_emergency_no_recall ? "\n\nWarning: Shuttle recall subroutines disabled; Recall not possible." : ""]", null, ANNOUNCER_SHUTTLECALLED, "Priority")
|
||||
|
||||
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
|
||||
if(mode != SHUTTLE_CALL)
|
||||
|
||||
Reference in New Issue
Block a user