[MIRROR] Sends a message to admins when a headrev/head disconnects during a revolution. They are no longer immediately treated as dead but are given a chance to reconnect [MDB IGNORE] (#23976)

* Sends a message to admins when a headrev/head disconnects during a revolution. They are no longer immediately treated as dead but are given a chance to reconnect (#78586)

## About The Pull Request
As the title says, headrevs and heads of staff during a revolution won't
be disqualified when they either disconnect or go AFK. Instead, they're
given a 2 minute timer to reconnect or stop being AFK and a warning is
sent out to admins so that they can offer up the player if time is close
to running out.
Two admin messages are sent, one when they're initially disconnected or
AFK and one sent a minute after, giving the admin a minute to act on the
log.

## Why It's Good For The Game
Disconnects can happen for any number of reasons, but sometimes they can
be unintentional, like the game crashing or briefly losing connection.
This will give headrevs and heads more leeway. Additionally, a solo
headrev who disconnects before they've converted anyone could be spotted
by admins and replaced so that the revolution gamemode isn't wasted.

## Changelog
🆑
balance: Head revolutionaries and heads of staff are no longer
immediately considered disqualified when going AFK or disconnecting and
are given a 2 minute grace period.
admin: Admins now get a log when a head revolutionary or head of staff
disconnects or goes AFK during a revolution. They also get the same log
1 minute after to give them a chance to act on the information.
/🆑

---------

Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com>

* Sends a message to admins when a headrev/head disconnects during a revolution. They are no longer immediately treated as dead but are given a chance to reconnect

---------

Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com>
Co-authored-by: Watermelon914 <3052169-Watermelon914@ users.noreply.gitlab.com>
This commit is contained in:
SkyratBot
2023-09-27 23:33:43 -04:00
committed by GitHub
co-authored by Watermelon914 Watermelon914
parent d157d55a33
commit 9501ca5be2
3 changed files with 62 additions and 6 deletions
+2
View File
@@ -108,4 +108,6 @@
#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0
#define COOLDOWN_STARTED(cd_source, cd_index) (cd_source.cd_index != 0)
#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time))
+29 -1
View File
@@ -236,18 +236,46 @@ GLOBAL_LIST_EMPTY(objectives) //SKYRAT EDIT ADDITION
/datum/objective/assassinate/admin_edit(mob/admin)
admin_simple_target_pick(admin)
#define DISCONNECT_GRACE_TIME (2 MINUTES)
#define DISCONNECT_GRACE_WARNING_TIME (1 MINUTES)
/datum/objective/mutiny
name = "mutiny"
martyr_compatible = 1
var/target_role_type = FALSE
/// Not primarily used as a cooldown but a timer to give a little bit more of a chance for the player to reconnect.
COOLDOWN_DECLARE(disconnect_timer)
/// Whether admins have been warned about the potentially AFK player
var/warned_admins = FALSE
/datum/objective/mutiny/proc/warn_admins()
message_admins("[ADMIN_LOOKUPFLW(target.current)] has gone AFK with a mutiny objective that involves them. They only have [COOLDOWN_TIMELEFT(src, disconnect_timer) / 10] seconds remaining before they are treated as if they were dead.")
/datum/objective/mutiny/check_completion()
if(!target || !considered_alive(target) || considered_afk(target) || considered_exiled(target))
if(!target || !considered_alive(target) || considered_exiled(target))
return TRUE
if(considered_afk(target))
if(!COOLDOWN_STARTED(src, disconnect_timer))
COOLDOWN_START(src, disconnect_timer, DISCONNECT_GRACE_TIME)
warn_admins()
else if(COOLDOWN_FINISHED(src, disconnect_timer))
return TRUE
else if(COOLDOWN_TIMELEFT(src, disconnect_timer) <= DISCONNECT_GRACE_WARNING_TIME && !warned_admins)
warned_admins = TRUE
warn_admins()
else
COOLDOWN_RESET(src, disconnect_timer)
warned_admins = FALSE
var/turf/T = get_turf(target.current)
return !T || !is_station_level(T.z)
#undef DISCONNECT_GRACE_TIME
#undef DISCONNECT_GRACE_WARNING_TIME
/datum/objective/mutiny/update_explanation_text()
..()
if(target?.current)
@@ -397,6 +397,9 @@
/// List of all ex-revs. Useful because dynamic removes antag status when it ends, so this can be kept for the roundend report.
var/list/ex_revs = list()
/// The objective of the heads of staff, aka to kill the headrevs.
var/list/datum/objective/mutiny/heads_objective = list()
/// Proc called on periodic timer.
/// Updates the rev team's objectives to make sure all heads are targets, useful when new heads latejoin.
/// Propagates all objectives to all revs.
@@ -472,11 +475,34 @@
/// Checks if heads have won
/datum/team/revolution/proc/check_heads_victory()
for(var/datum/mind/rev_mind in get_head_revolutionaries())
var/turf/rev_turf = get_turf(rev_mind.current)
if(!considered_afk(rev_mind) && considered_alive(rev_mind) && is_station_level(rev_turf.z))
return FALSE
return TRUE
// List of headrevs we're currently tracking
var/list/included_headrevs = list()
// List of current headrevs
var/list/current_headrevs = get_head_revolutionaries()
// A copy of the head of staff objective list, since we're going to be modifying the original list.
var/list/heads_objective_copy = heads_objective.Copy()
var/objective_complete = TRUE
// Here, we check current head of staff objectives and remove them if the target doesn't exist as a headrev anymore
for(var/datum/objective/mutiny/objective in heads_objective_copy)
if(!(objective.target in current_headrevs))
heads_objective -= objective
continue
if(!objective.check_completion())
objective_complete = FALSE
included_headrevs += objective.target
// Here, we check current headrevs and add them as objectives if they didn't exist as a head of staff objective before.
// Additionally, we make sure the objective is not completed by running the check_completion check on them.
for(var/datum/mind/rev_mind as anything in current_headrevs)
if(!(rev_mind in included_headrevs))
var/datum/objective/mutiny/objective = new()
objective.target = rev_mind
if(!objective.check_completion())
objective_complete = FALSE
heads_objective += objective
return objective_complete
/// 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.