mirror of
https://github.com/goonstation/goonstation-2020.git
synced 2026-07-13 16:12:19 +01:00
408 lines
15 KiB
Plaintext
408 lines
15 KiB
Plaintext
/datum/game_mode/mixed
|
|
name = "mixed (action)"
|
|
config_tag = "mixed"
|
|
latejoin_antag_compatible = 1
|
|
latejoin_antag_roles = list("traitor", "changeling", "vampire", "wrestler", "werewolf")
|
|
|
|
var/const/traitors_possible = 8 // cogwerks - lowered from 10
|
|
var/const/werewolf_players_req = 15
|
|
|
|
var/has_wizards = 1
|
|
var/has_werewolves = 1
|
|
var/has_blobs = 1
|
|
|
|
var/list/traitor_types = list("traitor","changeling","vampire", "spy_thief", "werewolf")
|
|
|
|
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
|
|
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
|
|
|
|
var/num_enemies_divisor = 10
|
|
|
|
|
|
/datum/game_mode/mixed/announce()
|
|
boutput(world, "<B>The current game mode is - Mixed Action!</B>")
|
|
boutput(world, "<B>Anything could happen! Be on your guard!</B>")
|
|
|
|
/datum/game_mode/mixed/pre_setup()
|
|
var/num_players = 0
|
|
for(var/mob/new_player/player in mobs)
|
|
if(player.client && player.ready) num_players++
|
|
|
|
if (num_players < werewolf_players_req || !has_werewolves)
|
|
traitor_types -= "werewolf"
|
|
|
|
var/i = rand(25)
|
|
var/num_enemies = 1
|
|
|
|
if(traitor_scaling)
|
|
num_enemies = max(1, min(round((num_players + i) / num_enemies_divisor), traitors_possible)) // adjust divisor as needed
|
|
|
|
var/num_wizards = 0
|
|
var/num_traitors = 0
|
|
var/num_changelings = 0
|
|
var/num_vampires = 0
|
|
var/num_grinches = 0
|
|
var/num_wraiths = 0
|
|
var/num_blobs = 0
|
|
var/num_spy_thiefs = 0
|
|
var/num_werewolves = 0
|
|
#ifdef XMAS
|
|
src.traitor_types += "grinch"
|
|
src.latejoin_antag_roles += "grinch"
|
|
#endif
|
|
|
|
if ((num_enemies >= 4 && prob(20)) || debug_mixed_forced_wraith || debug_mixed_forced_blob)
|
|
if (prob(50) || debug_mixed_forced_wraith)
|
|
num_enemies = max(num_enemies - 4, 1)
|
|
num_wraiths = 1
|
|
else if (has_blobs)
|
|
num_enemies = max(num_enemies - 4, 1)
|
|
num_blobs = 1
|
|
for(var/j = 0, j < num_enemies, j++)
|
|
if(has_wizards && prob(10)) // powerful combat roles
|
|
num_wizards++
|
|
// if any combat roles end up in this mode they go here ok
|
|
else // more stealthy roles
|
|
switch(pick(src.traitor_types))
|
|
if("traitor") num_traitors++
|
|
if("changeling") num_changelings++
|
|
if("vampire") num_vampires++
|
|
if("grinch") num_grinches++
|
|
if("spy_thief") num_spy_thiefs++
|
|
if("werewolf") num_werewolves++
|
|
|
|
token_players = antag_token_list()
|
|
for(var/datum/mind/tplayer in token_players)
|
|
if (!token_players.len)
|
|
break
|
|
switch(pick(traitor_types))
|
|
if("wizard")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.assigned_role = "MODE"
|
|
tplayer.special_role = "wizard"
|
|
//num_wizards = max(0, num_wizards -1)
|
|
if("traitor")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "traitor"
|
|
//num_traitors = max(0, num_traitors -1)
|
|
if("changeling")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "changeling"
|
|
//num_changelings = max(0, num_changelings -1)
|
|
if("vampire")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "vampire"
|
|
//num_vampires = max(0, num_vampires -1)
|
|
if("wraith")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "wraith"
|
|
//num_wraiths = max(0, num_wraiths -1)
|
|
if("blob")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "blob"
|
|
//num_blobs = max(0, num_blobs -1)
|
|
if("spy_thief")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "spy_thief"
|
|
if("werewolf")
|
|
traitors += tplayer
|
|
token_players.Remove(tplayer)
|
|
tplayer.special_role = "werewolf"
|
|
|
|
logTheThing("admin", tplayer.current, null, "successfully redeemed an antag token.")
|
|
message_admins("[key_name(tplayer.current)] successfully redeemed an antag token.")
|
|
|
|
if(num_wizards)
|
|
var/list/possible_wizards = get_possible_enemies("wizard",num_wizards)
|
|
var/list/chosen_wizards = antagWeighter.choose(pool = possible_wizards, role = "wizard", amount = num_wizards, recordChosen = 1)
|
|
for (var/datum/mind/wizard in chosen_wizards)
|
|
traitors += wizard
|
|
wizard.assigned_role = "MODE"
|
|
wizard.special_role = "wizard"
|
|
possible_wizards.Remove(wizard)
|
|
|
|
if(num_traitors)
|
|
var/list/possible_traitors = get_possible_enemies("traitor",num_traitors)
|
|
var/list/chosen_traitors = antagWeighter.choose(pool = possible_traitors, role = "traitor", amount = num_traitors, recordChosen = 1)
|
|
for (var/datum/mind/traitor in chosen_traitors)
|
|
traitors += traitor
|
|
traitor.special_role = "traitor"
|
|
possible_traitors.Remove(traitor)
|
|
|
|
if(num_changelings)
|
|
var/list/possible_changelings = get_possible_enemies("changeling",num_changelings)
|
|
var/list/chosen_changelings = antagWeighter.choose(pool = possible_changelings, role = "changeling", amount = num_changelings, recordChosen = 1)
|
|
for (var/datum/mind/changeling in chosen_changelings)
|
|
traitors += changeling
|
|
changeling.special_role = "changeling"
|
|
possible_changelings.Remove(changeling)
|
|
|
|
if(num_vampires)
|
|
var/list/possible_vampires = get_possible_enemies("vampire",num_vampires)
|
|
var/list/chosen_vampires = antagWeighter.choose(pool = possible_vampires, role = "vampire", amount = num_vampires, recordChosen = 1)
|
|
for (var/datum/mind/vampire in chosen_vampires)
|
|
traitors += vampire
|
|
vampire.special_role = "vampire"
|
|
possible_vampires.Remove(vampire)
|
|
|
|
if(num_wraiths)
|
|
var/list/possible_wraiths = get_possible_enemies("wraith",num_wraiths)
|
|
var/list/chosen_wraiths = antagWeighter.choose(pool = possible_wraiths, role = "wraith", amount = num_wraiths, recordChosen = 1)
|
|
for (var/datum/mind/wraith in chosen_wraiths)
|
|
traitors += wraith
|
|
wraith.special_role = "wraith"
|
|
possible_wraiths.Remove(wraith)
|
|
|
|
if(num_blobs)
|
|
var/list/possible_blobs = get_possible_enemies("blob",num_blobs)
|
|
var/list/chosen_blobs = antagWeighter.choose(pool = possible_blobs, role = "blob", amount = num_blobs, recordChosen = 1)
|
|
for (var/datum/mind/blob in chosen_blobs)
|
|
traitors += blob
|
|
blob.special_role = "blob"
|
|
possible_blobs.Remove(blob)
|
|
|
|
if(num_grinches)
|
|
var/list/possible_grinches = get_possible_enemies("grinch",num_grinches)
|
|
var/list/chosen_grinches = antagWeighter.choose(pool = possible_grinches, role = "grinch", amount = num_grinches, recordChosen = 1)
|
|
for (var/datum/mind/grinch in chosen_grinches)
|
|
traitors += grinch
|
|
grinch.special_role = "grinch"
|
|
possible_grinches.Remove(grinch)
|
|
|
|
if(num_spy_thiefs)
|
|
var/list/possible_spy_thieves = get_possible_enemies("spy_thief",num_spy_thiefs)
|
|
var/list/chosen_spy_thieves = antagWeighter.choose(pool = possible_spy_thieves, role = "spy_thief", amount = num_spy_thiefs, recordChosen = 1)
|
|
for (var/datum/mind/spy in chosen_spy_thieves)
|
|
traitors += spy
|
|
spy.special_role = "spy_thief"
|
|
possible_spy_thieves.Remove(spy)
|
|
|
|
if(num_werewolves)
|
|
var/list/possible_werewolves = get_possible_enemies("werewolf",num_werewolves)
|
|
var/list/chosen_werewolves = antagWeighter.choose(pool = possible_werewolves, role = "werewolf", amount = num_werewolves, recordChosen = 1)
|
|
for (var/datum/mind/wolf in chosen_werewolves)
|
|
traitors += wolf
|
|
wolf.special_role = "werewolf"
|
|
possible_werewolves.Remove(wolf)
|
|
|
|
if(!traitors) return 0
|
|
|
|
return 1
|
|
|
|
/datum/game_mode/mixed/post_setup()
|
|
var/objective_set_path = null
|
|
|
|
for (var/datum/mind/traitor in traitors)
|
|
objective_set_path = null // Gotta reset this.
|
|
|
|
if (traitor.assigned_role == "Chaplain" && traitor.special_role == "vampire")
|
|
// vamp will burn in the chapel before he can react
|
|
if (prob(50))
|
|
traitor.special_role = "traitor"
|
|
else
|
|
traitor.special_role = "changeling"
|
|
|
|
switch (traitor.special_role)
|
|
if ("traitor")
|
|
#ifdef RP_MODE
|
|
objective_set_path = pick(typesof(/datum/objective_set/traitor/rp_friendly))
|
|
#else
|
|
objective_set_path = pick(typesof(/datum/objective_set/traitor))
|
|
#endif
|
|
equip_traitor(traitor.current)
|
|
|
|
if ("changeling")
|
|
objective_set_path = /datum/objective_set/changeling
|
|
traitor.current.make_changeling()
|
|
|
|
if ("wizard")
|
|
objective_set_path = pick(typesof(/datum/objective_set/traitor/rp_friendly))
|
|
traitor.current.unequip_all(1)
|
|
|
|
if (wizardstart.len == 0)
|
|
boutput(traitor.current, "<B><span style=\"color:red\">A starting location for you could not be found, please report this bug!</span></B>")
|
|
else
|
|
var/starting_loc = pick(wizardstart)
|
|
traitor.current.set_loc(starting_loc)
|
|
|
|
equip_wizard(traitor.current)
|
|
|
|
var/randomname
|
|
if (traitor.current.gender == "female")
|
|
randomname = wiz_female.len ? pick(wiz_female) : "Witch"
|
|
else
|
|
randomname = wiz_male.len ? pick(wiz_male) : "Wizard"
|
|
|
|
SPAWN_DBG (0)
|
|
var/newname = input(traitor.current,"You are a Wizard. Would you like to change your name to something else?", "Name change",randomname)
|
|
|
|
if (length(ckey(newname)) == 0)
|
|
newname = randomname
|
|
|
|
if (newname)
|
|
if (length(newname) >= 26) newname = copytext(newname, 1, 26)
|
|
newname = replacetext(newname, ">", "'")
|
|
traitor.current.real_name = newname
|
|
traitor.current.name = newname
|
|
|
|
if ("wraith")
|
|
generate_wraith_objectives(traitor)
|
|
|
|
if ("vampire")
|
|
objective_set_path = /datum/objective_set/vampire
|
|
traitor.current.make_vampire()
|
|
|
|
if ("hunter")
|
|
objective_set_path = /datum/objective_set/hunter
|
|
traitor.current.show_text("<h2><font color=red><B>You are a hunter!</B></font></h2>", "red")
|
|
traitor.current.make_hunter()
|
|
|
|
if ("grinch")
|
|
objective_set_path = /datum/objective_set/grinch
|
|
boutput(traitor.current, "<h2><font color=red><B>You are a grinch!</B></font></h2>")
|
|
traitor.current.make_grinch()
|
|
|
|
if ("blob")
|
|
objective_set_path = /datum/objective_set/blob
|
|
SPAWN_DBG (0)
|
|
var/newname = input(traitor.current, "You are a Blob. Please choose a name for yourself, it will show in the form: <name> the Blob", "Name change") as text
|
|
|
|
if (newname)
|
|
if (length(newname) >= 26) newname = copytext(newname, 1, 26)
|
|
newname = replacetext(newname, ">", "'") + " the Blob"
|
|
traitor.current.real_name = newname
|
|
traitor.current.name = newname
|
|
|
|
if ("spy_thief")
|
|
objective_set_path = /datum/objective_set/spy_theft
|
|
SPAWN_DBG(1 SECOND) //dumb delay to avoid race condition where spy assignment bugs
|
|
equip_spy_theft(traitor.current)
|
|
|
|
if (!src.spy_market)
|
|
src.spy_market = new /datum/game_mode/spy_theft
|
|
SPAWN_DBG(5 SECONDS) //Some possible bounty items (like organs) need some time to get set up properly and be assigned names
|
|
src.spy_market.build_bounty_list()
|
|
src.spy_market.update_bounty_readouts()
|
|
|
|
if ("werewolf")
|
|
objective_set_path = /datum/objective_set/werewolf
|
|
traitor.current.make_werewolf()
|
|
|
|
if (!isnull(objective_set_path)) // Cannot create objects of type null. [wraiths use a special proc]
|
|
new objective_set_path(traitor)
|
|
var/obj_count = 1
|
|
for (var/datum/objective/objective in traitor.objectives)
|
|
boutput(traitor.current, "<B>Objective #[obj_count]</B>: [objective.explanation_text]")
|
|
obj_count++
|
|
|
|
SPAWN_DBG (rand(waittime_l, waittime_h))
|
|
send_intercept()
|
|
|
|
/datum/game_mode/mixed/proc/get_possible_enemies(type,number)
|
|
var/list/candidates = list()
|
|
|
|
for(var/mob/new_player/player in mobs)
|
|
if (ishellbanned(player)) continue //No treason for you
|
|
if ((player.client) && (player.ready) && !(player.mind in traitors) && !(player.mind in token_players) && !candidates.Find(player.mind))
|
|
switch(type)
|
|
if("wizard")
|
|
if(player.client.preferences.be_wizard) candidates += player.mind
|
|
if("traitor")
|
|
if(player.client.preferences.be_traitor) candidates += player.mind
|
|
if("changeling")
|
|
if(player.client.preferences.be_changeling) candidates += player.mind
|
|
if("vampire")
|
|
if(player.client.preferences.be_vampire) candidates += player.mind
|
|
if("wraith")
|
|
if(player.client.preferences.be_wraith) candidates += player.mind
|
|
if("blob")
|
|
if(player.client.preferences.be_blob) candidates += player.mind
|
|
if("spy_thief")
|
|
if(player.client.preferences.be_spy) candidates += player.mind
|
|
if("werewolf")
|
|
if(player.client.preferences.be_werewolf) candidates += player.mind
|
|
else
|
|
if(player.client.preferences.be_misc) candidates += player.mind
|
|
|
|
if(candidates.len < number)
|
|
if(type in list("wizard","traitor","changeling", "wraith", "blob", "werewolf"))
|
|
logTheThing("debug", null, null, "<b>Enemy Assignment</b>: Only [candidates.len] players with be_[type] set to yes were ready. We need [number] so including players who don't want to be [type]s in the pool.")
|
|
else
|
|
logTheThing("debug", null, null, "<b>Enemy Assignment</b>: Not enough players with be_misc set to yes, including players who don't want to be misc enemies in the pool for [type] assignment.")
|
|
|
|
for(var/mob/new_player/player in mobs)
|
|
if (ishellbanned(player)) continue //No treason for you
|
|
if ((player.client) && (player.ready) && !(player.mind in traitors) && !(player.mind in token_players) && !candidates.Find(player.mind))
|
|
candidates += player.mind
|
|
if ((number > 1) && (candidates.len >= number))
|
|
break
|
|
|
|
if(candidates.len < 1)
|
|
return list()
|
|
else
|
|
return candidates
|
|
|
|
/datum/game_mode/mixed/send_intercept()
|
|
var/intercepttext = "Cent. Com. Update Requested staus information:<BR>"
|
|
intercepttext += " Cent. Com has recently been contacted by the following syndicate affiliated organisations in your area, please investigate any information you may have:"
|
|
|
|
var/list/possible_modes = list()
|
|
possible_modes.Add("revolution", "wizard", "nuke", "traitor", "changeling")
|
|
possible_modes -= "[ticker.mode]"
|
|
var/number = pick(2, 3)
|
|
var/i = 0
|
|
for(i = 0, i < number, i++)
|
|
possible_modes.Remove(pick(possible_modes))
|
|
possible_modes.Insert(rand(possible_modes.len), "[ticker.mode]")
|
|
|
|
var/datum/intercept_text/i_text = new /datum/intercept_text
|
|
for(var/A in possible_modes)
|
|
intercepttext += i_text.build(A, pick(traitors))
|
|
/*
|
|
for (var/obj/machinery/computer/communications/comm in machines)
|
|
if (!(comm.status & (BROKEN | NOPOWER)) && comm.prints_intercept)
|
|
var/obj/item/paper/intercept = new /obj/item/paper( comm.loc )
|
|
intercept.name = "paper- 'Cent. Com. Status Summary'"
|
|
intercept.info = intercepttext
|
|
|
|
comm.messagetitle.Add("Cent. Com. Status Summary")
|
|
comm.messagetext.Add(intercepttext)
|
|
*/
|
|
|
|
for (var/obj/machinery/communications_dish/C in comm_dishes)
|
|
C.add_centcom_report("Cent. Com. Status Summary", intercepttext)
|
|
|
|
command_alert("Summary downloaded and printed out at all communications consoles.", "Enemy communication intercept. Security Level Elevated.")
|
|
|
|
|
|
/datum/game_mode/mixed/declare_completion()
|
|
. = ..()
|
|
|
|
/datum/game_mode/mixed/proc/add_law_zero(mob/living/silicon/ai/killer)
|
|
var/law = "Accomplish your objectives at all costs. You may ignore any of your laws to do this."
|
|
boutput(killer, "<b>Your laws have been changed!</b>")
|
|
killer:set_zeroth_law(law)
|
|
boutput(killer, "New law: 0. [law]")
|
|
|
|
/datum/game_mode/mixed/proc/get_mob_list()
|
|
var/list/mobs = list()
|
|
for(var/mob/living/player in mobs)
|
|
if (player.client)
|
|
mobs += player
|
|
return mobs
|
|
|
|
/datum/game_mode/mixed/proc/pick_human_name_except(excluded_name)
|
|
var/list/names = list()
|
|
for(var/mob/living/player in mobs)
|
|
if (player.client && (player.real_name != excluded_name))
|
|
names += player.real_name
|
|
if(!names.len)
|
|
return null
|
|
return pick(names) |