mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-09 16:05:07 +00:00
Adds Coroner to Mafia & Bunch of Mafia changes (#92158)
Changeling chat is now at night, rather than :j saymode, and it is also separated from normal messages as [CHANGELING CHAT] Adds a new [DEAD CHAT], all dead players in Mafia are corpselocked and talking will instead go to Dead chat. The Chaplain's ability is now being able to hear Dead chat at night, and being able to in turn speak to the Dead. The Chaplain's old ability has been given to a new role, the Coroner. "Pray" is now "Autopsy". Deaths in the Mafia arena aren't broadcasted anymore, to lessen annoyance to round observers. Also updates role icons & some outfits, as well as some bug fixes I encountered while messing with it on localhost. I also tried (but not fully) to make Mafia games more modular and independent, so maybe in the future we can have more than one Mafia game running at a time. I am limited to 2 player testing for this, so it is very much possible that there's some issues I haven't found from my local testing, let me know if you find anything please. Being dead in Mafia boots you out of the round regardless of how invested you were, that kidna sucks so hopefully being able to still contribute something to the game, or at least discuss it with other dead players in your own chat, makes players feel important to the game they're playing. I have a previous attempt of this here - https://github.com/tgstation/tgstation/pull/75879 - but it staled out. This differs from that attempt, as only dead players from the Mafia game can speak in dead chat, while the old attempt allowed anyone that was observing a mafia sign post (so dead players from the game, but not observing the post, weren't able to speak to Chaplains, making him very hard to be useful especially since getting information like that across is a little hard). Being corpselocked also prevents them from being able to see who Changelings are by simply looking at who has maptext at night, and keeps them more focused on the game being played. 🆑 add: Added a new role to Mafia; the Coroner, which takes the Chaplain's ability to see dead people's roles. add: Mafia Chaplains now speak with the dead at night instead, and the dead are corpselocked to prevent cheating. fix: Mafia's HoS doesn't kill himself when executing non-townies. qol: You can now update your notes & send them in chat while dead, as well as look up the descriptions of other roles. /🆑
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
#define MAFIA_MEDAL_DETECTIVE "Detective"
|
||||
#define MAFIA_MEDAL_PSYCHOLOGIST "Psychologist"
|
||||
#define MAFIA_MEDAL_CHAPLAIN "Chaplain"
|
||||
#define MAFIA_MEDAL_CORONER "Coroner"
|
||||
#define MAFIA_MEDAL_MD "Medical Doctor"
|
||||
#define MAFIA_MEDAL_OFFICER "Security Officer"
|
||||
#define MAFIA_MEDAL_LAWYER "Lawyer"
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#define RADIO_EXTENSION "department specific"
|
||||
#define RADIO_KEY "department specific key"
|
||||
#define LANGUAGE_EXTENSION "language specific"
|
||||
///This is a mob that is forcing us to say something, so we can use the mob typing the text for bans rather than the one speaking.
|
||||
#define MANNEQUIN_CONTROLLED "mannequin controlled"
|
||||
/// Message mod which contains a list of bonus "mutual understanding" to allow arbitrary understanding of any speech
|
||||
#define LANGUAGE_MUTUAL_BONUS "language mutual bonus"
|
||||
#define SAY_MOD_VERB "say_mod_verb"
|
||||
|
||||
@@ -23,10 +23,16 @@
|
||||
|
||||
/datum/award/achievement/mafia/chaplain
|
||||
name = "Chaplain Victory"
|
||||
desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector."
|
||||
desc = "The curse finally broken."
|
||||
database_id = MAFIA_MEDAL_CHAPLAIN
|
||||
icon_state = "town"
|
||||
|
||||
/datum/award/achievement/mafia/coroner
|
||||
name = "Coroner Victory"
|
||||
desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector."
|
||||
database_id = MAFIA_MEDAL_CORONER
|
||||
icon_state = "town"
|
||||
|
||||
/datum/award/achievement/mafia/md
|
||||
name = "Medical Doctor Victory"
|
||||
desc = "Congratulations on learning how to not talk!"
|
||||
|
||||
@@ -24,31 +24,34 @@
|
||||
///How fast the game will speed up when half the players are gone.
|
||||
#define MAFIA_SPEEDUP_INCREASE 2
|
||||
|
||||
#define MAFIA_TEAM_TOWN "town"
|
||||
#define MAFIA_TEAM_MAFIA "mafia"
|
||||
#define MAFIA_TEAM_SOLO "solo"
|
||||
//'Team' flags, used to know which alliance your role is part of.
|
||||
#define MAFIA_TEAM_TOWN (1<<0)
|
||||
#define MAFIA_TEAM_MAFIA (1<<1)
|
||||
#define MAFIA_TEAM_SOLO (1<<2)
|
||||
//those part of the 'dead' faction can hear dead chat, not a "faction" of players.
|
||||
#define MAFIA_TEAM_DEAD (1<<3)
|
||||
|
||||
//types of town roles for random setup gen
|
||||
/// Add this if you don't want a role to be a choice in the selection
|
||||
#define TOWN_OVERFLOW "overflow"
|
||||
#define TOWN_OVERFLOW "town overflow"
|
||||
/// roles that learn info about others in the game (chaplain, detective, psych)
|
||||
#define TOWN_INVEST "invest"
|
||||
#define TOWN_INVEST "town invest"
|
||||
/// roles that keep other roles safe (doctor, sec officer, and weirdly enough lawyer counts)
|
||||
#define TOWN_PROTECT "protect"
|
||||
#define TOWN_PROTECT "town protect"
|
||||
/// roles that are only there to kill bad guys.
|
||||
#define TOWN_KILLING "killing"
|
||||
#define TOWN_KILLING "town killing"
|
||||
/// roles that don't fit into anything else (hop)
|
||||
#define TOWN_SUPPORT "support"
|
||||
#define TOWN_SUPPORT "town support"
|
||||
|
||||
//other types (mafia team, neutrals)
|
||||
/// normal vote kill changelings
|
||||
#define MAFIA_REGULAR "regular"
|
||||
#define MAFIA_REGULAR "mafia"
|
||||
/// every other changeling role that has extra abilities
|
||||
#define MAFIA_SPECIAL "special"
|
||||
#define MAFIA_SPECIAL "mafia special"
|
||||
/// role that wins solo that nobody likes
|
||||
#define NEUTRAL_KILL "kill"
|
||||
#define NEUTRAL_KILL "neutral killing"
|
||||
/// role that upsets the game aka obsessed, usually worse for town than mafia but they can vote against mafia
|
||||
#define NEUTRAL_DISRUPT "disrupt"
|
||||
#define NEUTRAL_DISRUPT "neutral chaos"
|
||||
|
||||
//role flags (special status of roles like detection immune)
|
||||
///to all forms of detection, shows themselves as an assistant.
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
///The mafia role this ability is targeting, if necessary.
|
||||
var/datum/mafia_role/target_role
|
||||
|
||||
/datum/mafia_ability/New(datum/mafia_controller/game, datum/mafia_role/host_role)
|
||||
/datum/mafia_ability/New(datum/mafia_role/host_role)
|
||||
. = ..()
|
||||
src.host_role = host_role
|
||||
if(action_priority)
|
||||
RegisterSignal(game, action_priority, PROC_REF(perform_action_target))
|
||||
RegisterSignal(game, COMSIG_MAFIA_NIGHT_END, PROC_REF(clean_action_refs))
|
||||
RegisterSignal(host_role.mafia_game_controller, action_priority, PROC_REF(perform_action_target))
|
||||
RegisterSignal(host_role.mafia_game_controller, COMSIG_MAFIA_NIGHT_END, PROC_REF(clean_action_refs))
|
||||
|
||||
/datum/mafia_ability/Destroy(force)
|
||||
host_role = null
|
||||
@@ -35,7 +35,7 @@
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Called when refs need to be cleared, when the target is no longer set.
|
||||
* Called when refs need to be cleared, the last thing that is called in a night cycle.
|
||||
*/
|
||||
/datum/mafia_ability/proc/clean_action_refs(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
@@ -51,16 +51,16 @@
|
||||
* potential_target - The player we are attempting to validate the action on.
|
||||
* silent - Whether to give feedback to the player about why the action cannot be used.
|
||||
*/
|
||||
/datum/mafia_ability/proc/validate_action_target(datum/mafia_controller/game, datum/mafia_role/potential_target, silent = FALSE)
|
||||
/datum/mafia_ability/proc/validate_action_target(datum/mafia_role/potential_target, silent = FALSE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
if(game.phase != valid_use_period)
|
||||
if(host_role.game_status == MAFIA_DEAD)
|
||||
return FALSE
|
||||
if(host_role.mafia_game_controller.phase != valid_use_period)
|
||||
return FALSE
|
||||
if(host_role.role_flags & ROLE_ROLEBLOCKED)
|
||||
host_role.send_message_to_player(span_warning("You were roleblocked!"))
|
||||
return FALSE
|
||||
if(host_role.game_status == MAFIA_DEAD)
|
||||
return FALSE
|
||||
|
||||
if(potential_target)
|
||||
if(use_flags & CAN_USE_ON_DEAD)
|
||||
@@ -95,9 +95,7 @@
|
||||
|
||||
if(!using_ability)
|
||||
return FALSE
|
||||
if(host_role.game_status == MAFIA_DEAD)
|
||||
return FALSE
|
||||
if(!validate_action_target(game, target_role))
|
||||
if(!validate_action_target(target_role))
|
||||
return FALSE
|
||||
|
||||
if(target_role)
|
||||
@@ -114,8 +112,8 @@
|
||||
* Sets the ability's target, which will cause the action to be performed on them at the end of the night.
|
||||
* Subtypes can override this for things like self-abilities (such as shooting visitors).
|
||||
*/
|
||||
/datum/mafia_ability/proc/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
|
||||
if(!validate_action_target(game, new_target))
|
||||
/datum/mafia_ability/proc/set_target(datum/mafia_role/new_target)
|
||||
if(!validate_action_target(new_target))
|
||||
return FALSE
|
||||
|
||||
var/feedback_text = "You will %WILL_PERFORM% [ability_action]%SELF%"
|
||||
|
||||
18
code/modules/mafia/abilities/investigative/autopsy.dm
Normal file
18
code/modules/mafia/abilities/investigative/autopsy.dm
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Autopsy
|
||||
*
|
||||
* During the night, choose someone to check their role.
|
||||
*/
|
||||
/datum/mafia_ability/autopsy
|
||||
name = "Autopsy"
|
||||
ability_action = "perform an autopsy on"
|
||||
use_flags = CAN_USE_ON_OTHERS|CAN_USE_ON_DEAD
|
||||
|
||||
/datum/mafia_ability/autopsy/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
to_chat(host_role.body, span_warning("Your autopsy report on [target_role.body.real_name] \
|
||||
reveals their role was <b>[target_role.name]<b>."))
|
||||
return TRUE
|
||||
@@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Pray
|
||||
*
|
||||
* During the night, revealing someone will announce their role when day comes.
|
||||
* This is one time use, we'll delete ourselves once done.
|
||||
*/
|
||||
/datum/mafia_ability/seance
|
||||
name = "Seance"
|
||||
ability_action = "commune with the spirit of"
|
||||
use_flags = CAN_USE_ON_OTHERS|CAN_USE_ON_DEAD
|
||||
|
||||
/datum/mafia_ability/seance/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
host_role.send_message_to_player(span_warning("You invoke spirit of [target_role.body.real_name] and learn their role was <b>[target_role.name]<b>."))
|
||||
return TRUE
|
||||
@@ -8,7 +8,7 @@
|
||||
ability_action = "send any visitors home with buckshot tonight"
|
||||
use_flags = CAN_USE_ON_SELF
|
||||
|
||||
/datum/mafia_ability/attack_visitors/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
|
||||
/datum/mafia_ability/attack_visitors/set_target(datum/mafia_role/new_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
host_role.send_message_to_player(span_danger("Your attempt at killing [target_role.body.real_name] was prevented!"))
|
||||
else
|
||||
target_role.send_message_to_player(span_userdanger("You have been [attack_action] \a [host_role.name]!"))
|
||||
if(honorable && (target_role.team != MAFIA_TEAM_TOWN))
|
||||
if(honorable && (target_role.team & MAFIA_TEAM_TOWN))
|
||||
host_role.send_message_to_player(span_userdanger("You have killed an innocent crewmember. You will die tomorrow night."))
|
||||
RegisterSignal(game, COMSIG_MAFIA_SUNDOWN, PROC_REF(internal_affairs))
|
||||
return TRUE
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
///The message sent when you've successfully saved someone.
|
||||
var/saving_message = "someone nursed you back to health"
|
||||
|
||||
/datum/mafia_ability/heal/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
|
||||
/datum/mafia_ability/heal/set_target(datum/mafia_role/new_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
///Amount of vests that can be used until the power deletes itself.
|
||||
var/charges = STARTING_VEST_AMOUNT
|
||||
|
||||
/datum/mafia_ability/vest/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
|
||||
/datum/mafia_ability/vest/set_target(datum/mafia_role/new_target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
|
||||
24
code/modules/mafia/abilities/support/seance.dm
Normal file
24
code/modules/mafia/abilities/support/seance.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Seance
|
||||
*
|
||||
* An ability that doesn't give you any actions, instead grants the ability to speak with the dead during the Night.
|
||||
*/
|
||||
/datum/mafia_ability/seance
|
||||
name = "Speak with the Dead"
|
||||
action_priority = null
|
||||
use_flags = NONE
|
||||
|
||||
/**
|
||||
* handle_message
|
||||
*
|
||||
* During the night, Seancers speaking will instead be talking to deadchat.
|
||||
*/
|
||||
/datum/mafia_ability/seance/handle_speech(datum/source, list/speech_args)
|
||||
. = ..()
|
||||
if(host_role.mafia_game_controller.phase != MAFIA_PHASE_NIGHT)
|
||||
return FALSE
|
||||
|
||||
var/message = span_changeling("<b>\[DEAD CHAT - CHAPLAIN\] [source]</b>: [html_decode(speech_args[SPEECH_MESSAGE])]")
|
||||
host_role.mafia_game_controller.send_message(message, team = MAFIA_TEAM_DEAD)
|
||||
speech_args[SPEECH_MESSAGE] = ""
|
||||
return TRUE
|
||||
@@ -34,28 +34,25 @@
|
||||
game.send_message(span_danger("[host_role.body.real_name] was selected to attack [target_role.body.real_name] tonight!"), MAFIA_TEAM_MAFIA)
|
||||
return TRUE
|
||||
|
||||
/datum/mafia_ability/changeling_kill/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
|
||||
if(new_target.team == MAFIA_TEAM_MAFIA)
|
||||
/datum/mafia_ability/changeling_kill/set_target(datum/mafia_role/new_target)
|
||||
if(new_target.team & MAFIA_TEAM_MAFIA)
|
||||
return FALSE
|
||||
if(!validate_action_target(game, new_target))
|
||||
if(!validate_action_target(new_target))
|
||||
return FALSE
|
||||
using_ability = TRUE
|
||||
game.vote_for(host_role, new_target, "Mafia", MAFIA_TEAM_MAFIA)
|
||||
host_role.mafia_game_controller.vote_for(host_role, new_target, "Mafia", MAFIA_TEAM_MAFIA)
|
||||
|
||||
/**
|
||||
* handle_message
|
||||
* handle_speech
|
||||
*
|
||||
* During the night, Changelings talking will instead redirect it to Changeling chat.
|
||||
*/
|
||||
/datum/mafia_ability/changeling_kill/handle_speech(datum/source, list/speech_args)
|
||||
. = ..()
|
||||
var/datum/mafia_controller/mafia_game = GLOB.mafia_game
|
||||
if(!mafia_game)
|
||||
return FALSE
|
||||
if (mafia_game.phase != MAFIA_PHASE_NIGHT)
|
||||
if (host_role.mafia_game_controller.phase != MAFIA_PHASE_NIGHT)
|
||||
return FALSE
|
||||
|
||||
var/phrase = html_decode(speech_args[SPEECH_MESSAGE])
|
||||
mafia_game.send_message(span_changeling("<b>[host_role.body.real_name]:</b> [phrase]"), MAFIA_TEAM_MAFIA)
|
||||
var/message = span_changeling("<b>\[CHANGELING CHAT\] [source]</b>: [html_decode(speech_args[SPEECH_MESSAGE])]")
|
||||
host_role.mafia_game_controller.send_message(message, MAFIA_TEAM_MAFIA)
|
||||
speech_args[SPEECH_MESSAGE] = ""
|
||||
return TRUE
|
||||
|
||||
@@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
|
||||
/proc/setup_mafia_roles_by_name()
|
||||
var/list/rolelist_dict = list()
|
||||
for(var/datum/mafia_role/mafia_role as anything in typesof(/datum/mafia_role))
|
||||
rolelist_dict[initial(mafia_role.name) + " ([uppertext(initial(mafia_role.team))])"] = mafia_role
|
||||
rolelist_dict[initial(mafia_role.name) + " ([uppertext(initial(mafia_role.role_type))])"] = mafia_role
|
||||
return rolelist_dict
|
||||
|
||||
/proc/setup_mafia_role_by_alignment()
|
||||
@@ -170,11 +170,23 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
|
||||
role.player_pda = selected_player
|
||||
ready_ghosts_and_pdas -= selected_player
|
||||
|
||||
///Sends a global message to all players, or just 'team' if set.
|
||||
/**
|
||||
* send_message
|
||||
* By default, this will send a message to every single role in the game, and putting it in their role message history
|
||||
* to view on their PDA/Mafia panel.
|
||||
* Args:
|
||||
* - msg: The message being sent.
|
||||
* - team: A specific team flag that will receive the message, so people not part of it will not get it. Ex: Changeling-only messages.
|
||||
* - log_only: Will not send the message to the player's chat, only their PDA/Mafia panel, for messages that aren't
|
||||
* needed to be flooding their chat for people who are there physically, such as Day/Night starting.
|
||||
*/
|
||||
/datum/mafia_controller/proc/send_message(msg, team, log_only = FALSE)
|
||||
for(var/datum/mafia_role/role as anything in all_roles)
|
||||
if(team && role.team != team)
|
||||
if(team && !(role.team & team))
|
||||
continue
|
||||
//people who can "hear" the dead, but are alive, can only hear at night.
|
||||
if((team & MAFIA_TEAM_DEAD) && role.game_status == MAFIA_ALIVE && phase != MAFIA_PHASE_NIGHT)
|
||||
return
|
||||
role.role_messages += msg
|
||||
if(!log_only)
|
||||
to_chat(role.body, msg)
|
||||
@@ -336,20 +348,21 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
|
||||
var/town_can_kill = FALSE
|
||||
|
||||
for(var/datum/mafia_role/R as anything in living_roles)
|
||||
switch(R.team)
|
||||
if(MAFIA_TEAM_MAFIA)
|
||||
living_mafia += R
|
||||
if(MAFIA_TEAM_TOWN)
|
||||
living_town += R
|
||||
anti_mafia_power += R.vote_power
|
||||
//the game cannot autoresolve with killing roles (unless a solo wins anyways, like traitors who are immune)
|
||||
if(R.role_flags & ROLE_CAN_KILL)
|
||||
town_can_kill = TRUE
|
||||
if(MAFIA_TEAM_SOLO)
|
||||
living_neutrals += R
|
||||
anti_mafia_power += R.vote_power
|
||||
if(R.role_flags & ROLE_CAN_KILL)
|
||||
neutral_killers += R
|
||||
if(R.team & MAFIA_TEAM_MAFIA)
|
||||
living_mafia += R
|
||||
else if(R.team & MAFIA_TEAM_TOWN)
|
||||
living_town += R
|
||||
anti_mafia_power += R.vote_power
|
||||
//the game cannot autoresolve with killing roles (unless a solo wins anyways, like traitors who are immune)
|
||||
if(R.role_flags & ROLE_CAN_KILL)
|
||||
town_can_kill = TRUE
|
||||
else if(R.team & MAFIA_TEAM_SOLO)
|
||||
living_neutrals += R
|
||||
anti_mafia_power += R.vote_power
|
||||
if(R.role_flags & ROLE_CAN_KILL)
|
||||
neutral_killers += R
|
||||
else
|
||||
stack_trace("[R] somehow lacks a faction while alive in a Mafia match!")
|
||||
|
||||
if(living_mafia.len && living_town.len && living_neutrals.len)
|
||||
return FALSE
|
||||
@@ -581,7 +594,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
|
||||
|
||||
if(phase != MAFIA_PHASE_VOTING)
|
||||
return
|
||||
var/v = get_vote_count(get_role_player(source),"Day")
|
||||
var/v = get_vote_count(get_role_player(source), "Day")
|
||||
var/mutable_appearance/MA = mutable_appearance('icons/obj/mafia.dmi',"vote_[v > 12 ? "over_12" : v]")
|
||||
overlay_list += MA
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"desc" = user_role.desc,
|
||||
"hud_icon" = user_role.hud_icon,
|
||||
"revealed_icon" = user_role.revealed_icon,
|
||||
"role_dead" = (user_role.game_status == MAFIA_DEAD),
|
||||
)
|
||||
|
||||
return data
|
||||
@@ -68,7 +69,7 @@
|
||||
if(user_role) //not observer
|
||||
player_info["is_you"] = (role.body.real_name == user_role.body.real_name)
|
||||
for(var/datum/mafia_ability/action as anything in user_role.role_unique_actions)
|
||||
if(action.validate_action_target(src, potential_target = role, silent = TRUE))
|
||||
if(action.validate_action_target(potential_target = role, silent = TRUE))
|
||||
player_info["possible_actions"] += list(list("name" = action, "ref" = REF(action)))
|
||||
|
||||
data["players"] += list(player_info)
|
||||
@@ -88,6 +89,7 @@
|
||||
var/obj/item/modular_computer/modpc = ui.src_object
|
||||
if(!istype(modpc))
|
||||
modpc = null
|
||||
|
||||
//Admin actions
|
||||
if(ui.user.client.holder)
|
||||
switch(action)
|
||||
@@ -147,21 +149,10 @@
|
||||
if("start_now")
|
||||
forced_setup()
|
||||
|
||||
switch(action) //both living and dead
|
||||
if("mf_lookup")
|
||||
var/role_lookup = params["role_name"]
|
||||
var/datum/mafia_role/helper
|
||||
for(var/datum/mafia_role/role as anything in all_roles)
|
||||
if(role_lookup == role.name)
|
||||
helper = role
|
||||
break
|
||||
helper.show_help(usr)
|
||||
|
||||
if(!user_role)//just the dead
|
||||
if(!user_role) // non-player & pre-game actions.
|
||||
switch(action)
|
||||
if("mf_signup")
|
||||
if(signup_mafia(usr, ui.user.client, modpc))
|
||||
return TRUE
|
||||
signup_mafia(ui.user, ui.user.client, modpc)
|
||||
if("vote_to_start")
|
||||
var/client/ghost_client = ui.user.client
|
||||
if(phase != MAFIA_PHASE_SETUP)
|
||||
@@ -191,35 +182,41 @@
|
||||
to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [max(round(length(GLOB.mafia_signup + GLOB.pda_mafia_signup) / 2), round(MAFIA_MIN_PLAYER_COUNT / 2))])."))
|
||||
if(check_start_votes()) //See if we have enough votes to start
|
||||
forced_setup()
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
if(user_role && user_role.game_status == MAFIA_DEAD)
|
||||
return
|
||||
|
||||
//User actions (just living)
|
||||
switch(action)
|
||||
switch(action) //actions that both living and dead players can perform.
|
||||
if("mf_lookup")
|
||||
var/role_lookup = params["role_name"]
|
||||
var/datum/mafia_role/helper
|
||||
for(var/datum/mafia_role/role as anything in all_roles)
|
||||
if(role_lookup == role.name)
|
||||
helper = role
|
||||
break
|
||||
helper.show_help(usr)
|
||||
if("change_notes")
|
||||
if(user_role.game_status == MAFIA_DEAD)
|
||||
return TRUE
|
||||
user_role.written_notes = sanitize_text(params["new_notes"])
|
||||
user_role.send_message_to_player("notes saved", balloon_alert = TRUE)
|
||||
return TRUE
|
||||
if("send_message_to_chat")
|
||||
if(user_role.game_status == MAFIA_DEAD)
|
||||
return TRUE
|
||||
var/message_said = sanitize_text(params["message"])
|
||||
user_role.body.say(message_said, forced = "mafia chat (sent by [ui.user.client])")
|
||||
return TRUE
|
||||
if("send_notes_to_chat")
|
||||
if(user_role.game_status == MAFIA_DEAD || !user_role.written_notes)
|
||||
return TRUE
|
||||
if(phase == MAFIA_PHASE_NIGHT)
|
||||
if(!user_role.written_notes)
|
||||
return TRUE
|
||||
if(!COOLDOWN_FINISHED(user_role, note_chat_sending_cooldown))
|
||||
return FALSE
|
||||
COOLDOWN_START(user_role, note_chat_sending_cooldown, MAFIA_NOTE_SENDING_COOLDOWN)
|
||||
user_role.body.say("[user_role.written_notes]", forced = "mafia notes sending")
|
||||
var/list/message_mods = list()
|
||||
message_mods[MANNEQUIN_CONTROLLED] = ui.user
|
||||
user_role.body.say("[user_role.written_notes]", forced = "mafia notes sending", message_mods = message_mods)
|
||||
return TRUE
|
||||
if("send_message_to_chat")
|
||||
var/message_said = sanitize_text(params["message"])
|
||||
var/list/message_mods = list()
|
||||
message_mods[MANNEQUIN_CONTROLLED] = ui.user
|
||||
user_role.body.say(message_said, forced = "mafia chat (sent by [ui.user.client])", message_mods = message_mods)
|
||||
|
||||
if(user_role.game_status == MAFIA_DEAD)
|
||||
return TRUE
|
||||
|
||||
switch(action) //actions that only living players can perform.
|
||||
if("perform_action")
|
||||
var/datum/mafia_role/target = locate(params["target"]) in all_roles
|
||||
if(!istype(target))
|
||||
@@ -232,11 +229,11 @@
|
||||
used_action.using_ability = TRUE
|
||||
used_action.perform_action_target(src, target)
|
||||
if(MAFIA_PHASE_NIGHT)
|
||||
used_action.set_target(src, target)
|
||||
used_action.set_target(target)
|
||||
return TRUE
|
||||
|
||||
if(user_role != on_trial)
|
||||
switch(action)
|
||||
switch(action) // actions that can only be done while someone is on stand (that isn't you)
|
||||
if("vote_abstain")
|
||||
if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_abstain_votes))
|
||||
return
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/obj/effect/landmark/mafia_game_area //locations where mafia will be loaded by the datum
|
||||
name = "Mafia Area Spawn"
|
||||
var/game_id = "mafia"
|
||||
|
||||
/obj/effect/landmark/mafia
|
||||
name = "Mafia Player Spawn"
|
||||
var/game_id = "mafia"
|
||||
|
||||
/obj/effect/landmark/mafia/town_center
|
||||
name = "Mafia Town Center"
|
||||
@@ -15,7 +13,6 @@
|
||||
icon = 'icons/obj/mafia.dmi'
|
||||
icon_state = "board"
|
||||
anchored = TRUE
|
||||
var/game_id = "mafia"
|
||||
var/datum/mafia_controller/MF
|
||||
|
||||
/obj/mafia_game_board/attack_ghost(mob/user)
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
name = "Mafia Chaplain"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/civilian/chaplain
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
|
||||
/datum/outfit/mafia/md
|
||||
name = "Mafia Medical Doctor"
|
||||
@@ -101,6 +102,14 @@
|
||||
suit = /obj/item/clothing/suit/toggle/lawyer
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
|
||||
/datum/outfit/mafia/coroner
|
||||
name = "Mafia Coroner"
|
||||
|
||||
gloves = /obj/item/clothing/gloves/latex/coroner
|
||||
head = /obj/item/clothing/head/utility/surgerycap/black
|
||||
uniform = /obj/item/clothing/under/rank/medical/scrubs/coroner
|
||||
shoes = /obj/item/clothing/shoes/sneakers/black
|
||||
|
||||
/datum/outfit/mafia/hop
|
||||
name = "Mafia Head of Personnel"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/datum/mafia_role/mafia
|
||||
name = "Changeling"
|
||||
desc = "You're a member of the changeling hive. You may speak with your fellow Changelings at night."
|
||||
desc = "You're a member of the changeling hive. Talk during the Night period to coordinate with your allies, and kill all non-Changelings."
|
||||
team = MAFIA_TEAM_MAFIA
|
||||
role_type = MAFIA_REGULAR
|
||||
role_flags = ROLE_CAN_KILL
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
/datum/mafia_role/mafia/thoughtfeeder
|
||||
name = "Thoughtfeeder"
|
||||
desc = "You're a changeling variant that feeds on the memories of others. Use ':j' talk prefix to talk to your fellow lings, and visit people at night to learn their role."
|
||||
desc = "You're a changeling variant that feeds on the memories of others. Talk during the Night period to coordinate with your allies, \
|
||||
and kill all non-Changelings, using your ability to learn people's roles to your advantage."
|
||||
role_type = MAFIA_SPECIAL
|
||||
hud_icon = "hudthoughtfeeder"
|
||||
revealed_icon = "thoughtfeeder"
|
||||
winner_award = /datum/award/achievement/mafia/thoughtfeeder
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/changeling_kill, /datum/mafia_ability/thoughtfeeder)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
var/list/all_roles_shuffle = shuffle(game.living_roles) - src
|
||||
for(var/datum/mafia_role/possible as anything in all_roles_shuffle)
|
||||
if(possible.team == MAFIA_TEAM_TOWN)
|
||||
if(possible.team & MAFIA_TEAM_TOWN)
|
||||
obsession = possible
|
||||
break
|
||||
if(!obsession)
|
||||
@@ -59,7 +59,7 @@
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_DISRUPT
|
||||
special_ui_theme = "neutral"
|
||||
hud_icon = "hudclown"
|
||||
hud_icon = SECHUD_CLOWN
|
||||
revealed_icon = "clown"
|
||||
winner_award = /datum/award/achievement/mafia/clown
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
var/role_type = TOWN_OVERFLOW
|
||||
///role flags (special status of roles like detection immune)
|
||||
var/role_flags = NONE
|
||||
///The mafia controller board this mafia role is tied to, in case there's several Mafia games at once.
|
||||
var/datum/mafia_controller/mafia_game_controller
|
||||
|
||||
///The mafia popup we edit text to give different alerts for (such as when to vote).
|
||||
var/atom/movable/screen/mafia_popup/mafia_alert
|
||||
@@ -41,7 +43,7 @@
|
||||
var/game_status = MAFIA_ALIVE
|
||||
|
||||
///icon state in the mafia dmi of the hud of the role, used in the mafia ui
|
||||
var/hud_icon = "hudassistant"
|
||||
var/hud_icon = SECHUD_ASSISTANT
|
||||
///icon state in the mafia dmi of the hud of the role, used in the mafia ui
|
||||
var/revealed_icon = "assistant"
|
||||
///set this to something cool for antagonists and their window will look different
|
||||
@@ -50,15 +52,16 @@
|
||||
///The cooldown between being able to send your will in chat.
|
||||
COOLDOWN_DECLARE(note_chat_sending_cooldown)
|
||||
|
||||
/datum/mafia_role/New(datum/mafia_controller/game)
|
||||
/datum/mafia_role/New(datum/mafia_controller/new_game)
|
||||
. = ..()
|
||||
mafia_panel = new(null, game)
|
||||
src.mafia_game_controller = new_game
|
||||
mafia_panel = new(null, new_game)
|
||||
for(var/datum/mafia_ability/abilities as anything in role_unique_actions + /datum/mafia_ability/voting)
|
||||
role_unique_actions += new abilities(game, src)
|
||||
role_unique_actions += new abilities(src)
|
||||
role_unique_actions -= abilities
|
||||
|
||||
/datum/mafia_role/Destroy(force)
|
||||
UnregisterSignal(body, COMSIG_MOB_SAY)
|
||||
UnregisterSignal(body, list(COMSIG_MOB_SAY, COMSIG_MOB_DEADSAY))
|
||||
QDEL_NULL(mafia_alert)
|
||||
QDEL_NULL(mafia_panel)
|
||||
QDEL_LIST(role_unique_actions)
|
||||
@@ -70,10 +73,11 @@
|
||||
|
||||
/datum/mafia_role/proc/register_body(mob/living/carbon/human/new_body)
|
||||
if(body)
|
||||
UnregisterSignal(new_body, COMSIG_MOB_SAY)
|
||||
UnregisterSignal(new_body, list(COMSIG_MOB_SAY, COMSIG_MOB_DEADSAY))
|
||||
mafia_panel.Remove(body)
|
||||
body = new_body
|
||||
RegisterSignal(new_body, COMSIG_MOB_SAY, PROC_REF(handle_speech))
|
||||
RegisterSignal(new_body, COMSIG_MOB_DEADSAY, PROC_REF(handle_speech_dead))
|
||||
mafia_panel.Grant(new_body)
|
||||
|
||||
/**
|
||||
@@ -97,19 +101,25 @@
|
||||
* handle_speech
|
||||
*
|
||||
* Handles Mafia roles talking in chat.
|
||||
* First it will go through their abilities for Ability-specific speech,
|
||||
* if none affects it, we will go to day chat.
|
||||
* First we'll go through their abilities for Ability-specific speech,
|
||||
* if none affects it, we will go to day chat (if it is indeed day).
|
||||
*/
|
||||
/datum/mafia_role/proc/handle_speech(datum/source, list/speech_args)
|
||||
SIGNAL_HANDLER
|
||||
for(var/datum/mafia_ability/abilities as anything in role_unique_actions)
|
||||
if(abilities.handle_speech(source, speech_args))
|
||||
return
|
||||
var/datum/mafia_controller/mafia_game = GLOB.mafia_game
|
||||
if(!mafia_game || mafia_game.phase == MAFIA_PHASE_NIGHT)
|
||||
if(mafia_game_controller.phase == MAFIA_PHASE_NIGHT)
|
||||
return
|
||||
var/message = "[source]: [html_decode(speech_args[SPEECH_MESSAGE])]"
|
||||
mafia_game.send_message(message, log_only = TRUE)
|
||||
mafia_game_controller.send_message(message, log_only = TRUE)
|
||||
|
||||
///Same as handle_speech, but for dead players.
|
||||
/datum/mafia_role/proc/handle_speech_dead(datum/source, message)
|
||||
SIGNAL_HANDLER
|
||||
var/message_sent = span_changeling("<b>\[DEAD CHAT\] [source]</b>: [message]")
|
||||
mafia_game_controller.send_message(message_sent, team = MAFIA_TEAM_DEAD)
|
||||
return MOB_DEADSAY_SIGNAL_INTERCEPT
|
||||
|
||||
/**
|
||||
* Puts the player in their body and keeps track of their previous one to put them back in later.
|
||||
@@ -123,6 +133,7 @@
|
||||
old_body = player.mob.mind.current, \
|
||||
)
|
||||
body.PossessByPlayer(player.key)
|
||||
ADD_TRAIT(body, TRAIT_CORPSELOCKED, MAFIA_TRAIT)
|
||||
|
||||
/**
|
||||
* Tests kill immunities, if nothing prevents the kill, kills this role.
|
||||
@@ -137,6 +148,8 @@
|
||||
if(SEND_SIGNAL(src, COMSIG_MAFIA_ON_KILL, game, attacker, lynch) & MAFIA_PREVENT_KILL)
|
||||
return FALSE
|
||||
game_status = MAFIA_DEAD
|
||||
//can now hear dead chat speaking.
|
||||
team |= MAFIA_TEAM_DEAD
|
||||
body.death()
|
||||
if(lynch)
|
||||
reveal_role(game, verbose = TRUE)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
role_type = TOWN_INVEST
|
||||
winner_award = /datum/award/achievement/mafia/detective
|
||||
|
||||
hud_icon = "huddetective"
|
||||
hud_icon = SECHUD_DETECTIVE
|
||||
revealed_icon = "detective"
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/investigate)
|
||||
@@ -17,18 +17,18 @@
|
||||
role_type = TOWN_INVEST
|
||||
winner_award = /datum/award/achievement/mafia/psychologist
|
||||
|
||||
hud_icon = "hudpsychologist"
|
||||
hud_icon = SECHUD_PSYCHOLOGIST
|
||||
revealed_icon = "psychologist"
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/reveal_role)
|
||||
|
||||
/datum/mafia_role/chaplain
|
||||
name = "Chaplain"
|
||||
desc = "You can communicate with spirits of the dead each night to discover dead crewmember roles."
|
||||
revealed_outfit = /datum/outfit/mafia/chaplain
|
||||
/datum/mafia_role/coroner
|
||||
name = "Coroner"
|
||||
desc = "You can perform autopsies on the dead each night to discover their role."
|
||||
revealed_outfit = /datum/outfit/mafia/coroner
|
||||
role_type = TOWN_INVEST
|
||||
hud_icon = "hudchaplain"
|
||||
revealed_icon = "chaplain"
|
||||
winner_award = /datum/award/achievement/mafia/chaplain
|
||||
hud_icon = SECHUD_CORONER
|
||||
revealed_icon = "coroner"
|
||||
winner_award = /datum/award/achievement/mafia/coroner
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/seance)
|
||||
role_unique_actions = list(/datum/mafia_ability/autopsy)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
role_flags = ROLE_CAN_KILL | ROLE_UNIQUE
|
||||
revealed_outfit = /datum/outfit/mafia/hos
|
||||
revealed_icon = "headofsecurity"
|
||||
hud_icon = "hudheadofsecurity"
|
||||
hud_icon = SECHUD_HEAD_OF_SECURITY
|
||||
winner_award = /datum/award/achievement/mafia/hos
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/attack_player/execution)
|
||||
@@ -18,7 +18,7 @@
|
||||
role_flags = ROLE_CAN_KILL
|
||||
revealed_outfit = /datum/outfit/mafia/warden
|
||||
revealed_icon = "warden"
|
||||
hud_icon = "hudwarden"
|
||||
hud_icon = SECHUD_WARDEN
|
||||
winner_award = /datum/award/achievement/mafia/warden
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/attack_visitors)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "You can protect a single person each night from killing. You can heal yourself once."
|
||||
revealed_outfit = /datum/outfit/mafia/md
|
||||
role_type = TOWN_PROTECT
|
||||
hud_icon = "hudmedicaldoctor"
|
||||
hud_icon = SECHUD_MEDICAL_DOCTOR
|
||||
revealed_icon = "medicaldoctor"
|
||||
winner_award = /datum/award/achievement/mafia/md
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
desc = "You can protect a single person each night. If they are attacked, you will retaliate, killing yourself and the attacker. You can protect yourself once."
|
||||
revealed_outfit = /datum/outfit/mafia/security
|
||||
revealed_icon = "securityofficer"
|
||||
hud_icon = "hudsecurityofficer"
|
||||
hud_icon = SECHUD_SECURITY_OFFICER
|
||||
role_type = TOWN_PROTECT
|
||||
role_flags = ROLE_CAN_KILL
|
||||
winner_award = /datum/award/achievement/mafia/officer
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "You can choose a person to provide extensive legal advice to, preventing night actions."
|
||||
revealed_outfit = /datum/outfit/mafia/lawyer
|
||||
role_type = TOWN_SUPPORT
|
||||
hud_icon = "hudlawyer"
|
||||
hud_icon = SECHUD_LAWYER
|
||||
revealed_icon = "lawyer"
|
||||
winner_award = /datum/award/achievement/mafia/lawyer
|
||||
|
||||
@@ -15,9 +15,21 @@
|
||||
role_type = TOWN_SUPPORT
|
||||
role_flags = ROLE_UNIQUE
|
||||
role_flags = ROLE_CAN_KILL
|
||||
hud_icon = "hudheadofpersonnel"
|
||||
hud_icon = SECHUD_HEAD_OF_PERSONNEL
|
||||
revealed_icon = "headofpersonnel"
|
||||
revealed_outfit = /datum/outfit/mafia/hop
|
||||
winner_award = /datum/award/achievement/mafia/hop
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/self_reveal)
|
||||
|
||||
/datum/mafia_role/chaplain
|
||||
name = "Chaplain"
|
||||
desc = "You can communicate with spirits of the dead each night to discover dead crewmember roles."
|
||||
role_type = TOWN_INVEST
|
||||
team = MAFIA_TEAM_TOWN | MAFIA_TEAM_DEAD
|
||||
hud_icon = SECHUD_CHAPLAIN
|
||||
revealed_icon = "chaplain"
|
||||
revealed_outfit = /datum/outfit/mafia/chaplain
|
||||
winner_award = /datum/award/achievement/mafia/chaplain
|
||||
|
||||
role_unique_actions = list(/datum/mafia_ability/seance)
|
||||
|
||||
@@ -157,7 +157,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list(
|
||||
if(!message_mods[WHISPER_MODE])
|
||||
return
|
||||
if(DEAD)
|
||||
say_dead(original_message)
|
||||
say_dead(original_message, message_mods[MANNEQUIN_CONTROLLED])
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_SOFTSPOKEN) && !HAS_TRAIT(src, TRAIT_SIGN_LANG)) // softspoken trait only applies to spoken languages
|
||||
|
||||
@@ -108,8 +108,14 @@
|
||||
|
||||
return ..()
|
||||
|
||||
///Speak as a dead person (ghost etc)
|
||||
/mob/proc/say_dead(message)
|
||||
/**
|
||||
* say_dead
|
||||
* allows you to speak as a dead person
|
||||
* Args:
|
||||
* - message: The message you're sending to chat.
|
||||
* - mannequin_controller: If someone else is forcing you to speak, this is the mob doing it.
|
||||
*/
|
||||
/mob/proc/say_dead(message, mob/mannequin_controller)
|
||||
var/name = real_name
|
||||
var/alt_name = ""
|
||||
|
||||
@@ -123,7 +129,7 @@
|
||||
return
|
||||
//SKYRAT EDIT END
|
||||
|
||||
var/jb = is_banned_from(ckey, "Deadchat")
|
||||
var/jb = is_banned_from(mannequin_controller?.ckey || ckey, "Deadchat")
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
@@ -4868,8 +4868,8 @@
|
||||
#include "code\modules\mafia\map_pieces.dm"
|
||||
#include "code\modules\mafia\outfits.dm"
|
||||
#include "code\modules\mafia\abilities\abilities.dm"
|
||||
#include "code\modules\mafia\abilities\investigative\autopsy.dm"
|
||||
#include "code\modules\mafia\abilities\investigative\investigate.dm"
|
||||
#include "code\modules\mafia\abilities\investigative\pray.dm"
|
||||
#include "code\modules\mafia\abilities\investigative\reveal.dm"
|
||||
#include "code\modules\mafia\abilities\investigative\thoughtfeed.dm"
|
||||
#include "code\modules\mafia\abilities\killing\alert.dm"
|
||||
@@ -4878,6 +4878,7 @@
|
||||
#include "code\modules\mafia\abilities\protective\heal.dm"
|
||||
#include "code\modules\mafia\abilities\protective\vest.dm"
|
||||
#include "code\modules\mafia\abilities\support\roleblock.dm"
|
||||
#include "code\modules\mafia\abilities\support\seance.dm"
|
||||
#include "code\modules\mafia\abilities\support\self_reveal.dm"
|
||||
#include "code\modules\mafia\abilities\voting\changeling_kill.dm"
|
||||
#include "code\modules\mafia\abilities\voting\day_voting.dm"
|
||||
|
||||
@@ -23,6 +23,7 @@ type RoleInfo = {
|
||||
desc: string;
|
||||
hud_icon: string;
|
||||
revealed_icon: string;
|
||||
role_dead: string;
|
||||
};
|
||||
|
||||
type PlayerInfo = {
|
||||
@@ -286,7 +287,7 @@ const MafiaRole = (props) => {
|
||||
<Section
|
||||
fill
|
||||
title={phase + turn}
|
||||
minHeight="100px"
|
||||
minHeight="110px"
|
||||
maxHeight="50px"
|
||||
buttons={
|
||||
<Box
|
||||
@@ -299,10 +300,16 @@ const MafiaRole = (props) => {
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Stack align="center">
|
||||
<Stack>
|
||||
<Stack.Item grow>
|
||||
<Box bold>You are the {roleinfo.role}</Box>
|
||||
<Box italic>{roleinfo.desc}</Box>
|
||||
<Box fontSize="16px">You are the {roleinfo.role}</Box>
|
||||
{!!roleinfo.role_dead && (
|
||||
<Box bold>
|
||||
You are currently dead. You may speak with the Chaplain at night,
|
||||
if there is one.
|
||||
</Box>
|
||||
)}
|
||||
{!roleinfo.role_dead && <Box italic>{roleinfo.desc}</Box>}
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Box
|
||||
|
||||
Reference in New Issue
Block a user