From c3bbf807c5846e76f17f4f72b94d6c991ad9209a Mon Sep 17 00:00:00 2001 From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Date: Wed, 30 Jul 2025 05:59:30 -0400 Subject: [PATCH] Adds Coroner to Mafia & Bunch of Mafia changes (#92158) ## About The Pull Request 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. ## Why It's Good For The Game 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. ## Changelog :cl: 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. /:cl: --- code/__DEFINES/achievements.dm | 1 + code/__DEFINES/say.dm | 2 + .../datums/achievements/mafia_achievements.dm | 8 ++- code/modules/mafia/_defines.dm | 27 ++++---- code/modules/mafia/abilities/abilities.dm | 24 +++---- .../mafia/abilities/investigative/autopsy.dm | 18 +++++ .../mafia/abilities/investigative/pray.dm | 18 ----- code/modules/mafia/abilities/killing/alert.dm | 2 +- code/modules/mafia/abilities/killing/kill.dm | 2 +- .../mafia/abilities/protective/heal.dm | 2 +- .../mafia/abilities/protective/vest.dm | 2 +- .../modules/mafia/abilities/support/seance.dm | 24 +++++++ .../mafia/abilities/voting/changeling_kill.dm | 19 +++-- code/modules/mafia/controller.dm | 49 ++++++++----- code/modules/mafia/controller_ui.dm | 65 +++++++++--------- code/modules/mafia/map_pieces.dm | 3 - code/modules/mafia/outfits.dm | 9 +++ .../mafia/roles/changelings/changeling.dm | 6 +- .../mafia/roles/neutral/neutral_chaos.dm | 4 +- code/modules/mafia/roles/roles.dm | 35 +++++++--- .../mafia/roles/town/town_investigative.dm | 20 +++--- code/modules/mafia/roles/town/town_killing.dm | 4 +- .../mafia/roles/town/town_protective.dm | 4 +- code/modules/mafia/roles/town/town_support.dm | 16 ++++- code/modules/mob/living/living_say.dm | 2 +- code/modules/mob/mob_say.dm | 12 +++- icons/obj/mafia.dmi | Bin 16103 -> 17477 bytes tgstation.dme | 3 +- tgui/packages/tgui/interfaces/MafiaPanel.tsx | 15 ++-- 29 files changed, 241 insertions(+), 155 deletions(-) create mode 100644 code/modules/mafia/abilities/investigative/autopsy.dm delete mode 100644 code/modules/mafia/abilities/investigative/pray.dm create mode 100644 code/modules/mafia/abilities/support/seance.dm diff --git a/code/__DEFINES/achievements.dm b/code/__DEFINES/achievements.dm index 502f2c94d88..518369c1911 100644 --- a/code/__DEFINES/achievements.dm +++ b/code/__DEFINES/achievements.dm @@ -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" diff --git a/code/__DEFINES/say.dm b/code/__DEFINES/say.dm index 3405fc117b1..8827fbd38f4 100644 --- a/code/__DEFINES/say.dm +++ b/code/__DEFINES/say.dm @@ -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" diff --git a/code/datums/achievements/mafia_achievements.dm b/code/datums/achievements/mafia_achievements.dm index 31462f7a0ce..22c911305cc 100644 --- a/code/datums/achievements/mafia_achievements.dm +++ b/code/datums/achievements/mafia_achievements.dm @@ -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!" diff --git a/code/modules/mafia/_defines.dm b/code/modules/mafia/_defines.dm index ef24645bb05..eeca692766d 100644 --- a/code/modules/mafia/_defines.dm +++ b/code/modules/mafia/_defines.dm @@ -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. diff --git a/code/modules/mafia/abilities/abilities.dm b/code/modules/mafia/abilities/abilities.dm index deba0f670ff..cb1127711b8 100644 --- a/code/modules/mafia/abilities/abilities.dm +++ b/code/modules/mafia/abilities/abilities.dm @@ -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%" diff --git a/code/modules/mafia/abilities/investigative/autopsy.dm b/code/modules/mafia/abilities/investigative/autopsy.dm new file mode 100644 index 00000000000..9e5cef2ae51 --- /dev/null +++ b/code/modules/mafia/abilities/investigative/autopsy.dm @@ -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 [target_role.name].")) + return TRUE diff --git a/code/modules/mafia/abilities/investigative/pray.dm b/code/modules/mafia/abilities/investigative/pray.dm deleted file mode 100644 index cbf8459f9f2..00000000000 --- a/code/modules/mafia/abilities/investigative/pray.dm +++ /dev/null @@ -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 [target_role.name].")) - return TRUE diff --git a/code/modules/mafia/abilities/killing/alert.dm b/code/modules/mafia/abilities/killing/alert.dm index 74710087137..1024f90a20c 100644 --- a/code/modules/mafia/abilities/killing/alert.dm +++ b/code/modules/mafia/abilities/killing/alert.dm @@ -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 diff --git a/code/modules/mafia/abilities/killing/kill.dm b/code/modules/mafia/abilities/killing/kill.dm index d02fd6c287d..8c4382db964 100644 --- a/code/modules/mafia/abilities/killing/kill.dm +++ b/code/modules/mafia/abilities/killing/kill.dm @@ -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 diff --git a/code/modules/mafia/abilities/protective/heal.dm b/code/modules/mafia/abilities/protective/heal.dm index 4c47d1c85ab..b1be91e5dc3 100644 --- a/code/modules/mafia/abilities/protective/heal.dm +++ b/code/modules/mafia/abilities/protective/heal.dm @@ -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 diff --git a/code/modules/mafia/abilities/protective/vest.dm b/code/modules/mafia/abilities/protective/vest.dm index b65a8cb73ba..e8cb41671ff 100644 --- a/code/modules/mafia/abilities/protective/vest.dm +++ b/code/modules/mafia/abilities/protective/vest.dm @@ -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 diff --git a/code/modules/mafia/abilities/support/seance.dm b/code/modules/mafia/abilities/support/seance.dm new file mode 100644 index 00000000000..39b86d95535 --- /dev/null +++ b/code/modules/mafia/abilities/support/seance.dm @@ -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("\[DEAD CHAT - CHAPLAIN\] [source]: [html_decode(speech_args[SPEECH_MESSAGE])]") + host_role.mafia_game_controller.send_message(message, team = MAFIA_TEAM_DEAD) + speech_args[SPEECH_MESSAGE] = "" + return TRUE diff --git a/code/modules/mafia/abilities/voting/changeling_kill.dm b/code/modules/mafia/abilities/voting/changeling_kill.dm index bb1b1e76c81..261474a54c3 100644 --- a/code/modules/mafia/abilities/voting/changeling_kill.dm +++ b/code/modules/mafia/abilities/voting/changeling_kill.dm @@ -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("[host_role.body.real_name]: [phrase]"), MAFIA_TEAM_MAFIA) + var/message = span_changeling("\[CHANGELING CHAT\] [source]: [html_decode(speech_args[SPEECH_MESSAGE])]") + host_role.mafia_game_controller.send_message(message, MAFIA_TEAM_MAFIA) speech_args[SPEECH_MESSAGE] = "" return TRUE diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm index 957f7f2bc42..1d978be3dfe 100644 --- a/code/modules/mafia/controller.dm +++ b/code/modules/mafia/controller.dm @@ -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 diff --git a/code/modules/mafia/controller_ui.dm b/code/modules/mafia/controller_ui.dm index 83857f66837..ceeea9e7ce1 100644 --- a/code/modules/mafia/controller_ui.dm +++ b/code/modules/mafia/controller_ui.dm @@ -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 diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm index 78b2b284061..62f0fd2ca40 100644 --- a/code/modules/mafia/map_pieces.dm +++ b/code/modules/mafia/map_pieces.dm @@ -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) diff --git a/code/modules/mafia/outfits.dm b/code/modules/mafia/outfits.dm index 2fbd07d516a..f82f9de40cb 100644 --- a/code/modules/mafia/outfits.dm +++ b/code/modules/mafia/outfits.dm @@ -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" diff --git a/code/modules/mafia/roles/changelings/changeling.dm b/code/modules/mafia/roles/changelings/changeling.dm index 8e650515ffb..cf9039fa500 100644 --- a/code/modules/mafia/roles/changelings/changeling.dm +++ b/code/modules/mafia/roles/changelings/changeling.dm @@ -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) diff --git a/code/modules/mafia/roles/neutral/neutral_chaos.dm b/code/modules/mafia/roles/neutral/neutral_chaos.dm index de2c7fc4833..64ce9cf4252 100644 --- a/code/modules/mafia/roles/neutral/neutral_chaos.dm +++ b/code/modules/mafia/roles/neutral/neutral_chaos.dm @@ -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 diff --git a/code/modules/mafia/roles/roles.dm b/code/modules/mafia/roles/roles.dm index 85d1170d1a9..5f22153a03e 100644 --- a/code/modules/mafia/roles/roles.dm +++ b/code/modules/mafia/roles/roles.dm @@ -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("\[DEAD CHAT\] [source]: [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) diff --git a/code/modules/mafia/roles/town/town_investigative.dm b/code/modules/mafia/roles/town/town_investigative.dm index 76b81eab3bd..003d911612b 100644 --- a/code/modules/mafia/roles/town/town_investigative.dm +++ b/code/modules/mafia/roles/town/town_investigative.dm @@ -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) diff --git a/code/modules/mafia/roles/town/town_killing.dm b/code/modules/mafia/roles/town/town_killing.dm index 777581d0402..ea021102874 100644 --- a/code/modules/mafia/roles/town/town_killing.dm +++ b/code/modules/mafia/roles/town/town_killing.dm @@ -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) diff --git a/code/modules/mafia/roles/town/town_protective.dm b/code/modules/mafia/roles/town/town_protective.dm index 53e01c43418..a8433779991 100644 --- a/code/modules/mafia/roles/town/town_protective.dm +++ b/code/modules/mafia/roles/town/town_protective.dm @@ -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 diff --git a/code/modules/mafia/roles/town/town_support.dm b/code/modules/mafia/roles/town/town_support.dm index f508831720e..c95f93fcebd 100644 --- a/code/modules/mafia/roles/town/town_support.dm +++ b/code/modules/mafia/roles/town/town_support.dm @@ -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) diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 37695af09c5..a2ed3da6b45 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -152,7 +152,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 diff --git a/code/modules/mob/mob_say.dm b/code/modules/mob/mob_say.dm index 1a27f9f6c6b..3964ca0a731 100644 --- a/code/modules/mob/mob_say.dm +++ b/code/modules/mob/mob_say.dm @@ -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 = "" @@ -117,7 +123,7 @@ to_chat(usr, span_danger("Speech is currently admin-disabled.")) return - var/jb = is_banned_from(ckey, "Deadchat") + var/jb = is_banned_from(mannequin_controller?.ckey || ckey, "Deadchat") if(QDELETED(src)) return diff --git a/icons/obj/mafia.dmi b/icons/obj/mafia.dmi index 7c3b525c0055c899f33a0387e28ad70ee94f7fff..49e3e57674800264b5f8791cab4ae3a6d5bd70f9 100644 GIT binary patch literal 17477 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 R1QGxM002ovPDHLkV1hXGEdc-k literal 16103 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 {

{ } > - + - You are the {roleinfo.role} - {roleinfo.desc} + You are the {roleinfo.role} + {!!roleinfo.role_dead && ( + + You are currently dead. You may speak with the Chaplain at night, + if there is one. + + )} + {!roleinfo.role_dead && {roleinfo.desc}}