diff --git a/code/modules/mafia/_defines.dm b/code/modules/mafia/_defines.dm
index 3833d5aefe..194851beed 100644
--- a/code/modules/mafia/_defines.dm
+++ b/code/modules/mafia/_defines.dm
@@ -1,7 +1,30 @@
+///how many people can play mafia without issues (running out of spawns, procs not expecting more than this amount of people, etc)
+#define MAFIA_MAX_PLAYER_COUNT 12
+
#define MAFIA_TEAM_TOWN "town"
#define MAFIA_TEAM_MAFIA "mafia"
#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
+#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)
+#define TOWN_PROTECT "protect"
+/// roles that don't fit into anything else (hop)
+#define TOWN_MISC "misc"
+
+//other types (mafia team, neutrals)
+/// normal vote kill changelings
+#define MAFIA_REGULAR "regular"
+/// every other changeling role that has extra abilities
+#define MAFIA_SPECIAL "special"
+/// role that wins solo that nobody likes
+#define NEUTRAL_KILL "kill"
+/// role that upsets the game aka obsessed, usually worse for town than mafia but they can vote against mafia
+#define NEUTRAL_DISRUPT "disrupt"
+
#define MAFIA_PHASE_SETUP 1
#define MAFIA_PHASE_DAY 2
#define MAFIA_PHASE_VOTING 3
@@ -20,132 +43,23 @@
//in order of events + game end
-#define COMSIG_MAFIA_SUNDOWN "sundown" //the rest of these phases are at the end of the night when shutters raise, in a different order of resolution
+/// when the shutters fall, before the 45 second wait and night event resolution
+#define COMSIG_MAFIA_SUNDOWN "sundown"
+/// after the 45 second wait, for actions that must go first
#define COMSIG_MAFIA_NIGHT_START "night_start"
+/// most night actions now resolve
#define COMSIG_MAFIA_NIGHT_ACTION_PHASE "night_actions"
+/// now killing happens from the roles that do that. the reason this is post action phase is to ensure doctors can protect and lawyers can block
#define COMSIG_MAFIA_NIGHT_KILL_PHASE "night_kill"
+/// now undoing states like protection, actions that must happen last, etc. right before shutters raise and the day begins
#define COMSIG_MAFIA_NIGHT_END "night_end"
+/// signal sent to roles when the game is confirmed ending
#define COMSIG_MAFIA_GAME_END "game_end"
-//list of ghosts who want to play mafia, every time someone enters the list it checks to see if enough are in
+/// list of ghosts who want to play mafia, every time someone enters the list it checks to see if enough are in
GLOBAL_LIST_EMPTY(mafia_signup)
-//the current global mafia game running.
-GLOBAL_VAR(mafia_game)
/// list of ghosts who want to play mafia that have since disconnected. They are kept in the lobby, but not counted for starting a game.
GLOBAL_LIST_EMPTY(mafia_bad_signup)
-
-GLOBAL_LIST_INIT(mafia_setups,generate_mafia_setups())
-
-/proc/generate_mafia_setups()
- . = list()
- for(var/T in subtypesof(/datum/mafia_setup))
- var/datum/mafia_setup/N = new T
- . += list(N.roles)
-
-/datum/mafia_setup
- var/name = "Make subtypes with the list and a name, more readable than list(list(),list()) etc"
- var/list/roles
-
-// 12 Player
-
-/datum/mafia_setup/twelve_basic
- name = "12 Player Setup Basic"
- roles = list(
- /datum/mafia_role=6,
- /datum/mafia_role/md=1,
- /datum/mafia_role/detective=1,
- /datum/mafia_role/clown=1,
- /datum/mafia_role/mafia=3
- )
-
-/datum/mafia_setup/twelve_md
- name = "12 Player Setup MD"
- roles = list(
- /datum/mafia_role=6,
- /datum/mafia_role/md=3,
- /datum/mafia_role/mafia=3
- )
-
-/datum/mafia_setup/twelve_all
- name = "12 Player Setup All"
- roles = list(
- /datum/mafia_role=1,
- /datum/mafia_role/psychologist=1,
- /datum/mafia_role/md=1,
- /datum/mafia_role/detective=1,
- /datum/mafia_role/clown=1,
- /datum/mafia_role/chaplain=1,
- /datum/mafia_role/lawyer=1,
- /datum/mafia_role/traitor=1,
- /datum/mafia_role/mafia=3,
- /datum/mafia_role/fugitive=1,
- /datum/mafia_role/obsessed=1
- )
-
-/datum/mafia_setup/twelve_joke
- name = "12 Player Setup Funny"
- roles = list(
- /datum/mafia_role=5,
- /datum/mafia_role/detective=2,
- /datum/mafia_role/clown=2,
- /datum/mafia_role/mafia=3
- )
-
-/datum/mafia_setup/twelve_lockdown
- name = "12 Player Setup Lockdown"
- roles = list(
- /datum/mafia_role=5,
- /datum/mafia_role/md=1,
- /datum/mafia_role/detective=1,
- /datum/mafia_role/lawyer=2,
- /datum/mafia_role/mafia=3
- )
-
-/datum/mafia_setup/twelve_rip
- name = "12 Player Setup RIP"
- roles = list(
- /datum/mafia_role=6,
- /datum/mafia_role/md=1,
- /datum/mafia_role/detective=1,
- /datum/mafia_role/mafia=3,
- /datum/mafia_role/traitor=1
- )
-
-/datum/mafia_setup/twelve_double_treason
- name = "12 Player Setup Double Treason"
- roles = list(
- /datum/mafia_role=8,
- /datum/mafia_role/detective=1,
- /datum/mafia_role/traitor=1,
- /datum/mafia_role/obsessed=2
- )
-
-/datum/mafia_setup/twelve_fugitives
- name = "12 Player Fugitives"
- roles = list(
- /datum/mafia_role=6,
- /datum/mafia_role/psychologist=1,
- /datum/mafia_role/mafia=3,
- /datum/mafia_role/fugitive=2
- )
-
-/datum/mafia_setup/twelve_traitor_mafia
- name = "12 Player Traitor Mafia"
- roles = list(
- /datum/mafia_role=3,
- /datum/mafia_role/psychologist=2,
- /datum/mafia_role/md=2,
- /datum/mafia_role/detective=2,
- /datum/mafia_role/traitor=3
- )
-
-/*
-/datum/mafia_setup/three_test
- name = "3 Player Test"
- roles = list(
- /datum/mafia_role/chaplain=1,
- /datum/mafia_role/psychologist=1,
- /datum/mafia_role/mafia=1
- )
-*/
+/// the current global mafia game running.
+GLOBAL_VAR(mafia_game)
diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm
index 602d697675..7a088dba1c 100644
--- a/code/modules/mafia/controller.dm
+++ b/code/modules/mafia/controller.dm
@@ -1,4 +1,3 @@
-/* DO NOT MERGE, REQUIRES TGUI3 MINIMUM, though the code only supports tgui4 */
/**
@@ -16,7 +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
-
+ ///for debugging and testing a full game, or adminbuse. If this is not null, 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
var/first_day_phase_period = 20 SECONDS
///talk with others about the last night
@@ -193,7 +193,7 @@
*/
/datum/mafia_controller/proc/check_trial(verbose = TRUE)
var/datum/mafia_role/loser = get_vote_winner("Day")//, majority_of_town = TRUE)
- var/loser_votes = get_vote_count(loser,"Day")
+ // var/loser_votes = get_vote_count(loser,"Day")
if(loser)
// if(loser_votes > 12)
// loser.body.client?.give_award(/datum/award/achievement/mafia/universally_hated, loser.body)
@@ -267,6 +267,10 @@
* * returns TRUE if someone won the game, halting other procs from continuing in the case of a victory
*/
/datum/mafia_controller/proc/check_victory()
+ //needed for achievements
+ var/list/total_town = list()
+ var/list/total_mafia = list()
+
var/alive_town = 0
var/alive_mafia = 0
var/list/solos_to_ask = list() //need to ask after because first round is counting team sizes
@@ -276,15 +280,19 @@
///PHASE ONE: TALLY UP ALL NUMBERS OF PEOPLE STILL ALIVE
for(var/datum/mafia_role/R in all_roles)
- if(R.game_status == MAFIA_ALIVE)
- switch(R.team)
- if(MAFIA_TEAM_MAFIA)
- alive_mafia++
- if(MAFIA_TEAM_TOWN)
- alive_town++
- if(MAFIA_TEAM_SOLO)
+ switch(R.team)
+ if(MAFIA_TEAM_MAFIA)
+ total_mafia += R
+ if(R.game_status == MAFIA_ALIVE)
+ alive_mafia += R.vote_power
+ if(MAFIA_TEAM_TOWN)
+ total_town += R
+ if(R.game_status == MAFIA_ALIVE)
+ alive_town += R.vote_power
+ if(MAFIA_TEAM_SOLO)
+ if(R.game_status == MAFIA_ALIVE)
if(R.solo_counts_as_town)
- alive_town++
+ alive_town += R.vote_power
solos_to_ask += R
///PHASE TWO: SEND STATS TO SOLO ANTAGS, SEE IF THEY WON OR TEAMS CANNOT WIN
@@ -299,6 +307,8 @@
var/solo_end = FALSE
for(var/datum/mafia_role/winner in total_victors)
send_message("!! [uppertext(winner.name)] VICTORY !!")
+ // var/client/winner_client = GLOB.directory[winner.player_key]
+ // winner_client?.give_award(winner.winner_award, winner.body)
solo_end = TRUE
if(solo_end)
start_the_end()
@@ -306,10 +316,16 @@
if(blocked_victory)
return FALSE
if(alive_mafia == 0)
+ // for(var/datum/mafia_role/townie in total_town)
+ // var/client/townie_client = GLOB.directory[townie.player_key]
+ // townie_client?.give_award(townie.winner_award, townie.body)
start_the_end("!! TOWN VICTORY !!")
return TRUE
else if(alive_mafia >= alive_town) //guess could change if town nightkill is added
start_the_end("!! MAFIA VICTORY !!")
+ // for(var/datum/mafia_role/changeling in total_mafia)
+ // var/client/changeling_client = GLOB.directory[changeling.player_key]
+ // changeling_client?.give_award(changeling.winner_award, changeling.body)
return TRUE
/**
@@ -337,8 +353,13 @@
/datum/mafia_controller/proc/end_game()
map_deleter.generate() //remove the map, it will be loaded at the start of the next one
QDEL_LIST(all_roles)
+ current_setup_text = null
+ custom_setup = list()
turn = 0
votes = list()
+ //map gen does not deal with landmarks
+ QDEL_LIST(landmarks)
+ QDEL_NULL(town_center_landmark)
phase = MAFIA_PHASE_SETUP
/**
@@ -413,17 +434,17 @@
* Arguments:
* * voter: the mafia role that is trying to vote for...
* * target: the mafia role that is getting voted for
- * * vt: type of vote submitted (is this the day vote? is this the mafia night vote?)
+ * * vote_type: type of vote submitted (is this the day vote? is this the mafia night vote?)
* * teams: see mafia team defines for what to put in, makes the messages only send to a specific team (so mafia night votes only sending messages to mafia at night)
*/
-/datum/mafia_controller/proc/vote_for(datum/mafia_role/voter,datum/mafia_role/target,vt, teams)
- if(!votes[vt])
- votes[vt] = list()
- var/old_vote = votes[vt][voter]
+/datum/mafia_controller/proc/vote_for(datum/mafia_role/voter,datum/mafia_role/target,vote_type, teams)
+ if(!votes[vote_type])
+ votes[vote_type] = list()
+ var/old_vote = votes[vote_type][voter]
if(old_vote && old_vote == target)
- votes[vt] -= voter
+ votes[vote_type] -= voter
else
- votes[vt][voter] = target
+ votes[vote_type][voter] = target
if(old_vote && old_vote == target)
send_message("[voter.body.real_name] retracts their vote for [target.body.real_name]!", team = teams)
else
@@ -437,12 +458,12 @@
/**
* Clears out the votes of a certain type (day votes, mafia kill votes) while leaving others untouched
*/
-/datum/mafia_controller/proc/reset_votes(vt)
+/datum/mafia_controller/proc/reset_votes(vote_type)
var/list/bodies_to_update = list()
- for(var/vote in votes[vt])
- var/datum/mafia_role/R = votes[vt][vote]
+ for(var/vote in votes[vote_type])
+ var/datum/mafia_role/R = votes[vote_type][vote]
bodies_to_update += R.body
- votes[vt] = list()
+ votes[vote_type] = list()
for(var/mob/M in bodies_to_update)
M.update_icon()
@@ -450,38 +471,39 @@
* Returns how many people voted for the role, in whatever vote (day vote, night kill vote)
* Arguments:
* * role: the mafia role the proc tries to get the amount of votes for
- * * vt: the vote type (getting how many day votes were for the role, or mafia night votes for the role)
+ * * vote_type: the vote type (getting how many day votes were for the role, or mafia night votes for the role)
*/
-/datum/mafia_controller/proc/get_vote_count(role,vt)
+/datum/mafia_controller/proc/get_vote_count(role,vote_type)
. = 0
- for(var/votee in votes[vt])
- if(votes[vt][votee] == role)
- . += 1
+ for(var/v in votes[vote_type])
+ var/datum/mafia_role/votee = v
+ if(votes[vote_type][votee] == role)
+ . += votee.vote_power
/**
* Returns whichever role got the most votes, in whatever vote (day vote, night kill vote)
* returns null if no votes
* Arguments:
- * * vt: the vote type (getting the role that got the most day votes, or the role that got the most mafia votes)
+ * * vote_type: the vote type (getting the role that got the most day votes, or the role that got the most mafia votes)
*/
-/datum/mafia_controller/proc/get_vote_winner(vt)
+/datum/mafia_controller/proc/get_vote_winner(vote_type)
var/list/tally = list()
- for(var/votee in votes[vt])
- if(!tally[votes[vt][votee]])
- tally[votes[vt][votee]] = 1
+ for(var/votee in votes[vote_type])
+ if(!tally[votes[vote_type][votee]])
+ tally[votes[vote_type][votee]] = 1
else
- tally[votes[vt][votee]] += 1
+ tally[votes[vote_type][votee]] += 1
sortTim(tally,/proc/cmp_numeric_dsc,associative=TRUE)
return length(tally) ? tally[1] : null
/**
* Returns a random person who voted for whatever vote (day vote, night kill vote)
* Arguments:
- * * vt: vote type (getting a random day voter, or mafia night voter)
+ * * vote_type: vote type (getting a random day voter, or mafia night voter)
*/
-/datum/mafia_controller/proc/get_random_voter(vt)
- if(length(votes[vt]))
- return pick(votes[vt])
+/datum/mafia_controller/proc/get_random_voter(vote_type)
+ if(length(votes[vote_type]))
+ return pick(votes[vote_type])
/**
* Adds mutable appearances to people who get publicly voted on (so not night votes) showing how many people are picking them
@@ -604,9 +626,6 @@
basic_setup()
if("nuke")
end_game()
- for(var/i in landmarks)
- qdel(i)
- qdel(town_center_landmark)
qdel(src)
if("next_phase")
var/datum/timedevent/timer = SStimer.timer_id_dict[next_phase_timer]
@@ -623,11 +642,33 @@
continue
player.body.forceMove(get_turf(player.assigned_landmark))
if(failed.len)
- to_chat(usr, "List of players who no longer had a body (if you see this, the game is runtiming anyway so just hit \"New Game\" to end it")
+ to_chat(usr, "List of players who no longer had a body (if you see this, the game is runtiming anyway so just hit \"New Game\" to end it)")
for(var/i in failed)
var/datum/mafia_role/fail = i
to_chat(usr, fail.player_key)
- switch(action)
+ if("debug_setup")
+ var/list/debug_setup = list()
+ var/list/rolelist_dict = list()
+ var/done = FALSE
+ for(var/p in typesof(/datum/mafia_role))
+ var/datum/mafia_role/path = p
+ rolelist_dict[initial(path.name) + " ([uppertext(initial(path.team))])"] = path
+ rolelist_dict = list("CANCEL", "FINISH") + rolelist_dict
+ while(!done)
+ to_chat(usr, "You have a total player count of [assoc_value_sum(debug_setup)] in this setup.")
+ var/chosen_role_name = input(usr,"Select a role!","Custom Setup Creation",rolelist_dict[1]) as null|anything in rolelist_dict
+ if(chosen_role_name == "CANCEL")
+ return
+ if(chosen_role_name == "FINISH")
+ break
+ var/found_path = rolelist_dict[chosen_role_name]
+ var/role_count = input(usr,"How many? Zero to cancel.","Custom Setup Creation",0) as null|num
+ if(role_count > 0)
+ debug_setup[found_path] = role_count
+ custom_setup = debug_setup
+ if("cancel_setup")
+ custom_setup = list()
+ switch(action) //both living and dead
if("mf_lookup")
var/role_lookup = params["atype"]
var/datum/mafia_role/helper
@@ -662,8 +703,7 @@
spectators += C.ckey
if(user_role.game_status == MAFIA_DEAD)
return
- var/self_voting = user_role == on_trial ? TRUE : FALSE //used to block people from voting themselves innocent or guilty
- //User actions
+ //User actions (just living)
switch(action)
if("mf_action")
if(!user_role.actions.Find(params["atype"]))
@@ -678,7 +718,7 @@
if("Vote")
if(phase != MAFIA_PHASE_VOTING)
return
- vote_for(user_role,target,vt="Day")
+ vote_for(user_role,target,vote_type="Day")
if("Kill Vote")
if(phase != MAFIA_PHASE_NIGHT || user_role.team != MAFIA_TEAM_MAFIA)
return
@@ -731,31 +771,87 @@
. += L[key]
/**
- * Returns all setups that the amount of players signed up could support (so fill each role)
- * Arguments:
- * * ready_count: the amount of players signed up (not sane, so some players may have disconnected or rejoined ss13).
+ * 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.
+ *
+ * See _defines.dm in the mafia folder for a rundown on what these groups of roles include.
*/
-/datum/mafia_controller/proc/find_best_setup(ready_count)
- var/list/all_setups = GLOB.mafia_setups
- var/valid_setups = list()
- for(var/S in all_setups)
- var/req_players = assoc_value_sum(S)
- if(req_players <= ready_count)
- valid_setups += list(S)
- return length(valid_setups) > 0 ? pick(valid_setups) : null
+/datum/mafia_controller/proc/generate_random_setup()
+ var/invests_left = 2
+ var/protects_left = 1
+ var/miscs_left = prob(35)
+ 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)
+
+ var/list/random_setup = 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)
+ invests_left--
+ else if(protects_left)
+ add_setup_role(random_setup, TOWN_PROTECT)
+ protects_left--
+ else if(miscs_left)
+ add_setup_role(random_setup, TOWN_MISC)
+ miscs_left--
+ else if(mafiareg_left)
+ add_setup_role(random_setup, MAFIA_REGULAR)
+ mafiareg_left--
+ else if(mafiaspe_left)
+ add_setup_role(random_setup, MAFIA_SPECIAL)
+ mafiaspe_left--
+ else if(killing_role)
+ add_setup_role(random_setup, NEUTRAL_KILL)
+ killing_role--
+ else
+ add_setup_role(random_setup, NEUTRAL_DISRUPT)
+ 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
+ */
+/datum/mafia_controller/proc/add_setup_role(setup_list, 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)
+ role_type_paths += instance
+
+ var/mafia_path = pick(role_type_paths)
+ var/datum/mafia_role/mafia_path_type = mafia_path
+ var/found_role
+ for(var/searched_path in setup_list)
+ var/datum/mafia_role/searched_path_type = searched_path
+ if(initial(mafia_path_type.name) == initial(searched_path_type.name))
+ found_role = searched_path
+ break
+ if(found_role)
+ setup_list[found_role] += 1
+ return
+ setup_list[mafia_path] = 1
/**
* Called when enough players have signed up to fill a setup. DOESN'T NECESSARILY MEAN THE GAME WILL START.
*
+ * Checks for a custom setup, if so gets the required players from that and if not it sets the player requirement to MAFIA_MAX_PLAYER_COUNT and generates one IF basic setup starts a game.
* Checks if everyone signed up is an observer, and is still connected. If people aren't, they're removed from the list.
* If there aren't enough players post sanity, it aborts. otherwise, it selects enough people for the game and starts preparing the game for real.
*/
/datum/mafia_controller/proc/basic_setup()
- var/ready_count = length(GLOB.mafia_signup)
- var/list/setup = find_best_setup(ready_count)
- if(!setup)
- return
- var/req_players = assoc_value_sum(setup) //12
+ var/req_players
+ var/list/setup = custom_setup
+ if(!setup.len)
+ req_players = MAFIA_MAX_PLAYER_COUNT
+ else
+ req_players = assoc_value_sum(setup)
//final list for all the players who will be in this game
var/list/filtered_keys = list()
@@ -783,8 +879,10 @@
for(var/unpicked in possible_keys)
var/client/unpicked_client = GLOB.directory[unpicked]
to_chat(unpicked_client, "Sorry, the starting mafia game has too many players and you were not picked.")
- to_chat(unpicked_client, "You're still signed up, and have another chance to join when the one starting now finishes.")
+ to_chat(unpicked_client, "You're still signed up, getting messages from the current round, and have another chance to join when the one starting now finishes.")
+ if(!setup.len) //don't actually have one yet, so generate a max player random setup. it's good to do this here instead of above so it doesn't generate one every time a game could possibly start.
+ setup = generate_random_setup()
prepare_game(setup,filtered_keys)
start_game()
@@ -794,12 +892,9 @@
* Only checks if everyone is actually valid to start (still connected and an observer) if there are enough players (basic_setup)
*/
/datum/mafia_controller/proc/try_autostart()
- if(phase != MAFIA_PHASE_SETUP)
+ if(phase != MAFIA_PHASE_SETUP) // || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME))
return
- var/min_players = INFINITY // fairly sure mmo mafia is not a thing and i'm lazy
- for(var/setup in GLOB.mafia_setups)
- min_players = min(min_players,assoc_value_sum(setup))
- if(GLOB.mafia_signup.len >= min_players)//enough people to try and make something
+ if(GLOB.mafia_signup.len >= MAFIA_MAX_PLAYER_COUNT || custom_setup.len)//enough people to try and make something (or debug mode)
basic_setup()
/**
diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm
index 1bca4467a1..d1756d7f11 100644
--- a/code/modules/mafia/map_pieces.dm
+++ b/code/modules/mafia/map_pieces.dm
@@ -14,11 +14,14 @@
name = "Mafia Game Board"
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)
. = ..()
- var/datum/mafia_controller/MF = GLOB.mafia_game
+ if(!MF)
+ MF = GLOB.mafia_game
if(!MF)
MF = create_mafia_game()
MF.ui_interact(user)
@@ -30,7 +33,7 @@
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
- //block_suicide = TRUE
+ // block_suicide = TRUE
/datum/map_template/mafia
var/description = ""
diff --git a/code/modules/mafia/outfits.dm b/code/modules/mafia/outfits.dm
index 5bdc66a219..bbc72bd120 100644
--- a/code/modules/mafia/outfits.dm
+++ b/code/modules/mafia/outfits.dm
@@ -17,7 +17,7 @@
name = "Mafia Detective"
uniform = /obj/item/clothing/under/rank/security/detective
- //neck = /obj/item/clothing/neck/tie/detective
+ // neck = /obj/item/clothing/neck/tie/detective
shoes = /obj/item/clothing/shoes/sneakers/brown
suit = /obj/item/clothing/suit/det_suit
gloves = /obj/item/clothing/gloves/color/black
@@ -42,13 +42,6 @@
uniform = /obj/item/clothing/under/rank/civilian/chaplain
-/datum/outfit/mafia/clown
- name = "Mafia Clown"
-
- uniform = /obj/item/clothing/under/rank/civilian/clown
- shoes = /obj/item/clothing/shoes/clown_shoes
- mask = /obj/item/clothing/mask/gas/clown_hat
-
/datum/outfit/mafia/lawyer
name = "Mafia Lawyer"
@@ -56,8 +49,14 @@
suit = /obj/item/clothing/suit/toggle/lawyer
shoes = /obj/item/clothing/shoes/laceup
+/datum/outfit/mafia/hop
+ name = "Mafia Head of Personnel"
-
+ uniform = /obj/item/clothing/under/rank/civilian/head_of_personnel
+ suit = /obj/item/clothing/suit/armor/vest/alt
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/hopcap
+ glasses = /obj/item/clothing/glasses/sunglasses
//mafia
@@ -88,9 +87,22 @@
carried_item.add_mob_blood(H)//Oh yes, there will be blood...
H.regenerate_icons()
+/datum/outfit/mafia/clown
+ name = "Mafia Clown"
+
+ uniform = /obj/item/clothing/under/rank/civilian/clown
+ shoes = /obj/item/clothing/shoes/clown_shoes
+ mask = /obj/item/clothing/mask/gas/clown_hat
+
/datum/outfit/mafia/traitor
name = "Mafia Traitor"
mask = /obj/item/clothing/mask/gas/syndicate
uniform = /obj/item/clothing/under/syndicate/tacticool
shoes = /obj/item/clothing/shoes/jackboots
+
+/datum/outfit/mafia/nightmare
+ name = "Mafia Nightmare"
+
+ uniform = null
+ shoes = null
diff --git a/code/modules/mafia/roles.dm b/code/modules/mafia/roles.dm
index 914cbb0bd3..2461a93976 100644
--- a/code/modules/mafia/roles.dm
+++ b/code/modules/mafia/roles.dm
@@ -3,20 +3,26 @@
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
var/player_key
var/mob/living/carbon/human/body
var/obj/effect/landmark/mafia/assigned_landmark
+ ///how many votes submitted when you vote.
+ 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
var/list/actions = list()
var/list/targeted_actions = list()
+ //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)
-
var/game_status = MAFIA_ALIVE
///icon state in the mafia dmi of the hud of the role, used in the mafia ui
@@ -60,7 +66,6 @@
to_chat(body,"You are not aligned to town or mafia. Accomplish your own objectives!")
to_chat(body, "Be sure to read the wiki page to learn more, if you have no idea what's going on.")
-//please take care with this, they can break shit with their equipment unless you specifically disallow them (aka stun at the end of the game)
/datum/mafia_role/proc/reveal_role(datum/mafia_controller/game, verbose = FALSE)
if(revealed)
return
@@ -69,9 +74,13 @@
var/list/oldoutfit = body.get_equipped_items()
for(var/thing in oldoutfit)
qdel(thing)
+ special_reveal_equip(game)
body.equipOutfit(revealed_outfit)
revealed = TRUE
+/datum/mafia_role/proc/special_reveal_equip(datum/mafia_controller/game)
+ return
+
/datum/mafia_role/proc/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target)
return
@@ -114,6 +123,8 @@
name = "Detective"
desc = "You can investigate a single person each night to learn their team."
revealed_outfit = /datum/outfit/mafia/detective
+ role_type = TOWN_INVEST
+ // winner_award = /datum/award/achievement/mafia/detective
hud_icon = "huddetective"
revealed_icon = "detective"
@@ -140,32 +151,109 @@
current_investigation = target
/datum/mafia_role/detective/proc/investigate(datum/mafia_controller/game)
- var/datum/mafia_role/R = current_investigation
- if(R)
- var/team_text
- var/fluff
- switch(R.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,"Your investigations reveal that [R.body.real_name] is [fluff]")
- add_note("N[game.turn] - [R.body.real_name] - [team_text]")
+ var/datum/mafia_role/target = current_investigation
+ if(target)
+ if(target.detect_immune)
+ to_chat(body,"Your investigations reveal that [target.body.real_name] is a true member of the station.")
+ 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,"Your investigations reveal that [target.body.real_name] is [fluff]")
+ add_note("N[game.turn] - [target.body.real_name] - [team_text]")
current_investigation = null
+/datum/mafia_role/psychologist
+ name = "Psychologist"
+ desc = "You can visit someone ONCE PER GAME to reveal their true role in the morning!"
+ revealed_outfit = /datum/outfit/mafia/psychologist
+ role_type = TOWN_INVEST
+ // winner_award = /datum/award/achievement/mafia/psychologist
+
+ hud_icon = "hudpsychologist"
+ revealed_icon = "psychologist"
+
+ targeted_actions = list("Reveal")
+ var/datum/mafia_role/current_target
+ var/can_use = TRUE
+
+/datum/mafia_role/psychologist/New(datum/mafia_controller/game)
+ . = ..()
+ RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/therapy_reveal)
+
+/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)
+ return FALSE
+
+/datum/mafia_role/psychologist/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
+ . = ..()
+ to_chat(body,"You will reveal [target.body.real_name] tonight.")
+ current_target = target
+
+/datum/mafia_role/psychologist/proc/therapy_reveal(datum/mafia_controller/game)
+ 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,"You have revealed the true nature of the [current_target]!")
+ current_target.reveal_role(game, verbose = TRUE)
+ current_target = null
+ can_use = FALSE
+
+/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
+ role_type = TOWN_INVEST
+ hud_icon = "hudchaplain"
+ revealed_icon = "chaplain"
+ // winner_award = /datum/award/achievement/mafia/chaplain
+
+ targeted_actions = list("Pray")
+ var/current_target
+
+/datum/mafia_role/chaplain/New(datum/mafia_controller/game)
+ . = ..()
+ RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/commune)
+
+/datum/mafia_role/chaplain/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
+ . = ..()
+ if(!.)
+ return
+ return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_DEAD && target != src && !target.revealed
+
+/datum/mafia_role/chaplain/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
+ to_chat(body,"You will commune with the spirit of [target.body.real_name] tonight.")
+ current_target = target
+
+/datum/mafia_role/chaplain/proc/commune(datum/mafia_controller/game)
+ var/datum/mafia_role/target = current_target
+ if(target)
+ to_chat(body,"You invoke spirit of [target.body.real_name] and learn their role was [target.name].")
+ 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)
+ role_type = TOWN_PROTECT
hud_icon = "hudmedicaldoctor"
revealed_icon = "medicaldoctor"
- targeted_actions = list("Protect")
+ // winner_award = /datum/award/achievement/mafia/md
+ targeted_actions = list("Protect")
var/datum/mafia_role/current_protected
/datum/mafia_role/md/New(datum/mafia_controller/game)
@@ -177,6 +265,8 @@
. = ..()
if(!.)
return
+ if(target.name == "Head of Personnel" && target.revealed)
+ return FALSE
return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src
/datum/mafia_role/md/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target)
@@ -201,44 +291,16 @@
UnregisterSignal(current_protected,COMSIG_MAFIA_ON_KILL)
current_protected = null
-/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
- hud_icon = "hudchaplain"
- revealed_icon = "chaplain"
- targeted_actions = list("Pray")
- var/current_target
-
-/datum/mafia_role/chaplain/New(datum/mafia_controller/game)
- . = ..()
- RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/commune)
-
-/datum/mafia_role/chaplain/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
- . = ..()
- if(!.)
- return
- return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_DEAD && target != src && !target.revealed
-
-/datum/mafia_role/chaplain/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
- to_chat(body,"You will commune with the spirit of [target.body.real_name] tonight.")
- current_target = target
-
-/datum/mafia_role/chaplain/proc/commune(datum/mafia_controller/game)
- var/datum/mafia_role/R = current_target
- if(R)
- to_chat(body,"You invoke spirit of [R.body.real_name] and learn their role was [R.name].")
- add_note("N[game.turn] - [R.body.real_name] - [R.name]")
- current_target = 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
hud_icon = "hudlawyer"
revealed_icon = "lawyer"
- targeted_actions = list("Advise")
+ // winner_award = /datum/award/achievement/mafia/lawyer
+ targeted_actions = list("Advise")
var/datum/mafia_role/current_target
/datum/mafia_role/lawyer/New(datum/mafia_controller/game)
@@ -286,41 +348,26 @@
if(game_status == MAFIA_ALIVE) //in case we got killed while imprisoning sk - bad luck edge
return MAFIA_PREVENT_ACTION
-/datum/mafia_role/psychologist
- name = "Psychologist"
- desc = "You can visit someone ONCE PER GAME to reveal their true role in the morning!"
- revealed_outfit = /datum/outfit/mafia/psychologist
-
- hud_icon = "hudpsychologist"
- revealed_icon = "psychologist"
+/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
+ hud_icon = "hudheadofpersonnel"
+ revealed_icon = "headofpersonnel"
+ // winner_award = /datum/award/achievement/mafia/hop
targeted_actions = list("Reveal")
- var/datum/mafia_role/current_target
- var/can_use = TRUE
-/datum/mafia_role/psychologist/New(datum/mafia_controller/game)
+/datum/mafia_role/hop/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
. = ..()
- RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/therapy_reveal)
-
-/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(!. || game.phase == MAFIA_PHASE_NIGHT || game.turn == 1 || target.game_status != MAFIA_ALIVE || target != src || revealed)
return FALSE
-/datum/mafia_role/psychologist/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
+/datum/mafia_role/hop/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
. = ..()
- to_chat(body,"You will reveal [target.body.real_name] tonight.")
- current_target = target
-
-/datum/mafia_role/psychologist/proc/therapy_reveal(datum/mafia_controller/game)
- 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,"You have revealed the true nature of the [current_target]!")
- current_target.reveal_role(game, verbose = TRUE)
- current_target = null
- can_use = FALSE
+ reveal_role(game, TRUE)
+ vote_power = 2
///MAFIA ROLES/// only one until i rework this to allow more, they're the "anti-town" working to kill off townies to win
@@ -328,9 +375,12 @@
name = "Changeling"
desc = "You're a member of the changeling hive. Use ':j' talk prefix to talk to your fellow lings."
team = MAFIA_TEAM_MAFIA
- revealed_outfit = /datum/outfit/mafia/changeling
+ role_type = MAFIA_REGULAR
hud_icon = "hudchangeling"
revealed_icon = "changeling"
+ // winner_award = /datum/award/achievement/mafia/changeling
+
+ revealed_outfit = /datum/outfit/mafia/changeling
special_theme = "syndicate"
win_condition = "become majority over the town and no solo killing role can stop them."
@@ -341,6 +391,48 @@
/datum/mafia_role/mafia/proc/mafia_text(datum/mafia_controller/source)
to_chat(body,"Vote for who to kill tonight. The killer will be chosen randomly from voters.")
+//better detective for mafia
+/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."
+ role_type = MAFIA_SPECIAL
+ hud_icon = "hudthoughtfeeder"
+ revealed_icon = "thoughtfeeder"
+ // winner_award = /datum/award/achievement/mafia/thoughtfeeder
+
+ targeted_actions = list("Learn Role")
+ var/datum/mafia_role/current_investigation
+
+/datum/mafia_role/mafia/thoughtfeeder/New(datum/mafia_controller/game)
+ . = ..()
+ RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/investigate)
+
+/datum/mafia_role/mafia/thoughtfeeder/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/mafia/thoughtfeeder/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target)
+ to_chat(body,"You will feast on the memories of [target.body.real_name] tonight.")
+ current_investigation = target
+
+/datum/mafia_role/mafia/thoughtfeeder/proc/investigate(datum/mafia_controller/game)
+ 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,"You were unable to investigate [target.body.real_name].")
+ add_note("N[game.turn] - [target.body.real_name] - Unable to investigate")
+ return
+ if(target)
+ if(target.detect_immune)
+ to_chat(body,"[target.body.real_name]'s memories reveal that they are the Assistant.")
+ add_note("N[game.turn] - [target.body.real_name] - Assistant")
+ else
+ to_chat(body,"[target.body.real_name]'s memories reveal that they are the [target.name].")
+ 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.
/datum/mafia_role/traitor
@@ -348,6 +440,9 @@
desc = "You're a solo traitor. You are immune to night kills, can kill every night and you win by outnumbering everyone else."
win_condition = "kill everyone."
team = MAFIA_TEAM_SOLO
+ role_type = NEUTRAL_KILL
+ // winner_award = /datum/award/achievement/mafia/traitor
+
targeted_actions = list("Night Kill")
revealed_outfit = /datum/outfit/mafia/traitor
@@ -386,10 +481,85 @@
to_chat(body,"You will attempt to kill [target.body.real_name] tonight.")
/datum/mafia_role/traitor/proc/try_to_kill(datum/mafia_controller/source)
- if(game_status == MAFIA_ALIVE && current_victim && current_victim.game_status == MAFIA_ALIVE)
- if(!current_victim.kill(source))
- to_chat(body,"Your attempt at killing [current_victim.body] was prevented!")
+ 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)
+ return
+ if(game_status == MAFIA_ALIVE && target && target.game_status == MAFIA_ALIVE)
+ if(!target.kill(source))
+ to_chat(body,"Your attempt at killing [target.body] was prevented!")
+
+/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."
+ win_condition = "kill everyone."
+ revealed_outfit = /datum/outfit/mafia/nightmare
+ detect_immune = TRUE
+ team = MAFIA_TEAM_SOLO
+ role_type = NEUTRAL_KILL
+ special_theme = "neutral"
+ hud_icon = "hudnightmare"
+ revealed_icon = "nightmare"
+ // winner_award = /datum/award/achievement/mafia/nightmare
+
+ targeted_actions = list("Flicker", "Hunt")
+ var/list/flickering = list()
+ var/datum/mafia_role/flicker_target
+
+/datum/mafia_role/nightmare/New(datum/mafia_controller/game)
+ . = ..()
+ 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
+ return alive_town + alive_mafia <= 1
+
+/datum/mafia_role/nightmare/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/nightmare/special_reveal_equip()
+ body.underwear = "Nude"
+ body.undershirt = "Nude"
+ body.socks = "Nude"
+ body.set_species(/datum/species/shadow)
+ body.update_body()
+
+/datum/mafia_role/nightmare/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
+ . = ..()
+ if(!. || game.phase != MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE)
+ return FALSE
+ if(action == "Flicker")
+ return target != src && !(target in flickering)
+ return target == src
+
+/datum/mafia_role/nightmare/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
+ . = ..()
+ if(target == flicker_target)
+ to_chat(body,"You will do nothing tonight.")
+ flicker_target = null
+ flicker_target = target
+ if(action == "Flicker")
+ to_chat(body,"You will attempt to flicker [target.body.real_name]'s room tonight.")
+ else
+ to_chat(body,"You will hunt everyone in a flickering room down tonight.")
+
+/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/source)
+ 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, "Your actions were prevented!")
+ return
+ var/datum/mafia_role/target = flicker_target
+ flicker_target = null
+ if(target != src) //flicker instead of hunt
+ to_chat(target.body, "The lights begin to flicker and dim. You're in danger.")
+ flickering += target
+ return
+ for(var/r in flickering)
+ var/datum/mafia_role/role = r
+ if(role && role.game_status == MAFIA_ALIVE)
+ to_chat(role.body, "A shadowy monster appears out of the darkness!")
+ role.kill(source)
+ flickering -= role
//just helps read better
#define FUGITIVE_NOT_PRESERVING 0//will not become night immune tonight
@@ -399,15 +569,19 @@
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"
- team = MAFIA_TEAM_SOLO
- actions = list("Self Preservation")
- var/charges = 2
- var/protection_status = FUGITIVE_NOT_PRESERVING
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
special_theme = "neutral"
hud_icon = "hudfugitive"
revealed_icon = "fugitive"
+ // winner_award = /datum/award/achievement/mafia/fugitive
+
+ actions = list("Self Preservation")
+ var/charges = 2
+ var/protection_status = FUGITIVE_NOT_PRESERVING
+
/datum/mafia_role/fugitive/New(datum/mafia_controller/game)
. = ..()
@@ -447,6 +621,8 @@
/datum/mafia_role/fugitive/proc/survived(datum/mafia_controller/game)
if(game_status == MAFIA_ALIVE)
+ // var/client/winner_client = GLOB.directory[player_key]
+ // winner_client?.give_award(winner_award, body)
game.send_message("!! FUGITIVE VICTORY !!")
#undef FUGITIVE_NOT_PRESERVING
@@ -456,11 +632,17 @@
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."
- team = MAFIA_TEAM_SOLO
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!
+ team = MAFIA_TEAM_SOLO
+ role_type = NEUTRAL_DISRUPT
special_theme = "neutral"
hud_icon = "hudobsessed"
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
@@ -490,6 +672,8 @@
return
if(lynch)
game.send_message("!! OBSESSED VICTORY !!")
+ // var/client/winner_client = GLOB.directory[player_key]
+ // winner_client?.give_award(winner_award, body)
reveal_role(game, FALSE)
else
to_chat(body, "You have failed your objective to lynch [obsession.body]!")
@@ -501,9 +685,11 @@
revealed_outfit = /datum/outfit/mafia/clown
solo_counts_as_town = TRUE
team = MAFIA_TEAM_SOLO
+ role_type = NEUTRAL_DISRUPT
special_theme = "neutral"
hud_icon = "hudclown"
revealed_icon = "clown"
+ // winner_award = /datum/award/achievement/mafia/clown
/datum/mafia_role/clown/New(datum/mafia_controller/game)
. = ..()
@@ -514,4 +700,6 @@
var/datum/mafia_role/victim = pick(game.judgement_guilty_votes + game.judgement_abstain_votes)
game.send_message("[body.real_name] WAS A CLOWN! HONK! They take down [victim.body.real_name] with their last prank.")
game.send_message("!! CLOWN VICTORY !!")
+ // var/client/winner_client = GLOB.directory[player_key]
+ // winner_client?.give_award(winner_award, body)
victim.kill(game,FALSE)