mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 11:36:24 +01:00
2a637dd6bb
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. /🆑
208 lines
7.7 KiB
Plaintext
208 lines
7.7 KiB
Plaintext
/datum/mafia_role
|
|
var/name = JOB_ASSISTANT
|
|
var/desc = "You are a crewmember without any special abilities."
|
|
var/win_condition = "kill all mafia and solo killing roles."
|
|
var/team = MAFIA_TEAM_TOWN
|
|
///how the random setup chooses which roles get put in
|
|
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
|
|
///List of all mafia abilities this role is able to perform.
|
|
var/list/datum/mafia_ability/role_unique_actions = list()
|
|
///The player's written notes, that they can send to chat at any time.
|
|
var/written_notes
|
|
|
|
///The ckey of the person playing as this Mafia role, CAN BE NULL IN FAVOR OF player_pda.
|
|
var/player_key
|
|
///The PDA of the person playing as this Mafia role, CAN BE NULL IN FAVOR OF player_key.
|
|
var/obj/item/modular_computer/player_pda
|
|
|
|
///List of all messages this role got throughout the game.
|
|
var/list/role_messages = list()
|
|
|
|
|
|
var/mob/living/carbon/human/body
|
|
var/obj/effect/landmark/mafia/assigned_landmark
|
|
|
|
///The Mafia innate action panel that allows players to view the game's state.
|
|
var/datum/action/innate/mafia_panel/mafia_panel
|
|
|
|
///how many votes submitted when you vote. used in voting and deciding victory.
|
|
var/vote_power = 1
|
|
///what they get equipped with when they are revealed
|
|
var/datum/outfit/revealed_outfit = /datum/outfit/mafia/assistant
|
|
///what the role gets when it wins a game
|
|
var/winner_award = /datum/award/achievement/mafia/assistant
|
|
|
|
///so mafia have to also kill them to have a majority
|
|
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 = 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
|
|
var/special_ui_theme
|
|
|
|
///The cooldown between being able to send your will in chat.
|
|
COOLDOWN_DECLARE(note_chat_sending_cooldown)
|
|
|
|
/datum/mafia_role/New(datum/mafia_controller/new_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(src)
|
|
role_unique_actions -= abilities
|
|
|
|
/datum/mafia_role/Destroy(force)
|
|
UnregisterSignal(body, list(COMSIG_MOB_SAY, COMSIG_MOB_DEADSAY))
|
|
QDEL_NULL(mafia_alert)
|
|
QDEL_NULL(mafia_panel)
|
|
QDEL_LIST(role_unique_actions)
|
|
//we null these instead of qdel because Mafia controller's mapdeleter deletes it all.
|
|
assigned_landmark = null
|
|
body = null
|
|
role_messages.Cut()
|
|
return ..()
|
|
|
|
/datum/mafia_role/proc/register_body(mob/living/carbon/human/new_body)
|
|
if(body)
|
|
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)
|
|
|
|
/**
|
|
* send_message_to_player
|
|
*
|
|
* Sends a message to a player, checking if they are playing through a PDA or not.
|
|
* Args:
|
|
* * message - The message to send to the person
|
|
* * balloon_alert - Whether it should be as a balloon alert, only if it's to a non-PDA user.
|
|
*/
|
|
/datum/mafia_role/proc/send_message_to_player(message, balloon_alert = FALSE)
|
|
if(player_pda)
|
|
role_messages += message
|
|
return
|
|
if(balloon_alert)
|
|
body.balloon_alert(body, message)
|
|
return
|
|
to_chat(body, message)
|
|
|
|
/**
|
|
* handle_speech
|
|
*
|
|
* Handles Mafia roles talking in 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
|
|
if(mafia_game_controller.phase == MAFIA_PHASE_NIGHT)
|
|
return
|
|
var/message = "[source]: [html_decode(speech_args[SPEECH_MESSAGE])]"
|
|
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.
|
|
* Adds the playing_mafia trait so people examining them will know why they're currently lacking a soul.
|
|
*/
|
|
/datum/mafia_role/proc/put_player_in_body(client/player)
|
|
if(player.mob.mind)
|
|
body.AddComponent( \
|
|
/datum/component/temporary_body, \
|
|
old_mind = player.mob.mind, \
|
|
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.
|
|
*
|
|
* Does not count as visiting, see visit proc.
|
|
*/
|
|
/datum/mafia_role/proc/kill(datum/mafia_controller/game, datum/mafia_role/attacker, lynch = FALSE)
|
|
if(game_status == MAFIA_DEAD)
|
|
return FALSE
|
|
if(attacker && (attacker.role_flags & ROLE_ROLEBLOCKED))
|
|
return FALSE
|
|
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)
|
|
game.living_roles -= src
|
|
return TRUE
|
|
|
|
/datum/mafia_role/proc/greet()
|
|
mafia_alert = new(body, src)
|
|
SEND_SOUND(body, 'sound/ambience/misc/ambifailure.ogg')
|
|
to_chat(body, span_danger("You are the [name]."))
|
|
to_chat(body, span_danger("[desc]"))
|
|
switch(team)
|
|
if(MAFIA_TEAM_MAFIA)
|
|
to_chat(body,span_danger("You and your co-conspirators win if you outnumber crewmembers."))
|
|
if(MAFIA_TEAM_TOWN)
|
|
to_chat(body,span_danger("You are a crewmember. Find out and lynch the changelings!"))
|
|
if(MAFIA_TEAM_SOLO)
|
|
to_chat(body,span_danger("You are not aligned to town or mafia. Accomplish your own objectives!"))
|
|
to_chat(body, "<span class='warningplain'><b>Be sure to read <a href=\"https://tgstation13.org/wiki/Mafia\">the wiki page</a> to learn more, if you have no idea what's going on.</b></span>")
|
|
|
|
/datum/mafia_role/proc/reveal_role(datum/mafia_controller/game, verbose = FALSE)
|
|
if((role_flags & ROLE_REVEALED))
|
|
return
|
|
if(verbose)
|
|
game.send_message("<span class='big bold notice'>It is revealed that the true role of [body] [game_status == MAFIA_ALIVE ? "is" : "was"] [name]!</span>")
|
|
var/list/oldoutfit = body.get_equipped_items()
|
|
for(var/thing in oldoutfit)
|
|
qdel(thing)
|
|
special_reveal_equip(game)
|
|
body.equipOutfit(revealed_outfit)
|
|
role_flags |= ROLE_REVEALED
|
|
|
|
/datum/mafia_role/proc/special_reveal_equip(datum/mafia_controller/game)
|
|
return
|
|
|
|
/datum/mafia_role/proc/show_help(clueless)
|
|
var/list/result = list()
|
|
var/team_desc = ""
|
|
var/team_span = ""
|
|
var/the = TRUE
|
|
switch(team)
|
|
if(MAFIA_TEAM_TOWN)
|
|
team_desc = "Town"
|
|
team_span = "nicegreen"
|
|
if(MAFIA_TEAM_MAFIA)
|
|
team_desc = "Mafia"
|
|
team_span = "red"
|
|
if(MAFIA_TEAM_SOLO)
|
|
team_desc = "Nobody"
|
|
team_span = "comradio"
|
|
the = FALSE
|
|
result += span_notice("The [span_bold("[name]")] is aligned with [the ? "the " : ""]<span class='[team_span]'>[team_desc]</span>")
|
|
result += "<span class='bold notice'>\"[initial(desc)]\"</span>"
|
|
result += span_notice("[name] wins when they [win_condition]")
|
|
to_chat(clueless, result.Join("</br>"))
|