|
|
|
@@ -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_danger("Your [action] was blocked!"))
|
|
|
|
|
return FALSE
|
|
|
|
|
if(game_status != MAFIA_ALIVE) //They're already dead
|
|
|
|
|
to_chat(visitor,span_danger("[body.real_name] perished before you could visit!"))
|
|
|
|
|
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_danger("Your [action] was interrupted!"))
|
|
|
|
|
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()
|
|
|
|
@@ -55,19 +79,19 @@
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/proc/greet()
|
|
|
|
|
SEND_SOUND(body, 'sound/ambience/ambifailure.ogg')
|
|
|
|
|
to_chat(body,"<span class='danger'>You are the [name].</span>")
|
|
|
|
|
to_chat(body,"<span class='danger'>[desc]</span>")
|
|
|
|
|
to_chat(body,span_danger("You are the [name]."))
|
|
|
|
|
to_chat(body,span_danger("[desc]"))
|
|
|
|
|
switch(team)
|
|
|
|
|
if(MAFIA_TEAM_MAFIA)
|
|
|
|
|
to_chat(body,"<span class='danger'>You and your co-conspirators win if you outnumber crewmembers.</span>")
|
|
|
|
|
to_chat(body,span_danger("You and your co-conspirators win if you outnumber crewmembers."))
|
|
|
|
|
if(MAFIA_TEAM_TOWN)
|
|
|
|
|
to_chat(body,"<span class='danger'>You are a crewmember. Find out and lynch the changelings!</span>")
|
|
|
|
|
to_chat(body,span_danger("You are a crewmember. Find out and lynch the changelings!"))
|
|
|
|
|
if(MAFIA_TEAM_SOLO)
|
|
|
|
|
to_chat(body,"<span class='danger'>You are not aligned to town or mafia. Accomplish your own objectives!</span>")
|
|
|
|
|
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>")
|
|
|
|
|
to_chat(body,span_danger("You are not aligned to town or mafia. Accomplish your own objectives!"))
|
|
|
|
|
to_chat(body, "<span class='warningplain'><b>Be sure to read <a href=\"https://tgstation13.org/wiki/Mafia\">the wiki page</a> to learn more, if you have no idea what's going on.</b></span>")
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/proc/reveal_role(datum/mafia_controller/game, verbose = FALSE)
|
|
|
|
|
if(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
|
|
|
|
|
|
|
|
|
@@ -114,9 +138,9 @@
|
|
|
|
|
team_desc = "Nobody"
|
|
|
|
|
team_span = "comradio"
|
|
|
|
|
the = FALSE
|
|
|
|
|
result += "<span class='notice'>The <span class='bold'>[name]</span> is aligned with [the ? "the " : ""]<span class='[team_span]'>[team_desc]</span></span>"
|
|
|
|
|
result += span_notice("The [span_bold("[name]")] is aligned with [the ? "the " : ""]<span class='[team_span]'>[team_desc]</span>")
|
|
|
|
|
result += "<span class='bold notice'>\"[desc]\"</span>"
|
|
|
|
|
result += "<span class='notice'>[name] wins when they [win_condition]</span>"
|
|
|
|
|
result += span_notice("[name] wins when they [win_condition]")
|
|
|
|
|
to_chat(clueless, result.Join("</br>"))
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/detective
|
|
|
|
@@ -145,35 +169,39 @@
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/detective/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 investigate alive people.</span>")
|
|
|
|
|
to_chat(body,span_warning("You can only investigate alive people."))
|
|
|
|
|
return
|
|
|
|
|
to_chat(body,"<span class='warning'>You will investigate [target.body.real_name] tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will investigate [target.body.real_name] tonight."))
|
|
|
|
|
current_investigation = target
|
|
|
|
|
|
|
|
|
|
/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_warning("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,span_warning("Your investigations reveal that [target.body.real_name] is [fluff]"))
|
|
|
|
|
add_note("N[game.turn] - [target.body.real_name] - [team_text]")
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/psychologist
|
|
|
|
|
name = "Psychologist"
|
|
|
|
@@ -195,25 +223,27 @@
|
|
|
|
|
|
|
|
|
|
/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)
|
|
|
|
|
. = ..()
|
|
|
|
|
to_chat(body,"<span class='warning'>You will reveal [target.body.real_name] tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will reveal [target.body.real_name] tonight."))
|
|
|
|
|
current_target = target
|
|
|
|
|
|
|
|
|
|
/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] - [target.body.real_name] - Revealed true identity")
|
|
|
|
|
to_chat(body,span_warning("You have revealed the true nature of the [target]!"))
|
|
|
|
|
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,25 +265,29 @@
|
|
|
|
|
. = ..()
|
|
|
|
|
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>")
|
|
|
|
|
to_chat(body,span_warning("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)
|
|
|
|
|
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>")
|
|
|
|
|
to_chat(body,span_warning("You invoke spirit of [target.body.real_name] and learn their role was <b>[target.name]<b>."))
|
|
|
|
|
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,29 +305,38 @@
|
|
|
|
|
. = ..()
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/md/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 protect alive people.</span>")
|
|
|
|
|
to_chat(body,span_warning("You can only protect alive people."))
|
|
|
|
|
return
|
|
|
|
|
to_chat(body,"<span class='warning'>You will protect [target.body.real_name] tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will protect [target.body.real_name] tonight."))
|
|
|
|
|
current_protected = target
|
|
|
|
|
|
|
|
|
|
/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
|
|
|
|
|
|
|
|
|
|
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>")
|
|
|
|
|
if((current_protected.role_flags & ROLE_VULNERABLE))
|
|
|
|
|
to_chat(body,span_warning("The person you protected could not be saved."))
|
|
|
|
|
return
|
|
|
|
|
to_chat(body,span_warning("The person you protected tonight was attacked!"))
|
|
|
|
|
to_chat(current_protected.body,span_greentext("You were attacked last night, but someone nursed you back to life!"))
|
|
|
|
|
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_warning("You can only defend alive people."))
|
|
|
|
|
return
|
|
|
|
|
to_chat(body,span_warning("You will defend [target.body.real_name] tonight."))
|
|
|
|
|
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_warning("The person you defended could not be saved. You could not attack the killer."))
|
|
|
|
|
return
|
|
|
|
|
to_chat(body,span_userdanger("The person you defended tonight was attacked!"))
|
|
|
|
|
to_chat(current_defended.body,span_userdanger("You were attacked last night, but security fought off the attacker!"))
|
|
|
|
|
if(attacker.kill(game,src,FALSE)) //you attack the attacker
|
|
|
|
|
to_chat(attacker.body, span_userdanger("You have been ambushed by Security!"))
|
|
|
|
|
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)
|
|
|
|
@@ -343,53 +459,164 @@
|
|
|
|
|
. = ..()
|
|
|
|
|
if(target == current_target)
|
|
|
|
|
current_target = null
|
|
|
|
|
to_chat(body,"<span class='warning'>You have decided against blocking anyone tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You have decided against blocking anyone tonight."))
|
|
|
|
|
else
|
|
|
|
|
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)
|
|
|
|
|
to_chat(body,span_warning("You will block [target.body.real_name] tonight."))
|
|
|
|
|
|
|
|
|
|
/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_warning("You have decided against executing tonight."))
|
|
|
|
|
to_chat(body,span_warning("You have decided to execute [target.body.real_name] tonight."))
|
|
|
|
|
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_danger("Your attempt at executing [target.body.real_name] was prevented, or [target.body.real_name] is immune!"))
|
|
|
|
|
else
|
|
|
|
|
to_chat(target.body, span_userdanger("You have been executed by the Head of Security!"))
|
|
|
|
|
target.reveal_role(game, verbose = TRUE)
|
|
|
|
|
if(target.team == MAFIA_TEAM_TOWN)
|
|
|
|
|
to_chat(body,span_userdanger("You have killed an innocent crewmember. You will die tomorrow night."))
|
|
|
|
|
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_userdanger("You have been killed by Nanotrasen Internal Affairs!"))
|
|
|
|
|
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_danger("You've already locked down this game!"))
|
|
|
|
|
return
|
|
|
|
|
if(game.phase == MAFIA_PHASE_NIGHT)
|
|
|
|
|
to_chat(body,span_danger("You don't have time to lockdown, night has already arrived."))
|
|
|
|
|
return
|
|
|
|
|
if(protection_status == WARDEN_WILL_LOCKDOWN)
|
|
|
|
|
to_chat(body,span_danger("You decide to not lockdown tonight."))
|
|
|
|
|
else
|
|
|
|
|
to_chat(body,span_danger("You decide to lockdown, killing any visitors."))
|
|
|
|
|
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_danger("Any and all visitors are going to eat buckshot tonight."))
|
|
|
|
|
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_danger("You are no longer protected. You have used up your power."))
|
|
|
|
|
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_userdanger("You have shot a visitor!"))
|
|
|
|
|
to_chat(attacker,span_userdanger("You have visited the warden!"))
|
|
|
|
|
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"
|
|
|
|
@@ -436,7 +663,7 @@
|
|
|
|
|
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,"<span class='warning'>You will feast on the memories of [target.body.real_name] tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("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)
|
|
|
|
@@ -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_warning("[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,span_warning("[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.
|
|
|
|
|
|
|
|
|
@@ -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,17 +704,17 @@
|
|
|
|
|
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)
|
|
|
|
|
to_chat(body,"<span class='userdanger'>You were attacked, but they'll have to try harder than that to put you down.</span>")
|
|
|
|
|
to_chat(body,span_userdanger("You were attacked, but they'll have to try harder than that to put you down."))
|
|
|
|
|
return MAFIA_PREVENT_KILL
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/traitor/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target)
|
|
|
|
@@ -504,25 +727,29 @@
|
|
|
|
|
/datum/mafia_role/traitor/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
|
|
|
|
. = ..()
|
|
|
|
|
current_victim = target
|
|
|
|
|
to_chat(body,"<span class='warning'>You will attempt to kill [target.body.real_name] tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will attempt to kill [target.body.real_name] tonight."))
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/traitor/proc/try_to_kill(datum/mafia_controller/source)
|
|
|
|
|
// SIGNAL_HANDLER
|
|
|
|
|
/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_danger("Your attempt at killing [target.body.real_name] was prevented!"))
|
|
|
|
|
else
|
|
|
|
|
to_chat(target.body, span_userdanger("You have been killed by a Traitor!"))
|
|
|
|
|
|
|
|
|
|
/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
|
|
|
|
@@ -562,33 +790,42 @@
|
|
|
|
|
/datum/mafia_role/nightmare/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
|
|
|
|
. = ..()
|
|
|
|
|
if(target == flicker_target)
|
|
|
|
|
to_chat(body,"<span class='warning'>You will do nothing tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will do nothing tonight."))
|
|
|
|
|
flicker_target = null
|
|
|
|
|
flicker_target = target
|
|
|
|
|
if(action == "Flicker")
|
|
|
|
|
to_chat(body,"<span class='warning'>You will attempt to flicker [target.body.real_name]'s room tonight.</span>")
|
|
|
|
|
to_chat(body,span_warning("You will attempt to flicker [target.body.real_name]'s room tonight."))
|
|
|
|
|
else
|
|
|
|
|
to_chat(body,"<span class='danger'>You will hunt everyone in a flickering room down tonight.</span>")
|
|
|
|
|
to_chat(body,span_danger("You will hunt everyone in a flickering room down tonight."))
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/source)
|
|
|
|
|
// SIGNAL_HANDLER
|
|
|
|
|
/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(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(attacker in flickering)
|
|
|
|
|
to_chat(body,span_userdanger("You were attacked by someone in a flickering room. You have danced in the shadows, evading them."))
|
|
|
|
|
return MAFIA_PREVENT_KILL
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/game)
|
|
|
|
|
SIGNAL_HANDLER
|
|
|
|
|
|
|
|
|
|
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>")
|
|
|
|
|
to_chat(target.body, span_userdanger("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, "<span class='userdanger'>A shadowy monster appears out of the darkness!</span>")
|
|
|
|
|
role.kill(source)
|
|
|
|
|
to_chat(role.body, span_userdanger("A shadowy figure appears out of the darkness!"))
|
|
|
|
|
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
|
|
|
|
@@ -622,22 +858,22 @@
|
|
|
|
|
/datum/mafia_role/fugitive/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target)
|
|
|
|
|
. = ..()
|
|
|
|
|
if(!charges)
|
|
|
|
|
to_chat(body,"<span class='danger'>You're out of supplies and cannot protect yourself anymore.</span>")
|
|
|
|
|
to_chat(body,span_danger("You're out of supplies and cannot protect yourself anymore."))
|
|
|
|
|
return
|
|
|
|
|
if(game.phase == MAFIA_PHASE_NIGHT)
|
|
|
|
|
to_chat(body,"<span class='danger'>You don't have time to prepare, night has already arrived.</span>")
|
|
|
|
|
to_chat(body,span_danger("You don't have time to prepare, night has already arrived."))
|
|
|
|
|
return
|
|
|
|
|
if(protection_status == FUGITIVE_WILL_PRESERVE)
|
|
|
|
|
to_chat(body,"<span class='danger'>You decide to not prepare tonight.</span>")
|
|
|
|
|
to_chat(body,span_danger("You decide to not prepare tonight."))
|
|
|
|
|
else
|
|
|
|
|
to_chat(body,"<span class='danger'>You decide to prepare for a horrible night.</span>")
|
|
|
|
|
to_chat(body,span_danger("You decide to prepare for a horrible night."))
|
|
|
|
|
protection_status = !protection_status
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/fugitive/proc/night_start(datum/mafia_controller/game)
|
|
|
|
|
SIGNAL_HANDLER
|
|
|
|
|
|
|
|
|
|
if(protection_status == FUGITIVE_WILL_PRESERVE)
|
|
|
|
|
to_chat(body,"<span class='danger'>Your preparations are complete. Nothing could kill you tonight!</span>")
|
|
|
|
|
to_chat(body,span_danger("Your preparations are complete. Nothing could kill you tonight!"))
|
|
|
|
|
RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/prevent_death)
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/fugitive/proc/night_end(datum/mafia_controller/game)
|
|
|
|
@@ -646,13 +882,13 @@
|
|
|
|
|
if(protection_status == FUGITIVE_WILL_PRESERVE)
|
|
|
|
|
charges--
|
|
|
|
|
UnregisterSignal(src,COMSIG_MAFIA_ON_KILL)
|
|
|
|
|
to_chat(body,"<span class='danger'>You are no longer protected. You have [charges] use[charges == 1 ? "" : "s"] left of your power.</span>")
|
|
|
|
|
to_chat(body,span_danger("You are no longer protected. You have [charges] use[charges == 1 ? "" : "s"] left of your power."))
|
|
|
|
|
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>")
|
|
|
|
|
to_chat(body,span_userdanger("You were attacked! Luckily, you were ready for this!"))
|
|
|
|
|
return MAFIA_PREVENT_KILL
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/fugitive/proc/survived(datum/mafia_controller/game)
|
|
|
|
@@ -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
|
|
|
|
|
|
|
|
|
@@ -700,12 +932,12 @@
|
|
|
|
|
if(!obsession)
|
|
|
|
|
obsession = pick(all_roles_shuffle) //okay no town just pick anyone here
|
|
|
|
|
//if you still don't have an obsession you're playing a single player game like i can't help your dumb ass
|
|
|
|
|
to_chat(body, "<span class='userdanger'>Your obsession is [obsession.body.real_name]! Get them lynched to win!</span>")
|
|
|
|
|
to_chat(body, span_userdanger("Your obsession is [obsession.body.real_name]! Get them lynched to win!"))
|
|
|
|
|
add_note("N[game.turn] - I vowed to watch my obsession, [obsession.body.real_name], hang!") //it'll always be N1 but whatever
|
|
|
|
|
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_userdanger("You have failed your objective to lynch [obsession.body.real_name]!"))
|
|
|
|
|
|
|
|
|
|
/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,8 +966,8 @@
|
|
|
|
|
. = ..()
|
|
|
|
|
RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/prank)
|
|
|
|
|
|
|
|
|
|
/datum/mafia_role/clown/proc/prank(datum/source,datum/mafia_controller/game,lynch)
|
|
|
|
|
// SIGNAL_HANDLER
|
|
|
|
|
/datum/mafia_role/clown/proc/prank(datum/source,datum/mafia_controller/game,datum/mafia_role/attacker,lynch)
|
|
|
|
|
SIGNAL_HANDLER
|
|
|
|
|
|
|
|
|
|
if(lynch)
|
|
|
|
|
var/datum/mafia_role/victim = pick(game.judgement_guilty_votes + game.judgement_abstain_votes)
|
|
|
|
|