Revives old Mafia PR adding security, a mind bogglingly large amount of refactors, some documentation, and other niceities (#56199)
@@ -41,8 +41,11 @@
|
||||
#define MAFIA_MEDAL_PSYCHOLOGIST "Psychologist"
|
||||
#define MAFIA_MEDAL_CHAPLAIN "Chaplain"
|
||||
#define MAFIA_MEDAL_MD "Medical Doctor"
|
||||
#define MAFIA_MEDAL_OFFICER "Security Officer"
|
||||
#define MAFIA_MEDAL_LAWYER "Lawyer"
|
||||
#define MAFIA_MEDAL_HOP "Head of Personnel"
|
||||
#define MAFIA_MEDAL_HOS "Head of Security"
|
||||
#define MAFIA_MEDAL_WARDEN "Warden"
|
||||
#define MAFIA_MEDAL_CHANGELING "CHANGELING"
|
||||
#define MAFIA_MEDAL_THOUGHTFEEDER "Thoughtfeeder"
|
||||
#define MAFIA_MEDAL_TRAITOR "Traitor"
|
||||
@@ -53,6 +56,8 @@
|
||||
|
||||
//Mafia medal hub IDs (misc stuff)
|
||||
#define MAFIA_MEDAL_HATED "Universally Hated"
|
||||
#define MAFIA_MEDAL_CHARISMATIC "Charismatic"
|
||||
#define MAFIA_MEDAL_VIP "VIP"
|
||||
|
||||
//Boss medals
|
||||
|
||||
|
||||
@@ -8,85 +8,103 @@
|
||||
name = "Assistant Victory"
|
||||
desc = "If you got killed instead of someone more important, you just flexed the true strength of your \"\"\"\"role\"\"\"\"."
|
||||
database_id = MAFIA_MEDAL_ASSISTANT
|
||||
icon = "assistant"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/detective
|
||||
name = "Detective Victory"
|
||||
desc = "If you did this with a Medical Doctor in the game, i'm not really that impressed."
|
||||
database_id = MAFIA_MEDAL_DETECTIVE
|
||||
icon = "detective"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/psychologist
|
||||
name = "Psychologist Victory"
|
||||
desc = "You learned how to not reveal someone random night one! Or... maybe you're just a lucky bastard."
|
||||
database_id = MAFIA_MEDAL_PSYCHOLOGIST
|
||||
icon = "psychologist"
|
||||
icon = "town"
|
||||
|
||||
/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."
|
||||
database_id = MAFIA_MEDAL_CHAPLAIN
|
||||
icon = "chaplain"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/md
|
||||
name = "Medical Doctor Victory"
|
||||
desc = "Congratulations on learning how to not talk!"
|
||||
database_id = MAFIA_MEDAL_MD
|
||||
icon = "md"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/officer
|
||||
name = "Security Officer Victory"
|
||||
desc = "Don't worry, you can win this if you're dead! You... did use your ability to become dead, right?"
|
||||
database_id = MAFIA_MEDAL_OFFICER
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/lawyer
|
||||
name = "Lawyer Victory"
|
||||
desc = "Oh don't mind me, i'm just the worst rol- Oops, I just instantly ended the game."
|
||||
database_id = MAFIA_MEDAL_LAWYER
|
||||
icon = "lawyer"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hop
|
||||
name = "Head of Personnel Victory"
|
||||
desc = "King of Assistants, waster of a single mafia's night, thrower of games."
|
||||
database_id = MAFIA_MEDAL_HOP
|
||||
icon = "hop"
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/warden
|
||||
name = "Warden Victory"
|
||||
desc = "Make changelings think you're detective, go on lockdown, actual detective investigates you and dies. Cha cha real smooth!"
|
||||
database_id = MAFIA_MEDAL_WARDEN
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hos
|
||||
name = "Head of Security Victory"
|
||||
desc = "Certified not shitcurity."
|
||||
database_id = MAFIA_MEDAL_HOS
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/changeling
|
||||
name = "Changeling Victory"
|
||||
desc = "I think the changelings are metacomming."
|
||||
database_id = MAFIA_MEDAL_CHANGELING
|
||||
icon = "changeling"
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/thoughtfeeder
|
||||
name = "Thoughtfeeder Victory"
|
||||
desc = "Clown's best friend. And Obsessed. And fugitive? Whose side are you on?!"
|
||||
database_id = MAFIA_MEDAL_THOUGHTFEEDER
|
||||
icon = "thoughtfeeder"
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/traitor
|
||||
name = "Traitor Victory"
|
||||
desc = "Guys, we still have two more changelings to ki-!! TRAITOR VICTORY !!"
|
||||
database_id = MAFIA_MEDAL_TRAITOR
|
||||
icon = "traitor"
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/nightmare
|
||||
name = "Nightmare Victory"
|
||||
desc = "DID YOUR LIGHT FLICKER?!"
|
||||
database_id = MAFIA_MEDAL_NIGHTMARE
|
||||
icon = "nightmare"
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/fugitive
|
||||
name = "Fugitive Victory"
|
||||
desc = "I'm just the description on an achievement, but if you end up having to choose between town and changelings, go changelings."
|
||||
database_id = MAFIA_MEDAL_FUGITIVE
|
||||
icon = "fugitive"
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/obsessed
|
||||
name = "Obsessed Victory"
|
||||
desc = "You got your target lynched, so instead of being spiteful and annoying, you're just smug and annoying."
|
||||
database_id = MAFIA_MEDAL_OBSESSED
|
||||
icon = "obsessed"
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/clown
|
||||
name = "Clown Victory"
|
||||
desc = "Did you know this works on traitors, despite their immunity? If you hit the jackpot and manage to kill one, they'll salt into the next dimension. Clown tips!"
|
||||
database_id = MAFIA_MEDAL_CLOWN
|
||||
icon = "clown"
|
||||
icon = "neutral"
|
||||
|
||||
///ALL THE ACHIEVEMENTS FOR MISC MAFIA ODDITIES///
|
||||
|
||||
|
||||
@@ -251,21 +251,9 @@
|
||||
"rustascend" = 'icons/UI_Icons/Achievements/Misc/rustascend.png',
|
||||
"voidascend" = 'icons/UI_Icons/Achievements/Misc/voidascend.png',
|
||||
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
|
||||
"assistant" = 'icons/UI_Icons/Achievements/Mafia/assistant.png',
|
||||
"changeling" = 'icons/UI_Icons/Achievements/Mafia/changeling.png',
|
||||
"chaplain" = 'icons/UI_Icons/Achievements/Mafia/chaplain.png',
|
||||
"clown" = 'icons/UI_Icons/Achievements/Mafia/clown.png',
|
||||
"detective" = 'icons/UI_Icons/Achievements/Mafia/detective.png',
|
||||
"fugitive" = 'icons/UI_Icons/Achievements/Mafia/fugitive.png',
|
||||
"hated" = 'icons/UI_Icons/Achievements/Mafia/hated.png',
|
||||
"hop" = 'icons/UI_Icons/Achievements/Mafia/hop.png',
|
||||
"lawyer" = 'icons/UI_Icons/Achievements/Mafia/lawyer.png',
|
||||
"md" = 'icons/UI_Icons/Achievements/Mafia/md.png',
|
||||
"nightmare" = 'icons/UI_Icons/Achievements/Mafia/nightmare.png',
|
||||
"obsessed" = 'icons/UI_Icons/Achievements/Mafia/obsessed.png',
|
||||
"psychologist" = 'icons/UI_Icons/Achievements/Mafia/psychologist.png',
|
||||
"thoughtfeeder" = 'icons/UI_Icons/Achievements/Mafia/thoughtfeeder.png',
|
||||
"traitor" = 'icons/UI_Icons/Achievements/Mafia/traitor.png',
|
||||
"changeling" = 'icons/UI_Icons/Achievements/Mafia/mafia.png',
|
||||
"chaplain" = 'icons/UI_Icons/Achievements/Mafia/town.png',
|
||||
"clown" = 'icons/UI_Icons/Achievements/Mafia/neutral.png',
|
||||
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png',
|
||||
"frenching" = 'icons/UI_Icons/Achievements/Misc/frenchingthebubble.png'
|
||||
)
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
#define MAFIA_TEAM_SOLO "solo"
|
||||
|
||||
//types of town roles for random setup gen
|
||||
/// assistants it's just assistants filling up the rest of the roles
|
||||
/// Add this if you don't want a role to be a choice in the selection
|
||||
#define TOWN_OVERFLOW "overflow"
|
||||
/// roles that learn info about others in the game (chaplain, detective, psych)
|
||||
#define TOWN_INVEST "invest"
|
||||
/// roles that keep other roles safe (doctor, and weirdly enough lawyer counts)
|
||||
/// roles that keep other roles safe (doctor, sec officer, and weirdly enough lawyer counts)
|
||||
#define TOWN_PROTECT "protect"
|
||||
/// roles that are only there to kill bad guys.
|
||||
#define TOWN_KILLING "killing"
|
||||
/// roles that don't fit into anything else (hop)
|
||||
#define TOWN_MISC "misc"
|
||||
#define TOWN_SUPPORT "support"
|
||||
|
||||
//other types (mafia team, neutrals)
|
||||
/// normal vote kill changelings
|
||||
@@ -25,6 +27,20 @@
|
||||
/// role that upsets the game aka obsessed, usually worse for town than mafia but they can vote against mafia
|
||||
#define NEUTRAL_DISRUPT "disrupt"
|
||||
|
||||
//role flags (special status of roles like detection immune)
|
||||
///to all forms of detection, shows themselves as an assistant.
|
||||
#define ROLE_UNDETECTABLE (1<<0)
|
||||
///has the ability to kill at night and thus, blocks the game from ending with other teams alive.
|
||||
#define ROLE_CAN_KILL (1<<1)
|
||||
///can only be one in a randomly generated game
|
||||
#define ROLE_UNIQUE (1<<2)
|
||||
///role is public to all other players in the game.
|
||||
#define ROLE_REVEALED (1<<3)
|
||||
///can not be defended, protected, or any other form of protection. all kills succeed no matter what.
|
||||
#define ROLE_VULNERABLE (1<<4)
|
||||
///cannot perform any actions that night, preselected actions fail
|
||||
#define ROLE_ROLEBLOCKED (1<<5)
|
||||
|
||||
#define MAFIA_PHASE_SETUP 1
|
||||
#define MAFIA_PHASE_DAY 2
|
||||
#define MAFIA_PHASE_VOTING 3
|
||||
@@ -35,12 +51,12 @@
|
||||
#define MAFIA_ALIVE 1
|
||||
#define MAFIA_DEAD 2
|
||||
|
||||
#define COMSIG_MAFIA_ON_VISIT "mafia_onvisit"
|
||||
#define MAFIA_VISIT_INTERRUPTED 1
|
||||
|
||||
#define COMSIG_MAFIA_ON_KILL "mafia_onkill"
|
||||
#define MAFIA_PREVENT_KILL 1
|
||||
|
||||
#define COMSIG_MAFIA_CAN_PERFORM_ACTION "mafia_can_perform_action"
|
||||
#define MAFIA_PREVENT_ACTION 1
|
||||
|
||||
//in order of events + game end
|
||||
|
||||
/// when the shutters fall, before the 45 second wait and night event resolution
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
var/phase = MAFIA_PHASE_SETUP
|
||||
///how long the game has gone on for, changes with every sunrise. day one, night one, day two, etc.
|
||||
var/turn = 0
|
||||
///if enabled, the game has fallen under half pop and is sped up
|
||||
var/speed_up = FALSE
|
||||
///for debugging and testing a full game, or adminbuse. If this is not empty, it will use this as a setup. clears when game is over
|
||||
var/list/custom_setup = list()
|
||||
///first day has no voting, and thus is shorter
|
||||
@@ -158,6 +160,20 @@
|
||||
turn += 1
|
||||
phase = MAFIA_PHASE_DAY
|
||||
if(!check_victory())
|
||||
if(!speed_up)//lets check if the game should be sped up, if not already.
|
||||
var/living_players = 0
|
||||
for(var/i in all_roles)
|
||||
var/datum/mafia_role/player = i
|
||||
if(player.game_status == MAFIA_ALIVE)
|
||||
living_players += 1
|
||||
if(living_players < all_roles.len / 2)
|
||||
speed_up = TRUE
|
||||
send_message("<span class='bold notice'>With only [living_players] living players left, the game timers have been sped up.</span>")
|
||||
day_phase_period /= 2
|
||||
voting_phase_period /= 2
|
||||
judgement_phase_period /= 2
|
||||
judgement_lynch_period /= 2
|
||||
night_phase_period /= 2
|
||||
if(turn == 1)
|
||||
send_message("<span class='notice'><b>The selected map is [current_map.name]!</b></br>[current_map.description]</span>")
|
||||
send_message("<b>Day [turn] started! There is no voting on the first day. Say hello to everybody!</b>")
|
||||
@@ -237,7 +253,7 @@
|
||||
send_message("<span class='red'>[role.body.real_name] voted guilty.</span>")
|
||||
if(judgement_guilty_votes.len > judgement_innocent_votes.len) //strictly need majority guilty to lynch
|
||||
send_message("<span class='red'><b>Guilty wins majority, [on_trial.body.real_name] has been lynched.</b></span>")
|
||||
on_trial.kill(src, lynch = TRUE)
|
||||
on_trial.kill(src,lynch = TRUE)
|
||||
addtimer(CALLBACK(src, .proc/send_home, on_trial),judgement_lynch_period)
|
||||
else
|
||||
send_message("<span class='green'><b>Innocent wins majority, [on_trial.body.real_name] has been spared.</b></span>")
|
||||
@@ -271,11 +287,14 @@
|
||||
var/list/total_town = list()
|
||||
var/list/total_mafia = list()
|
||||
|
||||
var/alive_town = 0
|
||||
//voting power of town + solos (since they don't want mafia to overpower)
|
||||
var/anti_mafia_power = 0
|
||||
//voting power of mafia (greater than anti mafia power + team end not blocked = mafia victory)
|
||||
var/alive_mafia = 0
|
||||
var/list/solos_to_ask = list() //need to ask after because first round is counting team sizes
|
||||
var/list/total_victors = list() //if this list gets filled with anyone, they win. list because side antags can with with people
|
||||
var/blocked_victory = FALSE //if a solo antagonist is stopping the town or mafia from finishing the game.
|
||||
var/town_can_kill = FALSE //Town has a killing role and it cannot allow mafia to win
|
||||
|
||||
///PHASE ONE: TALLY UP ALL NUMBERS OF PEOPLE STILL ALIVE
|
||||
|
||||
@@ -284,23 +303,24 @@
|
||||
if(MAFIA_TEAM_MAFIA)
|
||||
total_mafia += R
|
||||
if(R.game_status == MAFIA_ALIVE)
|
||||
alive_mafia += R.vote_power
|
||||
alive_mafia += R.vote_potential
|
||||
if(MAFIA_TEAM_TOWN)
|
||||
total_town += R
|
||||
if(R.game_status == MAFIA_ALIVE)
|
||||
alive_town += R.vote_power
|
||||
anti_mafia_power += R.vote_potential
|
||||
if(R.role_flags & ROLE_CAN_KILL) //the game cannot autoresolve with killing roles (unless a solo wins anyways, like traitors who are immune)
|
||||
town_can_kill = TRUE
|
||||
if(MAFIA_TEAM_SOLO)
|
||||
if(R.game_status == MAFIA_ALIVE)
|
||||
if(R.solo_counts_as_town)
|
||||
alive_town += R.vote_power
|
||||
anti_mafia_power += R.vote_potential
|
||||
solos_to_ask += R
|
||||
|
||||
///PHASE TWO: SEND STATS TO SOLO ANTAGS, SEE IF THEY WON OR TEAMS CANNOT WIN
|
||||
|
||||
for(var/datum/mafia_role/solo in solos_to_ask)
|
||||
if(solo.check_total_victory(alive_town, alive_mafia))
|
||||
if(solo.check_total_victory(anti_mafia_power, alive_mafia))
|
||||
total_victors += solo
|
||||
if(solo.block_team_victory(alive_town, alive_mafia))
|
||||
if(solo.block_team_victory(anti_mafia_power, alive_mafia))
|
||||
blocked_victory = TRUE
|
||||
|
||||
//solo victories!
|
||||
@@ -319,7 +339,7 @@
|
||||
award_role(townie.winner_award, townie)
|
||||
start_the_end("<span class='big green'>!! TOWN VICTORY !!</span>")
|
||||
return TRUE
|
||||
else if(alive_mafia >= alive_town) //guess could change if town nightkill is added
|
||||
else if(alive_mafia >= anti_mafia_power && !town_can_kill)
|
||||
start_the_end("<span class='big red'>!! MAFIA VICTORY !!</span>")
|
||||
for(var/datum/mafia_role/changeling in total_mafia)
|
||||
award_role(changeling.winner_award, changeling)
|
||||
@@ -367,6 +387,13 @@
|
||||
custom_setup = list()
|
||||
turn = 0
|
||||
votes = list()
|
||||
|
||||
day_phase_period = initial(day_phase_period)
|
||||
voting_phase_period = initial(voting_phase_period)
|
||||
judgement_phase_period = initial(judgement_phase_period)
|
||||
judgement_lynch_period = initial(judgement_lynch_period)
|
||||
night_phase_period = initial(night_phase_period)
|
||||
|
||||
//map gen does not deal with landmarks
|
||||
QDEL_LIST(landmarks)
|
||||
QDEL_NULL(town_center_landmark)
|
||||
@@ -422,14 +449,15 @@
|
||||
SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_START)
|
||||
SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_ACTION_PHASE)
|
||||
//resolve mafia kill, todo unsnowflake this
|
||||
var/datum/mafia_role/R = get_vote_winner("Mafia")
|
||||
if(R)
|
||||
var/datum/mafia_role/victim = get_vote_winner("Mafia")
|
||||
if(victim)
|
||||
var/datum/mafia_role/killer = get_random_voter("Mafia")
|
||||
if(SEND_SIGNAL(killer,COMSIG_MAFIA_CAN_PERFORM_ACTION,src,"mafia killing",R) & MAFIA_PREVENT_ACTION)
|
||||
send_message("<span class='danger'>[killer.body.real_name] was unable to attack [R.body.real_name] tonight!</span>",MAFIA_TEAM_MAFIA)
|
||||
if(!victim.can_action(src, killer, "changeling murder"))
|
||||
send_message("<span class='danger'>[killer.body.real_name] was unable to attack [victim.body.real_name] tonight!</span>",MAFIA_TEAM_MAFIA)
|
||||
else
|
||||
send_message("<span class='danger'>[killer.body.real_name] has attacked [R.body.real_name]!</span>",MAFIA_TEAM_MAFIA)
|
||||
R.kill(src)
|
||||
send_message("<span class='danger'>[killer.body.real_name] has attacked [victim.body.real_name]!</span>",MAFIA_TEAM_MAFIA)
|
||||
if(victim.kill(src,killer,lynch=FALSE))
|
||||
to_chat(victim.body, "<span class='userdanger'>You have been killed by a Changeling!</span>")
|
||||
reset_votes("Mafia")
|
||||
SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_KILL_PHASE)
|
||||
SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_END)
|
||||
@@ -678,6 +706,7 @@
|
||||
if(role_count > 0)
|
||||
debug_setup[found_path] = role_count
|
||||
custom_setup = debug_setup
|
||||
try_autostart()//don't worry, this fails if there's a game in progress
|
||||
if("cancel_setup")
|
||||
custom_setup = list()
|
||||
switch(action) //both living and dead
|
||||
@@ -715,7 +744,7 @@
|
||||
to_chat(usr, "<span class='notice'>You will now get messages from the game.</span>")
|
||||
spectators += C.ckey
|
||||
return TRUE
|
||||
if(user_role.game_status == MAFIA_DEAD)
|
||||
if(user_role && user_role.game_status == MAFIA_DEAD)
|
||||
return
|
||||
//User actions (just living)
|
||||
switch(action)
|
||||
@@ -785,58 +814,59 @@
|
||||
. += L[key]
|
||||
|
||||
/**
|
||||
* Returns a semirandom setup, with...
|
||||
* Town, Two invest roles, one protect role, sometimes a misc role, and the rest assistants for town.
|
||||
* Mafia, 2 normal mafia and one special.
|
||||
* Neutral, two disruption roles, sometimes one is a killing.
|
||||
* Returns a semirandom setup with 12 roles. balance not guaranteed!
|
||||
*
|
||||
* See _defines.dm in the mafia folder for a rundown on what these groups of roles include.
|
||||
* please check the variables at the top of the proc to see how much of each role types it picks
|
||||
*/
|
||||
/datum/mafia_controller/proc/generate_random_setup()
|
||||
var/invests_left = 2
|
||||
var/protects_left = 1
|
||||
var/miscs_left = prob(35)
|
||||
var/protects_left = 2
|
||||
var/killings_left = 1
|
||||
var/supports_left = 2
|
||||
|
||||
var/mafiareg_left = 2
|
||||
var/mafiaspe_left = 1
|
||||
var/killing_role = prob(50)
|
||||
var/disruptors = killing_role ? 1 : 2 //still required to calculate overflow
|
||||
var/overflow_left = MAFIA_MAX_PLAYER_COUNT - (invests_left + protects_left + miscs_left + mafiareg_left + mafiaspe_left + killing_role + disruptors)
|
||||
|
||||
// if there is one killing role, there will be less disruptors
|
||||
var/neutral_killing_role = prob(50)
|
||||
|
||||
var/list/random_setup = list()
|
||||
var/list/unique_roles_added = list()
|
||||
for(var/i in 1 to MAFIA_MAX_PLAYER_COUNT) //should match the number of roles to add
|
||||
if(overflow_left)
|
||||
add_setup_role(random_setup, TOWN_OVERFLOW)
|
||||
overflow_left--
|
||||
else if(invests_left)
|
||||
add_setup_role(random_setup, TOWN_INVEST)
|
||||
if(invests_left)
|
||||
add_setup_role(random_setup, unique_roles_added, TOWN_INVEST)
|
||||
invests_left--
|
||||
else if(protects_left)
|
||||
add_setup_role(random_setup, TOWN_PROTECT)
|
||||
add_setup_role(random_setup, unique_roles_added, TOWN_PROTECT)
|
||||
protects_left--
|
||||
else if(miscs_left)
|
||||
add_setup_role(random_setup, TOWN_MISC)
|
||||
miscs_left--
|
||||
else if(killings_left)
|
||||
add_setup_role(random_setup, unique_roles_added, TOWN_KILLING)
|
||||
killings_left--
|
||||
else if(supports_left)
|
||||
add_setup_role(random_setup, unique_roles_added, TOWN_SUPPORT)
|
||||
supports_left--
|
||||
else if(mafiareg_left)
|
||||
add_setup_role(random_setup, MAFIA_REGULAR)
|
||||
add_setup_role(random_setup, unique_roles_added, MAFIA_REGULAR)
|
||||
mafiareg_left--
|
||||
else if(mafiaspe_left)
|
||||
add_setup_role(random_setup, MAFIA_SPECIAL)
|
||||
add_setup_role(random_setup, unique_roles_added, MAFIA_SPECIAL)
|
||||
mafiaspe_left--
|
||||
else if(killing_role)
|
||||
add_setup_role(random_setup, NEUTRAL_KILL)
|
||||
killing_role--
|
||||
else if(neutral_killing_role)
|
||||
add_setup_role(random_setup, unique_roles_added, NEUTRAL_KILL)
|
||||
neutral_killing_role--
|
||||
else
|
||||
add_setup_role(random_setup, NEUTRAL_DISRUPT)
|
||||
add_setup_role(random_setup, unique_roles_added, NEUTRAL_DISRUPT)
|
||||
debug = random_setup
|
||||
return random_setup
|
||||
|
||||
/**
|
||||
* Helper proc that adds a random role of a type to a setup. if it doesn't exist in the setup, it adds the path to the list and otherwise bumps the path in the list up one
|
||||
* Helper proc that adds a random role of a type to a setup. if it doesn't exist in the setup, it adds the path to the list and otherwise bumps the path in the list up one. unique roles can only get added once.
|
||||
*/
|
||||
/datum/mafia_controller/proc/add_setup_role(setup_list, wanted_role_type)
|
||||
/datum/mafia_controller/proc/add_setup_role(setup_list, banned_roles, wanted_role_type)
|
||||
var/list/role_type_paths = list()
|
||||
for(var/path in typesof(/datum/mafia_role))
|
||||
var/datum/mafia_role/instance = path
|
||||
if(initial(instance.role_type) == wanted_role_type)
|
||||
if(initial(instance.role_type) == wanted_role_type && !(path in banned_roles))
|
||||
role_type_paths += instance
|
||||
|
||||
var/mafia_path = pick(role_type_paths)
|
||||
@@ -851,6 +881,8 @@
|
||||
setup_list[found_role] += 1
|
||||
return
|
||||
setup_list[mafia_path] = 1
|
||||
if(initial(mafia_path_type.role_flags) & ROLE_UNIQUE) //check to see if we should no longer consider this okay to add to the game
|
||||
banned_roles += mafia_path
|
||||
|
||||
/**
|
||||
* Called when enough players have signed up to fill a setup. DOESN'T NECESSARILY MEAN THE GAME WILL START.
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
uniform = /obj/item/clothing/under/suit/black
|
||||
shoes = /obj/item/clothing/shoes/laceup
|
||||
|
||||
/datum/outfit/mafia/chaplain
|
||||
name = "Mafia Chaplain"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/civilian/chaplain
|
||||
|
||||
/datum/outfit/mafia/md
|
||||
name = "Mafia Medical Doctor"
|
||||
|
||||
@@ -37,10 +42,14 @@
|
||||
shoes = /obj/item/clothing/shoes/sneakers/white
|
||||
suit = /obj/item/clothing/suit/toggle/labcoat
|
||||
|
||||
/datum/outfit/mafia/chaplain
|
||||
name = "Mafia Chaplain"
|
||||
/datum/outfit/mafia/security
|
||||
name = "Mafia Security Officer"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/civilian/chaplain
|
||||
uniform = /obj/item/clothing/under/rank/security/officer
|
||||
gloves = /obj/item/clothing/gloves/color/black
|
||||
head = /obj/item/clothing/head/helmet/sec
|
||||
suit = /obj/item/clothing/suit/armor/vest/alt
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
|
||||
/datum/outfit/mafia/lawyer
|
||||
name = "Mafia Lawyer"
|
||||
@@ -58,6 +67,26 @@
|
||||
head = /obj/item/clothing/head/hopcap
|
||||
glasses = /obj/item/clothing/glasses/sunglasses
|
||||
|
||||
/datum/outfit/mafia/hos
|
||||
name = "Mafia Head of Security"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/security/head_of_security
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
suit = /obj/item/clothing/suit/armor/hos/trenchcoat
|
||||
gloves = /obj/item/clothing/gloves/color/black
|
||||
head = /obj/item/clothing/head/hos/beret
|
||||
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
|
||||
|
||||
/datum/outfit/mafia/warden
|
||||
name = "Mafia Warden"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/security/warden
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
suit = /obj/item/clothing/suit/armor/vest/warden/alt
|
||||
gloves = /obj/item/clothing/gloves/color/black
|
||||
head = /obj/item/clothing/head/warden
|
||||
glasses = /obj/item/clothing/glasses/hud/security/sunglasses
|
||||
|
||||
//mafia
|
||||
|
||||
/datum/outfit/mafia/changeling
|
||||
|
||||
@@ -10,19 +10,21 @@
|
||||
var/mob/living/carbon/human/body
|
||||
var/obj/effect/landmark/mafia/assigned_landmark
|
||||
|
||||
///how many votes submitted when you vote.
|
||||
///role flags (special status of roles like detection immune)
|
||||
var/role_flags = NONE
|
||||
///how many votes submitted when you vote. used in voting, but not victory
|
||||
var/vote_power = 1
|
||||
var/detect_immune = FALSE
|
||||
var/revealed = FALSE
|
||||
var/datum/outfit/revealed_outfit = /datum/outfit/mafia/assistant //the assistants need a special path to call out they were in fact assistant, everything else can just use job equipment
|
||||
//action = uses
|
||||
///how many votes your role COULD count for, now or later. used in checking victory
|
||||
var/vote_potential = 1
|
||||
///what they get equipped with when they are revealed
|
||||
var/datum/outfit/revealed_outfit = /datum/outfit/mafia/assistant
|
||||
///action = uses
|
||||
var/list/actions = list()
|
||||
var/list/targeted_actions = list()
|
||||
//what the role gets when it wins a game
|
||||
///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/solo_counts_as_town = FALSE //(don't set this for town)
|
||||
///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
|
||||
@@ -38,8 +40,30 @@
|
||||
/datum/mafia_role/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
|
||||
/datum/mafia_role/proc/kill(datum/mafia_controller/game,lynch=FALSE)
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_ON_KILL,game,lynch) & MAFIA_PREVENT_KILL)
|
||||
/**
|
||||
* Tests if a visitor can actually perform an action on this role. Verbose on purpose!
|
||||
*
|
||||
* Will return false if: Your visit is roleblocked, they have perished, or your visit was interrupted
|
||||
*/
|
||||
/datum/mafia_role/proc/can_action(datum/mafia_controller/game, datum/mafia_role/visitor, action)
|
||||
if(role_flags & ROLE_ROLEBLOCKED)
|
||||
to_chat(visitor,"<span class='danger'>Your [action] was blocked!</span>")
|
||||
return FALSE
|
||||
if(game_status != MAFIA_ALIVE) //They're already dead
|
||||
to_chat(visitor,"<span class='danger'>[body.real_name] perished before you could visit!</span>")
|
||||
return FALSE
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_ON_VISIT,game,visitor) & MAFIA_VISIT_INTERRUPTED) //visited a warden. something that prevents you by visiting that person
|
||||
to_chat(visitor,"<span class='danger'>Your [action] was interrupted!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* 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(SEND_SIGNAL(src,COMSIG_MAFIA_ON_KILL,game,attacker,lynch) & MAFIA_PREVENT_KILL)
|
||||
return FALSE
|
||||
game_status = MAFIA_DEAD
|
||||
body.death()
|
||||
@@ -67,7 +91,7 @@
|
||||
to_chat(body, "<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>")
|
||||
|
||||
/datum/mafia_role/proc/reveal_role(datum/mafia_controller/game, verbose = FALSE)
|
||||
if(revealed)
|
||||
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>")
|
||||
@@ -76,7 +100,7 @@
|
||||
qdel(thing)
|
||||
special_reveal_equip(game)
|
||||
body.equipOutfit(revealed_outfit)
|
||||
revealed = TRUE
|
||||
role_flags |= ROLE_REVEALED
|
||||
|
||||
/datum/mafia_role/proc/special_reveal_equip(datum/mafia_controller/game)
|
||||
return
|
||||
@@ -85,7 +109,7 @@
|
||||
return
|
||||
|
||||
/datum/mafia_role/proc/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target)
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,action,target) & MAFIA_PREVENT_ACTION)
|
||||
if((role_flags & ROLE_ROLEBLOCKED))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -153,27 +177,31 @@
|
||||
/datum/mafia_role/detective/proc/investigate(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!current_investigation)
|
||||
return
|
||||
|
||||
var/datum/mafia_role/target = current_investigation
|
||||
if(target)
|
||||
if(target.detect_immune)
|
||||
to_chat(body,"<span class='warning'>Your investigations reveal that [target.body.real_name] is a true member of the station.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - Town")
|
||||
else
|
||||
var/team_text
|
||||
var/fluff
|
||||
switch(target.team)
|
||||
if(MAFIA_TEAM_TOWN)
|
||||
team_text = "Town"
|
||||
fluff = "a true member of the station."
|
||||
if(MAFIA_TEAM_MAFIA)
|
||||
team_text = "Mafia"
|
||||
fluff = "an unfeeling, hideous changeling!"
|
||||
if(MAFIA_TEAM_SOLO)
|
||||
team_text = "Solo"
|
||||
fluff = "a rogue, with their own objectives..."
|
||||
to_chat(body,"<span class='warning'>Your investigations reveal that [target.body.real_name] is [fluff]</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - [team_text]")
|
||||
current_investigation = null
|
||||
if(!target.can_action(game, src, "investigation"))
|
||||
return
|
||||
if((target.role_flags & ROLE_UNDETECTABLE))
|
||||
to_chat(body,"<span class='warning'>Your investigations reveal that [target.body.real_name] is a true member of the station.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - Town")
|
||||
else
|
||||
var/team_text
|
||||
var/fluff
|
||||
switch(target.team)
|
||||
if(MAFIA_TEAM_TOWN)
|
||||
team_text = "Town"
|
||||
fluff = "a true member of the station."
|
||||
if(MAFIA_TEAM_MAFIA)
|
||||
team_text = "Mafia"
|
||||
fluff = "an unfeeling, hideous changeling!"
|
||||
if(MAFIA_TEAM_SOLO)
|
||||
team_text = "Solo"
|
||||
fluff = "a rogue, with their own objectives..."
|
||||
to_chat(body,"<span class='warning'>Your investigations reveal that [target.body.real_name] is [fluff]</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - [team_text]")
|
||||
|
||||
/datum/mafia_role/psychologist
|
||||
name = "Psychologist"
|
||||
@@ -195,7 +223,7 @@
|
||||
|
||||
/datum/mafia_role/psychologist/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!. || !can_use || game.phase == MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE || target.revealed || target == src)
|
||||
if(!. || !can_use || game.phase == MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE || (target.role_flags & ROLE_REVEALED) || target == src)
|
||||
return FALSE
|
||||
|
||||
/datum/mafia_role/psychologist/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
@@ -206,14 +234,16 @@
|
||||
/datum/mafia_role/psychologist/proc/therapy_reveal(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"reveal",current_target) & MAFIA_PREVENT_ACTION || game_status != MAFIA_ALIVE) //Got lynched or roleblocked by a lawyer.
|
||||
current_target = null
|
||||
if(current_target)
|
||||
add_note("N[game.turn] - [current_target.body.real_name] - Revealed true identity")
|
||||
to_chat(body,"<span class='warning'>You have revealed the true nature of the [current_target]!</span>")
|
||||
current_target.reveal_role(game, verbose = TRUE)
|
||||
current_target = null
|
||||
can_use = FALSE
|
||||
if(!current_target)
|
||||
return
|
||||
var/datum/mafia_role/target = current_target
|
||||
current_target = null
|
||||
if(!target.can_action(game, src, "role reveal"))
|
||||
return
|
||||
add_note("N[game.turn] - [current_target.body.real_name] - Revealed true identity")
|
||||
to_chat(body,"<span class='warning'>You have revealed the true nature of the [current_target]!</span>")
|
||||
target.reveal_role(game, verbose = TRUE)
|
||||
can_use = FALSE
|
||||
|
||||
/datum/mafia_role/chaplain
|
||||
name = "Chaplain"
|
||||
@@ -225,7 +255,7 @@
|
||||
winner_award = /datum/award/achievement/mafia/chaplain
|
||||
|
||||
targeted_actions = list("Pray")
|
||||
var/current_target
|
||||
var/datum/mafia_role/current_target
|
||||
|
||||
/datum/mafia_role/chaplain/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
@@ -235,7 +265,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_DEAD && target != src && !target.revealed
|
||||
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_DEAD && target != src && !(target.role_flags & ROLE_REVEALED)
|
||||
|
||||
/datum/mafia_role/chaplain/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
to_chat(body,"<span class='warning'>You will commune with the spirit of [target.body.real_name] tonight.</span>")
|
||||
@@ -244,16 +274,20 @@
|
||||
/datum/mafia_role/chaplain/proc/commune(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!current_target)
|
||||
return
|
||||
var/datum/mafia_role/target = current_target
|
||||
current_target = null
|
||||
if(!target.can_action(game, src, "communion"))
|
||||
return
|
||||
if(target)
|
||||
to_chat(body,"<span class='warning'>You invoke spirit of [target.body.real_name] and learn their role was <b>[target.name]<b>.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - [target.name]")
|
||||
current_target = null
|
||||
|
||||
/datum/mafia_role/md
|
||||
name = "Medical Doctor"
|
||||
desc = "You can protect a single person each night from killing."
|
||||
revealed_outfit = /datum/outfit/mafia/md // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these)
|
||||
revealed_outfit = /datum/outfit/mafia/md
|
||||
role_type = TOWN_PROTECT
|
||||
hud_icon = "hudmedicaldoctor"
|
||||
revealed_icon = "medicaldoctor"
|
||||
@@ -271,7 +305,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(target.name == "Head of Personnel" && target.revealed)
|
||||
if((target.role_flags & ROLE_VULNERABLE) && (target.role_flags & ROLE_REVEALED)) //do not give the option to protect roles that your protection will fail on
|
||||
return FALSE
|
||||
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src
|
||||
|
||||
@@ -285,15 +319,24 @@
|
||||
/datum/mafia_role/md/proc/protect(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(current_protected)
|
||||
RegisterSignal(current_protected,COMSIG_MAFIA_ON_KILL,.proc/prevent_kill)
|
||||
add_note("N[game.turn] - Protected [current_protected.body.real_name]")
|
||||
if(!current_protected)
|
||||
return
|
||||
var/datum/mafia_role/target = current_protected
|
||||
//current protected is unset at the end, as this action ends at a different phase
|
||||
if(!target.can_action(game, src, "medical assistance"))
|
||||
return
|
||||
|
||||
/datum/mafia_role/md/proc/prevent_kill(datum/source)
|
||||
RegisterSignal(target,COMSIG_MAFIA_ON_KILL,.proc/prevent_kill)
|
||||
add_note("N[game.turn] - Protected [target.body.real_name]")
|
||||
|
||||
/datum/mafia_role/md/proc/prevent_kill(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if((current_protected.role_flags & ROLE_VULNERABLE))
|
||||
to_chat(body,"<span class='warning'>The person you protected could not be saved.</span>")
|
||||
return
|
||||
to_chat(body,"<span class='warning'>The person you protected tonight was attacked!</span>")
|
||||
to_chat(current_protected.body,"<span class='userdanger'>You were attacked last night, but someone nursed you back to life!</span>")
|
||||
to_chat(current_protected.body,"<span class='greentext'>You were attacked last night, but someone nursed you back to life!</span>")
|
||||
return MAFIA_PREVENT_KILL
|
||||
|
||||
/datum/mafia_role/md/proc/end_protection(datum/mafia_controller/game)
|
||||
@@ -303,11 +346,77 @@
|
||||
UnregisterSignal(current_protected,COMSIG_MAFIA_ON_KILL)
|
||||
current_protected = null
|
||||
|
||||
/datum/mafia_role/officer
|
||||
name = "Security Officer"
|
||||
desc = "You can protect a single person each night. If they are attacked, you will retaliate, killing yourself and the attacker."
|
||||
revealed_outfit = /datum/outfit/mafia/security
|
||||
revealed_icon = "securityofficer"
|
||||
hud_icon = "hudsecurityofficer"
|
||||
role_type = TOWN_PROTECT
|
||||
role_flags = ROLE_CAN_KILL
|
||||
winner_award = /datum/award/achievement/mafia/officer
|
||||
|
||||
targeted_actions = list("Defend")
|
||||
var/datum/mafia_role/current_defended
|
||||
|
||||
/datum/mafia_role/officer/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/defend)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/end_defense)
|
||||
|
||||
/datum/mafia_role/officer/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if((role_flags & ROLE_VULNERABLE) && (target.role_flags & ROLE_REVEALED)) //do not give the option to protect roles that your protection will fail on
|
||||
return FALSE
|
||||
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src
|
||||
|
||||
/datum/mafia_role/officer/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target)
|
||||
if(!target || target.game_status != MAFIA_ALIVE)
|
||||
to_chat(body,"<span class='warning'>You can only defend alive people.</span>")
|
||||
return
|
||||
to_chat(body,"<span class='warning'>You will defend [target.body.real_name] tonight.</span>")
|
||||
current_defended = target
|
||||
|
||||
/datum/mafia_role/officer/proc/defend(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!current_defended)
|
||||
return
|
||||
var/datum/mafia_role/target = current_defended
|
||||
//current defended is unset at the end, as this action ends at a different phase
|
||||
if(!target.can_action(game, src, "security patrol"))
|
||||
return
|
||||
if(target)
|
||||
RegisterSignal(target,COMSIG_MAFIA_ON_KILL,.proc/retaliate)
|
||||
add_note("N[game.turn] - Defended [target.body.real_name]")
|
||||
|
||||
/datum/mafia_role/officer/proc/retaliate(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if((current_defended.role_flags & ROLE_VULNERABLE))
|
||||
to_chat(body,"<span class='warning'>The person you defended could not be saved. You could not attack the killer.</span>")
|
||||
return
|
||||
to_chat(body,"<span class='userdanger'>The person you defended tonight was attacked!</span>")
|
||||
to_chat(current_defended.body,"<span class='userdanger'>You were attacked last night, but security fought off the attacker!</span>")
|
||||
if(attacker.kill(game,src,FALSE)) //you attack the attacker
|
||||
to_chat(attacker.body, "<span class='userdanger'>You have been ambushed by Security!</span>")
|
||||
kill(game,attacker,FALSE) //the attacker attacks you, they were able to attack the target so they can attack you.
|
||||
return MAFIA_PREVENT_KILL
|
||||
|
||||
/datum/mafia_role/officer/proc/end_defense(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(current_defended)
|
||||
UnregisterSignal(current_defended,COMSIG_MAFIA_ON_KILL)
|
||||
current_defended = null
|
||||
|
||||
/datum/mafia_role/lawyer
|
||||
name = "Lawyer"
|
||||
desc = "You can choose a person during the day to provide extensive legal advice to during the night, preventing night actions."
|
||||
revealed_outfit = /datum/outfit/mafia/lawyer
|
||||
role_type = TOWN_PROTECT
|
||||
role_type = TOWN_SUPPORT
|
||||
hud_icon = "hudlawyer"
|
||||
revealed_icon = "lawyer"
|
||||
winner_award = /datum/award/achievement/mafia/lawyer
|
||||
@@ -317,23 +426,30 @@
|
||||
|
||||
/datum/mafia_role/lawyer/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/roleblock_text)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_START,.proc/try_to_roleblock)
|
||||
RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/roleblock)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/release)
|
||||
|
||||
/datum/mafia_role/lawyer/proc/roleblock_text(datum/mafia_controller/game)
|
||||
/datum/mafia_role/lawyer/proc/roleblock(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"roleblock",current_target) & MAFIA_PREVENT_ACTION || game_status != MAFIA_ALIVE) //Got lynched or roleblocked by another lawyer.
|
||||
if(!current_target)
|
||||
return
|
||||
|
||||
var/datum/mafia_role/target = current_target
|
||||
if(!target.can_action(game, src, "roleblock")) //roleblocking a warden moment
|
||||
current_target = null
|
||||
if(current_target)
|
||||
to_chat(current_target.body,"<span class='big bold red'>YOU HAVE BEEN BLOCKED! YOU CANNOT PERFORM ANY ACTIONS TONIGHT.</span>")
|
||||
add_note("N[game.turn] - [current_target.body.real_name] - Blocked")
|
||||
return
|
||||
|
||||
to_chat(target.body,"<span class='big bold red'>YOU HAVE BEEN BLOCKED! YOU CANNOT PERFORM ANY ACTIONS TONIGHT.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - Blocked")
|
||||
target.role_flags |= ROLE_ROLEBLOCKED
|
||||
|
||||
/datum/mafia_role/lawyer/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(target == src)
|
||||
return FALSE
|
||||
if(game.phase == MAFIA_PHASE_NIGHT)
|
||||
return FALSE
|
||||
if(target.game_status != MAFIA_ALIVE)
|
||||
@@ -348,48 +464,159 @@
|
||||
current_target = target
|
||||
to_chat(body,"<span class='warning'>You will block [target.body.real_name] tonight.</span>")
|
||||
|
||||
/datum/mafia_role/lawyer/proc/try_to_roleblock(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(current_target)
|
||||
RegisterSignal(current_target,COMSIG_MAFIA_CAN_PERFORM_ACTION, .proc/prevent_action)
|
||||
|
||||
/datum/mafia_role/lawyer/proc/release(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
. = ..()
|
||||
if(current_target)
|
||||
UnregisterSignal(current_target, COMSIG_MAFIA_CAN_PERFORM_ACTION)
|
||||
current_target.role_flags &= ROLE_ROLEBLOCKED
|
||||
current_target = null
|
||||
|
||||
/datum/mafia_role/lawyer/proc/prevent_action(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(game_status == MAFIA_ALIVE) //in case we got killed while imprisoning sk - bad luck edge
|
||||
return MAFIA_PREVENT_ACTION
|
||||
|
||||
/datum/mafia_role/hop
|
||||
name = "Head of Personnel"
|
||||
desc = "You can reveal yourself once per game, tripling your vote power but becoming unable to be protected!"
|
||||
revealed_outfit = /datum/outfit/mafia/hop
|
||||
role_type = TOWN_MISC
|
||||
role_type = TOWN_SUPPORT
|
||||
role_flags = ROLE_UNIQUE
|
||||
hud_icon = "hudheadofpersonnel"
|
||||
revealed_icon = "headofpersonnel"
|
||||
revealed_outfit = /datum/outfit/mafia/hop
|
||||
winner_award = /datum/award/achievement/mafia/hop
|
||||
|
||||
targeted_actions = list("Reveal")
|
||||
vote_potential = 3
|
||||
|
||||
/datum/mafia_role/hop/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!. || game.phase == MAFIA_PHASE_NIGHT || game.turn == 1 || target.game_status != MAFIA_ALIVE || target != src || revealed)
|
||||
if(!. || game.phase == MAFIA_PHASE_NIGHT || game.turn == 1 || target.game_status != MAFIA_ALIVE || target != src || (role_flags & ROLE_REVEALED))
|
||||
return FALSE
|
||||
|
||||
/datum/mafia_role/hop/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
. = ..()
|
||||
reveal_role(game, TRUE)
|
||||
vote_power = 2
|
||||
role_flags |= ROLE_VULNERABLE
|
||||
vote_power = 3
|
||||
|
||||
///MAFIA ROLES/// only one until i rework this to allow more, they're the "anti-town" working to kill off townies to win
|
||||
/datum/mafia_role/hos
|
||||
name = "Head of Security"
|
||||
desc = "You can decide to execute during the night, visiting someone killing, and revealing them. If they are innocent, you will die at the start of the next night."
|
||||
role_type = TOWN_KILLING
|
||||
role_flags = ROLE_CAN_KILL | ROLE_UNIQUE
|
||||
revealed_outfit = /datum/outfit/mafia/hos
|
||||
revealed_icon = "headofsecurity"
|
||||
hud_icon = "hudheadofsecurity"
|
||||
winner_award = /datum/award/achievement/mafia/hos
|
||||
|
||||
targeted_actions = list("Execute")
|
||||
var/datum/mafia_role/execute_target
|
||||
|
||||
/datum/mafia_role/hos/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/execute)
|
||||
|
||||
/datum/mafia_role/hos/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src
|
||||
|
||||
/datum/mafia_role/hos/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target)
|
||||
if(execute_target == target)
|
||||
to_chat(body,"<span class='warning'>You have decided against executing tonight.</span>")
|
||||
to_chat(body,"<span class='warning'>You have decided to execute [target.body.real_name] tonight.</span>")
|
||||
execute_target = target
|
||||
|
||||
/datum/mafia_role/hos/proc/execute(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!execute_target)
|
||||
return
|
||||
var/datum/mafia_role/target = execute_target
|
||||
execute_target = null
|
||||
if(!target.can_action(game, src, "execution")) //roleblocking a warden moment
|
||||
return
|
||||
if(!target.kill(game,src,FALSE))//protection
|
||||
to_chat(body,"<span class='danger'>Your attempt at executing [target.body.real_name] was prevented, or [target.body.real_name] is immune!</span>")
|
||||
else
|
||||
to_chat(target.body, "<span class='userdanger'>You have been executed by the Head of Security!</span>")
|
||||
target.reveal_role(game, verbose = TRUE)
|
||||
if(target.team == MAFIA_TEAM_TOWN)
|
||||
to_chat(body,"<span class='userdanger'>You have killed an innocent crewmember. You will die tomorrow night.</span>")
|
||||
RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/internal_affairs)
|
||||
role_flags |= ROLE_VULNERABLE
|
||||
|
||||
/datum/mafia_role/hos/proc/internal_affairs(datum/mafia_controller/game)
|
||||
to_chat(body,"<span class='userdanger'>You have been killed by Nanotrasen Internal Affairs!</span>")
|
||||
reveal_role(game, verbose = TRUE)
|
||||
kill(game,src,FALSE) //you technically kill yourself but that shouldn't matter
|
||||
|
||||
|
||||
//just helps read better
|
||||
#define WARDEN_NOT_LOCKDOWN 0//will NOT kill visitors tonight
|
||||
#define WARDEN_WILL_LOCKDOWN 1 //will kill visitors tonight
|
||||
|
||||
/datum/mafia_role/warden
|
||||
name = "Warden"
|
||||
desc = "You can lockdown during the night once, killing any visitors. WARNING: This kills fellow town members, too!"
|
||||
|
||||
role_type = TOWN_KILLING
|
||||
role_flags = ROLE_CAN_KILL
|
||||
revealed_outfit = /datum/outfit/mafia/warden
|
||||
revealed_icon = "warden"
|
||||
hud_icon = "hudwarden"
|
||||
winner_award = /datum/award/achievement/mafia/warden
|
||||
|
||||
actions = list("Lockdown")
|
||||
var/charges = 1
|
||||
var/protection_status = WARDEN_NOT_LOCKDOWN
|
||||
|
||||
|
||||
/datum/mafia_role/warden/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/night_start)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/night_end)
|
||||
|
||||
/datum/mafia_role/warden/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
||||
. = ..()
|
||||
if(!charges)
|
||||
to_chat(body,"<span class='danger'>You've already locked down this game!</span>")
|
||||
return
|
||||
if(game.phase == MAFIA_PHASE_NIGHT)
|
||||
to_chat(body,"<span class='danger'>You don't have time to lockdown, night has already arrived.</span>")
|
||||
return
|
||||
if(protection_status == WARDEN_WILL_LOCKDOWN)
|
||||
to_chat(body,"<span class='danger'>You decide to not lockdown tonight.</span>")
|
||||
else
|
||||
to_chat(body,"<span class='danger'>You decide to lockdown, killing any visitors.</span>")
|
||||
protection_status = !protection_status
|
||||
|
||||
/datum/mafia_role/warden/proc/night_start(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(protection_status == WARDEN_WILL_LOCKDOWN)
|
||||
to_chat(body,"<span class='danger'>Any and all visitors are going to eat buckshot tonight.</span>")
|
||||
RegisterSignal(src,COMSIG_MAFIA_ON_VISIT,.proc/self_defense)
|
||||
|
||||
/datum/mafia_role/warden/proc/night_end(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(protection_status == WARDEN_WILL_LOCKDOWN)
|
||||
charges--
|
||||
UnregisterSignal(src,COMSIG_MAFIA_ON_KILL)
|
||||
to_chat(body,"<span class='danger'>You are no longer protected. You have used up your power.</span>")
|
||||
protection_status = WARDEN_NOT_LOCKDOWN
|
||||
|
||||
/datum/mafia_role/warden/proc/self_defense(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
to_chat(body,"<span class='userdanger'>You have shot a visitor!</span>")
|
||||
to_chat(attacker,"<span class='userdanger'>You have visited the warden!</span>")
|
||||
attacker.kill(game, src, lynch = FALSE)
|
||||
return MAFIA_VISIT_INTERRUPTED
|
||||
|
||||
#undef WARDEN_NOT_LOCKDOWN
|
||||
#undef WARDEN_WILL_LOCKDOWN
|
||||
|
||||
///MAFIA ROLES/// they're the "anti-town" working to kill off townies to win
|
||||
|
||||
/datum/mafia_role/mafia
|
||||
name = "Changeling"
|
||||
@@ -444,18 +671,15 @@
|
||||
|
||||
var/datum/mafia_role/target = current_investigation
|
||||
current_investigation = null
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"thoughtfeed",target) & MAFIA_PREVENT_ACTION)
|
||||
to_chat(body,"<span class='warning'>You were unable to investigate [target.body.real_name].</span>")
|
||||
if(!target.can_action(game, src, "thought feeding"))
|
||||
add_note("N[game.turn] - [target.body.real_name] - Unable to investigate")
|
||||
return
|
||||
if(target)
|
||||
if(target.detect_immune)
|
||||
to_chat(body,"<span class='warning'>[target.body.real_name]'s memories reveal that they are the Assistant.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - Assistant")
|
||||
else
|
||||
to_chat(body,"<span class='warning'>[target.body.real_name]'s memories reveal that they are the [target.name].</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - [target.name]")
|
||||
|
||||
if((target.role_flags & ROLE_UNDETECTABLE))
|
||||
to_chat(body,"<span class='warning'>[target.body.real_name]'s memories reveal that they are the Assistant.</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - Assistant")
|
||||
else
|
||||
to_chat(body,"<span class='warning'>[target.body.real_name]'s memories reveal that they are the [target.name].</span>")
|
||||
add_note("N[game.turn] - [target.body.real_name] - [target.name]")
|
||||
|
||||
///SOLO ROLES/// they range from anomalous factors to deranged killers that try to win alone.
|
||||
|
||||
@@ -465,15 +689,14 @@
|
||||
win_condition = "kill everyone."
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_KILL
|
||||
role_flags = ROLE_CAN_KILL
|
||||
winner_award = /datum/award/achievement/mafia/traitor
|
||||
|
||||
targeted_actions = list("Night Kill")
|
||||
revealed_outfit = /datum/outfit/mafia/traitor
|
||||
|
||||
hud_icon = "hudtraitor"
|
||||
revealed_icon = "traitor"
|
||||
hud_icon = "hudtraitor"
|
||||
special_theme = "neutral"
|
||||
|
||||
targeted_actions = list("Night Kill")
|
||||
var/datum/mafia_role/current_victim
|
||||
|
||||
/datum/mafia_role/traitor/New(datum/mafia_controller/game)
|
||||
@@ -481,13 +704,13 @@
|
||||
RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/nightkill_immunity)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_KILL_PHASE,.proc/try_to_kill)
|
||||
|
||||
/datum/mafia_role/traitor/check_total_victory(alive_town, alive_mafia) //serial killers just want teams dead
|
||||
/datum/mafia_role/traitor/check_total_victory(alive_town, alive_mafia) //serial killers just want teams dead, they cannot be stopped by killing roles anyways
|
||||
return alive_town + alive_mafia <= 1
|
||||
|
||||
/datum/mafia_role/traitor/block_team_victory(alive_town, alive_mafia) //no team can win until they're dead
|
||||
return TRUE //while alive, town AND mafia cannot win (though since mafia know who is who it's pretty easy to win from that point)
|
||||
|
||||
/datum/mafia_role/traitor/proc/nightkill_immunity(datum/source,datum/mafia_controller/game,lynch)
|
||||
/datum/mafia_role/traitor/proc/nightkill_immunity(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(game.phase == MAFIA_PHASE_NIGHT && !lynch)
|
||||
@@ -506,23 +729,27 @@
|
||||
current_victim = target
|
||||
to_chat(body,"<span class='warning'>You will attempt to kill [target.body.real_name] tonight.</span>")
|
||||
|
||||
/datum/mafia_role/traitor/proc/try_to_kill(datum/mafia_controller/source)
|
||||
/datum/mafia_role/traitor/proc/try_to_kill(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!current_victim)
|
||||
return
|
||||
var/datum/mafia_role/target = current_victim
|
||||
current_victim = null
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,source,"traitor kill",target) & MAFIA_PREVENT_ACTION)
|
||||
if(!target.can_action(game, src, "flickering")) //flickering a warden
|
||||
return
|
||||
if(game_status == MAFIA_ALIVE && target && target.game_status == MAFIA_ALIVE)
|
||||
if(!target.kill(source))
|
||||
to_chat(body,"<span class='danger'>Your attempt at killing [target.body] was prevented!</span>")
|
||||
if(game_status == MAFIA_ALIVE)
|
||||
if(!target.kill(game,src,FALSE))
|
||||
to_chat(body,"<span class='danger'>Your attempt at killing [target.body.real_name] was prevented!</span>")
|
||||
else
|
||||
to_chat(target.body, "<span class='userdanger'>You have been killed by a Traitor!</span>")
|
||||
|
||||
/datum/mafia_role/nightmare
|
||||
name = "Nightmare"
|
||||
desc = "You're a solo monster that cannot be detected by detective roles. You can flicker lights of another room each night. You can instead decide to hunt, killing everyone in a flickering room. Kill everyone to win."
|
||||
desc = "You're a solo monster that cannot be detected by detective roles. You can flicker lights of another room each night, becoming immune to attacks from those roles. You can instead decide to hunt, killing everyone in a flickering room. Kill everyone to win."
|
||||
win_condition = "kill everyone."
|
||||
revealed_outfit = /datum/outfit/mafia/nightmare
|
||||
detect_immune = TRUE
|
||||
role_flags = ROLE_UNDETECTABLE | ROLE_CAN_KILL
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_KILL
|
||||
special_theme = "neutral"
|
||||
@@ -536,6 +763,7 @@
|
||||
|
||||
/datum/mafia_role/nightmare/New(datum/mafia_controller/game)
|
||||
. = ..()
|
||||
RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/flickering_immunity)
|
||||
RegisterSignal(game,COMSIG_MAFIA_NIGHT_KILL_PHASE,.proc/flicker_or_hunt)
|
||||
|
||||
/datum/mafia_role/nightmare/check_total_victory(alive_town, alive_mafia) //nightmares just want teams dead
|
||||
@@ -570,16 +798,25 @@
|
||||
else
|
||||
to_chat(body,"<span class='danger'>You will hunt everyone in a flickering room down tonight.</span>")
|
||||
|
||||
/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/source)
|
||||
/datum/mafia_role/nightmare/proc/flickering_immunity(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
if(!attacker)
|
||||
return //no chance man, that's a town lynch
|
||||
|
||||
if(attacker in flickering)
|
||||
to_chat(body,"<span class='userdanger'>You were attacked by someone in a flickering room. You have danced in the shadows, evading them.</span>")
|
||||
return MAFIA_PREVENT_KILL
|
||||
|
||||
/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/game)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(game_status != MAFIA_ALIVE || !flicker_target)
|
||||
return
|
||||
if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,source,"nightmare actions",flicker_target) & MAFIA_PREVENT_ACTION)
|
||||
to_chat(flicker_target.body, "<span class='warning'>Your actions were prevented!</span>")
|
||||
if(!flicker_target)
|
||||
return
|
||||
var/datum/mafia_role/target = flicker_target
|
||||
flicker_target = null
|
||||
if(!target.can_action(game, src, "flickering")) //flickering a warden
|
||||
return
|
||||
|
||||
if(target != src) //flicker instead of hunt
|
||||
to_chat(target.body, "<span class='userdanger'>The lights begin to flicker and dim. You're in danger.</span>")
|
||||
flickering += target
|
||||
@@ -587,8 +824,8 @@
|
||||
for(var/r in flickering)
|
||||
var/datum/mafia_role/role = r
|
||||
if(role && role.game_status == MAFIA_ALIVE)
|
||||
to_chat(role.body, "<span class='userdanger'>A shadowy monster appears out of the darkness!</span>")
|
||||
role.kill(source)
|
||||
to_chat(role.body, "<span class='userdanger'>A shadowy figure appears out of the darkness!</span>")
|
||||
role.kill(game,src,FALSE)
|
||||
flickering -= role
|
||||
|
||||
//just helps read better
|
||||
@@ -599,7 +836,6 @@
|
||||
name = "Fugitive"
|
||||
desc = "You're on the run. You can become immune to night kills exactly twice, and you win by surviving to the end of the game with anyone."
|
||||
win_condition = "survive to the end of the game, with anyone"
|
||||
solo_counts_as_town = TRUE //should not count towards mafia victory, they should have the option to work with town
|
||||
revealed_outfit = /datum/outfit/mafia/fugitive
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_DISRUPT
|
||||
@@ -649,7 +885,7 @@
|
||||
to_chat(body,"<span class='danger'>You are no longer protected. You have [charges] use[charges == 1 ? "" : "s"] left of your power.</span>")
|
||||
protection_status = FUGITIVE_NOT_PRESERVING
|
||||
|
||||
/datum/mafia_role/fugitive/proc/prevent_death(datum/mafia_controller/game)
|
||||
/datum/mafia_role/fugitive/proc/prevent_death(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
to_chat(body,"<span class='userdanger'>You were attacked! Luckily, you were ready for this!</span>")
|
||||
@@ -669,8 +905,7 @@
|
||||
name = "Obsessed"
|
||||
desc = "You're completely lost in your own mind. You win by lynching your obsession before you get killed in this mess. Obsession assigned on the first night!"
|
||||
win_condition = "lynch their obsession."
|
||||
revealed_outfit = /datum/outfit/mafia/obsessed // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these)
|
||||
solo_counts_as_town = TRUE //after winning or whatever, can side with whoever. they've already done their objective!
|
||||
revealed_outfit = /datum/outfit/mafia/obsessed
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_DISRUPT
|
||||
special_theme = "neutral"
|
||||
@@ -678,9 +913,6 @@
|
||||
revealed_icon = "obsessed"
|
||||
|
||||
winner_award = /datum/award/achievement/mafia/obsessed
|
||||
|
||||
revealed_outfit = /datum/outfit/mafia/obsessed // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these)
|
||||
solo_counts_as_town = TRUE //after winning or whatever, can side with whoever. they've already done their objective!
|
||||
var/datum/mafia_role/obsession
|
||||
var/lynched_target = FALSE
|
||||
|
||||
@@ -705,7 +937,7 @@
|
||||
RegisterSignal(obsession,COMSIG_MAFIA_ON_KILL,.proc/check_victory)
|
||||
UnregisterSignal(game,COMSIG_MAFIA_SUNDOWN)
|
||||
|
||||
/datum/mafia_role/obsessed/proc/check_victory(datum/source,datum/mafia_controller/game,lynch)
|
||||
/datum/mafia_role/obsessed/proc/check_victory(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
UnregisterSignal(source,COMSIG_MAFIA_ON_KILL)
|
||||
@@ -716,14 +948,13 @@
|
||||
game.award_role(winner_award, src)
|
||||
reveal_role(game, FALSE)
|
||||
else
|
||||
to_chat(body, "<span class='userdanger'>You have failed your objective to lynch [obsession.body]!</span>")
|
||||
to_chat(body, "<span class='userdanger'>You have failed your objective to lynch [obsession.body.real_name]!</span>")
|
||||
|
||||
/datum/mafia_role/clown
|
||||
name = "Clown"
|
||||
desc = "If you are lynched you take down one of your voters (guilty or abstain) with you and win. HONK!"
|
||||
win_condition = "get themselves lynched!"
|
||||
revealed_outfit = /datum/outfit/mafia/clown
|
||||
solo_counts_as_town = TRUE
|
||||
team = MAFIA_TEAM_SOLO
|
||||
role_type = NEUTRAL_DISRUPT
|
||||
special_theme = "neutral"
|
||||
@@ -735,7 +966,7 @@
|
||||
. = ..()
|
||||
RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/prank)
|
||||
|
||||
/datum/mafia_role/clown/proc/prank(datum/source,datum/mafia_controller/game,lynch)
|
||||
/datum/mafia_role/clown/proc/prank(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(lynch)
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |