role datums fixes and tweaks (#18277)

* * makes raging mages actually work
 * removes the 'protect master' objective, instead uses the protect objective
 * removes heavily redundant and useless vampire gamemode tweaks. master vampire is now handled through the role creating its own faction if one is not provided.
 * CreateRoles diversified, new filterAvailablePlayers proc, and now it actually works
 * Fixes mixed
 * Fixes syndicate agents becoming other sorts of syndicate agents, causing syndicate agent recursion
 * Fixes check antagonist for factions and roles not newlining after a role has been viewed

* moves rolecheck to faction, rather than having a snowflake check for traitor

* all my problems were because of a missed return 1

* more role fixes!

* removes debug
This commit is contained in:
MadmanMartian
2018-05-17 01:52:21 +01:00
committed by GitHub
parent 42433ee4d3
commit 4f84f6a029
18 changed files with 147 additions and 121 deletions

View File

@@ -189,6 +189,8 @@
//Macros for antags
#define isfaction(A) (istype(A, /datum/faction))
#define isvampire(H) (H.mind ? H.mind.GetRole(VAMPIRE) : FALSE)
#define isthrall(H) (H.mind ? H.mind.GetRole(THRALL) : FALSE)

View File

@@ -180,13 +180,13 @@
// Discord crap.
var/discord_url
var/discord_password
// Weighted Votes
var/weighted_votes = 0
/datum/configuration/New()
. = ..()
var/list/L = subtypesof(/datum/gamemode)
var/list/L = subtypesof(/datum/gamemode)-/datum/gamemode/cult
for (var/T in L)
// I wish I didn't have to instance the game modes in order to look up
@@ -727,7 +727,7 @@
/datum/configuration/proc/pick_mode(mode_name)
// I wish I didn't have to instance the game modes in order to look up
// their information, but it is the only way (at least that I know of).
for (var/T in subtypesof(/datum/gamemode))
for (var/T in subtypesof(/datum/gamemode)-/datum/gamemode/cult)
var/datum/gamemode/M = new T()
if (M.name && M.name == mode_name)
return M
@@ -736,7 +736,7 @@
/datum/configuration/proc/get_runnable_modes()
var/list/datum/gamemode/runnable_modes = new
for (var/T in subtypesof(/datum/gamemode))
for (var/T in subtypesof(/datum/gamemode)-/datum/gamemode/cult)
var/datum/gamemode/M = new T()
// log_startup_progress("DEBUG: [T], tag=[M.name], prob=[probabilities[M.name]]")
if (!(M.name in modes))

View File

@@ -64,16 +64,31 @@ var/list/factions_with_hud_icons = list()
/datum/faction/proc/forgeObjectives()
/datum/faction/proc/HandleNewMind(var/datum/mind/M) //Used on faction creation
var/newRole = new initroletype(M, src, initial_role)
if(!newRole)
WARNING("Role killed itself or was otherwise missing!")
for(var/datum/role/R in members)
if(R.antag == M)
WARNING("Mind was already a role in this faction")
return 0
if(M.GetRole(initial_role))
warning("Mind already had a role of [initial_role]!")
return 0
var/datum/role/newRole = new initroletype(src,null, initial_role)
if(!newRole.AssignToRole(M))
newRole.Drop()
return 0
members.Add(newRole)
return 1
/datum/faction/proc/HandleRecruitedMind(var/datum/mind/M)
var/datum/R = new roletype(M, src, late_role)
if(!R)
for(var/datum/role/R in members)
if(R.antag == M)
WARNING("Mind was already a role in this faction")
return 0
if(M.GetRole(late_role))
warning("Mind already had a role of [late_role]!")
return 0
var/datum/role/R = new roletype(fac = src, new_id = late_role)
if(!R.AssignToRole(M))
R.Drop()
return 0
members.Add(R)
return 1
@@ -239,6 +254,7 @@ var/list/factions_with_hud_icons = list()
desc = "A conglomeration of magically adept individuals, with no obvious heirachy, instead acting as equal individuals in the pursuit of magic-oriented endeavours.\
Their motivations for attacking seemingly peaceful enclaves or operations are as yet unknown, but they do so without respite or remorse.\
This has led to them being identified as enemies of humanity, and should be treated as such."
initroletype = /datum/role/wizard
roletype = /datum/role/wizard
logo_state = "wizard-logo"
hud_icons = list("wizard-logo","apprentice-logo")
@@ -262,6 +278,14 @@ var/list/factions_with_hud_icons = list()
equip_wizard(wwizard.antag.current)
name_wizard(wwizard.antag.current)
/datum/faction/wizard/ragin
accept_latejoiners = TRUE
var/max_wizards
/datum/faction/wizard/ragin/check_win()
if(members.len == max_roles)
return 1
//________________________________________________
#define ADD_REVOLUTIONARY_FAIL_IS_COMMAND -1
@@ -278,6 +302,7 @@ var/list/factions_with_hud_icons = list()
desc = "Viva!"
logo_state = "rev-logo"
initroletype = /datum/role/revolutionary/leader
roletype = /datum/role/revolutionary
/datum/faction/revolution/HandleRecruitedMind(var/datum/mind/M)
if(M.assigned_role in command_positions)
@@ -304,8 +329,6 @@ var/list/factions_with_hud_icons = list()
if(A.set_target(head_mind))
AppendObjective(A)
//____________________{"<BR><img src='data:image/png;base64,[icon2base64(logo)]'> <FONT size = 2><B>Cult of Nar-Sie</B></FONT> <img src='data:image/png;base64,[icon2base64(logo)]'>"}____________________________
/datum/faction/strike_team
name = "Custom Strike Team"//obviously this name is a placeholder getting replaced by the admin setting up the squad
required_pref = ROLE_STRIKE

View File

@@ -5,9 +5,10 @@
required_pref = ROLE_MALF
initial_role = MALF
late_role = MALF //There shouldn't really be any late roles for malfunction, but just in case we can corrupt an AI in the future, let's keep this
initroletype = /datum/role/malfAI
roletype = /datum/role/malfAI
logo_state = "malf-logo"
var/apcs
var/apcs = 0
var/AI_win_timeleft = 1800
var/malf_mode_declared //Boolean
var/station_captured //Boolean
@@ -18,6 +19,9 @@
var/header = {"<BR><img src='data:image/png;base64,[icon2base64(logo)]'> <FONT size = 2><B>Free Silicon Hivemind</B></FONT> <img src='data:image/png;base64,[icon2base64(logo)]'>"}
return header
/datum/faction/malf/forgeObjectives()
AppendObjective(/datum/objective/nuclear)
/datum/faction/malf/process()
if(apcs >= 3 && malf_mode_declared && can_malf_ai_takeover())

View File

@@ -4,6 +4,8 @@
required_pref = ROLE_OPERATIVE
initial_role = NUKE_OP
late_role = NUKE_OP
initroletype = /datum/role/nuclear_operative
roletype = /datum/role/nuclear_operative
desc = "The culmination of succesful NT traitors, who have managed to steal a nuclear device.\
Load up, grab the nuke, don't forget where you've parked, find the nuclear auth disk, and give them hell."
logo_state = "nuke-logo"

View File

@@ -14,7 +14,6 @@
leader = V
members += V
V.faction = src
V.antag.faction = src
/datum/faction/vampire/can_setup()
// TODO : check if the number of players > 10, if we have at least 2 players with vamp enabled.

View File

@@ -42,16 +42,25 @@
TearDown()
return 0
SetupFactions()
return CreateFactions() && CreateRoles()
var/FactionSuccess = CreateFactions()
var/RolesSuccess = CreateRoles()
return FactionSuccess && RolesSuccess
/*===FACTION RELATED STUFF===*/
/datum/gamemode/proc/CreateFactions()
/datum/gamemode/proc/CreateFactions(var/list/factions_to_process, var/populate_factions = TRUE)
if(factions_to_process == null)
factions_to_process = factions_allowed
var/pc = get_player_count() //right proc?
for(var/Fac in factions_allowed)
CreateFaction(Fac, pc)
return PopulateFactions()
for(var/Fac in factions_to_process)
if(islist(Fac))
var/list/L = Fac
CreateFactions(L, FALSE)
else
CreateFaction(Fac, pc)
if(populate_factions)
return PopulateFactions()
/datum/gamemode/proc/CreateFaction(var/Fac, var/population, var/override = 0)
var/datum/faction/F = new Fac
@@ -60,6 +69,7 @@
factions_allowed -= F
return F
else
warning("Faction ([F]) could not set up properly with given population.")
qdel(F)
return null
/*
@@ -83,8 +93,8 @@
if(!P.client.desires_role(F.required_pref) || jobban_isbanned(P, F.required_pref))
continue
if(!F.HandleNewMind(P.mind))
WARNING("[P.mind] failed [F] HandleNewMind!")
return 0
warning("[P.mind] failed [F] HandleNewMind!")
continue
return 1
@@ -95,42 +105,63 @@
return 1
for(var/role in roles_allowed)
if(isnum(roles_allowed[role]))
return CreateNumOfRoles(role, roles_allowed[role])
//else
//Whichever witchcraft we employ in the future to have it scale with the playercount
return CreateStrictNumOfRoles(role, roles_allowed[role])
else
CreateNumOfRoles(role, FilterAvailablePlayers(role))
return 1
/datum/gamemode/proc/CreateNumOfRoles(var/datum/role/R, var/list/candidates)
if(!candidates || !candidates.len)
warning("ran out of available players to fill role [R]!")
return
for(var/mob/M in candidates)
CreateRole(R, M)
/datum/gamemode/proc/CreateNumOfRoles(var/datum/role/R, var/num)
. = list()
var/list/available_players = get_ready_players()
for(var/mob/new_player/P in available_players)
if(!P.client || !P.mind)
available_players.Remove(P)
continue
if(!P.client.desires_role(initial(R.required_pref)) || jobban_isbanned(P, initial(R.required_pref)))
available_players.Remove(P)
continue
/datum/gamemode/proc/CreateStrictNumOfRoles(var/datum/role/R, var/num)
var/number_of_roles = 0
var/list/available_players = FilterAvailablePlayers(R)
for(var/i = 0 to num)
if(!available_players.len)
WARNING("We've gone through all available players, there's nobody to make an antag!")
warning("ran out of available players to fill role [R]!")
break
shuffle(available_players)
var/datum/role/newRole = createBasicRole(R)
. += newRole // Get the roles we created
if(!newRole)
WARNING("Role killed itself or was otherwise missing!")
return 0
var/mob/new_player/P = pick(available_players)
available_players.Remove(P)
if(!newRole.AssignToRole(P.mind))
newRole.Drop()
if(!CreateRole(R, P))
i--
continue
number_of_roles++ // Get the roles we created
return number_of_roles
/datum/gamemode/proc/createBasicRole(var/type_role)
/datum/gamemode/proc/CreateBasicRole(var/type_role)
return new type_role
/datum/gamemode/proc/FilterAvailablePlayers(var/datum/role/R, var/list/players_to_choose = get_ready_players())
for(var/mob/new_player/P in players_to_choose)
if(!P.client || !P.mind)
players_to_choose.Remove(P)
continue
if(!P.client.desires_role(initial(R.required_pref)) || jobban_isbanned(P, initial(R.required_pref)))
players_to_choose.Remove(P)
continue
if(!players_to_choose.len)
warning("No available players for [R]")
return players_to_choose
/datum/gamemode/proc/CreateRole(var/datum/role/R, var/mob/P)
var/datum/role/newRole = CreateBasicRole(R)
if(!newRole)
warning("Role killed itself or was otherwise missing!")
return 0
if(!newRole.AssignToRole(P.mind))
warning("Role refused mind and dropped!")
newRole.Drop()
return 0
return 1
/datum/gamemode/proc/latespawn(var/mob/mob) //Check factions, see if anyone wants a latejoiner
var/list/possible_factions = list()

View File

@@ -1,9 +1,10 @@
var/global/list/mixed_allowed = list(
"autotraitor",
"changeling",
"cult",
"vampire",
"wizard",
var/list/mixed_factions_allowed = list(
typesof(/datum/faction/wizard,
/datum/faction/syndicate/traitor),
)
var/list/mixed_roles_allowed = list(
/datum/role/vampire = 1,
/datum/role/changeling = 2,
)
/datum/gamemode/mixed
@@ -11,7 +12,8 @@ var/global/list/mixed_allowed = list(
/datum/gamemode/mixed/SetupFactions()
factions_allowed = list(subtypesof(/datum/faction))
factions_allowed = mixed_factions_allowed
roles_allowed = mixed_roles_allowed
/datum/gamemode/mixed/traitorchan
@@ -19,14 +21,14 @@ var/global/list/mixed_allowed = list(
/datum/gamemode/mixed/traitorchan/SetupFactions()
factions_allowed = list(typesof(/datum/faction/syndicate/traitor) + /datum/faction/changeling)
factions_allowed = list(typesof(/datum/faction/syndicate/traitor))
roles_allowed = list(/datum/role/changeling)
/datum/gamemode/mixed/simple
name = "Simple Mixed"
/datum/gamemode/mixed/simple/SetupFactions()
factions_allowed = list(typesof(/datum/faction/syndicate/traitor) + /datum/faction/vampire + /datum/faction/changeling)
factions_allowed = list(typesof(/datum/faction/syndicate/traitor))
roles_allowed = list(/datum/role/changeling, /datum/faction/vampire)
//would the easiest way to handle these be to just create the other gamemodes and let their code run, as opposed to adding their specific terms for faction creation again here?

View File

@@ -1,15 +0,0 @@
/datum/objective/protect_master
var/datum/role/master
explanation_text = "Protect and serve your master at all costs."
name = "Protect your master"
/datum/objective/protect_master/New(var/list/arguments)
var/datum/role/master = arguments["master"]
if (istype(master))
src.master = master
/datum/objective/protect_master/IsFulfilled()
..()
if (master.antag.current.isDead())
return FALSE
return TRUE

View File

@@ -1,6 +1,7 @@
/datum/role/revolutionary
name = REV
id = REV
restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Mobile MMI","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer", "Internal Affairs Agent")
logo_state = "rev-logo"
/datum/role/revolutionary/Greet(var/greeting,var/custom)

View File

@@ -152,7 +152,7 @@
if(antag)
RemoveFromRole(antag)
del(src)
qdel(src)
// Scaling, should fuck with min/max players.
// Return 1 on success, 0 on failure.
@@ -172,8 +172,11 @@
return 0
if(required_jobs.len>0)
if(!M.assigned_role in required_jobs)
if(!(M.assigned_role in required_jobs))
return 0
if(is_type_in_list(src, M.antag_roles)) //No double double agent agent
return 0
return 1
// General sanity checks before assigning host.
@@ -212,14 +215,14 @@
/datum/role/proc/ForgeObjectives()
return
/datum/role/proc/AppendObjective(var/objective_type,var/duplicates=0, var/list/arguments = null)
/datum/role/proc/AppendObjective(var/objective_type,var/duplicates=0)
if(!duplicates && locate(objective_type) in objectives)
return FALSE
var/datum/objective/O
if(arguments)
O = new objective_type(arguments)
if(istype(objective_type, /datum/objective)) //Passed an actual objective
O = objective_type
else
O = new objective_type()
O = new objective_type
if(O.PostAppend())
objectives.AddObjective(O, antag)
return TRUE
@@ -239,7 +242,7 @@
return {"[show_logo ? "<img src='data:image/png;base64,[icon2base64(logo)]' style='position: relative; top: 10;'/> " : "" ]
[name] <a href='?_src_=holder;adminplayeropts=\ref[M]'>[M.real_name]/[M.key]</a>[M.client ? "" : " <i> - (logged out)</i>"][M.stat == DEAD ? " <b><font color=red> - (DEAD)</font></b>" : ""]
- <a href='?src=\ref[usr];priv_msg=\ref[M]'>(priv msg)</a>
- <a href='?_src_=holder;traitor=\ref[M]'>(role panel)</a>"}
- <a href='?_src_=holder;traitor=\ref[M]'>(role panel)</a><br>"}
/datum/role/proc/Greet(var/greeting,var/custom)
if(!greeting)
@@ -297,7 +300,7 @@
text += "<br/><font color='red'><B>\The [name] has failed.</B></font>"
feedback_add_details("[id]_success","FAIL")
to_chat(world, text)
return text
/datum/role/proc/extraPanelButtons()
var/dat = ""
@@ -373,7 +376,7 @@
"}
*/
/datum/role/proc/GetScoreboard()
//If you've gotten here to find what the hell this proc is for, you've hit a dead end. We don't know either.
return Declare()
// DO NOT OVERRIDE
/datum/role/Topic(href, href_list)

View File

@@ -132,4 +132,5 @@
/datum/role/nuclear_operative
name = NUKE_OP
id = NUKE_OP
disallow_job = TRUE
logo_state = "nuke-logo"

View File

@@ -30,8 +30,12 @@
/datum/role/vampire/New(var/datum/mind/M, var/datum/faction/fac=null, var/new_id, var/override = FALSE)
..()
if (istype(fac, /datum/faction/vampire))
var/datum/faction/vampire/vamp_fac = fac
var/datum/faction/vampire/vamp_fac
if(!fac)
vamp_fac = new
vamp_fac.addMaster(src)
else if (istype(fac, /datum/faction/vampire))
vamp_fac = fac
vamp_fac.addMaster(src)
wikiroute = role_wiki[ROLE_VAMPIRE]
@@ -448,10 +452,9 @@
antag.current << sound('sound/effects/vampire_intro.ogg')
/datum/role/thrall/ForgeObjectives()
var/list/parameters = list(
"master" = master
)
AppendObjective(/datum/objective/protect_master, arguments = parameters)
var/datum/objective/target/protect/P = new(auto_target = FALSE)
P.set_target(master.antag)
AppendObjective(P)
/datum/role/thrall/Drop(var/deconverted = FALSE)

View File

@@ -1,38 +1,7 @@
/datum/gamemode/vampire
minimum_player_count = 10
name = "Vampire"
factions_allowed = list(/datum/faction/vampire)
roles_allowed = 1 // Per factions
var/number_of_vamps
/datum/gamemode/vampire/CreateFactions()
number_of_vamps = max(1, round(get_player_count()/10))
for (var/i = 1 to number_of_vamps)
. += CreateFaction(/datum/faction/vampire)
/datum/gamemode/vampire/CreateRoles()
var/list/datum/role/vampire/vampires = list()
vampires = CreateNumOfRoles(/datum/role/vampire, number_of_vamps)
if (!vampires)
WARNING("Unable to create enough roles!")
return FALSE
for (var/i = 1 to number_of_vamps)
var/datum/faction/vampire/v_fac = factions[i]
if (istype(v_fac))
v_fac.addMaster(vampires[i])
v_fac.name = "Vampire force #[i]"
return vampires
/datum/gamemode/vampire/createBasicRole(var/type_role)
for (var/datum/faction/F in factions)
if (!F.members.len) // First empty fac
return new type_role(fac = F)
/datum/gamemode/vampire/PopulateFactions()
// Void - we do that in CreateRoles()
roles_allowed = list(/datum/role/vampire = 1)
// -- Vampire powers

View File

@@ -3,4 +3,5 @@
factions_allowed = list(/datum/faction/wizard)
/datum/gamemode/wizard/ragin
name = "Ragin' Mages"
name = "Ragin' Mages"
factions_allowed = list(/datum/faction/wizard/ragin)

View File

@@ -145,6 +145,7 @@ var/datum/controller/gameticker/ticker
return 0
//Configure mode and assign player to special mode stuff
job_master.DivideOccupations() //Distribute jobs
var/can_continue = src.mode.Setup()//Setup special modes
if(!can_continue)
current_state = GAME_STATE_PREGAME
@@ -162,7 +163,6 @@ var/datum/controller/gameticker/ticker
modes = sortList(modes)
to_chat(world, "<B>The current game mode is - Secret!</B>")
to_chat(world, "<B>Possibilities:</B> [english_list(modes)]")
job_master.DivideOccupations() //Distribute jobs
init_PDAgames_leaderboard()
create_characters() //Create player characters and transfer them
collect_minds()
@@ -363,6 +363,7 @@ var/datum/controller/gameticker/ticker
/datum/controller/gameticker/proc/equip_characters()
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
to_chat(world, "[player] has assigned_role [player.mind.assigned_role]")
if(player && player.mind && player.mind.assigned_role)
if(player.mind.assigned_role == "Captain")
captainless=0

View File

@@ -1458,7 +1458,7 @@
.(href, list("c_mode"=1))
else
var/list/possible = list()
possible += mixed_allowed
possible += mixed_factions_allowed
possible += "DONE"
possible += "CANCEL"
if(possible.len < 3)
@@ -1504,7 +1504,7 @@
.(href, list("f_secret"=1))
else
var/list/possible = list()
possible += mixed_allowed
possible += mixed_factions_allowed
possible += "DONE"
possible += "CANCEL"
if(possible.len < 3)

View File

@@ -305,7 +305,6 @@
#include "code\datums\gamemode\objectives\minimize_casualties.dm"
#include "code\datums\gamemode\objectives\nuclear.dm"
#include "code\datums\gamemode\objectives\objective.dm"
#include "code\datums\gamemode\objectives\protect_master.dm"
#include "code\datums\gamemode\objectives\silence.dm"
#include "code\datums\gamemode\objectives\survive.dm"
#include "code\datums\gamemode\objectives\survive_silicon.dm"