diff --git a/SQL/beestation_schema.sql b/SQL/beestation_schema.sql index 632d928b17a..ea6af3a19df 100644 --- a/SQL/beestation_schema.sql +++ b/SQL/beestation_schema.sql @@ -122,6 +122,7 @@ CREATE TABLE IF NOT EXISTS `SS13_characters` ( `general_record` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_general_ci', `security_record` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_general_ci', `medical_record` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_general_ci', + `role_preferences` MEDIUMTEXT NOT NULL COLLATE 'utf8mb4_general_ci', PRIMARY KEY (`slot`, `ckey`) USING BTREE ) COLLATE='utf8mb4_general_ci' ENGINE=InnoDB; diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 6620df43f48..93f62654284 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -76,6 +76,11 @@ #define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic)) #define IS_HERETIC_MONSTER(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic_monster)) +#define FACTION_SYNDICATE "Syndicate" +#define FACTION_BLOB "Blob" +#define FACTION_ALIEN "Xenomorph" +#define FACTION_WIZARD "Wizard" + #define PATH_SIDE "Side" #define PATH_ASH "Ash" diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 003ccf3e3db..7fc49bbf376 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -6,7 +6,7 @@ #define PREFTOGGLE_SOUND_LOBBY (1<<3) #define PREFTOGGLE_MEMBER_PUBLIC (1<<4) #define PREFTOGGLE_INTENT_STYLE (1<<5) -#define PREFTOGGLE_MIDROUND_ANTAG (1<<6) +//#define PREFTOGGLE_MIDROUND_ANTAG (1<<6) #define PREFTOGGLE_SOUND_INSTRUMENTS (1<<7) #define PREFTOGGLE_SOUND_SHIP_AMBIENCE (1<<8) #define PREFTOGGLE_SOUND_PRAYERS (1<<9) @@ -27,7 +27,7 @@ #define PREFTOGGLE_RUNECHAT_NONMOBS (1<<22) #define PREFTOGGLE_RUNECHAT_EMOTES (1<<23) -#define TOGGLES_DEFAULT (PREFTOGGLE_SOUND_ADMINHELP|PREFTOGGLE_SOUND_MIDI|PREFTOGGLE_SOUND_AMBIENCE|PREFTOGGLE_SOUND_LOBBY|PREFTOGGLE_MEMBER_PUBLIC|PREFTOGGLE_INTENT_STYLE|PREFTOGGLE_MIDROUND_ANTAG|PREFTOGGLE_SOUND_INSTRUMENTS|PREFTOGGLE_SOUND_SHIP_AMBIENCE|PREFTOGGLE_SOUND_PRAYERS|PREFTOGGLE_SOUND_ANNOUNCEMENTS|PREFTOGGLE_OUTLINE_ENABLED|PREFTOGGLE_RUNECHAT_GLOBAL|PREFTOGGLE_RUNECHAT_NONMOBS|PREFTOGGLE_RUNECHAT_EMOTES) +#define TOGGLES_DEFAULT (PREFTOGGLE_SOUND_ADMINHELP|PREFTOGGLE_SOUND_MIDI|PREFTOGGLE_SOUND_AMBIENCE|PREFTOGGLE_SOUND_LOBBY|PREFTOGGLE_MEMBER_PUBLIC|PREFTOGGLE_INTENT_STYLE|PREFTOGGLE_SOUND_INSTRUMENTS|PREFTOGGLE_SOUND_SHIP_AMBIENCE|PREFTOGGLE_SOUND_PRAYERS|PREFTOGGLE_SOUND_ANNOUNCEMENTS|PREFTOGGLE_OUTLINE_ENABLED|PREFTOGGLE_RUNECHAT_GLOBAL|PREFTOGGLE_RUNECHAT_NONMOBS|PREFTOGGLE_RUNECHAT_EMOTES) // You CANNOT go above 1<<23 in BYOND due to integer limits // Please add subsequent ones as PREFTOGGLE_2_[name] @@ -183,7 +183,7 @@ #define PREFERENCE_TAG_PDA_COLOUR "23" #define PREFERENCE_TAG_KEYBINDS "24" #define PREFERENCE_TAG_PURCHASED_GEAR "25" -#define PREFERENCE_TAG_BE_SPECIAL "26" +#define PREFERENCE_TAG_ROLE_PREFERENCES "26" #define PREFERENCE_TAG_PREFERRED_SYNDIE_ROLE "27" //NSV13 - syndicate crew role // True value of max save slots (3 is default, 8 is byond member, +1 to either if you have the extra slot loadout entry). Potential max is 9 diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index c5ba51036ad..c1da00441f8 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -4,21 +4,21 @@ +// Banning snowflake - global antag ban. Does not include ghost roles that aren't antagonists or forced antagonists +#define BAN_ROLE_ALL_ANTAGONISTS "All Antagonists" + //These are synced with the Database, if you change the values of the defines //then you MUST update the database! -#define ROLE_SYNDICATE "Syndicate" #define ROLE_TRAITOR "Traitor" -#define ROLE_OPERATIVE "Operative" +#define ROLE_OPERATIVE "Nuclear Operative" #define ROLE_CHANGELING "Changeling" #define ROLE_WIZARD "Wizard" -#define ROLE_MALF "Malf AI" +//#define ROLE_MALF "Malf AI" // Currently under traitor datum, so we can't have this separate. #define ROLE_INCURSION "Incursion Team" #define ROLE_EXCOMM "Excommunicated Syndicate Agent" #define ROLE_REV "Revolutionary" #define ROLE_REV_HEAD "Head Revolutionary" -#define ROLE_REV_SUCCESSFUL "Victorious Revolutionary" #define ROLE_ALIEN "Xenomorph" -#define ROLE_PAI "pAI" #define ROLE_CULTIST "Cultist" #define ROLE_SERVANT_OF_RATVAR "Servant of Ratvar" #define ROLE_HERETIC "Heretic" @@ -28,66 +28,222 @@ #define ROLE_REVENANT "Revenant" #define ROLE_DEVIL "Devil" #define ROLE_BROTHER "Blood Brother" -#define ROLE_BRAINWASHED "Brainwashed Victim" #define ROLE_OVERTHROW "Syndicate Mutineer" #define ROLE_HIVE "Hivemind Host" -#define ROLE_HIVE_VESSEL "Awakened Vessel" #define ROLE_OBSESSED "Obsessed" -#define ROLE_SENTIENCE "Sentience Potion Spawn" -#define ROLE_MIND_TRANSFER "Mind Transfer Potion" -#define ROLE_POSIBRAIN "Posibrain" -#define ROLE_DRONE "Drone" -#define ROLE_DEATHSQUAD "Deathsquad" -#define ROLE_LAVALAND "Lavaland" +#define ROLE_SPACE_DRAGON "Space Dragon" #define ROLE_INTERNAL_AFFAIRS "Internal Affairs Agent" #define ROLE_GANG "Gangster" #define ROLE_HOLOPARASITE "Holoparasite" #define ROLE_TERATOMA "Teratoma" - +#define ROLE_MORPH "Morph" +#define ROLE_NIGHTMARE "Nightmare" +#define ROLE_SPACE_PIRATE "Space Pirate" +#define ROLE_FUGITIVE "Fugitive" +#define ROLE_FUGITIVE_HUNTER "Fugitive Hunter" #define ROLE_SYNDI_CREW "Syndicate crew" //Nsv13 - added pvp role #define ROLE_BLOODLING "Bloodling" //Nsv13 - Bloodling #define ROLE_GHOSTSHIP "Ghost Ship" //NSV13 - Playable "NPC" ships -#define ROLE_EXPERIMENTAL_CLONE "Experimental Clone" +#define ROLE_SLAUGHTER_DEMON "Slaughter Demon" +#define ROLE_CONTRACTOR_SUPPORT_UNIT "Contractor Support Unit" +#define ROLE_PYRO_SLIME "Pyroclastic Anomaly Slime" -//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. -//The gamemode specific ones are just so the gamemodes can query whether a player is old enough -//(in game days played) to play that role -GLOBAL_LIST_INIT(special_roles, list( - ROLE_TRAITOR = /datum/game_mode/traitor, - ROLE_BROTHER = /datum/game_mode/traitor/bros, - ROLE_INCURSION = /datum/game_mode/incursion, - ROLE_EXCOMM = /datum/game_mode/incursion, - ROLE_OPERATIVE = /datum/game_mode/nuclear, - ROLE_CHANGELING = /datum/game_mode/changeling, - ROLE_WIZARD = /datum/game_mode/wizard, - ROLE_MALF, - ROLE_REV = /datum/game_mode/revolution, +/// Roles that are antagonists, roundstart or not, and have passes to do.. antagonistry +GLOBAL_LIST_INIT(antagonist_bannable_roles, list( + ROLE_TRAITOR, + ROLE_OPERATIVE, + ROLE_CHANGELING, + ROLE_WIZARD, +// ROLE_MALF, + ROLE_INCURSION, + ROLE_EXCOMM, + ROLE_REV, + ROLE_REV_HEAD, ROLE_ALIEN, - ROLE_PAI, - ROLE_CULTIST = /datum/game_mode/cult, - ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockcult, + ROLE_CULTIST, + ROLE_SERVANT_OF_RATVAR, + ROLE_HERETIC, ROLE_BLOB, ROLE_NINJA, - ROLE_OBSESSED, - ROLE_REVENANT, ROLE_ABDUCTOR, - ROLE_DEVIL = /datum/game_mode/devil, - ROLE_OVERTHROW = /datum/game_mode/overthrow, - ROLE_HIVE = /datum/game_mode/hivemind, - ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs, - ROLE_SENTIENCE, - ROLE_GANG = /datum/game_mode/gang, + ROLE_REVENANT, + ROLE_DEVIL, + ROLE_BROTHER, + ROLE_OVERTHROW, + ROLE_HIVE, + ROLE_OBSESSED, + ROLE_SPACE_DRAGON, + ROLE_INTERNAL_AFFAIRS, + ROLE_GANG, ROLE_HOLOPARASITE, - ROLE_HERETIC = /datum/game_mode/heretics, - ROLE_SYNDI_CREW = /datum/game_mode/pvp, //NSV13 - ROLE_BLOODLING = /datum/game_mode/bloodling, //NSV13 + ROLE_MORPH, + ROLE_NIGHTMARE, + ROLE_SPACE_PIRATE, + ROLE_SYNDI_CREW, //NSV13 + ROLE_BLOODLING, //NSV13 ROLE_GHOSTSHIP, //NSV13 - ROLE_TERATOMA + ROLE_TERATOMA, + ROLE_FUGITIVE, + ROLE_FUGITIVE_HUNTER, + ROLE_SLAUGHTER_DEMON, + ROLE_CONTRACTOR_SUPPORT_UNIT, )) //nsv13 - pvp + bloodling modes added here +#define BAN_ROLE_FORCED_ANTAGONISTS "Forced Antagonists" + +#define ROLE_BRAINWASHED "Brainwashed Victim" +#define ROLE_HYPNOTIZED "Hypnotized Victim" +#define ROLE_HIVE_VESSEL "Awakened Vessel" + +/// Forced antagonist roles +GLOBAL_LIST_INIT(forced_bannable_roles, list( + ROLE_BRAINWASHED, + ROLE_HYPNOTIZED, + ROLE_HIVE_VESSEL, +)) + +#define BAN_ROLE_ALL_GHOST "Non-Antagonist Ghost Roles" + +#define ROLE_PAI "pAI" +#define ROLE_POSIBRAIN "Posibrain" +#define ROLE_DRONE "Drone" +#define ROLE_SENTIENCE "Sentience Potion Spawn" +#define ROLE_EXPERIMENTAL_CLONE "Experimental Clone" +#define ROLE_LAVALAND_ELITE "Lavaland Elite" +#define ROLE_SPECTRAL_BLADE "Spectral Blade" +#define ROLE_ASHWALKER "Ashwalker" +#define ROLE_LIFEBRINGER "Lifebringer" +#define ROLE_FREE_GOLEM "Free Golem" +#define ROLE_HERMIT "Hermit" +#define ROLE_TRANSLOCATED_VET "Translocated Vet" +#define ROLE_LAVALAND_ESCAPED_PRISONER "Lavaland Escaped Prisoner" +#define ROLE_BEACH_BUM "Beach Bum" +#define ROLE_HOTEL_STAFF "Hotel Staff" +#define ROLE_LAVALAND_SYNDICATE "Lavaland Syndicate" +#define ROLE_DEMONIC_FRIEND "Demonic Friend" +#define ROLE_ANCIENT_CREW "Ancient Crew" +#define ROLE_SKELETAL_REMAINS "Skeletal Remains" +#define ROLE_SENTIENT_ANIMAL "Sentient Animal" +#define ROLE_HOLY_SUMMONED "Holy Summoned" +#define ROLE_SURVIVALIST "Exploration Survivalist" +#define ROLE_EXPLORATION_VIP "Exploration VIP" +#define ROLE_SENTIENT_XENOARTIFACT "Sentient Xenoartifiact" + +/// Any ghost role that is not really an antagonist or doesn't antagonize (lavaland, sentience potion, etc) +GLOBAL_LIST_INIT(ghost_role_bannable_roles, list( + ROLE_PAI, + ROLE_POSIBRAIN, + ROLE_DRONE, + ROLE_SENTIENCE, + ROLE_EXPERIMENTAL_CLONE, + ROLE_LAVALAND_ELITE, + ROLE_SPECTRAL_BLADE, + ROLE_ASHWALKER, + ROLE_LIFEBRINGER, + ROLE_FREE_GOLEM, + ROLE_HERMIT, + ROLE_TRANSLOCATED_VET, + ROLE_LAVALAND_ESCAPED_PRISONER, + ROLE_BEACH_BUM, + ROLE_HOTEL_STAFF, + ROLE_LAVALAND_SYNDICATE, + ROLE_DEMONIC_FRIEND, + ROLE_ANCIENT_CREW, + ROLE_SKELETAL_REMAINS, + ROLE_SENTIENT_ANIMAL, + ROLE_HOLY_SUMMONED, +)) + +#define ROLE_IMAGINARY_FRIEND "Imaginary Friend" +#define ROLE_SPLIT_PERSONALITY "Split Personality" +#define ROLE_MIND_TRANSFER "Mind Transfer Potion" +#define ROLE_ERT "Emergency Response Team" + +/// Other roles that don't really fit any of the above, and probably shouldn't be banned with the others as a group +/// Little to no impact on anything +GLOBAL_LIST_INIT(other_bannable_roles, list( + ROLE_IMAGINARY_FRIEND, + ROLE_SPLIT_PERSONALITY, + ROLE_MIND_TRANSFER, + ROLE_ERT, +)) + +/// Do not ban this role. Oh my god. Please. +#define UNBANNABLE_ANTAGONIST "Unbannable" + +/client/proc/role_preference_enabled(role_preference_key) + if(!ispath(role_preference_key, /datum/role_preference)) + CRASH("Invalid role_preference_key [role_preference_key] passed to role_preference_enabled!") + if(!src.prefs) + return FALSE + var/list/source = src.prefs.role_preferences + var/datum/role_preference/pref = role_preference_key + if(initial(pref.per_character)) + source = src.prefs.active_character.role_preferences_character + var/role_preference_value = source["[role_preference_key]"] + if(isnum(role_preference_value) && !role_preference_value) // explicitly disabled and not null + return FALSE + return TRUE + +/// If the client given is fit for a given role based on the arguments passed +/// banning_key: ROLE_X used for this role - to check if the player is banned. +/// role_preference_key: The /datum/role_preference typepath to check if the player has the role enabled and would like to receive the poll. +/// poll_ignore_key: The POLL_IGNORE_X define for this role, used for temporarily disabling ghost polls for high volume roles. +/// req_hours: The amount of living hours required to receive this role. +/// feedback: if we should send a to_chat +/client/proc/should_include_for_role(banning_key = BAN_ROLE_ALL_ANTAGONISTS, role_preference_key = null, poll_ignore_key = null, req_hours = 0, feedback = FALSE) + if(QDELETED(src) || (poll_ignore_key && GLOB.poll_ignore[poll_ignore_key] && (src.ckey in GLOB.poll_ignore[poll_ignore_key]))) + return FALSE + if(role_preference_key) + if(!ispath(role_preference_key, /datum/role_preference)) + CRASH("Invalid role_preference_key [role_preference_key] passed to should_include_for_role!") + if(!src.role_preference_enabled(role_preference_key)) + return FALSE + if(banning_key) + if(is_banned_from(src.ckey, banning_key)) + if(feedback) + to_chat(src, "You are banned from this role!") + return FALSE + if(req_hours) //minimum living hour count + if((src.get_exp_living(TRUE)/60) < req_hours) + if(feedback) + to_chat(src, "You do not have enough living hours to take this role ([req_hours]hrs required)!") + return FALSE + return TRUE + +/client/proc/can_take_ghost_spawner(banning_key = BAN_ROLE_ALL_ANTAGONISTS, use_cooldown = TRUE, is_ghost_role = FALSE, is_admin_spawned = FALSE) + if(!istype(src)) + return FALSE + if(is_ghost_role && !(GLOB.ghost_role_flags & GHOSTROLE_SPAWNER) && !is_admin_spawned) + to_chat(src, "An admin has temporarily disabled non-admin ghost roles!") + return FALSE + if(!src.should_include_for_role( + banning_key = banning_key, + feedback = TRUE + )) + return FALSE + if(use_cooldown && src.next_ghost_role_tick > world.time) + to_chat(src, "You have died recently, you must wait [(src.next_ghost_role_tick - world.time)/10] seconds until you can use a ghost spawner.") + return FALSE + return TRUE + //Job defines for what happens when you fail to qualify for any job during job selection #define BEOVERFLOW 1 #define BERANDOMJOB 2 #define RETURNTOLOBBY 3 + +#define ROLE_PREFERENCE_CATEGORY_ANAGONIST "Antagonists" +#define ROLE_PREFERENCE_CATEGORY_MIDROUND_LIVING "Midrounds (Living)" +#define ROLE_PREFERENCE_CATEGORY_MIDROUND_GHOST "Midrounds (Ghost Poll)" + +GLOBAL_LIST_INIT(role_preference_entries, init_role_preference_entries()) + +/proc/init_role_preference_entries() + var/list/output = list() + for (var/datum/role_preference/preference_type as anything in subtypesof(/datum/role_preference)) + if (initial(preference_type.abstract_type) == preference_type) + continue + output[preference_type] = new preference_type + return output diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index dae5cf88e73..89c70e94cc6 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -425,7 +425,7 @@ else candidates -= M -/proc/pollGhostCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, req_hours = 0) +/proc/pollGhostCandidates(Question, jobbanType, role_preference_key, poll_time = 300, ignore_category = null, flashwindow = TRUE, req_hours = 0) var/list/candidates = list() if(!(GLOB.ghost_role_flags & GHOSTROLE_STATION_SENTIENCE)) return candidates @@ -433,31 +433,30 @@ for(var/mob/dead/observer/G in GLOB.player_list) candidates += G - return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates, req_hours) + return pollCandidates(Question, jobbanType, role_preference_key, poll_time, ignore_category, flashwindow, candidates, req_hours) -/proc/pollCandidates(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null, req_hours = 0) +/proc/pollCandidates(Question, banning_key, role_preference_key = null, poll_time = 300, poll_ignore_key = null, flashwindow = TRUE, list/group = null, req_hours = 0) var/time_passed = world.time if (!Question) Question = "Would you like to be a special role?" + if(isnull(poll_ignore_key)) // FALSE will not put one, no matter what + if(role_preference_key) + poll_ignore_key = "role_[role_preference_key]" + else if(banning_key) + poll_ignore_key = "ban_[role_preference_key]" var/list/result = list() for(var/m in group) var/mob/M = m - if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && (M.ckey in GLOB.poll_ignore[ignore_category]))) + if(QDELETED(M) || !M.key || !M.client) continue - if(be_special_flag) - if(!(M.client.prefs) || !(be_special_flag in M.client.prefs.be_special)) - continue - if(gametypeCheck) - if(!gametypeCheck.age_check(M.client)) - continue - if(jobbanType) - if(QDELETED(M) || is_banned_from(M.ckey, list(jobbanType, ROLE_SYNDICATE))) - continue - if(req_hours) //minimum living hour count - if((M.client.get_exp_living(TRUE)/60) < req_hours) - continue - - showCandidatePollWindow(M, poll_time, Question, result, ignore_category, time_passed, flashwindow) + if(!M.client.should_include_for_role( + banning_key = banning_key, + role_preference_key = role_preference_key, + poll_ignore_key = poll_ignore_key, + req_hours = req_hours + )) + continue + showCandidatePollWindow(M, poll_time, Question, result, poll_ignore_key, time_passed, flashwindow) sleep(poll_time) //Check all our candidates, to make sure they didn't log off or get deleted during the wait period. @@ -469,14 +468,14 @@ return result -/proc/pollCandidatesForMob(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, mob/M, ignore_category = null) - var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) +/proc/pollCandidatesForMob(Question, jobbanType, role_preference_key, poll_time = 300, mob/M, ignore_category = null) + var/list/L = pollGhostCandidates(Question, jobbanType, role_preference_key, poll_time, ignore_category) if(QDELETED(M) || !M.loc) return list() return L -/proc/pollCandidatesForMobs(Question, jobbanType, datum/game_mode/gametypeCheck, be_special_flag = 0, poll_time = 300, list/mobs, ignore_category = null) - var/list/L = pollGhostCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category) +/proc/pollCandidatesForMobs(Question, jobbanType, role_preference_key, poll_time = 300, list/mobs, ignore_category = null) + var/list/L = pollGhostCandidates(Question, jobbanType, role_preference_key, poll_time, ignore_category) var/i=1 for(var/v in mobs) var/atom/A = v diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm index 6f15e22d270..1cca65374b0 100644 --- a/code/_globalvars/lists/poll_ignore.dm +++ b/code/_globalvars/lists/poll_ignore.dm @@ -1,57 +1,42 @@ //Each lists stores ckeys for "Never for this round" option category -#define POLL_IGNORE_SENTIENCE_POTION "sentience_potion" -#define POLL_IGNORE_POSSESSED_BLADE "possessed_blade" #define POLL_IGNORE_ALIEN_LARVA "alien_larva" -#define POLL_IGNORE_SYNDICATE "syndicate" -#define POLL_IGNORE_HOLOPARASITE "holoparasite" #define POLL_IGNORE_POSIBRAIN "posibrain" -#define POLL_IGNORE_SPECTRAL_BLADE "spectral_blade" -#define POLL_IGNORE_CONSTRUCT "construct" #define POLL_IGNORE_SPIDER "spider" #define POLL_IGNORE_ASHWALKER "ashwalker" +#define POLL_IGNORE_BLOB_HELPER "blob_helper" +#define POLL_IGNORE_CLOCKWORK_HELPER "clockwork_helper" +#define POLL_IGNORE_CULT_SHADE "cult_shade" #define POLL_IGNORE_GOLEM "golem" -#define POLL_IGNORE_SWARMER "swarmer" #define POLL_IGNORE_DRONE "drone" -#define POLL_IGNORE_FUGITIVE "fugitive" -#define POLL_IGNORE_DEFECTIVECLONE "defective_clone" -#define POLL_IGNORE_PYROSLIME "slime" +#define POLL_IGNORE_SWARMER "swarmer" +#define POLL_IGNORE_SPECTRAL_BLADE "spectral_blade" #define POLL_IGNORE_SHADE "shade" -#define POLL_IGNORE_IMAGINARYFRIEND "imaginary_friend" +#define POLL_IGNORE_FUGITIVE "fugitive" #define POLL_IGNORE_SPLITPERSONALITY "split_personality" -#define POLL_IGNORE_CONTRACTOR_SUPPORT "contractor_support" -#define POLL_IGNORE_CLOCKWORK "clockwork" #define POLL_IGNORE_GHOSTSHIP "ghost ships" //NSV13 -#define POLL_IGNORE_EXPERIMENTAL_CLONE "experimental_clone" +#define POLL_IGNORE_WIZARD_HELPER "wizard_helper" -GLOBAL_LIST_INIT(poll_ignore_desc, list( - POLL_IGNORE_SENTIENCE_POTION = "Sentience potion", - POLL_IGNORE_POSSESSED_BLADE = "Possessed blade", - POLL_IGNORE_ALIEN_LARVA = "Xenomorph larva", - POLL_IGNORE_SYNDICATE = "Syndicate", - POLL_IGNORE_HOLOPARASITE = "Holoparasite", - POLL_IGNORE_POSIBRAIN = "Positronic brain", - POLL_IGNORE_SPECTRAL_BLADE = "Spectral blade", - POLL_IGNORE_CONSTRUCT = "Construct", - POLL_IGNORE_SPIDER = "Spiders", - POLL_IGNORE_ASHWALKER = "Ashwalker eggs", - POLL_IGNORE_GOLEM = "Golems", - POLL_IGNORE_SWARMER = "Swarmer shells", - POLL_IGNORE_DRONE = "Drone shells", - POLL_IGNORE_FUGITIVE = "Fugitive Hunter", - POLL_IGNORE_DEFECTIVECLONE = "Defective clone", - POLL_IGNORE_PYROSLIME = "Slime", - POLL_IGNORE_SHADE = "Shade", - POLL_IGNORE_IMAGINARYFRIEND = "Imaginary Friend", - POLL_IGNORE_SPLITPERSONALITY = "Split Personality", - POLL_IGNORE_CONTRACTOR_SUPPORT = "Contractor Support Unit", - POLL_IGNORE_GHOSTSHIP = "Ghost Ship", //NSV13 - POLL_IGNORE_EXPERIMENTAL_CLONE = "Experimental clone" +GLOBAL_LIST_INIT(poll_ignore_list, list( + POLL_IGNORE_ALIEN_LARVA, + POLL_IGNORE_ASHWALKER, + POLL_IGNORE_BLOB_HELPER, + POLL_IGNORE_CLOCKWORK_HELPER, + POLL_IGNORE_CULT_SHADE, + POLL_IGNORE_GOLEM, + POLL_IGNORE_DRONE, + POLL_IGNORE_POSIBRAIN, + POLL_IGNORE_SPECTRAL_BLADE, + POLL_IGNORE_SHADE, + POLL_IGNORE_SPIDER, + POLL_IGNORE_GHOSTSHIP, //NSV13 + POLL_IGNORE_WIZARD_HELPER, )) + GLOBAL_LIST_INIT(poll_ignore, init_poll_ignore()) /proc/init_poll_ignore() . = list() - for (var/k in GLOB.poll_ignore_desc) + for (var/k in GLOB.poll_ignore_list) .[k] = list() diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index bd62bf9d98e..41a29447708 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -137,8 +137,8 @@ SUBSYSTEM_DEF(job) return FALSE job.current_positions = max(0, job.current_positions - 1) -/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level, flag) - JobDebug("Running FOC, Job: [job], Level: [level], Flag: [flag]") +/datum/controller/subsystem/job/proc/FindOccupationCandidates(datum/job/job, level) + JobDebug("Running FOC, Job: [job], Level: [level]") var/list/candidates = list() for(var/mob/dead/new_player/player in unassigned) if(QDELETED(player) || is_banned_from(player.ckey, job.title)) @@ -150,9 +150,6 @@ SUBSYSTEM_DEF(job) if(job.required_playtime_remaining(player.client)) JobDebug("FOC player not enough xp, Player: [player]") continue - if(flag && (!(flag in player.client.prefs.be_special))) - JobDebug("FOC flag failed, Player: [player], Flag: [flag], ") - continue if(player.mind && (job.title in player.mind.restricted_roles)) JobDebug("FOC incompatible with antagonist role, Player: [player]") continue diff --git a/code/controllers/subsystem/pai.dm b/code/controllers/subsystem/pai.dm index d942dda58bd..4fc3090979d 100644 --- a/code/controllers/subsystem/pai.dm +++ b/code/controllers/subsystem/pai.dm @@ -149,8 +149,10 @@ SUBSYSTEM_DEF(pai) for(var/mob/dead/observer/G in GLOB.player_list) if(!G.key || !G.client) continue - if(!(ROLE_PAI in G.client.prefs.be_special)) - continue + //NSV13 - Disabled until Beemerge, I don't know what to put here without porting from another PR so WEH + //if(!(ROLE_PAI in G.client.prefs.be_special)) + // continue + //NSV13 - Stop to_chat(G, "[user] is requesting a pAI personality! Use the pAI button to submit yourself as one.") addtimer(CALLBACK(src, PROC_REF(spam_again)), spam_delay) var/list/available = list() diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index b77bd799465..ad30ac75041 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -46,7 +46,7 @@ if(owner.stat == DEAD || !owner.mind) qdel(src) return - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend, POLL_IGNORE_IMAGINARYFRIEND) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_IMAGINARY_FRIEND, null, 7.5 SECONDS, friend) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) friend.key = C.key @@ -193,7 +193,7 @@ hearers += client if(owner_chat_map) hearers += owner.client - + var/rendered = "[name] [say_quote(message)]" var/dead_rendered = "[name] (Imaginary friend of [owner]) [say_quote(message)]" diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index b2ebc6c1899..c5a8a5fd4fd 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -31,7 +31,7 @@ if(owner.stat == DEAD || !owner.mind) qdel(src) return - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat, POLL_IGNORE_SPLITPERSONALITY) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_SPLIT_PERSONALITY, null, 7.5 SECONDS, stranger_backseat) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) stranger_backseat.key = C.key @@ -196,7 +196,7 @@ /datum/brain_trauma/severe/split_personality/brainwashing/get_ghost() set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s brainwashed mind?", null, null, null, 75, stranger_backseat) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s brainwashed mind?", ROLE_TRAITOR, null, 7.5 SECONDS, stranger_backseat, ignore_category = FALSE) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) stranger_backseat.key = C.key diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index b60bedb1a3e..218d0255411 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -80,10 +80,11 @@ /datum/disease/transformation/proc/replace_banned_player(var/mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed. set waitfor = FALSE + affected_mob.playable_bantype = bantype affected_mob.ghostize(TRUE,SENTIENCE_FORCE) to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, bantype, 50, affected_mob) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, 7.5 SECONDS, affected_mob, ignore_category = FALSE) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbanned player.") @@ -108,7 +109,7 @@ stage5 = list("Your skin feels as if it's about to burst off!") new_form = /mob/living/silicon/robot infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC) - bantype = "Cyborg" + bantype = JOB_NAME_CYBORG /datum/disease/transformation/robot/stage_act() ..() diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 6059dba2a14..2ba9c586359 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -27,7 +27,7 @@ if(CONFIG_GET(flag/protect_heads_from_antagonist)) restricted_jobs += GLOB.command_positions - var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER) + var/list/datum/mind/possible_brothers = get_players_for_role(/datum/antagonist/brother, /datum/role_preference/antagonist/blood_brother) var/num_teams = team_amount var/bsc = CONFIG_GET(number/brother_scaling_coeff) @@ -40,7 +40,7 @@ var/datum/team/brother_team/team = new var/team_size = prob(10) ? min(3, possible_brothers.len) : 2 for(var/k = 1 to team_size) - var/datum/mind/bro = antag_pick(possible_brothers, ROLE_BROTHER) + var/datum/mind/bro = antag_pick(possible_brothers, /datum/role_preference/antagonist/blood_brother) possible_brothers -= bro antag_candidates -= bro team.add_member(bro) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index 884e9025c74..49b9cdcf0c9 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -10,7 +10,8 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w name = "changeling" config_tag = "changeling" report_type = "changeling" - antag_flag = ROLE_CHANGELING + role_preference = /datum/role_preference/antagonist/changeling + antag_datum = /datum/antagonist/changeling false_report_weight = 10 restricted_jobs = list(JOB_NAME_AI, JOB_NAME_CYBORG) protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) @@ -52,7 +53,7 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w for(var/i = 0, i < num_changelings, i++) if(!antag_candidates.len) break - var/datum/mind/changeling = antag_pick(antag_candidates, ROLE_CHANGELING) + var/datum/mind/changeling = antag_pick(antag_candidates, /datum/role_preference/antagonist/changeling) antag_candidates -= changeling changelings += changeling changeling.special_role = ROLE_CHANGELING @@ -75,12 +76,14 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w if(changelings.len >= changelingcap) //Caps number of latejoin antagonists return if(changelings.len <= (changelingcap - 2) || prob(100 - (csc * 2))) - if(ROLE_CHANGELING in character.client.prefs.be_special) - if(!is_banned_from(character.ckey, list(ROLE_CHANGELING, ROLE_SYNDICATE)) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - character.mind.make_Changeling() - changelings += character.mind + if(!QDELETED(character) && character.client?.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime) + )) + if(!(character.job in restricted_jobs)) + character.mind.make_Changeling() + changelings += character.mind /datum/game_mode/changeling/generate_report() return "The Gorlex Marauders have announced the successful raid and destruction of Central Command containment ship #S-[rand(1111, 9999)]. This ship housed only a single prisoner - \ diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index 95057675495..6912af56cbf 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -22,7 +22,7 @@ /datum/game_mode/traitor/changeling/can_start() if(!..()) return 0 - possible_changelings = get_players_for_role(ROLE_CHANGELING) + possible_changelings = get_players_for_role(/datum/antagonist/changeling, /datum/role_preference/antagonist/changeling) if(possible_changelings.len < required_enemies) return 0 return 1 @@ -37,7 +37,7 @@ if(CONFIG_GET(flag/protect_heads_from_antagonist)) restricted_jobs += GLOB.command_positions - var/list/datum/mind/possible_changelings = get_players_for_role(ROLE_CHANGELING) + var/list/datum/mind/possible_changelings = get_players_for_role(/datum/antagonist/changeling, /datum/role_preference/antagonist/changeling) var/num_changelings = 1 @@ -51,7 +51,7 @@ for(var/j = 0, j < num_changelings, j++) if(!possible_changelings.len) break - var/datum/mind/changeling = antag_pick(possible_changelings, ROLE_CHANGELING) + var/datum/mind/changeling = antag_pick(possible_changelings, /datum/role_preference/antagonist/changeling) antag_candidates -= changeling possible_changelings -= changeling changeling.special_role = ROLE_CHANGELING @@ -72,13 +72,16 @@ if(changelings.len >= changelingcap) //Caps number of latejoin antagonists ..() return + var/datum/antagonist/aux_antag_datum = /datum/antagonist/changeling if(changelings.len <= (changelingcap - 2) || prob(100 / (csc * 4))) - if(ROLE_CHANGELING in character.client.prefs.be_special) - if(!is_banned_from(character.ckey, list(ROLE_CHANGELING, ROLE_SYNDICATE)) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - character.mind.make_Changeling() - changelings += character.mind + if(!QDELETED(character) && character.client.should_include_for_role( + banning_key = initial(aux_antag_datum.banning_key), + role_preference_key = /datum/role_preference/antagonist/changeling, + req_hours = initial(aux_antag_datum.required_living_playtime) + )) + if(!(character.job in restricted_jobs)) + character.mind.make_Changeling() + changelings += character.mind if(QDELETED(character)) return ..() diff --git a/code/game/gamemodes/clock_cult/clockcult.dm b/code/game/gamemodes/clock_cult/clockcult.dm index b31dd9e379c..af4f68b3bc8 100644 --- a/code/game/gamemodes/clock_cult/clockcult.dm +++ b/code/game/gamemodes/clock_cult/clockcult.dm @@ -32,8 +32,8 @@ GLOBAL_VAR(clockcult_eminence) required_players = 24 required_enemies = 4 recommended_enemies = 4 - antag_flag = ROLE_SERVANT_OF_RATVAR - enemy_minimum_age = 14 + role_preference = /datum/role_preference/antagonist/clock_cultist + antag_datum = /datum/antagonist/servant_of_ratvar title_icon = "clockcult" announce_span = "danger" @@ -58,7 +58,7 @@ GLOBAL_VAR(clockcult_eminence) for(var/i in 1 to clock_cultists) if(!antag_candidates.len) break - var/datum/mind/clockie = antag_pick(antag_candidates, ROLE_SERVANT_OF_RATVAR) + var/datum/mind/clockie = antag_pick(antag_candidates, /datum/role_preference/antagonist/clock_cultist) //In case antag_pick breaks if(!clockie) continue diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 7b2498f9263..1280a629674 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -36,14 +36,14 @@ name = "cult" config_tag = "cult" report_type = "cult" - antag_flag = ROLE_CULTIST + role_preference = /datum/role_preference/antagonist/blood_cultist + antag_datum = /datum/antagonist/cult false_report_weight = 1 restricted_jobs = list(JOB_NAME_CHAPLAIN,JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL) protected_jobs = list() required_players = 29 required_enemies = 4 recommended_enemies = 4 - enemy_minimum_age = 14 announce_span = "cult" announce_text = "Some crew members are trying to start a cult to Nar'Sie!\n\ @@ -84,7 +84,7 @@ for(var/cultists_number = 1 to recommended_enemies) if(!antag_candidates.len) break - var/datum/mind/cultist = antag_pick(antag_candidates, ROLE_CULTIST) + var/datum/mind/cultist = antag_pick(antag_candidates, /datum/role_preference/antagonist/blood_cultist) antag_candidates -= cultist if(!cultist) cultists_number-- diff --git a/code/game/gamemodes/devil/devil_game_mode.dm b/code/game/gamemodes/devil/devil_game_mode.dm index b7d0bbe7766..95b7ab5db67 100644 --- a/code/game/gamemodes/devil/devil_game_mode.dm +++ b/code/game/gamemodes/devil/devil_game_mode.dm @@ -2,14 +2,14 @@ name = "devil" config_tag = "devil" report_type = "devil" - antag_flag = ROLE_DEVIL + role_preference = /datum/role_preference/antagonist/devil + antag_datum = /datum/antagonist/devil false_report_weight = 1 protected_jobs = list(JOB_NAME_LAWYER, JOB_NAME_CURATOR, JOB_NAME_CHAPLAIN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE) required_players = 0 required_enemies = 1 recommended_enemies = 4 reroll_friendly = 1 - enemy_minimum_age = 0 title_icon = "devil" allowed_special = list(/datum/special_role/traitor) @@ -42,7 +42,7 @@ for(var/j = 0, j < num_devils, j++) if (!antag_candidates.len) break - var/datum/mind/devil = antag_pick(antag_candidates, ROLE_DEVIL) + var/datum/mind/devil = antag_pick(antag_candidates, /datum/role_preference/antagonist/devil) devils += devil devil.special_role = traitor_name devil.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 8e07f35c244..de004e48a54 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -699,15 +699,6 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) log_game("DYNAMIC: [src] passed lowpop_lowimpact requirement: ([living_antags_count] antags of [living_players_count] players - [antag_percent]%)") return FALSE -/// Checks if client age is age or older. -/datum/game_mode/dynamic/proc/check_age(client/C, age) - enemy_minimum_age = age - if(get_remaining_days(C) == 0) - enemy_minimum_age = initial(enemy_minimum_age) - return TRUE // Available in 0 days = available right now = player is old enough to play. - enemy_minimum_age = initial(enemy_minimum_age) - return FALSE - /datum/game_mode/dynamic/make_antag_chance(mob/living/carbon/human/newPlayer) if (GLOB.dynamic_forced_extended) return diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index 3179f32c974..54d038e1447 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -18,12 +18,10 @@ var/list/mob/candidates = list() /// List of players that were selected for this rule var/list/datum/mind/assigned = list() - /// Preferences flag such as ROLE_WIZARD that need to be turned on for players to be antag - var/antag_flag = null + /// The /datum/role_preference typepath used for this ruleset. + var/role_preference = null /// The antagonist datum that is assigned to the mobs mind on ruleset execution. var/datum/antagonist/antag_datum = null - /// The required minimum account age for this ruleset. - var/minimum_required_age = 7 /// If set, and config flag protect_roles_from_antagonist is false, then the rule will not pick players from these roles. var/list/protected_roles = list() /// If set, rule will deny candidates from those roles always. @@ -55,8 +53,6 @@ var/list/requirements = list(40,30,20,10,10,10,10,10,10,10) /// Reference to the mode, use this instead of SSticker.mode. var/datum/game_mode/dynamic/mode = null - /// If a role is to be considered another for the purpose of banning. - var/antag_flag_override = null /// If a ruleset type which is in this list has been executed, then the ruleset will not be executed. var/list/blocking_rules = list() /// The minimum amount of players required for the rule to be considered. @@ -213,19 +209,19 @@ var/client/client = GET_CLIENT(P) if (!client || !P.mind) // Are they connected? candidates.Remove(P) - else if(!mode.check_age(client, minimum_required_age)) + continue + + if(!client.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime) + )) candidates.Remove(P) continue + if(P.mind.special_role) // We really don't want to give antag to an antag. candidates.Remove(P) - else if(antag_flag_override) - if(!(antag_flag_override in client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag_override, ROLE_SYNDICATE))) - candidates.Remove(P) - continue - else - if(!(antag_flag in client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag, ROLE_SYNDICATE))) - candidates.Remove(P) - continue + continue /// Do your checks if the ruleset is ready to be executed here. /// Should ignore certain checks if forced is TRUE diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index 375d1163e56..74cf8577ef0 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -9,21 +9,15 @@ if (!P.client || !P.mind || !P.mind.assigned_role) // Are they connected? candidates.Remove(P) continue - if(!mode.check_age(P.client, minimum_required_age)) - candidates.Remove(P) - continue - if(antag_flag_override) - if(!(antag_flag_override in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag_override, ROLE_SYNDICATE))) - candidates.Remove(P) - continue - else - if(!(antag_flag in P.client.prefs.be_special) || is_banned_from(P.ckey, list(antag_flag, ROLE_SYNDICATE))) - candidates.Remove(P) - continue if (P.mind.assigned_role in restricted_roles) // Does their job allow for it? candidates.Remove(P) - continue - if ((exclusive_roles.len > 0) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job? + else if(length(exclusive_roles) && !(P.mind.assigned_role in exclusive_roles)) // Is the rule exclusive to their job? + candidates.Remove(P) + else if(!P.client.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime) + )) candidates.Remove(P) continue @@ -53,7 +47,7 @@ /datum/dynamic_ruleset/latejoin/execute() var/mob/M = pick(candidates) assigned += M.mind - M.mind.special_role = antag_flag + M.mind.special_role = initial(antag_datum.banning_key) M.mind.add_antag_datum(antag_datum) return TRUE @@ -66,7 +60,7 @@ /datum/dynamic_ruleset/latejoin/infiltrator name = "Syndicate Infiltrator" antag_datum = /datum/antagonist/traitor - antag_flag = ROLE_TRAITOR + role_preference = /datum/role_preference/antagonist/traitor protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL) restricted_roles = list(JOB_NAME_AI,JOB_NAME_CYBORG) required_candidates = 1 @@ -92,8 +86,7 @@ name = "Provocateur" persistent = TRUE antag_datum = /datum/antagonist/rev/head - antag_flag = ROLE_REV_HEAD - antag_flag_override = ROLE_REV + role_preference = /datum/role_preference/antagonist/revolutionary restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_CHIEFENGINEER, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_MASTERATARMS) //NSV13 - added MAA enemy_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER,JOB_NAME_DETECTIVE,JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_WARDEN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -125,7 +118,7 @@ var/mob/M = pick(candidates) // This should contain a single player, but in case. if(check_eligible(M.mind)) // Didnt die/run off z-level/get implanted since leaving shuttle. assigned += M.mind - M.mind.special_role = antag_flag + M.mind.special_role = ROLE_REV_HEAD revolution = new() var/datum/antagonist/rev/head/new_head = new() new_head.give_flash = TRUE @@ -168,7 +161,7 @@ /datum/dynamic_ruleset/latejoin/heretic_smuggler name = "Heretic Smuggler" antag_datum = /datum/antagonist/heretic - antag_flag = ROLE_HERETIC + role_preference = /datum/role_preference/antagonist/heretic protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_AI,JOB_NAME_CYBORG) required_candidates = 1 diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 9aa65b5b481..0c6c3579dd2 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -51,17 +51,14 @@ if (!M.client) // Are they connected? trimmed_list.Remove(M) continue - if(!mode.check_age(M.client, minimum_required_age)) + if(!M.client.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + poll_ignore_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime) + )) trimmed_list.Remove(M) continue - if(antag_flag_override) - if(!(antag_flag_override in M.client.prefs.be_special) || is_banned_from(M.ckey, list(antag_flag_override, ROLE_SYNDICATE))) - trimmed_list.Remove(M) - continue - else - if(!(antag_flag in M.client.prefs.be_special) || is_banned_from(M.ckey, list(antag_flag, ROLE_SYNDICATE))) - trimmed_list.Remove(M) - continue if (M.mind) if (restrict_ghost_roles && (M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role? trimmed_list.Remove(M) @@ -114,7 +111,7 @@ message_admins("Polling [possible_volunteers.len] players to apply for the [name] ruleset.") log_game("DYNAMIC: Polling [possible_volunteers.len] players to apply for the [name] ruleset.") - candidates = pollGhostCandidates("The mode is looking for volunteers to become [antag_flag] for [name]", antag_flag, SSticker.mode, antag_flag_override ? antag_flag_override : antag_flag, poll_time = 300) + candidates = pollGhostCandidates("The mode is looking for volunteers to become [initial(antag_datum.name)] for [name]", initial(antag_datum.banning_key), role_preference, poll_time = 300) if(!length(candidates)) message_admins("The ruleset [name] received no applications.") @@ -170,7 +167,7 @@ var/datum/antagonist/new_role = new antag_datum() setup_role(new_role) new_character.mind.add_antag_datum(new_role) - new_character.mind.special_role = antag_flag + new_character.mind.special_role = new_role.banning_key /datum/dynamic_ruleset/midround/from_ghosts/proc/setup_role(datum/antagonist/new_role) return @@ -185,7 +182,7 @@ name = "Syndicate Sleeper Agent" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/traitor - antag_flag = ROLE_TRAITOR + role_preference = /datum/role_preference/midround_living/traitor protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_CYBORG, JOB_NAME_AI, "Positronic Brain") required_candidates = 1 @@ -239,7 +236,7 @@ name = "Malfunctioning AI" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/traitor - antag_flag = ROLE_MALF + role_preference = /datum/role_preference/midround_living/malfunctioning_ai enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_SCIENTIST, JOB_NAME_CHEMIST, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFENGINEER) exclusive_roles = list(JOB_NAME_AI) required_enemies = list(4,4,4,4,4,4,2,2,2,0) @@ -274,7 +271,7 @@ var/mob/living/silicon/ai/M = pick_n_take(candidates) assigned += M.mind var/datum/antagonist/traitor/AI = new - M.mind.special_role = antag_flag + M.mind.special_role = "Malf AI" M.mind.add_antag_datum(AI) if(prob(ion_announce)) priority_announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", ANNOUNCER_IONSTORM) @@ -294,7 +291,7 @@ name = "Wizard" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/wizard - antag_flag = ROLE_WIZARD + role_preference = /datum/role_preference/midround_ghost/wizard enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_RESEARCHDIRECTOR) //RD doesn't believe in magic required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 @@ -325,7 +322,7 @@ /datum/dynamic_ruleset/midround/from_ghosts/nuclear name = "Nuclear Assault" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY - antag_flag = ROLE_OPERATIVE + role_preference = /datum/role_preference/midround_ghost/nuclear_operative antag_datum = /datum/antagonist/nukeop enemy_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(3,3,3,3,3,2,1,1,0,0) @@ -351,8 +348,8 @@ return ..() /datum/dynamic_ruleset/midround/from_ghosts/nuclear/finish_setup(mob/new_character, index) - new_character.mind.special_role = "Nuclear Operative" - new_character.mind.assigned_role = "Nuclear Operative" + new_character.mind.special_role = ROLE_OPERATIVE + new_character.mind.assigned_role = ROLE_OPERATIVE if (index == 1) // Our first guy is the leader var/datum/antagonist/nukeop/leader/new_role = new nuke_team = new_role.nuke_team @@ -370,7 +367,7 @@ name = "Blob" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/blob - antag_flag = ROLE_BLOB + role_preference = /datum/role_preference/midround_ghost/blob enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 @@ -394,7 +391,7 @@ name = "Alien Infestation" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY antag_datum = /datum/antagonist/xeno - antag_flag = ROLE_ALIEN + role_preference = /datum/role_preference/midround_ghost/xenomorph enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,2,1,1,1,1,0,0,0) required_candidates = 1 @@ -442,8 +439,7 @@ name = "Nightmare" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/nightmare - antag_flag = "Nightmare" - antag_flag_override = ROLE_ALIEN + role_preference = /datum/role_preference/midround_ghost/space_dragon enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 @@ -490,8 +486,7 @@ /datum/dynamic_ruleset/midround/from_ghosts/abductors name = "Abductors" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY - antag_flag = "Abductor" - antag_flag_override = ROLE_ABDUCTOR + role_preference = /datum/role_preference/midround_ghost/abductor enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 2 @@ -529,8 +524,7 @@ name = "Revenant" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/revenant - antag_flag = "Revenant" - antag_flag_override = ROLE_REVENANT + role_preference = /datum/role_preference/midround_ghost/revenant enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) required_candidates = 1 @@ -581,7 +575,7 @@ /datum/dynamic_ruleset/midround/pirates name = "Space Pirates" midround_ruleset_style = MIDROUND_RULESET_STYLE_HEAVY - antag_flag = "Space Pirates" + role_preference = /datum/role_preference/midround_ghost/space_pirate required_type = /mob/dead/observer enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -608,7 +602,7 @@ name = "Obsessed" midround_ruleset_style = MIDROUND_RULESET_STYLE_LIGHT antag_datum = /datum/antagonist/obsessed - antag_flag = ROLE_OBSESSED + role_preference = /datum/role_preference/midround_living/obsessed restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, "Positronic Brain") enemy_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_DETECTIVE, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) required_enemies = list(2,2,1,1,1,1,1,0,0,0) @@ -625,7 +619,6 @@ !candidate.getorgan(/obj/item/organ/brain) \ || candidate.mind.has_antag_datum(/datum/antagonist/obsessed) \ || candidate.stat == DEAD \ - || !(ROLE_OBSESSED in candidate.client?.prefs?.be_special) \ || !SSjob.GetJob(candidate.mind.assigned_role) \ || (candidate.mind.assigned_role in GLOB.nonhuman_positions) \ ) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index 569319b8cf8..fe384067216 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -7,9 +7,8 @@ /datum/dynamic_ruleset/roundstart/traitor name = "Traitors" - antag_flag = ROLE_TRAITOR + role_preference = /datum/role_preference/antagonist/traitor antag_datum = /datum/antagonist/traitor - minimum_required_age = 0 protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_CYBORG) required_candidates = 1 @@ -41,8 +40,8 @@ /datum/dynamic_ruleset/roundstart/traitorbro name = "Blood Brothers" - antag_flag = ROLE_BROTHER - antag_datum = /datum/antagonist/brother/ + role_preference = /datum/role_preference/antagonist/blood_brother + antag_datum = /datum/antagonist/brother protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG) required_candidates = 2 @@ -66,7 +65,7 @@ var/mob/bro = pick_n_take(candidates) assigned += bro.mind team.add_member(bro.mind) - bro.mind.special_role = "brother" + bro.mind.special_role = ROLE_BROTHER bro.mind.restricted_roles = restricted_roles pre_brother_teams += team return TRUE @@ -89,7 +88,7 @@ /datum/dynamic_ruleset/roundstart/changeling name = "Changelings" - antag_flag = ROLE_CHANGELING + role_preference = /datum/role_preference/antagonist/changeling antag_datum = /datum/antagonist/changeling protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG) @@ -126,7 +125,7 @@ /datum/dynamic_ruleset/roundstart/heretics name = "Heretics" - antag_flag = ROLE_HERETIC + role_preference = /datum/role_preference/antagonist/heretic antag_datum = /datum/antagonist/heretic protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG) @@ -170,10 +169,9 @@ // Dynamic is a wonderful thing that adds wizards to every round and then adds even more wizards during the round. /datum/dynamic_ruleset/roundstart/wizard name = "Wizard" - antag_flag = ROLE_WIZARD + role_preference = /datum/role_preference/antagonist/wizard antag_datum = /datum/antagonist/wizard flags = HIGH_IMPACT_RULESET | NO_OTHER_ROUNDSTARTS_RULESET - minimum_required_age = 14 restricted_roles = list(JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) // Just to be sure that a wizard getting picked won't ever imply a Captain or HoS not getting drafted required_candidates = 1 weight = 2 @@ -214,9 +212,8 @@ /datum/dynamic_ruleset/roundstart/bloodcult name = "Blood Cult" - antag_flag = ROLE_CULTIST + role_preference = /datum/role_preference/antagonist/blood_cultist antag_datum = /datum/antagonist/cult - minimum_required_age = 14 restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_CHAPLAIN, JOB_NAME_HEADOFPERSONNEL) required_candidates = 2 weight = 3 @@ -269,10 +266,9 @@ /datum/dynamic_ruleset/roundstart/nuclear name = "Nuclear Emergency" - antag_flag = ROLE_OPERATIVE + role_preference = /datum/role_preference/antagonist/nuclear_operative antag_datum = /datum/antagonist/nukeop var/datum/antagonist/antag_leader_datum = /datum/antagonist/nukeop/leader - minimum_required_age = 14 restricted_roles = list(JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) // Just to be sure that a nukie getting picked won't ever imply a Captain or HoS not getting drafted required_candidates = 5 weight = 3 @@ -295,8 +291,8 @@ break var/mob/M = pick_n_take(candidates) assigned += M.mind - M.mind.assigned_role = "Nuclear Operative" - M.mind.special_role = "Nuclear Operative" + M.mind.assigned_role = ROLE_OPERATIVE + M.mind.special_role = ROLE_OPERATIVE return TRUE /datum/dynamic_ruleset/roundstart/nuclear/execute() @@ -354,10 +350,8 @@ /datum/dynamic_ruleset/roundstart/revs name = "Revolution" persistent = TRUE - antag_flag = ROLE_REV_HEAD - antag_flag_override = ROLE_REV + role_preference = /datum/role_preference/antagonist/revolutionary antag_datum = /datum/antagonist/rev/head - minimum_required_age = 14 restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_CHIEFENGINEER, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_MASTERATARMS) //NSV13 - added MAA required_candidates = 3 weight = 3 @@ -383,7 +377,7 @@ var/mob/M = pick_n_take(candidates) assigned += M.mind M.mind.restricted_roles = restricted_roles - M.mind.special_role = antag_flag + M.mind.special_role = ROLE_REV_HEAD return TRUE /datum/dynamic_ruleset/roundstart/revs/execute() @@ -437,7 +431,6 @@ /datum/dynamic_ruleset/roundstart/extended name = "Extended" - antag_flag = null antag_datum = null restricted_roles = list() required_candidates = 0 @@ -486,7 +479,7 @@ /datum/dynamic_ruleset/roundstart/devil name = "Devil" - antag_flag = ROLE_DEVIL + role_preference = /datum/role_preference/antagonist/devil antag_datum = /datum/antagonist/devil restricted_roles = list(JOB_NAME_LAWYER, JOB_NAME_CURATOR, JOB_NAME_CHAPLAIN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE) required_candidates = 1 @@ -574,7 +567,7 @@ /datum/dynamic_ruleset/roundstart/clockcult name = "Clockwork Cult" - antag_flag = ROLE_SERVANT_OF_RATVAR + role_preference = /datum/role_preference/antagonist/clock_cultist antag_datum = /datum/antagonist/servant_of_ratvar restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG, JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE,JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_CHAPLAIN, JOB_NAME_HEADOFPERSONNEL) required_candidates = 4 @@ -636,7 +629,7 @@ /datum/dynamic_ruleset/roundstart/incursion name = "Incursion" - antag_flag = ROLE_INCURSION + role_preference = /datum/role_preference/antagonist/incursionist antag_datum = /datum/antagonist/incursion protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFMEDICALOFFICER) restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG) @@ -688,7 +681,7 @@ /datum/dynamic_ruleset/roundstart/hivemind name = "Assimilation" - antag_flag = ROLE_HIVE + role_preference = /datum/role_preference/antagonist/hivemind_host antag_datum = /datum/antagonist/hivemind protected_roles = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE,JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_roles = list(JOB_NAME_AI, JOB_NAME_CYBORG) diff --git a/code/game/gamemodes/dynamic/dynamic_simulations.dm b/code/game/gamemodes/dynamic/dynamic_simulations.dm index 4b48955ce75..acba5d1cc42 100644 --- a/code/game/gamemodes/dynamic/dynamic_simulations.dm +++ b/code/game/gamemodes/dynamic/dynamic_simulations.dm @@ -29,11 +29,6 @@ var/datum/client_interface/mock_client = new var/datum/preferences/prefs = new - var/list/be_special = list() - for (var/special_role in GLOB.special_roles) - be_special += special_role - - prefs.be_special = be_special mock_client.prefs = prefs mock_new_player.mock_client = mock_client diff --git a/code/game/gamemodes/dynamic/readme.md b/code/game/gamemodes/dynamic/readme.md index 7faa5c2d870..9af317301d8 100644 --- a/code/game/gamemodes/dynamic/readme.md +++ b/code/game/gamemodes/dynamic/readme.md @@ -144,7 +144,6 @@ Rulesets have the following variables notable to developers and those interested - Traitor: `antag_cap = list("denominator" = 24)`. This means that for every 24 players, 1 traitor will be added (assuming no scaling). - Nuclear Emergency: `antag_cap = list("denominator" = 18, "offset" = 1)`. For every 18 players, 1 nuke op will be added. Starts at 1, meaning at 30 players, 3 nuke ops will be created, rather than 2. - Revolution: `antag_cap = 3`. There will always be 3 rev-heads, no matter what. -- `minimum_required_age` - The minimum age in order to apply for the ruleset. - `weight` - How likely this ruleset is to be picked. A higher weight results in a higher chance of drafting. - `cost` - The initial cost of the ruleset. This cost is taken from either the roundstart or midround budget, depending on the ruleset. - `scaling_cost` - Cost for every *additional* application of this ruleset. diff --git a/code/game/gamemodes/eldritch_cult/eldritch_cult.dm b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm index 307b1be0893..c169e11ae73 100644 --- a/code/game/gamemodes/eldritch_cult/eldritch_cult.dm +++ b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm @@ -2,7 +2,8 @@ name = "heresy" config_tag = "heresy" report_type = "heresy" - antag_flag = ROLE_HERETIC + role_preference = /datum/role_preference/antagonist/heretic + antag_datum = /datum/antagonist/heretic false_report_weight = 5 protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_jobs = list(JOB_NAME_AI, JOB_NAME_CYBORG) @@ -10,7 +11,6 @@ required_enemies = 1 recommended_enemies = 4 reroll_friendly = 1 - enemy_minimum_age = 0 allowed_special = list(/datum/special_role/traitor/higher_chance) @@ -44,7 +44,7 @@ for(var/i in 1 to num_ecult) if(!antag_candidates.len) break - var/datum/mind/cultie = antag_pick(antag_candidates, ROLE_HERETIC) + var/datum/mind/cultie = antag_pick(antag_candidates, /datum/role_preference/antagonist/heretic) antag_candidates -= cultie cultie.special_role = ROLE_HERETIC cultie.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 03300874083..80576b5813e 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -28,13 +28,15 @@ var/maximum_players = -1 // -1 is no maximum, positive numbers limit the selection of a mode on overstaffed stations var/required_enemies = 0 var/recommended_enemies = 0 - var/antag_flag = null //preferences flag such as BE_WIZARD that need to be turned on for players to be antag + /// The role preference used to poll players. + var/role_preference + /// The antag datum typepath primarily spawned by this gamemode. Used for checking the banning key and required playtime. + var/datum/antagonist/antag_datum var/mob/living/living_antag_player = null var/datum/game_mode/replacementmode = null var/round_converted = 0 //0: round not converted, 1: round going to convert, 2: round converted var/reroll_friendly //During mode conversion only these are in the running var/continuous_sanity_checked //Catches some cases where config options could be used to suggest that modes without antagonists should end when all antagonists die - var/enemy_minimum_age = 7 //How many days must players have been playing before they can play this antagonist var/list/allowed_special = list() //Special roles that can spawn (Add things like /datum/antagonist/special/undercover for them to be able to spawn during this gamemode) var/list/active_specials = list() //Special roles that have spawned, and can now spawn late @@ -87,7 +89,7 @@ return 1 /datum/game_mode/proc/setup_antag_candidates() - antag_candidates = get_players_for_role(antag_flag) + antag_candidates = get_players_for_role(antag_datum, role_preference) ///Attempts to select players for special roles the mode might have. /datum/game_mode/proc/pre_setup() @@ -121,11 +123,11 @@ if(candidates.len == 0) return //No more candidates, end the selection process, and active specials at this time will be handled by latejoins or not included var/mob/person - if(special.special_role_flag) - person = antag_pick(candidates, special.special_role_flag) + if(special.use_antag_rep) + person = antag_pick(candidates, special.preference_type) else person = pick_n_take(candidates) - if(is_banned_from(person.ckey, special.preference_type)) + if(is_banned_from(person.ckey, special.banning_key)) continue if(!person) continue @@ -205,7 +207,7 @@ continue if(!is_special_type(M, subantag.attached_antag_datum)) continue - if(is_banned_from(M.ckey, list(subantag.preference_type))) + if(is_banned_from(M.ckey, subantag.banning_key)) continue count++ if(count >= subantag.max_amount) @@ -256,7 +258,7 @@ var/list/antag_candidates = list() for(var/mob/living/carbon/human/H in living_crew) - if(H.client && (H.client.prefs.toggles & PREFTOGGLE_MIDROUND_ANTAG) && !is_centcom_level(H.z)) + if(H.client && !is_centcom_level(H.z)) antag_candidates += H if(!antag_candidates) @@ -429,7 +431,9 @@ // The odds become: // Player A: 150 / 250 = 0.6 = 60% // Player B: 100 / 250 = 0.4 = 40% -/datum/game_mode/proc/antag_pick(list/datum/candidates, role) +/// The role_preference argument is optional, but candidates will not use their PERSONAL antag rep if the preference is disabled, rather only using the "base" antag rep. +/// This is mainly used in the situation where someone is drafted for a ruleset despite having the preference disabled (a feature of gamemodes) - we don't want to spend their rep. +/datum/game_mode/proc/antag_pick(list/datum/candidates, role_preference = null) if(!CONFIG_GET(flag/use_antag_rep)) // || candidates.len <= 1) return pick(candidates) @@ -452,7 +456,10 @@ if(!player) candidates -= mind continue - total_tickets += min(((role in player.client.prefs.be_special) ? SSpersistence.antag_rep[p_ckey] : 0) + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) + var/role_enabled = TRUE + if(role_preference && player.client) + role_enabled = player.client.role_preference_enabled(role_preference) + total_tickets += min((role_enabled ? SSpersistence.antag_rep[p_ckey] : 0) + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) var/antag_select = rand(1,total_tickets) var/current = 1 @@ -461,9 +468,11 @@ p_ckey = ckey(mind.key) var/mob/dead/new_player/player = get_mob_by_ckey(p_ckey) p_rep = SSpersistence.antag_rep[p_ckey] - + var/role_enabled = TRUE + if(role_preference && player.client) + role_enabled = player.client.role_preference_enabled(role_preference) var/previous = current - var/spend = min(((role in player.client.prefs.be_special) ? p_rep : 0) + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) + var/spend = min((role_enabled ? p_rep : 0) + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL) current += spend if(antag_select >= previous && antag_select <= (current-1)) @@ -474,7 +483,9 @@ WARNING("Something has gone terribly wrong. /datum/game_mode/proc/antag_pick failed to select a candidate. Falling back to pick()") return pick(candidates) -/datum/game_mode/proc/get_players_for_role(role) +/datum/game_mode/proc/get_players_for_role(datum/antagonist/antag_datum, role_preference = null) + var/banning_key = ispath(antag_datum, /datum/antagonist) ? initial(antag_datum.banning_key) : null + var/req_hours = ispath(antag_datum, /datum/antagonist) ? initial(antag_datum.required_living_playtime) : 0 var/list/players = list() var/list/candidates = list() var/list/drafted = list() @@ -490,11 +501,13 @@ players = shuffle(players) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready == PLAYER_READY_TO_PLAY) - if(role in player.client.prefs.be_special) - if(!is_banned_from(player.ckey, list(role, ROLE_SYNDICATE)) && !QDELETED(player)) - if(age_check(player.client)) //Must be older than the minimum age - candidates += player.mind // Get a list of all the people who want to be the antagonist for this round + if(!QDELETED(player) && player.client && player.ready == PLAYER_READY_TO_PLAY) + if(player.client.should_include_for_role( + banning_key = banning_key, + role_preference_key = role_preference, + req_hours = req_hours + )) + candidates += player.mind // Get a list of all the people who want to be the antagonist for this round if(restricted_jobs) for(var/datum/mind/player in candidates) @@ -504,10 +517,14 @@ if(candidates.len < recommended_enemies) for(var/mob/dead/new_player/player in players) - if(player.client && player.ready == PLAYER_READY_TO_PLAY) - if(!(role in player.client.prefs.be_special)) // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one - if(!is_banned_from(player.ckey, list(role, ROLE_SYNDICATE)) && !QDELETED(player)) - drafted += player.mind + if(!QDELETED(player) && player.client && player.ready == PLAYER_READY_TO_PLAY) + // We don't have enough people who want to be antagonist, make a separate list of people who don't want to be one but are otherwise eligible + if(player.client.should_include_for_role( + banning_key = banning_key, + role_preference_key = null, + req_hours = req_hours + ) && !player.client.role_preference_enabled(role_preference)) + drafted += player.mind if(restricted_jobs) for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist @@ -550,15 +567,15 @@ // Less if there are not enough valid players in the game entirely to make recommended_enemies. -/datum/game_mode/proc/get_alive_non_antagonsist_players_for_role(role, list/restricted_roles) +/datum/game_mode/proc/get_alive_non_antagonsist_players_for_role(datum/antagonist/antag_datum, role_preference, list/restricted_roles) + var/banning_key = ispath(antag_datum, /datum/antagonist) ? initial(antag_datum.banning_key) : null + var/req_hours = ispath(antag_datum, /datum/antagonist) ? initial(antag_datum.required_living_playtime) : 0 var/list/candidates = list() for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.client && is_station_level(player.z)) - if(role in player.client.prefs.be_special) - if(!is_banned_from(player.ckey, list(role, ROLE_SYNDICATE)) && !QDELETED(player)) - if(age_check(player.client) && !player.mind.special_role) //Must be older than the minimum age - candidates += player.mind // Get a list of all the people who want to be the antagonist for this round + if(!QDELETED(player) && player.client && is_station_level(player.z) && !player.mind.special_role) + if(player.client.should_include_for_role(banning_key = banning_key, role_preference_key = role_preference, req_hours = req_hours)) + candidates += player.mind // Get a list of all the people who want to be the antagonist for this round // Get a list of all the people who want to be the antagonist for this round var/restricted_list = length(restricted_roles) ? restricted_roles : restricted_jobs if(restricted_list) @@ -728,25 +745,6 @@ for (var/C in GLOB.admins) to_chat(C, msg.Join()) -//If the configuration option is set to require players to be logged as old enough to play certain jobs, then this proc checks that they are, otherwise it just returns 1 -/datum/game_mode/proc/age_check(client/C) - if(get_remaining_days(C) == 0) - return 1 //Available in 0 days = available right now = player is old enough to play. - return 0 - - -/datum/game_mode/proc/get_remaining_days(client/C) - if(!C) - return 0 - if(!CONFIG_GET(flag/use_age_restriction_for_jobs)) - return 0 - if(!isnum_safe(C.player_age)) - return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced - if(!isnum_safe(enemy_minimum_age)) - return 0 - - return max(0, enemy_minimum_age - C.player_age) - /datum/game_mode/proc/remove_antag_for_borging(datum/mind/newborgie) SSticker.mode.remove_cultist(newborgie, 0, 0) remove_servant_of_ratvar(newborgie) diff --git a/code/game/gamemodes/gangs/gangs.dm b/code/game/gamemodes/gangs/gangs.dm index 7d1187ef1d9..f0e9536cdae 100644 --- a/code/game/gamemodes/gangs/gangs.dm +++ b/code/game/gamemodes/gangs/gangs.dm @@ -5,12 +5,12 @@ GLOBAL_LIST_EMPTY(gangs) /datum/game_mode/gang name = "gang war" config_tag = "gang" - antag_flag = ROLE_GANG + role_preference = /datum/role_preference/antagonist/gangster + antag_datum = /datum/antagonist/gang restricted_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_AI, JOB_NAME_CYBORG,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY) required_players = 15 //NSV13 - down from 30 required_enemies = 1 //NSV13 - down from 2 recommended_enemies = 2 //NSV13 - down from 3 - enemy_minimum_age = 14 announce_span = "danger" announce_text = "A violent turf war has erupted on the station!\n\ diff --git a/code/game/gamemodes/hivemind/hivemind.dm b/code/game/gamemodes/hivemind/hivemind.dm index 4fa0b6095c0..90bf74f93cc 100644 --- a/code/game/gamemodes/hivemind/hivemind.dm +++ b/code/game/gamemodes/hivemind/hivemind.dm @@ -4,7 +4,8 @@ GLOBAL_LIST_EMPTY(hivehosts) name = "assimilation" config_tag = "hivemind" report_type = "hivemind" - antag_flag = ROLE_HIVE + role_preference = /datum/role_preference/antagonist/hivemind_host + antag_datum = /datum/antagonist/hivemind false_report_weight = 5 protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) restricted_jobs = list(JOB_NAME_AI, JOB_NAME_CYBORG) @@ -12,7 +13,6 @@ GLOBAL_LIST_EMPTY(hivehosts) required_enemies = 3 recommended_enemies = 3 reroll_friendly = 1 - enemy_minimum_age = 0 announce_span = "danger" announce_text = "The hosts of several psionic hiveminds have infiltrated the station and are looking to assimilate the crew!\n\ @@ -62,7 +62,7 @@ GLOBAL_LIST_EMPTY(hivehosts) for(var/j = 0, j < num_hosts, j++) if (!antag_candidates.len) break - var/datum/mind/host = antag_pick(antag_candidates, ROLE_HIVE) + var/datum/mind/host = antag_pick(antag_candidates, /datum/role_preference/antagonist/hivemind_host) hosts += host host.special_role = ROLE_HIVE host.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/incursion/incursion.dm b/code/game/gamemodes/incursion/incursion.dm index adf8979f516..c5324e52111 100644 --- a/code/game/gamemodes/incursion/incursion.dm +++ b/code/game/gamemodes/incursion/incursion.dm @@ -7,9 +7,9 @@ config_tag = "incursion" restricted_jobs = list(JOB_NAME_AI, JOB_NAME_CYBORG) protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_MASTERATARMS) //NSV13 - added MAA - antag_flag = ROLE_INCURSION + role_preference = /datum/role_preference/antagonist/incursionist + antag_datum = /datum/antagonist/incursion false_report_weight = 10 - enemy_minimum_age = 0 announce_span = "danger" announce_text = "A large force of syndicate operatives have infiltrated the ranks of the station and wish to take it by force!\n\ @@ -30,8 +30,6 @@ if(CONFIG_GET(flag/protect_assistant_from_antagonist)) restricted_jobs += JOB_NAME_ASSISTANT - var/list/datum/mind/possible_traitors = get_players_for_role(ROLE_INCURSION) - var/datum/team/incursion/team = new var/cost_base = CONFIG_GET(number/incursion_cost_base) var/cost_increment = CONFIG_GET(number/incursion_cost_increment) @@ -41,11 +39,10 @@ team_size = CLAMP(team_size, CONFIG_GET(number/incursion_count_min), CONFIG_GET(number/incursion_count_max)) for(var/k = 1 to team_size) - var/datum/mind/incursion = antag_pick(possible_traitors, ROLE_INCURSION) + var/datum/mind/incursion = antag_pick(antag_candidates, /datum/role_preference/antagonist/incursionist) if(!incursion) message_admins("Ran out of people to put in an incursion team, wanted [team_size] but only got [k-1]") break - possible_traitors -= incursion antag_candidates -= incursion team.add_member(incursion) incursion.special_role = ROLE_INCURSION diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 281f3507fe3..9d2880be163 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -8,8 +8,8 @@ required_players = 30 // 30 players - 3 players to be the nuke ops = 27 players remaining required_enemies = 2 recommended_enemies = 5 - antag_flag = ROLE_OPERATIVE - enemy_minimum_age = 14 + role_preference = /datum/role_preference/antagonist/nuclear_operative + antag_datum = /datum/antagonist/nukeop announce_span = "danger" announce_text = "Syndicate forces are approaching the station in an attempt to destroy it!\n\ @@ -31,7 +31,7 @@ var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible) if(n_agents >= required_enemies) for(var/i = 0, i < n_agents, ++i) - var/datum/mind/new_op = antag_pick(antag_candidates, ROLE_OPERATIVE) + var/datum/mind/new_op = antag_pick(antag_candidates, /datum/role_preference/antagonist/nuclear_operative) pre_nukeops += new_op new_op.assigned_role = "Nuclear Operative" new_op.special_role = "Nuclear Operative" @@ -160,7 +160,7 @@ E.implant(H) var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(H) W.implant(H) - H.faction |= ROLE_SYNDICATE + H.faction |= FACTION_SYNDICATE H.update_icons() /datum/outfit/syndicate/full diff --git a/code/game/gamemodes/overthrow/overthrow.dm b/code/game/gamemodes/overthrow/overthrow.dm index 0783c862f5e..9fd0cd3863e 100644 --- a/code/game/gamemodes/overthrow/overthrow.dm +++ b/code/game/gamemodes/overthrow/overthrow.dm @@ -3,7 +3,8 @@ name = "overthrow" config_tag = "overthrow" report_type = "overthrow" - antag_flag = ROLE_OVERTHROW + role_preference = /datum/role_preference/antagonist/traitor // use traitor role pref + antag_datum = /datum/antagonist/overthrow restricted_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_AI, JOB_NAME_CYBORG,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_MASTERATARMS) //NSV13 - added MAA required_players = 20 // the core idea is of a swift, bloodless coup, so it shouldn't be as chaotic as revs. required_enemies = 2 // minimum two teams, otherwise it's just nerfed revs. @@ -28,7 +29,7 @@ for (var/i in 1 to sleeping_agents) if (!antag_candidates.len) break - var/datum/mind/sleeping_agent = antag_pick(antag_candidates, ROLE_OVERTHROW) + var/datum/mind/sleeping_agent = antag_pick(antag_candidates, /datum/role_preference/antagonist/traitor) antag_candidates -= sleeping_agent initial_agents += sleeping_agent sleeping_agent.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 0ff58d3c82b..a635784064a 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -11,14 +11,14 @@ name = "revolution" config_tag = "revolution" report_type = "revolution" - antag_flag = ROLE_REV + role_preference = /datum/role_preference/antagonist/revolutionary + antag_datum = /datum/antagonist/rev/head false_report_weight = 10 restricted_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_AI, JOB_NAME_CYBORG,JOB_NAME_CAPTAIN, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_HEADOFSECURITY, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_MASTERATARMS) //NSV13 - added MAA required_jobs = list(list(JOB_NAME_CAPTAIN=1),list(JOB_NAME_HEADOFPERSONNEL=1),list(JOB_NAME_HEADOFSECURITY=1),list(JOB_NAME_CHIEFENGINEER=1),list(JOB_NAME_RESEARCHDIRECTOR=1),list(JOB_NAME_CHIEFMEDICALOFFICER=1),list(JOB_NAME_MASTERATARMS=1)) //Any head present //NSV13 - added MAA required_players = 30 required_enemies = 2 recommended_enemies = 3 - enemy_minimum_age = 14 title_icon = "revolution" announce_span = "danger" @@ -55,7 +55,7 @@ for (var/i=1 to max_headrevs) if (antag_candidates.len==0) break - var/datum/mind/lenin = antag_pick(antag_candidates, ROLE_REV_HEAD) + var/datum/mind/lenin = antag_pick(antag_candidates, /datum/role_preference/antagonist/revolutionary) antag_candidates -= lenin headrev_candidates += lenin lenin.restricted_roles = restricted_jobs diff --git a/code/game/gamemodes/traitor/double_agents.dm b/code/game/gamemodes/traitor/double_agents.dm index 7e3db6e86c4..b5b6f9bbecc 100644 --- a/code/game/gamemodes/traitor/double_agents.dm +++ b/code/game/gamemodes/traitor/double_agents.dm @@ -12,11 +12,11 @@ recommended_enemies = 8 reroll_friendly = 0 traitor_name = "Nanotrasen Internal Affairs Agent" - antag_flag = ROLE_INTERNAL_AFFAIRS + antag_datum = /datum/antagonist/traitor/internal_affairs + role_preference = /datum/role_preference/antagonist/internal_affairs traitors_possible = 10 //hard limit on traitors if scaling is turned off num_modifier = 4 // Four additional traitors - antag_datum = /datum/antagonist/traitor/internal_affairs announce_text = "There are Nanotrasen Internal Affairs Agents trying to kill each other!\n\ IAA: Eliminate your targets and protect yourself!\n\ diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index b87f81f8570..30a6cea5124 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -9,7 +9,8 @@ name = "traitor" config_tag = "traitor" report_type = "traitor" - antag_flag = ROLE_TRAITOR + role_preference = /datum/role_preference/antagonist/traitor + antag_datum = /datum/antagonist/traitor false_report_weight = 20 //Reports of traitors are pretty common. restricted_jobs = list(JOB_NAME_CYBORG)//They are part of the AI if he is traitor so are they, they use to get double chances protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_PILOT, JOB_NAME_MASTERATARMS) //NSV13 added pilots and master at arms @@ -17,7 +18,6 @@ required_enemies = 1 recommended_enemies = 4 reroll_friendly = 1 - enemy_minimum_age = 0 announce_span = "danger" announce_text = "There are Syndicate agents on the station!\n\ @@ -29,7 +29,6 @@ var/list/datum/mind/pre_traitors = list() var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/num_modifier = 0 // Used for gamemodes, that are a child of traitor, that need more than the usual. - var/antag_datum = /datum/antagonist/traitor //what type of antag to create var/traitors_required = TRUE //Will allow no traitors @@ -55,7 +54,7 @@ for(var/j = 0, j < num_traitors, j++) if (!antag_candidates.len) break - var/datum/mind/traitor = antag_pick(antag_candidates, ROLE_TRAITOR) + var/datum/mind/traitor = antag_pick(antag_candidates, /datum/role_preference/antagonist/traitor) pre_traitors += traitor traitor.special_role = traitor_name traitor.restricted_roles = restricted_jobs @@ -90,11 +89,13 @@ if((SSticker.mode.traitors.len + pre_traitors.len) >= traitorcap) //Upper cap for number of latejoin antagonists return if((SSticker.mode.traitors.len + pre_traitors.len) <= (traitorcap - 2) || prob(100 / (tsc * 2))) - if(antag_flag in character.client.prefs.be_special) - if(!is_banned_from(character.ckey, list(ROLE_TRAITOR, ROLE_SYNDICATE)) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - add_latejoin_traitor(character.mind) + if(!QDELETED(character) && character.client?.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime), + )) + if(!(character.job in restricted_jobs)) + add_latejoin_traitor(character.mind) /datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character) var/datum/antagonist/traitor/new_antag = new antag_datum() diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index f72b5041322..f58b8b6c09d 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -6,12 +6,12 @@ name = "wizard" config_tag = "wizard" report_type = "wizard" - antag_flag = ROLE_WIZARD + role_preference = /datum/role_preference/antagonist/wizard + antag_datum = /datum/antagonist/wizard false_report_weight = 10 required_players = 20 required_enemies = 1 recommended_enemies = 1 - enemy_minimum_age = 14 round_ends_with_antag_death = 1 announce_span = "danger" announce_text = "There is a space wizard attacking the station!\n\ @@ -22,7 +22,7 @@ title_icon = "wizard" /datum/game_mode/wizard/pre_setup() - var/datum/mind/wizard = antag_pick(antag_candidates, ROLE_WIZARD) + var/datum/mind/wizard = antag_pick(antag_candidates, /datum/role_preference/antagonist/wizard) wizards += wizard wizard.assigned_role = ROLE_WIZARD wizard.special_role = ROLE_WIZARD diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index f3e600f570d..f3b490f4993 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -297,7 +297,7 @@ /obj/machinery/clonepod/proc/offer_to_ghost(mob/living/carbon/H) set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [H.real_name]'s experimental clone?", ROLE_EXPERIMENTAL_CLONE, null, null, 300, H, POLL_IGNORE_EXPERIMENTAL_CLONE) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [H.real_name]'s experimental clone?", ROLE_EXPERIMENTAL_CLONE, null, 30 SECONDS, H) if(length(candidates)) var/mob/dead/observer/C = pick(candidates) H.key = C.key diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 9830d6e5454..e60327d47be 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -424,7 +424,7 @@ if(iscyborg(sillycone)) var/mob/living/silicon/robot/sillyconerobot = A - if((ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE) + if((FACTION_SYNDICATE in faction) && sillyconerobot.emagged == TRUE) continue else if(iscarbon(A)) @@ -686,7 +686,7 @@ stun_projectile_sound = 'sound/weapons/gunshot.ogg' icon_state = "syndie_off" base_icon_state = "syndie" - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) desc = "A ballistic machine gun auto-turret." /obj/machinery/porta_turret/syndicate/ComponentInitialize() diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 68dcf131774..0a932d2a8b0 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -329,7 +329,7 @@ S.amount_grown = SLIME_EVOLUTION_THRESHOLD S.Evolve() S.flavor_text = FLAVOR_TEXT_EVIL - S.set_playable() + S.set_playable(ROLE_PYRO_SLIME) ///////////////////// diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 36845c8446d..3779a8f4450 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -518,7 +518,7 @@ possessed = TRUE - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_POSSESSED_BLADE) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the spirit of [user.real_name]'s blade?", ROLE_SPECTRAL_BLADE, null, 10 SECONDS, ignore_category = POLL_IGNORE_SPECTRAL_BLADE) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index d3156ca1370..244549a5f29 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -18,6 +18,7 @@ Estimated time of last contact: Deployment, 5000 millennia ago." assignedrole = "Lifebringer" use_cooldown = TRUE + banType = ROLE_LIFEBRINGER /obj/effect/mob_spawn/human/seed_vault/special(mob/living/new_spawn) var/plant_name = pick("Tomato", "Potato", "Broccoli", "Carrot", "Ambrosia", "Pumpkin", "Ivy", "Kudzu", "Banana", "Moss", "Flower", "Bloom", "Root", "Bark", "Glowshroom", "Petal", "Leaf", \ @@ -54,6 +55,7 @@ assignedrole = "Ash Walker" var/datum/team/ashwalkers/team use_cooldown = TRUE + banType = ROLE_ASHWALKER /obj/effect/mob_spawn/human/ash_walker/special(mob/living/new_spawn) to_chat(new_spawn, "Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Don't leave your nest undefended, protect it with your life. Glory to the Necropolis!") @@ -78,40 +80,6 @@ head = /obj/item/clothing/head/helmet/gladiator uniform = /obj/item/clothing/under/costume/gladiator/ash_walker - -//Timeless prisons: Spawns in Wish Granter prisons in lavaland. Ghosts become age-old users of the Wish Granter and are advised to seek repentance for their past. -/obj/effect/mob_spawn/human/exile - name = "timeless prison" - desc = "Although this stasis pod looks medicinal, it seems as though it's meant to preserve something for a very long time." - mob_name = "a penitent exile" - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "sleeper" - roundstart = FALSE - death = FALSE - mob_species = /datum/species/shadow - short_desc = "You are cursed." - flavour_text = "Years ago, you sacrificed the lives of your trusted friends and the humanity of yourself to reach the Wish Granter. Though you \ - did so, it has come at a cost: your very body rejects the light, dooming you to wander endlessly in this horrible wasteland." - assignedrole = "Exile" - use_cooldown = TRUE - -/obj/effect/mob_spawn/human/exile/Destroy() - new/obj/structure/fluff/empty_sleeper(get_turf(src)) - return ..() - -/obj/effect/mob_spawn/human/exile/special(mob/living/new_spawn) - new_spawn.fully_replace_character_name(null,"Wish Granter's Victim ([rand(1,999)])") - var/wish = rand(1,4) - switch(wish) - if(1) - to_chat(new_spawn, "You wished to kill, and kill you did. You've lost track of how many, but the spark of excitement that murder once held has winked out. You feel only regret.") - if(2) - to_chat(new_spawn, "You wished for unending wealth, but no amount of money was worth this existence. Maybe charity might redeem your soul?") - if(3) - to_chat(new_spawn, "You wished for power. Little good it did you, cast out of the light. You are the [gender == MALE ? "king" : "queen"] of a hell that holds no subjects. You feel only remorse.") - if(4) - to_chat(new_spawn, "You wished for immortality, even as your friends lay dying behind you. No matter how many times you cast yourself into the lava, you awaken in this room again within a few days. There is no escape.") - //Golem shells: Spawns in Free Golem ships in lavaland. Ghosts become mineral golems and are advised to spread personal freedom. /obj/effect/mob_spawn/human/golem name = "inert free golem shell" @@ -132,6 +100,7 @@ flavour_text = "In his infinite and divine wisdom, he set your clan free to \ travel the stars with a single declaration: \"Yeah go do whatever.\" Though you are bound to the one who created you, it is customary in your society to repeat those same words to newborn \ golems, so that no golem may ever be forced to serve again." + banType = ROLE_FREE_GOLEM /obj/effect/mob_spawn/human/golem/Initialize(mapload, datum/species/golem/species = null, mob/creator = null) if(species) //spawners list uses object name to register so this goes before ..() @@ -206,6 +175,7 @@ can_transfer = FALSE mob_species = /datum/species/golem/adamantine use_cooldown = TRUE //Only the roundstart free golems are + banType = ROLE_FREE_GOLEM //Malfunctioning cryostasis sleepers: Spawns in makeshift shelters in lavaland. Ghosts become hermits with knowledge of how they got to where they are now. /obj/effect/mob_spawn/human/hermit @@ -224,6 +194,7 @@ the fresh air of Earth. These thoughts are dispelled by yet another recollection of how you got here... " assignedrole = "Hermit" use_cooldown = TRUE + banType = ROLE_HERMIT /obj/effect/mob_spawn/human/hermit/Initialize(mapload) . = ..() @@ -266,6 +237,7 @@ all you did was apply bruise packs. Why is this place full of advanced medical equipment? And what are those screams you hear? The world outside is desolate - tormented with fire and brimstone. But you took an oath. \ You have to save these people! You might not have a fancy cloning machine like a real hospital, but surely there must be some way to save these people with the tools you have. Right?" assignedrole = "Translocated Vet" + banType = ROLE_TRANSLOCATED_VET /obj/effect/mob_spawn/human/doctor/alive/lavaland/Destroy() var/obj/structure/fluff/empty_sleeper/S = new(drop_location()) @@ -287,6 +259,7 @@ flavour_text = "Good. It seems as though your ship crashed. You remember that you were convicted of " assignedrole = "Escaped Prisoner" use_cooldown = TRUE + banType = ROLE_LAVALAND_ESCAPED_PRISONER /obj/effect/mob_spawn/human/prisoner_transport/special(mob/living/L) L.fully_replace_character_name(null,"NTP #LL-0[rand(111,999)]") //Nanotrasen Prisoner #Lavaland-(numbers) @@ -327,6 +300,7 @@ important_info = "DON'T leave the hotel" assignedrole = "Hotel Staff" use_cooldown = TRUE + banType = ROLE_HOTEL_STAFF /datum/outfit/hotelstaff name = "Hotel Staff" @@ -374,6 +348,7 @@ var/obj/effect/proc_holder/spell/targeted/summon_friend/spell var/datum/mind/owner assignedrole = "SuperFriend" + banType = ROLE_DEMONIC_FRIEND /obj/effect/mob_spawn/human/demonic_friend/Initialize(mapload, datum/mind/owner_mind, obj/effect/proc_holder/spell/targeted/summon_friend/summoning_spell) . = ..() @@ -414,77 +389,6 @@ implants = list(/obj/item/implant/mindshield) //No revolutionaries, he's MY friend. id = /obj/item/card/id -/obj/effect/mob_spawn/human/syndicate - name = "Syndicate Operative" - roundstart = FALSE - death = FALSE - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "sleeper_s" - outfit = /datum/outfit/syndicate_empty - assignedrole = "Space Syndicate" //I know this is really dumb, but Syndicate operative is nuke ops - -/datum/outfit/syndicate_empty - name = "Syndicate Operative Empty" - uniform = /obj/item/clothing/under/syndicate - shoes = /obj/item/clothing/shoes/combat - gloves = /obj/item/clothing/gloves/combat - ears = /obj/item/radio/headset/syndicate/alt - back = /obj/item/storage/backpack - implants = list(/obj/item/implant/weapons_auth) - id = /obj/item/card/id/syndicate - -/datum/outfit/syndicate_empty/post_equip(mob/living/carbon/human/H) - H.faction |= ROLE_SYNDICATE - -/obj/effect/mob_spawn/human/syndicate/battlecruiser - name = "Syndicate Battlecruiser Ship Operative" - short_desc = "You are a crewmember aboard the syndicate flagship: the SBC Starfury." - flavour_text = "Your job is to follow your captain's orders, maintain the ship, and keep the engine running. If you are not familiar with how the supermatter engine functions: do not attempt to start it." - important_info = "The armory is not a candy store, and your role is not to assault the station directly, leave that work to the assault operatives." - outfit = /datum/outfit/syndicate_empty/SBC - -/datum/outfit/syndicate_empty/SBC - name = "Syndicate Battlecruiser Ship Operative" - l_pocket = /obj/item/gun/ballistic/automatic/pistol - r_pocket = /obj/item/kitchen/knife/combat/survival - belt = /obj/item/storage/belt/military/assault - -/obj/effect/mob_spawn/human/syndicate/battlecruiser/assault - name = "Syndicate Battlecruiser Assault Operative" - short_desc = "You are an assault operative aboard the syndicate flagship: the SBC Starfury." - flavour_text = "Your job is to follow your captain's orders, keep intruders out of the ship, and assault Space Station 13. There is an armory, multiple assault ships, and beam cannons to attack the station with." - important_info = "Work as a team with your fellow operatives and work out a plan of attack. If you are overwhelmed, escape back to your ship!" - outfit = /datum/outfit/syndicate_empty/SBC/assault - -/datum/outfit/syndicate_empty/SBC/assault - name = "Syndicate Battlecruiser Assault Operative" - uniform = /obj/item/clothing/under/syndicate/combat - l_pocket = /obj/item/ammo_box/magazine/m10mm - r_pocket = /obj/item/kitchen/knife/combat/survival - belt = /obj/item/storage/belt/military - suit = /obj/item/clothing/suit/armor/vest - suit_store = /obj/item/gun/ballistic/automatic/pistol - back = /obj/item/storage/backpack/security - mask = /obj/item/clothing/mask/gas/syndicate - -/obj/effect/mob_spawn/human/syndicate/battlecruiser/captain - name = "Syndicate Battlecruiser Captain" - short_desc = "You are the captain aboard the syndicate flagship: the SBC Starfury." - flavour_text = "Your job is to oversee your crew, defend the ship, and destroy Space Station 13. The ship has an armory, multiple ships, beam cannons, and multiple crewmembers to accomplish this goal." - important_info = "As the captain, this whole operation falls on your shoulders. You do not need to nuke the station, causing sufficient damage and preventing your ship from being destroyed will be enough." - outfit = /datum/outfit/syndicate_empty/SBC/assault/captain - id_access_list = list(150,151) - -/datum/outfit/syndicate_empty/SBC/assault/captain - name = "Syndicate Battlecruiser Captain" - l_pocket = /obj/item/melee/transforming/energy/sword/saber/red - r_pocket = /obj/item/melee/classic_baton/police/telescopic - suit = /obj/item/clothing/suit/armor/vest/capcarapace/syndicate - suit_store = /obj/item/gun/ballistic/revolver/mateba - back = /obj/item/storage/backpack/satchel/leather - head = /obj/item/clothing/head/HoS/syndicate - mask = /obj/item/clothing/mask/cigarette/cigar/havana - glasses = /obj/item/clothing/glasses/thermal/eyepatch //Ancient cryogenic sleepers. Players become NT crewmen from a hundred year old space station, now on the verge of collapse. /obj/effect/mob_spawn/human/oldsec @@ -509,6 +413,7 @@ l_pocket = /obj/item/assembly/flash/handheld assignedrole = "Ancient Crew" use_cooldown = TRUE + banType = ROLE_ANCIENT_CREW /obj/effect/mob_spawn/human/oldsec/Destroy() new/obj/structure/showcase/machinery/oldpod/used(drop_location()) @@ -536,6 +441,7 @@ l_pocket = /obj/item/tank/internals/emergency_oxygen assignedrole = "Ancient Crew" use_cooldown = TRUE + banType = ROLE_ANCIENT_CREW /obj/effect/mob_spawn/human/oldeng/Destroy() new/obj/structure/showcase/machinery/oldpod/used(drop_location()) @@ -562,6 +468,7 @@ l_pocket = /obj/item/stack/medical/bruise_pack assignedrole = "Ancient Crew" use_cooldown = TRUE + banType = ROLE_ANCIENT_CREW /obj/effect/mob_spawn/human/oldsci/Destroy() new/obj/structure/showcase/machinery/oldpod/used(drop_location()) @@ -584,6 +491,7 @@ short_desc = "You are a space pirate." flavour_text = "The station refused to pay for your protection, protect the ship, siphon the credits from the station and raid it for even more loot." assignedrole = "Space Pirate" + is_antagonist = TRUE var/rank = "Mate" /obj/effect/mob_spawn/human/pirate/special(mob/living/new_spawn) diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index 0b41fcf8d49..8f7870e7b30 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -31,7 +31,7 @@ icon_state = "syndbeacon" spawn_text = "warps in from" mob_types = list(/mob/living/simple_animal/hostile/syndicate/ranged) - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) /obj/structure/spawner/skeleton name = "bone pit" diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm index 3dc29f2d1cf..5b4f5087d99 100644 --- a/code/modules/admin/antag_panel.dm +++ b/code/modules/admin/antag_panel.dm @@ -165,11 +165,19 @@ GLOBAL_VAR(antag_prototypes) continue pref_source = prototype break - if(pref_source.job_rank) - if(!is_banned_from(src.key, pref_source.job_rank)) - antag_header_parts += pref_source.enabled_in_preferences(src) ? "Enabled in Prefs" : "Disabled in Prefs" - else + if(pref_source.banning_key) + if(is_banned_from(src.key, pref_source.banning_key)) antag_header_parts += "\[BANNED\]" + else if(current.client) + var/list/related_preferences = list() + for(var/datum/role_preference/role_pref_type as anything in GLOB.role_preference_entries) + if(initial(role_pref_type.antag_datum) == pref_source.type) + related_preferences += role_pref_type + if(length(related_preferences) == 1) + antag_header_parts += current.client.role_preference_enabled(related_preferences[1]) ? "Enabled in Prefs" : "Disabled in Prefs" + else if(length(related_preferences) >= 1) + for(var/datum/role_preference/preftype as anything in related_preferences) + antag_header_parts += "[initial(preftype.name)]: [current.client.role_preference_enabled(preftype) ? "Enabled Pref" : "Disabled Pref"]" //Traitor : None | Traitor | IAA // Command1 | Command2 | Command3 diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm index ca395efabda..33308c17d44 100644 --- a/code/modules/admin/fun_balloon.dm +++ b/code/modules/admin/fun_balloon.dm @@ -53,7 +53,7 @@ bodies += M var/question = "Would you like to be [group_name]?" - var/list/candidates = pollCandidatesForMobs(question, ROLE_PAI, null, FALSE, 100, bodies) + var/list/candidates = pollCandidatesForMobs(question, ROLE_SENTIENCE, null, 10 SECONDS, bodies) while(LAZYLEN(candidates) && LAZYLEN(bodies)) var/mob/dead/observer/C = pick_n_take(candidates) var/mob/living/body = pick_n_take(bodies) diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 56759be507a..f05165e3a7a 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -690,7 +690,7 @@ GLOBAL_DATUM_INIT(admin_secrets, /datum/admin_secrets, new) continue if((L in GLOB.player_list) || L.mind || (L.flags_1 & HOLOGRAM_1)) continue - L.set_playable() + L.set_playable(ROLE_SENTIENT_ANIMAL) if("flipmovement") if(!check_rights(R_FUN)) @@ -789,7 +789,7 @@ GLOBAL_DATUM_INIT(admin_secrets, /datum/admin_secrets, new) var/list/candidates = list() if (prefs["offerghosts"]["value"] == "Yes") - candidates = pollGhostCandidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(pathToSpawn.name)), ROLE_TRAITOR) + candidates = pollGhostCandidates(replacetext(prefs["ghostpoll"]["value"], "%TYPE%", initial(pathToSpawn.name)), BAN_ROLE_ALL_ANTAGONISTS, ignore_category = FALSE) if (prefs["playersonly"]["value"] == "Yes" && length(candidates) < prefs["minplayers"]["value"]) message_admins("Not enough players signed up to create a portal storm, the minimum was [prefs["minplayers"]["value"]] and the number of signups [length(candidates)]") diff --git a/code/modules/admin/sql_ban_system.dm b/code/modules/admin/sql_ban_system.dm index 9b0efda4aec..255360d94de 100644 --- a/code/modules/admin/sql_ban_system.dm +++ b/code/modules/admin/sql_ban_system.dm @@ -1,20 +1,36 @@ #define MAX_ADMINBANS_PER_ADMIN 1 #define MAX_ADMINBANS_PER_HEADMIN 3 +/// Process global ban types +/proc/check_role_ban(ban_cache, role) + if(role in GLOB.antagonist_bannable_roles) + if((BAN_ROLE_ALL_ANTAGONISTS in ban_cache) || ("Syndicate" in ban_cache)) // Legacy "Syndicate" ban + return TRUE + if(role in GLOB.forced_bannable_roles) + if(BAN_ROLE_FORCED_ANTAGONISTS in ban_cache) + return TRUE + if(role in GLOB.ghost_role_bannable_roles) + if((BAN_ROLE_ALL_GHOST in ban_cache) || ("Lavaland" in ban_cache)) // Legacy "Lavaland" ban + return TRUE + return role in ban_cache + //checks client ban cache or DB ban table if ckey is banned from one or more roles //doesn't return any details, use only for if statements /proc/is_banned_from(player_ckey, list/roles) - if(!player_ckey) + if(!player_ckey || isnull(roles) || (islist(roles) && !length(roles))) return + player_ckey = ckey(player_ckey) var/client/C = GLOB.directory[player_ckey] if(C) if(!C.ban_cache) build_ban_cache(C) if(islist(roles)) for(var/R in roles) - if(R in C.ban_cache) + if(!R) + continue + if(check_role_ban(C.ban_cache, R)) return TRUE //they're banned from at least one role, no need to keep checking - else if(roles in C.ban_cache) + else if(check_role_ban(C.ban_cache, roles)) return TRUE else var/values = list( @@ -325,16 +341,14 @@ "} break_counter++ output += "" - var/list/long_job_lists = list(("Civilian" = GLOB.civilian_positions | JOB_NAME_GIMMICK), - "Ghost and Other Roles" = list(ROLE_BRAINWASHED, ROLE_DEATHSQUAD, ROLE_DRONE, ROLE_LAVALAND, ROLE_MIND_TRANSFER, ROLE_POSIBRAIN, ROLE_SENTIENCE), - "Antagonist Positions" = list(ROLE_ABDUCTOR, ROLE_ALIEN, ROLE_BLOB, - ROLE_BROTHER, ROLE_CHANGELING, ROLE_CULTIST, ROLE_HERETIC, - ROLE_DEVIL, ROLE_INTERNAL_AFFAIRS, ROLE_MALF, - ROLE_NINJA, ROLE_OPERATIVE, - ROLE_SERVANT_OF_RATVAR, - ROLE_OVERTHROW, ROLE_REV, ROLE_REVENANT, - ROLE_REV_HEAD, ROLE_SYNDICATE, - ROLE_TRAITOR, ROLE_WIZARD, ROLE_HIVE, ROLE_GANG, ROLE_TERATOMA)) //ROLE_REV_HEAD is excluded from this because rev jobbans are handled by ROLE_REV + var/list/long_job_lists = list( + "Civilian" = GLOB.civilian_positions | JOB_NAME_GIMMICK, + "Antagonist Positions" = list(BAN_ROLE_ALL_ANTAGONISTS) + GLOB.antagonist_bannable_roles, + "Forced Antagonist Positions" = list(BAN_ROLE_FORCED_ANTAGONISTS) + GLOB.forced_bannable_roles, + "Ghost Roles" = list(BAN_ROLE_ALL_GHOST) + GLOB.ghost_role_bannable_roles, + "Other" = GLOB.other_bannable_roles, + ) + for(var/department in long_job_lists) output += "
" break_counter = 0 diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index bcf50f3238b..b91367cca0b 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -27,10 +27,10 @@ popup.set_content(dat) popup.open() -/datum/admins/proc/isReadytoRumble(mob/living/carbon/human/applicant, targetrole, onstation = TRUE, conscious = TRUE) +/datum/admins/proc/isReadytoRumble(mob/living/carbon/human/applicant, targetrole, preference, onstation = TRUE, conscious = TRUE) if(applicant.mind.special_role) return FALSE - if(!(targetrole in applicant.client.prefs.be_special)) + if(!applicant.client?.should_include_for_role(targetrole, preference)) return FALSE if(onstation) var/turf/T = get_turf(applicant) @@ -40,7 +40,7 @@ return FALSE if(!considered_alive(applicant.mind) || considered_afk(applicant.mind)) //makes sure the player isn't a zombie, brain, or just afk all together return FALSE - return !is_banned_from(applicant.ckey, list(targetrole, ROLE_SYNDICATE)) + return TRUE /datum/admins/proc/makeTraitors(maxCount = 3) @@ -59,10 +59,9 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(isReadytoRumble(applicant, ROLE_TRAITOR)) - if(temp.age_check(applicant.client)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant + if(isReadytoRumble(applicant, ROLE_TRAITOR, /datum/role_preference/midround_living/traitor)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant if(candidates.len) var/numTraitors = min(candidates.len, maxCount) @@ -94,10 +93,9 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(isReadytoRumble(applicant, ROLE_CHANGELING)) - if(temp.age_check(applicant.client)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant + if(isReadytoRumble(applicant, ROLE_CHANGELING, /datum/role_preference/antagonist/changeling)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant if(candidates.len) var/numChangelings = min(candidates.len, maxCount) @@ -124,10 +122,9 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(isReadytoRumble(applicant, ROLE_REV)) - if(temp.age_check(applicant.client)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant + if(isReadytoRumble(applicant, ROLE_REV_HEAD, /datum/role_preference/antagonist/revolutionary)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant if(candidates.len) var/numRevs = min(candidates.len, maxCount) @@ -142,7 +139,7 @@ /datum/admins/proc/makeWizard() - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for the position of a Wizard Federation 'diplomat'?", ROLE_WIZARD, null) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for the position of a Wizard Federation 'diplomat'?", ROLE_WIZARD, /datum/role_preference/midround_ghost/wizard, ignore_category = POLL_IGNORE_WIZARD_HELPER) var/mob/dead/observer/selected = pick_n_take(candidates) @@ -166,10 +163,9 @@ var/mob/living/carbon/human/H = null for(var/mob/living/carbon/human/applicant in GLOB.player_list) - if(isReadytoRumble(applicant, ROLE_CULTIST)) - if(temp.age_check(applicant.client)) - if(!(applicant.job in temp.restricted_jobs)) - candidates += applicant + if(isReadytoRumble(applicant, ROLE_CULTIST, /datum/role_preference/antagonist/blood_cultist)) + if(!(applicant.job in temp.restricted_jobs)) + candidates += applicant if(candidates.len) var/numCultists = min(candidates.len, maxCount) @@ -186,8 +182,7 @@ /datum/admins/proc/makeNukeTeam(maxCount = 5) - var/datum/game_mode/nuclear/temp = new - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", ROLE_OPERATIVE, temp) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for a nuke team being sent in?", ROLE_OPERATIVE, /datum/role_preference/midround_ghost/nuclear_operative) var/list/mob/dead/observer/chosen = list() var/mob/dead/observer/theghost = null @@ -351,7 +346,7 @@ ertemplate.enforce_human = prefs["enforce_human"]["value"] == "Yes" ? TRUE : FALSE ertemplate.opendoors = prefs["open_armory"]["value"] == "Yes" ? TRUE : FALSE - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for [ertemplate.polldesc] ?", "deathsquad", null, req_hours = 50) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to be considered for [ertemplate.polldesc] ?", ROLE_ERT, req_hours = 50) var/teamSpawned = FALSE if(candidates.len > 0) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 6c949a6a165..6cdb4f7c102 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -300,7 +300,7 @@ for(var/mob/M in GLOB.player_list) if(M.stat != DEAD) continue //we are not dead! - if(!(ROLE_ALIEN in M.client.prefs.be_special)) + if(!M.client?.should_include_for_role(ROLE_ALIEN, /datum/role_preference/midround_ghost/xenomorph)) continue //we don't want to be an alium if(M.client.is_afk()) continue //we are afk @@ -474,7 +474,7 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.forceMove(pick(GLOB.wizardstart)) var/datum/antagonist/wizard/A = new_character.mind.has_antag_datum(/datum/antagonist/wizard,TRUE) A.equip_wizard() - if(ROLE_SYNDICATE) + if(ROLE_OPERATIVE) new_character.forceMove(pick(GLOB.nukeop_start)) var/datum/antagonist/nukeop/N = new_character.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE) N.equip_op() diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index a7cc7e8c0d6..4da2f23239f 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -12,7 +12,10 @@ GLOBAL_LIST(admin_antag_list) var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with var/delete_on_mind_deletion = TRUE - var/job_rank + /// The ROLE_X key used for this antagonist. + var/banning_key + /// Required living playtime to be included in the rolling for this antagonist + var/required_living_playtime = 0 var/give_objectives = TRUE //Should the default objectives be generated? var/replace_banned = TRUE //Should replace jobbanned player with ghosts if granted. var/list/objectives = list() @@ -114,12 +117,12 @@ GLOBAL_LIST(admin_antag_list) /datum/antagonist/proc/is_banned(mob/M) if(!M) return FALSE - . = (is_banned_from(M.ckey, list(ROLE_SYNDICATE, job_rank)) || QDELETED(M)) + . = (is_banned_from(M.ckey, banning_key) || QDELETED(M)) /datum/antagonist/proc/replace_banned_player() set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", job_rank, null, job_rank, 50, owner.current) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", banning_key, null, 7.5 SECONDS, owner.current, ignore_category = FALSE) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!") @@ -127,6 +130,7 @@ GLOBAL_LIST(admin_antag_list) owner.current.ghostize(FALSE) owner.current.key = C.key else + owner.current.playable_bantype = banning_key owner.current.ghostize(FALSE,SENTIENCE_FORCE) ///Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion. @@ -221,14 +225,6 @@ GLOBAL_LIST(admin_antag_list) /datum/antagonist/proc/antag_panel_data() return "" -/datum/antagonist/proc/enabled_in_preferences(datum/mind/M) - if(job_rank) - if(M.current && M.current.client && (job_rank in M.current.client.prefs.be_special)) - return TRUE - else - return FALSE - return TRUE - // List if ["Command"] = CALLBACK(), user will be appeneded to callback arguments on execution /datum/antagonist/proc/get_admin_commands() . = list() diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index d17f6c8e2e9..eff42e0d677 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -58,7 +58,7 @@ if(used) to_chat(H, "You already used this contract!") return - var/list/candidates = pollCandidatesForMob("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, null, ROLE_WIZARD, 150, src) + var/list/candidates = pollGhostCandidates("Do you want to play as a wizard's [href_list["school"]] apprentice?", ROLE_WIZARD, /datum/role_preference/midround_ghost/wizard, 15 SECONDS, ignore_category = POLL_IGNORE_WIZARD_HELPER) if(LAZYLEN(candidates)) if(QDELETED(src)) return @@ -123,7 +123,7 @@ return to_chat(user, "You activate [src] and wait for confirmation.") - var/list/nuke_candidates = pollGhostCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE) + var/list/nuke_candidates = pollGhostCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, /datum/role_preference/midround_ghost/nuclear_operative, 15 SECONDS) if(LAZYLEN(nuke_candidates)) if(QDELETED(src) || !check_usability(user)) return @@ -243,7 +243,7 @@ return if(used) return - var/list/candidates = pollCandidatesForMob("Do you want to play as a [initial(demon_type.name)]?", ROLE_ALIEN, null, ROLE_ALIEN, 50, src) + var/list/candidates = pollGhostCandidates("Do you want to play as a [initial(demon_type.name)]?", ROLE_SLAUGHTER_DEMON, null, 10 SECONDS, ignore_category = FALSE) if(LAZYLEN(candidates)) if(used || QDELETED(src)) return @@ -295,7 +295,7 @@ return to_chat(user, "You activate [src] and wait for confirmation.") - var/list/candidates = pollGhostCandidates("Do you want to play as a gangster reinforcements?", ROLE_GANG, null, ROLE_GANG, 150) + var/list/candidates = pollGhostCandidates("Do you want to play as a gangster reinforcements?", ROLE_GANG, /datum/role_preference/antagonist/gangster, 15 SECONDS) if(LAZYLEN(candidates)) if(QDELETED(src) || !check_usability(user)) return diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 4973e420256..054c9d137bf 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -4,7 +4,7 @@ name = "Abductor" roundend_category = "abductors" antagpanel_category = "Abductor" - job_rank = ROLE_ABDUCTOR + banning_key = ROLE_ABDUCTOR show_in_antagpanel = FALSE //should only show subtypes show_to_ghosts = TRUE var/datum/team/abductor_team/team @@ -179,6 +179,7 @@ name = "Abductee" roundend_category = "abductees" antagpanel_category = "Abductee" + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/abductee/on_gain() give_objective() diff --git a/code/modules/antagonists/ashwalker/ashwalker.dm b/code/modules/antagonists/ashwalker/ashwalker.dm index f7a35eb0a31..5f767a84800 100644 --- a/code/modules/antagonists/ashwalker/ashwalker.dm +++ b/code/modules/antagonists/ashwalker/ashwalker.dm @@ -4,7 +4,7 @@ /datum/antagonist/ashwalker name = "Ash Walker" - job_rank = ROLE_LAVALAND + banning_key = ROLE_ASHWALKER show_in_antagpanel = FALSE show_to_ghosts = TRUE prevent_roundtype_conversion = FALSE diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm index 9c58e95630b..802b38735b6 100644 --- a/code/modules/antagonists/blob/blob.dm +++ b/code/modules/antagonists/blob/blob.dm @@ -3,7 +3,7 @@ roundend_category = "blobs" antagpanel_category = "Blob" show_to_ghosts = TRUE - job_rank = ROLE_BLOB + banning_key = ROLE_BLOB var/datum/action/innate/blobpop/pop_action var/starting_points_human_blob = 60 diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm index 33bc9acd69a..f67e4d2aeca 100644 --- a/code/modules/antagonists/blob/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob_mobs.dm @@ -7,7 +7,7 @@ /mob/living/simple_animal/hostile/blob icon = 'icons/mob/blob.dmi' pass_flags = PASSBLOB - faction = list(ROLE_BLOB) + faction = list(FACTION_BLOB) bubble_icon = "blob" speak_emote = null //so we use verb_yell/verb_say/etc atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) @@ -166,7 +166,7 @@ update_icons() visible_message("The corpse of [H.name] suddenly rises!") if(!key) - set_playable() + set_playable(ROLE_BLOB) /mob/living/simple_animal/hostile/blob/blobspore/death(gibbed) // On death, create a small smoke of harmful gas (s-Acid) diff --git a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm index 82528d95828..7714ab6944c 100644 --- a/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blobstrains/explosive_lattice.dm @@ -31,7 +31,7 @@ var/obj/effect/temp_visual/explosion/fast/E = new /obj/effect/temp_visual/explosion/fast(get_turf(M)) E.alpha = 150 for(var/mob/living/L in ohearers(1, get_turf(M))) - if(ROLE_BLOB in L.faction) //no friendly fire + if(FACTION_BLOB in L.faction) //no friendly fire continue var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O) L.apply_damage(0.4*aoe_volume, BRUTE) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index 2c57a7da6dd..b2139d3cbac 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -18,7 +18,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) layer = FLY_LAYER pass_flags = PASSBLOB - faction = list(ROLE_BLOB) + faction = list(FACTION_BLOB) lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE hud_type = /datum/hud/blob_overmind var/obj/structure/blob/core/blob_core = null // The blob overmind's core @@ -145,7 +145,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) if(!(Ablob.area_flags & BLOBS_ALLOWED)) continue - if(!(ROLE_BLOB in L.faction)) + if(!(FACTION_BLOB in L.faction)) playsound(L, 'sound/effects/splat.ogg', 50, 1) L.death() new/mob/living/simple_animal/hostile/blob/blobspore(T) diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 706abeef12a..1040673e8b8 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -16,13 +16,13 @@ if(!placement_override) if(!pop_override) for(var/mob/living/M in range(7, src)) - if(ROLE_BLOB in M.faction) + if(FACTION_BLOB in M.faction) continue if(M.client) to_chat(src, "There is someone too close to place your blob core!") return 0 for(var/mob/living/M in hearers(13, src)) - if(ROLE_BLOB in M.faction) + if(FACTION_BLOB in M.faction) continue if(M.client) to_chat(src, "Someone could see your blob core from here!") @@ -172,7 +172,7 @@ B.naut = TRUE //temporary placeholder to prevent creation of more than one per factory. to_chat(src, "You attempt to produce a blobbernaut.") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, null, ROLE_BLOB, 50) //players must answer rapidly + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a [blobstrain.name] blobbernaut?", ROLE_BLOB, /datum/role_preference/midround_ghost/blob, 7.5 SECONDS, ignore_category = POLL_IGNORE_BLOB_HELPER) //players must answer rapidly if(LAZYLEN(candidates)) //if we got at least one candidate, they're a blobbernaut now. B.max_integrity = initial(B.max_integrity) * 0.25 //factories that produced a blobbernaut have much lower health B.obj_integrity = min(B.obj_integrity, B.max_integrity) @@ -268,7 +268,7 @@ if(can_buy(BLOB_SPREAD_COST)) var/attacksuccess = FALSE for(var/mob/living/L in T) - if(ROLE_BLOB in L.faction) //no friendly/dead fire + if(FACTION_BLOB in L.faction) //no friendly/dead fire continue if(L.stat != DEAD) attacksuccess = TRUE diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index dad188eaaaf..20dfcbb3aef 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -253,7 +253,7 @@ /obj/structure/blob/attack_animal(mob/living/simple_animal/M) - if(ROLE_BLOB in M.faction) //sorry, but you can't kill the blob as a blobbernaut + if(FACTION_BLOB in M.faction) //sorry, but you can't kill the blob as a blobbernaut return ..() diff --git a/code/modules/antagonists/blood_contract/blood_contract.dm b/code/modules/antagonists/blood_contract/blood_contract.dm index f2faecdd458..c1b79bc13b1 100644 --- a/code/modules/antagonists/blood_contract/blood_contract.dm +++ b/code/modules/antagonists/blood_contract/blood_contract.dm @@ -4,6 +4,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE var/duration = 2 MINUTES + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/blood_contract/on_gain() . = ..() @@ -37,6 +38,7 @@ for(var/mob/living/carbon/human/P in GLOB.player_list) if(P == H) continue + log_game("[key_name(P)] was selected to kill [key_name(H)] by blood contract") // holy shit why is there no antag datum. I'm doing a huge refactor so I don't have time for one but I had to add this log here to_chat(P, "You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!") var/obj/item/I = new /obj/item/kitchen/knife/butcher(get_turf(P)) diff --git a/code/modules/antagonists/brainwashing/brainwashing.dm b/code/modules/antagonists/brainwashing/brainwashing.dm index 57d082ec819..269e40ee32b 100644 --- a/code/modules/antagonists/brainwashing/brainwashing.dm +++ b/code/modules/antagonists/brainwashing/brainwashing.dm @@ -28,7 +28,7 @@ /datum/antagonist/brainwashed name = "Brainwashed Victim" - job_rank = ROLE_BRAINWASHED + banning_key = ROLE_BRAINWASHED roundend_category = "brainwashed victims" show_in_antagpanel = TRUE antagpanel_category = "Other" diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index efdea659704..b48cf60aa7f 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -1,8 +1,8 @@ /datum/antagonist/brother name = "Brother" antagpanel_category = "Brother" - job_rank = ROLE_BROTHER - var/special_role = ROLE_BROTHER + banning_key = ROLE_BROTHER + required_living_playtime = 4 hijack_speed = 0.5 var/datum/team/brother_team/team antag_moodlet = /datum/mood_event/focused @@ -22,14 +22,14 @@ objectives += team.objectives for(var/datum/objective/O in team.objectives) log_objective(owner, O.explanation_text) - owner.special_role = special_role + owner.special_role = ROLE_BROTHER finalize_brother() return ..() /datum/antagonist/brother/on_removal() SSticker.mode.brothers -= owner if(owner.current) - to_chat(owner.current,"You are no longer the [special_role]!") + to_chat(owner.current,"You are no longer the Blood Brother!") owner.special_role = null return ..() @@ -56,7 +56,7 @@ /datum/antagonist/brother/greet() var/brother_text = get_brother_names() - to_chat(owner.current, "You are the [owner.special_role] of [brother_text].") + to_chat(owner.current, "You are the Blood Brother of [brother_text].") to_chat(owner.current, "The Syndicate only accepts those that have proven themselves. Prove yourself and prove your [team.member_name]s by completing your objectives together! You and your team are outfitted with communication implants allowing for direct, encrypted communication.") owner.announce_objectives() give_meeting_area() diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 957db20573c..53c3a42b637 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -6,7 +6,8 @@ name = "Changeling" roundend_category = "changelings" antagpanel_category = "Changeling" - job_rank = ROLE_CHANGELING + banning_key = ROLE_CHANGELING + required_living_playtime = 4 antag_moodlet = /datum/mood_event/focused hijack_speed = 0.5 var/you_are_greet = TRUE diff --git a/code/modules/antagonists/changeling/powers/teratoma.dm b/code/modules/antagonists/changeling/powers/teratoma.dm index 482ac09834b..f0a89f41d6f 100644 --- a/code/modules/antagonists/changeling/powers/teratoma.dm +++ b/code/modules/antagonists/changeling/powers/teratoma.dm @@ -23,7 +23,7 @@ var/datum/antagonist/changeling/c = user.mind.has_antag_datum(/datum/antagonist/changeling) c.chem_charges -= chemical_cost //I'm taking your chemicals hostage! var/turf/A = get_turf(user) - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a living teratoma?", ROLE_TERATOMA, null, ROLE_TERATOMA, 5 SECONDS) //players must answer rapidly + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as a living teratoma?", ROLE_TERATOMA, null, 7.5 SECONDS) //players must answer rapidly if(!LAZYLEN(candidates)) //if we got at least one candidate, they're teratoma now to_chat(usr, "You fail at creating a tumor. Perhaps you should try again later?") c.chem_charges += chemical_cost //If it fails we want to refund the chemicals diff --git a/code/modules/antagonists/changeling/teratoma.dm b/code/modules/antagonists/changeling/teratoma.dm index e304ae4383c..3e5a4c51aaf 100644 --- a/code/modules/antagonists/changeling/teratoma.dm +++ b/code/modules/antagonists/changeling/teratoma.dm @@ -2,7 +2,7 @@ name = "Teratoma" roundend_category = "other" antagpanel_category = "Changeling" - job_rank = ROLE_TERATOMA + banning_key = ROLE_TERATOMA /datum/antagonist/teratoma/on_gain() owner.special_role = "Teratoma" @@ -45,7 +45,6 @@ name = "Maintenance Teratoma" roundend_category = "other" antagpanel_category = "Changeling" - job_rank = ROLE_TERATOMA /datum/antagonist/teratoma/hugbox/greet() ..() diff --git a/code/modules/antagonists/clock_cult/mobs/cogscarab.dm b/code/modules/antagonists/clock_cult/mobs/cogscarab.dm index 8d233a2d20d..d1be9760a77 100644 --- a/code/modules/antagonists/clock_cult/mobs/cogscarab.dm +++ b/code/modules/antagonists/clock_cult/mobs/cogscarab.dm @@ -65,11 +65,6 @@ GLOBAL_LIST_INIT(cogscarabs, list()) /obj/effect/mob_spawn/drone/cogscarab/attack_ghost(mob/user) if(is_banned_from(user.ckey, ROLE_SERVANT_OF_RATVAR) || QDELETED(src) || QDELETED(user)) return - if(CONFIG_GET(flag/use_age_restriction_for_jobs)) - if(!isnum(user.client.player_age)) //apparently what happens when there's no DB connected. just don't let anybody be a drone without admin intervention - if(user.client.player_age < 14) - to_chat(user, "You're too new to play as a drone! Please try again in [14 - user.client.player_age] days.") - return if(!SSticker.mode) to_chat(user, "Can't become a cogscarab before the game has started.") return diff --git a/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm b/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm index e4ce19d5f04..0d80bd2aa47 100644 --- a/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm +++ b/code/modules/antagonists/clock_cult/scriptures/sigil_of_vitality.dm @@ -53,7 +53,7 @@ if(M.mind) M.mind.grab_ghost(TRUE) else - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [M.name], an inactive clock cultist?", ROLE_SERVANT_OF_RATVAR, null, ROLE_SERVANT_OF_RATVAR, 50, M) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [M.name], an inactive clock cultist?", ROLE_SERVANT_OF_RATVAR, /datum/role_preference/antagonist/clock_cultist, 7.5 SECONDS, M) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(M)]) to replace an AFK player.") diff --git a/code/modules/antagonists/clock_cult/scriptures/summon_marauder.dm b/code/modules/antagonists/clock_cult/scriptures/summon_marauder.dm index ef41ed2bb61..d665cbeaee7 100644 --- a/code/modules/antagonists/clock_cult/scriptures/summon_marauder.dm +++ b/code/modules/antagonists/clock_cult/scriptures/summon_marauder.dm @@ -17,7 +17,7 @@ var/mob/dead/observer/selected /datum/clockcult/scripture/marauder/invoke() - candidates = pollGhostCandidates("Would you like to play as a clockwork marauder?", ROLE_SERVANT_OF_RATVAR, null, null, 100, POLL_IGNORE_CLOCKWORK) + candidates = pollGhostCandidates("Would you like to play as a clockwork marauder?", ROLE_SERVANT_OF_RATVAR, /datum/role_preference/antagonist/clock_cultist, 10 SECONDS, POLL_IGNORE_CLOCKWORK_HELPER) if(LAZYLEN(candidates)) selected = pick(candidates) if(!selected) diff --git a/code/modules/antagonists/clock_cult/servant_of_ratvar.dm b/code/modules/antagonists/clock_cult/servant_of_ratvar.dm index 470215b2696..d904a53fe91 100644 --- a/code/modules/antagonists/clock_cult/servant_of_ratvar.dm +++ b/code/modules/antagonists/clock_cult/servant_of_ratvar.dm @@ -7,7 +7,8 @@ roundend_category = "clock cultists" antagpanel_category = "Clockcult" antag_moodlet = /datum/mood_event/cult - job_rank = ROLE_SERVANT_OF_RATVAR + banning_key = ROLE_SERVANT_OF_RATVAR + required_living_playtime = 4 //The class of the servant var/datum/action/innate/clockcult/transmit/transmit_spell diff --git a/code/modules/antagonists/clock_cult/structure/eminence_beacon.dm b/code/modules/antagonists/clock_cult/structure/eminence_beacon.dm index 666acf43f25..0a04a5f1316 100644 --- a/code/modules/antagonists/clock_cult/structure/eminence_beacon.dm +++ b/code/modules/antagonists/clock_cult/structure/eminence_beacon.dm @@ -35,7 +35,7 @@ vote_active = FALSE used = TRUE if(!eminence) - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the eminence?", ROLE_SERVANT_OF_RATVAR, null, null, 100, POLL_IGNORE_PYROSLIME) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the eminence?", ROLE_SERVANT_OF_RATVAR, /datum/role_preference/antagonist/clock_cultist, 10 SECONDS) if(LAZYLEN(candidates)) eminence = pick(candidates) else diff --git a/code/modules/antagonists/creep/creep.dm b/code/modules/antagonists/creep/creep.dm index 6537250de14..63b43371dad 100644 --- a/code/modules/antagonists/creep/creep.dm +++ b/code/modules/antagonists/creep/creep.dm @@ -2,7 +2,7 @@ name = "Obsessed" show_in_antagpanel = TRUE antagpanel_category = "Other" - job_rank = ROLE_OBSESSED + banning_key = ROLE_OBSESSED show_name_in_check_antagonists = TRUE roundend_category = "obsessed" count_against_dynamic_roll_chance = FALSE diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm index 75ff9fe6815..0f8cf5cefed 100644 --- a/code/modules/antagonists/cult/cult.dm +++ b/code/modules/antagonists/cult/cult.dm @@ -8,7 +8,8 @@ var/datum/action/innate/cult/comm/communion = new var/datum/action/innate/cult/mastervote/vote = new var/datum/action/innate/cult/blood_magic/magic = new - job_rank = ROLE_CULTIST + banning_key = ROLE_CULTIST + required_living_playtime = 4 var/ignore_implant = FALSE var/give_equipment = FALSE var/datum/team/cult/cult_team diff --git a/code/modules/antagonists/cult/cult_comms.dm b/code/modules/antagonists/cult/cult_comms.dm index adb892f2e73..e28c1220f3a 100644 --- a/code/modules/antagonists/cult/cult_comms.dm +++ b/code/modules/antagonists/cult/cult_comms.dm @@ -108,7 +108,7 @@ if(B.current && B.current != Nominee && !B.current.incapacitated()) SEND_SOUND(B.current, 'sound/magic/exit_blood.ogg') asked_cultists += B.current - var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 300, group = asked_cultists) + var/list/yes_voters = pollCandidates("[Nominee] seeks to lead your cult, do you support [Nominee.p_them()]?", poll_time = 30 SECONDS, group = asked_cultists) if(QDELETED(Nominee) || Nominee.incapacitated()) team.cult_vote_called = FALSE for(var/datum/mind/B in team.members) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index fef483b3a3e..4f5d58cf7c7 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -603,7 +603,7 @@ structure_check() searches for nearby cultist structures required for the invoca mob_to_revive.grab_ghost() if(!mob_to_revive.client || mob_to_revive.client.is_afk()) set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", ROLE_CULTIST, null, ROLE_CULTIST, 50, mob_to_revive) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [mob_to_revive.name], an inactive blood cultist?", ROLE_CULTIST, /datum/role_preference/antagonist/blood_cultist, 7.5 SECONDS, mob_to_revive) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) to_chat(mob_to_revive.mind, "Your physical form has been taken over by another soul due to your inactivity! Ahelp if you wish to regain your form.") diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm index 15bc64418e0..8b548791769 100644 --- a/code/modules/antagonists/devil/devil.dm +++ b/code/modules/antagonists/devil/devil.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", name = "Devil" roundend_category = "devils" antagpanel_category = "Devil" - job_rank = ROLE_DEVIL + banning_key = ROLE_DEVIL //Don't delete upon mind destruction, otherwise soul re-selling will break. delete_on_mind_deletion = FALSE show_to_ghosts = TRUE diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm index bbe9b3978c7..0b8f25b0a25 100644 --- a/code/modules/antagonists/devil/imp/imp.dm +++ b/code/modules/antagonists/devil/imp/imp.dm @@ -64,6 +64,7 @@ name = "Imp" antagpanel_category = "Devil" show_in_roundend = FALSE + banning_key = ROLE_DEVIL /datum/antagonist/imp/on_gain() . = ..() diff --git a/code/modules/antagonists/devil/sintouched/sintouched.dm b/code/modules/antagonists/devil/sintouched/sintouched.dm index 29c3c77fd6d..014fdfcba30 100644 --- a/code/modules/antagonists/devil/sintouched/sintouched.dm +++ b/code/modules/antagonists/devil/sintouched/sintouched.dm @@ -10,6 +10,7 @@ name = "sintouched" roundend_category = "sintouched" antagpanel_category = "Devil" + banning_key = UNBANNABLE_ANTAGONIST var/sin var/static/list/sins = list(SIN_ACEDIA,SIN_GLUTTONY,SIN_GREED,SIN_SLOTH,SIN_WRATH,SIN_ENVY,SIN_PRIDE) diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm index bd98f6e4d07..b752da58ec1 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm @@ -3,7 +3,8 @@ roundend_category = "Heretics" antagpanel_category = "Heretic" antag_moodlet = /datum/mood_event/heretics - job_rank = ROLE_HERETIC + banning_key = ROLE_HERETIC + required_living_playtime = 4 var/antag_hud_type = ANTAG_HUD_HERETIC // someone make all the other antags conform to this too lol var/antag_hud_name = "heretic" hijack_speed = 0.5 diff --git a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm index 7ecba7e1df1..4a48677f763 100644 --- a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm +++ b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm @@ -4,7 +4,7 @@ roundend_category = "Heretics" antagpanel_category = "Heretic Beast" antag_moodlet = /datum/mood_event/heretics - job_rank = ROLE_HERETIC + banning_key = ROLE_HERETIC var/antag_hud_type = ANTAG_HUD_HERETIC var/antag_hud_name = "heretic_beast" var/datum/antagonist/heretic/master diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index 458280d6e0e..65f0e45db0d 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -22,6 +22,7 @@ show_to_ghosts = TRUE antag_moodlet = /datum/mood_event/focused count_against_dynamic_roll_chance = FALSE + banning_key = ROLE_ERT /datum/antagonist/ert/on_gain() if(random_names) diff --git a/code/modules/antagonists/fugitive/fugitive.dm b/code/modules/antagonists/fugitive/fugitive.dm index 164253f3f1f..b543d1752ef 100644 --- a/code/modules/antagonists/fugitive/fugitive.dm +++ b/code/modules/antagonists/fugitive/fugitive.dm @@ -2,6 +2,7 @@ /datum/antagonist/fugitive name = "Fugitive" roundend_category = "Fugitive" + banning_key = ROLE_FUGITIVE silent = TRUE //greet called by the event show_in_antagpanel = FALSE prevent_roundtype_conversion = FALSE diff --git a/code/modules/antagonists/fugitive/hunter.dm b/code/modules/antagonists/fugitive/hunter.dm index aba80479982..e5dc82de09f 100644 --- a/code/modules/antagonists/fugitive/hunter.dm +++ b/code/modules/antagonists/fugitive/hunter.dm @@ -2,6 +2,7 @@ /datum/antagonist/fugitive_hunter name = "Fugitive Hunter" roundend_category = "Fugitive" + banning_key = ROLE_FUGITIVE_HUNTER silent = TRUE //greet called by the spawn show_in_antagpanel = FALSE prevent_roundtype_conversion = FALSE diff --git a/code/modules/antagonists/gang/gang.dm b/code/modules/antagonists/gang/gang.dm index 37377021b71..479ffb27b90 100644 --- a/code/modules/antagonists/gang/gang.dm +++ b/code/modules/antagonists/gang/gang.dm @@ -2,7 +2,7 @@ name = "Gangster" roundend_category = "gangsters" can_coexist_with_others = FALSE - job_rank = ROLE_GANG + banning_key = ROLE_GANG antagpanel_category = "Gang" var/hud_type = "gangster" var/message_name = "Gangster" diff --git a/code/modules/antagonists/greentext/greentext.dm b/code/modules/antagonists/greentext/greentext.dm index a40ab260538..3409e710410 100644 --- a/code/modules/antagonists/greentext/greentext.dm +++ b/code/modules/antagonists/greentext/greentext.dm @@ -3,6 +3,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE //Not that it will be there for long count_against_dynamic_roll_chance = FALSE + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/greentext/proc/forge_objectives() var/datum/objective/O = new /datum/objective("Succeed") diff --git a/code/modules/antagonists/guardian/guardian.dm b/code/modules/antagonists/guardian/guardian.dm index 192f8675362..3d46c14c325 100644 --- a/code/modules/antagonists/guardian/guardian.dm +++ b/code/modules/antagonists/guardian/guardian.dm @@ -5,6 +5,7 @@ show_in_antagpanel = FALSE var/datum/guardian_stats/stats var/datum/mind/summoner + banning_key = ROLE_HOLOPARASITE /datum/antagonist/guardian/roundend_report() var/list/parts = list() diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm index c79a4845af6..5892dec8abf 100644 --- a/code/modules/antagonists/highlander/highlander.dm +++ b/code/modules/antagonists/highlander/highlander.dm @@ -5,6 +5,7 @@ show_name_in_check_antagonists = TRUE can_elimination_hijack = ELIMINATION_ENABLED count_against_dynamic_roll_chance = FALSE + banning_key = BAN_ROLE_ALL_ANTAGONISTS /datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override) var/mob/living/L = owner.current || mob_override diff --git a/code/modules/antagonists/hivemind/hivemind.dm b/code/modules/antagonists/hivemind/hivemind.dm index 0fceed869ef..fa4d0033ee2 100644 --- a/code/modules/antagonists/hivemind/hivemind.dm +++ b/code/modules/antagonists/hivemind/hivemind.dm @@ -2,7 +2,8 @@ name = "Hivemind Host" roundend_category = "hiveminds" antagpanel_category = "Hivemind Host" - job_rank = ROLE_HIVE + banning_key = ROLE_HIVE + required_living_playtime = 4 antag_moodlet = /datum/mood_event/hivehost var/special_role = ROLE_HIVE var/list/hivemembers = list() @@ -156,7 +157,7 @@ /datum/antagonist/hivemind/on_gain() - owner.special_role = special_role + owner.special_role = ROLE_HIVE GLOB.hivehosts += src generate_flavour() create_actions() diff --git a/code/modules/antagonists/hivemind/vessel.dm b/code/modules/antagonists/hivemind/vessel.dm index 2fad52867b8..393417f79d7 100644 --- a/code/modules/antagonists/hivemind/vessel.dm +++ b/code/modules/antagonists/hivemind/vessel.dm @@ -2,7 +2,7 @@ /datum/antagonist/hivevessel name = "Awoken Vessel" - job_rank = ROLE_BRAINWASHED + banning_key = ROLE_HIVE_VESSEL roundend_category = "awoken vessels" antagpanel_category = "Other" show_name_in_check_antagonists = TRUE @@ -36,7 +36,7 @@ mind.remove_antag_datum(/datum/antagonist/brainwashed) /datum/antagonist/hivevessel/on_gain() - owner.special_role = special_role + owner.special_role = ROLE_HIVE_VESSEL owner.AddSpell(fist) ..() diff --git a/code/modules/antagonists/incursion/incursion.dm b/code/modules/antagonists/incursion/incursion.dm index d9ccbb95d0e..5358e20ac0e 100644 --- a/code/modules/antagonists/incursion/incursion.dm +++ b/code/modules/antagonists/incursion/incursion.dm @@ -1,8 +1,8 @@ /datum/antagonist/incursion name = "Syndicate Incursion Member" antagpanel_category = "Incursion" - job_rank = ROLE_INCURSION - var/special_role = ROLE_INCURSION + banning_key = ROLE_INCURSION + required_living_playtime = 4 var/datum/team/incursion/team antag_moodlet = /datum/mood_event/focused hijack_speed = 0.5 @@ -22,7 +22,7 @@ for(var/datum/objective/O in team.objectives) objectives += O log_objective(owner, O.explanation_text) - owner.special_role = special_role + owner.special_role = ROLE_INCURSION finalize_incursion() return ..() @@ -198,15 +198,15 @@ /datum/team/incursion/proc/generate_traitor_kill_objective(list/restricted_jobs) //Spawn someone as a traitor - var/list/datum/mind/people = SSticker.mode.get_alive_non_antagonsist_players_for_role(ROLE_EXCOMM, restricted_jobs) + var/list/datum/mind/people = SSticker.mode.get_alive_non_antagonsist_players_for_role(/datum/antagonist/traitor, /datum/role_preference/antagonist/excommunicate, restricted_jobs) if(!LAZYLEN(people)) log_game("Not enough players for incursion role. [LAZYLEN(people)]") return - var/datum/mind/target = SSticker.mode.antag_pick(people, ROLE_EXCOMM) + var/datum/mind/target = SSticker.mode.antag_pick(people, /datum/role_preference/antagonist/excommunicate) if(!target) log_game("No mind selected.") return - target.make_Traitor() + target.add_antag_datum(/datum/antagonist/traitor/excommunicate) to_chat(target, "You have been declared an ex-communicate of the syndicate and are being hunted down.") to_chat(target, "You have stolen syndicate objective documents, complete the objectives to throw off the syndicate and sabotage their efforts.") target.store_memory("You have been declared an ex-communicate of the syndicate and are being hunted down by a group of traitors. Be careful!") diff --git a/code/modules/antagonists/magic_servant/servant.dm b/code/modules/antagonists/magic_servant/servant.dm index 3277991446c..9717e869475 100644 --- a/code/modules/antagonists/magic_servant/servant.dm +++ b/code/modules/antagonists/magic_servant/servant.dm @@ -3,6 +3,7 @@ show_in_roundend = FALSE show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE + banning_key = ROLE_WIZARD /datum/antagonist/magic_servant/proc/setup_master(mob/M) var/datum/objective/O = new("Serve [M.real_name].") diff --git a/code/modules/antagonists/morph/morph.dm b/code/modules/antagonists/morph/morph.dm index 7aa8db699f0..e88a891f1b1 100644 --- a/code/modules/antagonists/morph/morph.dm +++ b/code/modules/antagonists/morph/morph.dm @@ -276,7 +276,7 @@ role_name = "morphling" /datum/round_event/ghost_role/morph/spawn_role() - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_MORPH, /datum/role_preference/midround_ghost/morph) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/antagonists/morph/morph_antag.dm b/code/modules/antagonists/morph/morph_antag.dm index 7b0491e5de5..c648a24fdea 100644 --- a/code/modules/antagonists/morph/morph_antag.dm +++ b/code/modules/antagonists/morph/morph_antag.dm @@ -2,5 +2,6 @@ name = "Morph" show_name_in_check_antagonists = TRUE show_in_antagpanel = FALSE + banning_key = ROLE_MORPH //It does nothing! (Besides tracking) diff --git a/code/modules/antagonists/nightmare/nightmare.dm b/code/modules/antagonists/nightmare/nightmare.dm index 1739e249510..59ddb46b6f4 100644 --- a/code/modules/antagonists/nightmare/nightmare.dm +++ b/code/modules/antagonists/nightmare/nightmare.dm @@ -1,5 +1,6 @@ /datum/antagonist/nightmare name = "Nightmare" + banning_key = ROLE_NIGHTMARE show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE show_to_ghosts = TRUE diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm index 03b0f9042c8..b697e6684bd 100644 --- a/code/modules/antagonists/ninja/ninja.dm +++ b/code/modules/antagonists/ninja/ninja.dm @@ -1,7 +1,7 @@ /datum/antagonist/ninja name = "Ninja" antagpanel_category = "Ninja" - job_rank = ROLE_NINJA + banning_key = ROLE_NINJA show_name_in_check_antagonists = TRUE show_to_ghosts = TRUE antag_moodlet = /datum/mood_event/focused diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 52accf3923d..8126e12ff1c 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -2,7 +2,8 @@ name = "Nuclear Operative" roundend_category = "syndicate operatives" //just in case antagpanel_category = "NukeOp" - job_rank = ROLE_OPERATIVE + banning_key = ROLE_OPERATIVE + required_living_playtime = 8 antag_moodlet = /datum/mood_event/focused show_to_ghosts = TRUE hijack_speed = 2 //If you can't take out the station, take the shuttle instead. @@ -144,7 +145,7 @@ nuke_team = new_team /datum/antagonist/nukeop/admin_add(datum/mind/new_owner,mob/admin) - new_owner.assigned_role = ROLE_SYNDICATE + new_owner.assigned_role = ROLE_OPERATIVE new_owner.add_antag_datum(src) message_admins("[key_name_admin(admin)] has nuke op'ed [key_name_admin(new_owner)].") log_admin("[key_name(admin)] has nuke op'ed [key_name(new_owner)].") diff --git a/code/modules/antagonists/official/official.dm b/code/modules/antagonists/official/official.dm index a35ef429734..d1d73bc79b7 100644 --- a/code/modules/antagonists/official/official.dm +++ b/code/modules/antagonists/official/official.dm @@ -6,6 +6,7 @@ var/datum/objective/mission var/datum/team/ert/ert_team show_to_ghosts = TRUE + banning_key = ROLE_ERT /datum/antagonist/official/greet() to_chat(owner, "You are a CentCom Official.") diff --git a/code/modules/antagonists/overthrow/overthrow.dm b/code/modules/antagonists/overthrow/overthrow.dm index eeb25929891..da118ce87b4 100644 --- a/code/modules/antagonists/overthrow/overthrow.dm +++ b/code/modules/antagonists/overthrow/overthrow.dm @@ -9,7 +9,7 @@ name = "Syndicate mutineer" roundend_category = "syndicate mutineers" antagpanel_category = "Syndicate Mutineers" - job_rank = ROLE_TRAITOR // simply use the traitor preference & jobban settings + banning_key = ROLE_OVERTHROW var/datum/team/overthrow/team var/static/list/possible_useful_items diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm index b8fbd18c70e..5804e64f448 100644 --- a/code/modules/antagonists/pirate/pirate.dm +++ b/code/modules/antagonists/pirate/pirate.dm @@ -1,6 +1,6 @@ /datum/antagonist/pirate name = "Space Pirate" - job_rank = ROLE_TRAITOR + banning_key = ROLE_SPACE_PIRATE roundend_category = "space pirates" antagpanel_category = "Pirate" show_to_ghosts = TRUE diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index 803d8fd916c..02370743481 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -438,7 +438,7 @@ break if(!key_of_revenant) message_admins("The new revenant's old client either could not be found or is in a new, living mob - grabbing a random candidate instead...") - var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", ROLE_REVENANT, null, ROLE_REVENANT, 50, revenant) + var/list/candidates = pollCandidatesForMob("Do you want to be [revenant.name] (reforming)?", ROLE_REVENANT, /datum/role_preference/midround_ghost/revenant, 7.5 SECONDS, revenant) if(!LAZYLEN(candidates)) qdel(revenant) message_admins("No candidates were found for the new revenant. Oh well!") diff --git a/code/modules/antagonists/revenant/revenant_antag.dm b/code/modules/antagonists/revenant/revenant_antag.dm index 169d23d25c0..2c9aa4d8a87 100644 --- a/code/modules/antagonists/revenant/revenant_antag.dm +++ b/code/modules/antagonists/revenant/revenant_antag.dm @@ -3,6 +3,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE show_to_ghosts = TRUE + banning_key = ROLE_REVENANT /datum/antagonist/revenant/greet() owner.announce_objectives() diff --git a/code/modules/antagonists/revenant/revenant_spawn_event.dm b/code/modules/antagonists/revenant/revenant_spawn_event.dm index 10ee621a9b8..54368fd8721 100644 --- a/code/modules/antagonists/revenant/revenant_spawn_event.dm +++ b/code/modules/antagonists/revenant/revenant_spawn_event.dm @@ -26,7 +26,7 @@ message_admins("Event attempted to spawn a revenant, but there were only [deadMobs]/[REVENANT_SPAWN_THRESHOLD] dead mobs.") return WAITING_FOR_SOMETHING - var/list/candidates = get_candidates(ROLE_REVENANT, null, ROLE_REVENANT) + var/list/candidates = get_candidates(ROLE_REVENANT, /datum/role_preference/midround_ghost/revenant) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm index d5dce9e21ef..17591952189 100644 --- a/code/modules/antagonists/revolution/revolution.dm +++ b/code/modules/antagonists/revolution/revolution.dm @@ -7,7 +7,7 @@ name = "Revolutionary" roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen antagpanel_category = "Revolution" - job_rank = ROLE_REV + banning_key = ROLE_REV antag_moodlet = /datum/mood_event/revolution var/hud_type = "rev" var/datum/team/revolution/rev_team @@ -159,6 +159,8 @@ /datum/antagonist/rev/head name = "Head Revolutionary" hud_type = "rev_head" + banning_key = ROLE_REV_HEAD + required_living_playtime = 4 var/remove_clumsy = FALSE var/give_flash = FALSE var/give_hud = TRUE @@ -289,6 +291,7 @@ /datum/antagonist/revolution_enemy name = "Enemy of the Revolution" show_in_antagpanel = FALSE + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/revolution_enemy/on_gain() owner.special_role = "revolution enemy" @@ -342,7 +345,7 @@ var/list/datum/mind/nonhuman_promotable = list() for(var/datum/mind/khrushchev in non_heads) if(khrushchev.current && !khrushchev.current.incapacitated() && !khrushchev.current.restrained() && khrushchev.current.client && khrushchev.current.stat != DEAD) - if(ROLE_REV in khrushchev.current.client.prefs.be_special) + if(khrushchev.current.client.should_include_for_role(ROLE_REV_HEAD, /datum/role_preference/antagonist/revolutionary)) if(ishuman(khrushchev.current)) promotable += khrushchev else diff --git a/code/modules/antagonists/role_preference/_role_preference.dm b/code/modules/antagonists/role_preference/_role_preference.dm new file mode 100644 index 00000000000..710ce5d2430 --- /dev/null +++ b/code/modules/antagonists/role_preference/_role_preference.dm @@ -0,0 +1,27 @@ +/datum/role_preference + var/name + /// What heading to display this entry under in the preferences menu. Use ROLE_PREFERENCE_CATEGORY defines. + var/category + /// The Antagonist datum typepath for this entry, if there is one. Used to get data about the role for display (bans etc) + var/datum/antagonist/antag_datum + /// The base abstract path for this subtype. + var/abstract_type = /datum/role_preference + /// If this preference can vary between characters. + var/per_character = FALSE + +/// Includes latejoin and roundstart antagonists +/datum/role_preference/antagonist + category = ROLE_PREFERENCE_CATEGORY_ANAGONIST + abstract_type = /datum/role_preference/antagonist + per_character = TRUE + +/// Includes autotraitor and gamemode midround assignments - being forced into an antagonist during a round (does not apply to conversion antags). +/datum/role_preference/midround_living + category = ROLE_PREFERENCE_CATEGORY_MIDROUND_LIVING + abstract_type = /datum/role_preference/midround_living + per_character = TRUE + +/// Includes anything polled from ghosts that does antagonist stuff +/datum/role_preference/midround_ghost + category = ROLE_PREFERENCE_CATEGORY_MIDROUND_GHOST + abstract_type = /datum/role_preference/midround_ghost diff --git a/code/modules/antagonists/role_preference/role_antagonists.dm b/code/modules/antagonists/role_preference/role_antagonists.dm new file mode 100644 index 00000000000..b952e5ad233 --- /dev/null +++ b/code/modules/antagonists/role_preference/role_antagonists.dm @@ -0,0 +1,43 @@ +/datum/role_preference/antagonist/blood_brother + name = "Blood Brother" + antag_datum = /datum/antagonist/brother + +/datum/role_preference/antagonist/blood_cultist + name = "Blood Cultist" + antag_datum = /datum/antagonist/cult + +/datum/role_preference/antagonist/clock_cultist + name = "Clock Cultist" + antag_datum = /datum/antagonist/servant_of_ratvar + +/datum/role_preference/antagonist/devil + name = "Devil" + antag_datum = /datum/antagonist/devil + +/datum/role_preference/antagonist/revolutionary + name = "Head Revolutionary" + antag_datum = /datum/antagonist/rev/head + +/datum/role_preference/antagonist/heretic + name = "Heretic" + antag_datum = /datum/antagonist/heretic + +/datum/role_preference/antagonist/hivemind_host + name = "Hivemind Host" + antag_datum = /datum/antagonist/hivemind + +/datum/role_preference/antagonist/incursionist + name = "Incursionist" + antag_datum = /datum/antagonist/incursion + +/datum/role_preference/antagonist/excommunicate + name = "Excommunicated Syndicate Agent" + antag_datum = /datum/antagonist/traitor/excommunicate + +/datum/role_preference/antagonist/gangster + name = "Gangster" + antag_datum = /datum/antagonist/gang + +/datum/role_preference/antagonist/internal_affairs + name = "Internal Affairs Agent" + antag_datum = /datum/antagonist/traitor/internal_affairs diff --git a/code/modules/antagonists/role_preference/role_changeling.dm b/code/modules/antagonists/role_preference/role_changeling.dm new file mode 100644 index 00000000000..cf0399b0bcf --- /dev/null +++ b/code/modules/antagonists/role_preference/role_changeling.dm @@ -0,0 +1,3 @@ +/datum/role_preference/antagonist/changeling + name = "Changeling" + antag_datum = /datum/antagonist/changeling diff --git a/code/modules/antagonists/role_preference/role_midrounds.dm b/code/modules/antagonists/role_preference/role_midrounds.dm new file mode 100644 index 00000000000..77a4c08d798 --- /dev/null +++ b/code/modules/antagonists/role_preference/role_midrounds.dm @@ -0,0 +1,69 @@ +/datum/role_preference/midround_ghost/blob + name = "Blob" + antag_datum = /datum/antagonist/blob + +/datum/role_preference/midround_ghost/xenomorph + name = "Xenomorph" + antag_datum = /datum/antagonist/xeno + +/datum/role_preference/midround_ghost/nightmare + name = "Nightmare" + antag_datum = /datum/antagonist/nightmare + +/datum/role_preference/midround_ghost/space_dragon + name = "Space Dragon" + antag_datum = /datum/antagonist/space_dragon + +/datum/role_preference/midround_ghost/abductor + name = "Abductor" + antag_datum = /datum/antagonist/abductor + +/datum/role_preference/midround_ghost/space_pirate + name = "Space Pirate" + antag_datum = /datum/antagonist/pirate + +/datum/role_preference/midround_ghost/revenant + name = "Revenant" + antag_datum = /datum/antagonist/revenant + +/* NSV13 - Disabled because we don't have this ported yet. +/datum/role_preference/midround_ghost/spider + name = "Spider" + antag_datum = /datum/antagonist/spider + +/datum/role_preference/midround_ghost/swarmer + name = "Swarmer" + antag_datum = /datum/antagonist/swarmer +*/ + +/datum/role_preference/midround_ghost/morph + name = "Morph" + antag_datum = /datum/antagonist/morph + +/datum/role_preference/midround_ghost/fugitive + name = "Fugitive" + antag_datum = /datum/antagonist/fugitive + +/datum/role_preference/midround_ghost/fugitive_hunter + name = "Fugitive Hunter" + antag_datum = /datum/antagonist/fugitive_hunter + +/datum/role_preference/midround_ghost/slaughter_demon + name = "Slaughter Demon" + antag_datum = /datum/antagonist/slaughter + +/datum/role_preference/midround_ghost/devil + name = "Devil (Midround)" + antag_datum = /datum/antagonist/devil + +/datum/role_preference/midround_ghost/ninja + name = "Ninja" + antag_datum = /datum/antagonist/ninja + +/datum/role_preference/midround_living/malfunctioning_ai + name = "Malfunctioning AI" + antag_datum = /datum/antagonist/traitor + +/datum/role_preference/midround_living/obsessed + name = "Obsessed" + antag_datum = /datum/antagonist/obsessed diff --git a/code/modules/antagonists/role_preference/role_operative.dm b/code/modules/antagonists/role_preference/role_operative.dm new file mode 100644 index 00000000000..6a4fe7a5b9e --- /dev/null +++ b/code/modules/antagonists/role_preference/role_operative.dm @@ -0,0 +1,7 @@ +/datum/role_preference/antagonist/nuclear_operative + name = "Nuclear Operative" + antag_datum = /datum/antagonist/nukeop + +/datum/role_preference/midround_ghost/nuclear_operative + name = "Nuclear Operative (Midround)" + antag_datum = /datum/antagonist/nukeop diff --git a/code/modules/antagonists/role_preference/role_traitor.dm b/code/modules/antagonists/role_preference/role_traitor.dm new file mode 100644 index 00000000000..46d11945a14 --- /dev/null +++ b/code/modules/antagonists/role_preference/role_traitor.dm @@ -0,0 +1,7 @@ +/datum/role_preference/antagonist/traitor + name = "Traitor" + antag_datum = /datum/antagonist/traitor + +/datum/role_preference/midround_living/traitor + name = "Traitor (Sleeper Agent)" + antag_datum = /datum/antagonist/traitor diff --git a/code/modules/antagonists/role_preference/role_wizard.dm b/code/modules/antagonists/role_preference/role_wizard.dm new file mode 100644 index 00000000000..31681493a58 --- /dev/null +++ b/code/modules/antagonists/role_preference/role_wizard.dm @@ -0,0 +1,7 @@ +/datum/role_preference/antagonist/wizard + name = "Wizard" + antag_datum = /datum/antagonist/wizard + +/datum/role_preference/midround_ghost/wizard + name = "Wizard (Midround)" + antag_datum = /datum/antagonist/wizard diff --git a/code/modules/antagonists/roundstart_special/special_antagonist.dm b/code/modules/antagonists/roundstart_special/special_antagonist.dm index 7d39652e9bf..603623e4830 100644 --- a/code/modules/antagonists/roundstart_special/special_antagonist.dm +++ b/code/modules/antagonists/roundstart_special/special_antagonist.dm @@ -24,8 +24,10 @@ var/max_occurrences = 1 var/holidayID = "" //Preferences - var/preference_type = ROLE_TRAITOR - var/special_role_flag = null //Will use antag rep if enabled + var/preference_type = null + /// If we should use antag rep. Do note that having a preference_type enables checking during gamemode execution. + var/use_antag_rep = TRUE + var/banning_key = ROLE_TRAITOR /datum/special_role/proc/setup() if(CONFIG_GET(flag/protect_roles_from_antagonist)) @@ -46,6 +48,7 @@ E.antagonist_datum = attached_antag_datum E.antag_name = role_name E.preference_type = preference_type + E.banning_key = banning_key E.protected_jobs = restricted_jobs E.typepath = /datum/round_event/create_special_antag E.weight = weight @@ -72,8 +75,8 @@ //The datum associated with the role /datum/antagonist/special - name = "Role that should not be accessable in game." - job_rank = ROLE_SYNDICATE + name = "Role that should not be accessible in game." + banning_key = BAN_ROLE_ALL_ANTAGONISTS show_in_antagpanel = FALSE show_name_in_check_antagonists = FALSE prevent_roundtype_conversion = FALSE diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm index fb1d304f8bb..563e89059cb 100644 --- a/code/modules/antagonists/santa/santa.dm +++ b/code/modules/antagonists/santa/santa.dm @@ -3,6 +3,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE show_to_ghosts = TRUE + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/santa/on_gain() . = ..() diff --git a/code/modules/antagonists/separatist/separatist.dm b/code/modules/antagonists/separatist/separatist.dm index 20a6d84bdec..cc9a84836e6 100644 --- a/code/modules/antagonists/separatist/separatist.dm +++ b/code/modules/antagonists/separatist/separatist.dm @@ -6,6 +6,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE var/datum/team/nation/nation + banning_key = BAN_ROLE_ALL_ANTAGONISTS /datum/antagonist/separatist/create_team(datum/team/nation/new_team) if(!new_team) diff --git a/code/modules/antagonists/slaughter/slaughter_antag.dm b/code/modules/antagonists/slaughter/slaughter_antag.dm index 9f80462f578..557b2ec5c49 100644 --- a/code/modules/antagonists/slaughter/slaughter_antag.dm +++ b/code/modules/antagonists/slaughter/slaughter_antag.dm @@ -3,7 +3,7 @@ show_name_in_check_antagonists = TRUE var/objective_verb = "Kill" var/datum/mind/summoner - job_rank = ROLE_ALIEN + banning_key = ROLE_SLAUGHTER_DEMON show_in_antagpanel = FALSE show_to_ghosts = TRUE diff --git a/code/modules/antagonists/slaughter/slaughterevent.dm b/code/modules/antagonists/slaughter/slaughterevent.dm index 8ad463763ce..9c2fdaf3d13 100644 --- a/code/modules/antagonists/slaughter/slaughterevent.dm +++ b/code/modules/antagonists/slaughter/slaughterevent.dm @@ -14,7 +14,7 @@ role_name = "slaughter demon" /datum/round_event/ghost_role/slaughter/spawn_role() - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_SLAUGHTER_DEMON, null) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 5cc275660d3..68ad2195fab 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -1,5 +1,6 @@ /datum/antagonist/space_dragon name = "Space Dragon" + banning_key = ROLE_SPACE_DRAGON show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE show_to_ghosts = TRUE diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 4c36b4e1354..819d8c07fd0 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -2,6 +2,7 @@ name = "Survivalist" show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE + banning_key = ROLE_SURVIVALIST var/greet_message = "" /datum/antagonist/survivalist/proc/forge_objectives() diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 506f2695465..02396b7388b 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -5,7 +5,8 @@ name = "Traitor" roundend_category = "traitors" antagpanel_category = "Traitor" - job_rank = ROLE_TRAITOR + banning_key = ROLE_TRAITOR + required_living_playtime = 4 antag_moodlet = /datum/mood_event/focused hijack_speed = 0.5 //10 seconds per hijack stage by default var/special_role = ROLE_TRAITOR @@ -435,3 +436,8 @@ /datum/antagonist/traitor/is_gamemode_hero() return SSticker.mode.name == "traitor" + +/datum/antagonist/traitor/excommunicate + name = "Excommunicate Traitor" + banning_key = ROLE_EXCOMM + special_role = ROLE_EXCOMM diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm index 7827bf9f394..b97d5ad70c9 100644 --- a/code/modules/antagonists/traitor/equipment/contractor.dm +++ b/code/modules/antagonists/traitor/equipment/contractor.dm @@ -165,7 +165,7 @@ if (.) to_chat(user, "The uplink vibrates quietly, connecting to nearby agents...") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_CONTRACTOR_SUPPORT_UNIT, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) diff --git a/code/modules/antagonists/traitor/traitor_spawner.dm b/code/modules/antagonists/traitor/traitor_spawner.dm index 7d42fa8fc4f..f3c31485d74 100644 --- a/code/modules/antagonists/traitor/traitor_spawner.dm +++ b/code/modules/antagonists/traitor/traitor_spawner.dm @@ -13,9 +13,9 @@ allowAntagTargets = TRUE latejoin_allowed = TRUE protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN) - - special_role_flag = ROLE_TRAITOR - role_name = ROLE_TRAITOR + role_name = "Traitor" + preference_type = /datum/role_preference/antagonist/traitor + use_antag_rep = TRUE var/traitors_possible = 4 //hard limit on traitors if scaling is turned off diff --git a/code/modules/antagonists/valentines/heartbreaker.dm b/code/modules/antagonists/valentines/heartbreaker.dm index 39ffdfa1496..51e80761140 100644 --- a/code/modules/antagonists/valentines/heartbreaker.dm +++ b/code/modules/antagonists/valentines/heartbreaker.dm @@ -3,6 +3,7 @@ roundend_category = "valentines" show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE + banning_key = BAN_ROLE_ALL_ANTAGONISTS /datum/antagonist/heartbreaker/proc/forge_objectives() diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm index df695fadce5..cc1f81ed1bf 100644 --- a/code/modules/antagonists/valentines/valentine.dm +++ b/code/modules/antagonists/valentines/valentine.dm @@ -5,6 +5,7 @@ prevent_roundtype_conversion = FALSE var/datum/mind/date count_against_dynamic_roll_chance = FALSE + banning_key = UNBANNABLE_ANTAGONIST /datum/antagonist/valentine/proc/forge_objectives() var/datum/objective/protect/protect_objective = new /datum/objective/protect diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm index 497bf49b00d..960d49bdc46 100644 --- a/code/modules/antagonists/wishgranter/wishgranter.dm +++ b/code/modules/antagonists/wishgranter/wishgranter.dm @@ -3,6 +3,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE can_elimination_hijack = ELIMINATION_ENABLED + banning_key = BAN_ROLE_ALL_ANTAGONISTS /datum/antagonist/wishgranter/proc/forge_objectives() var/datum/objective/elimination/highlander/elimination_objective = new diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index af5087b5c84..6909768dca2 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -338,7 +338,7 @@ break if(!chosen_ghost) //Failing that, we grab a ghost - var/list/consenting_candidates = pollGhostCandidates("Would you like to play as a Shade?", "Cultist", null, ROLE_CULTIST, 50, POLL_IGNORE_SHADE) + var/list/consenting_candidates = pollGhostCandidates("Would you like to play as a Shade?", ROLE_CULTIST, null, 5 SECONDS, ignore_category = POLL_IGNORE_CULT_SHADE) if(consenting_candidates.len) chosen_ghost = pick(consenting_candidates) if(!T) diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index b08b67b13c7..46cbfb3c857 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -2,7 +2,8 @@ name = "Space Wizard" roundend_category = "wizards/witches" antagpanel_category = "Wizard" - job_rank = ROLE_WIZARD + banning_key = ROLE_WIZARD + required_living_playtime = 8 antag_moodlet = /datum/mood_event/focused hijack_speed = 0.5 var/strip = TRUE //strip before equipping @@ -182,12 +183,12 @@ /datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override) var/mob/living/M = mob_override || owner.current update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard - M.faction |= ROLE_WIZARD + M.faction |= FACTION_WIZARD /datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override) var/mob/living/M = mob_override || owner.current update_wiz_icons_removed(M) - M.faction -= ROLE_WIZARD + M.faction -= FACTION_WIZARD /datum/antagonist/wizard/get_admin_commands() diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index 7845ec7d225..dfabb8366e4 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -11,7 +11,7 @@ /datum/antagonist/xeno name = "Xenomorph" - job_rank = ROLE_ALIEN + banning_key = ROLE_ALIEN show_in_antagpanel = FALSE prevent_roundtype_conversion = FALSE show_to_ghosts = TRUE diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 45d5cc86506..281f873cc73 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -28,9 +28,11 @@ var/mob_color //Change the mob's color var/assignedrole var/show_flavour = TRUE - var/banType = ROLE_LAVALAND + var/banType var/ghost_usable = TRUE var/use_cooldown = FALSE + /// If this should ignore admins disabling ghost roles (like lavaland roles), since it's actually an antagonist. + var/is_antagonist = FALSE //ATTACK GHOST IGNORING PARENT RETURN VALUE /obj/effect/mob_spawn/attack_ghost(mob/user) @@ -42,6 +44,10 @@ if(!uses) to_chat(user, "This spawner is out of charges!") return + if(!SSticker.HasRoundStarted()) + return + if(!user?.client?.can_take_ghost_spawner(banType, use_cooldown, is_ghost_role = !is_antagonist, is_admin_spawned = flags_1 & ADMIN_SPAWNED_1)) + return if(is_banned_from(user.key, banType)) to_chat(user, "You are jobanned!") return @@ -402,6 +408,17 @@ id_job = JOB_NAME_BARTENDER use_cooldown = TRUE +/obj/effect/mob_spawn/human/bartender/alive/beach + assignedrole = "Beach Bartender" + banType = ROLE_BEACH_BUM + outfit = /datum/outfit/spacebartender/beach + +/datum/outfit/spacebartender/beach/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) + ..() + if(visualsOnly) + return + H.dna.add_mutation(STONER) + /datum/outfit/spacebartender name = "Space Bartender" uniform = /obj/item/clothing/under/rank/civilian/bartender @@ -434,6 +451,7 @@ flavour_text = "Ch'yea. You came here, like, on spring break, hopin' to pick up some bangin' hot chicks, y'knaw?" assignedrole = "Beach Bum" use_cooldown = TRUE + banType = ROLE_BEACH_BUM /obj/effect/mob_spawn/human/beach/alive/lifeguard short_desc = "You're a spunky lifeguard!" @@ -512,29 +530,6 @@ back = /obj/item/storage/backpack/security id = /obj/item/card/id/job/security_officer - -/obj/effect/mob_spawn/human/commander/alive - death = FALSE - roundstart = FALSE - mob_name = "\improper Nanotrasen Commander" - name = "sleeper" - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "sleeper" - short_desc = "You are a Nanotrasen Commander!" - use_cooldown = TRUE - -/obj/effect/mob_spawn/human/nanotrasensoldier/alive - death = FALSE - roundstart = FALSE - mob_name = "Private Security Officer" - name = "sleeper" - icon = 'icons/obj/machines/sleeper.dmi' - icon_state = "sleeper" - faction = "nanotrasenprivate" - short_desc = "You are a Nanotrasen Private Security Officer!" - use_cooldown = TRUE - - /////////////////Spooky Undead////////////////////// /obj/effect/mob_spawn/human/skeleton @@ -549,30 +544,16 @@ icon = 'icons/effects/blood.dmi' icon_state = "remains" short_desc = "By unknown powers, your skeletal remains have been reanimated!" - flavour_text = "Walk this mortal plain and terrorize all living adventurers who dare cross your path." + flavour_text = "Walk this mortal plane and terrorize all living adventurers who dare cross your path." assignedrole = "Skeleton" use_cooldown = TRUE + banType = ROLE_SKELETAL_REMAINS /obj/effect/mob_spawn/human/skeleton/alive/equip(mob/living/carbon/human/H) var/obj/item/implant/exile/implant = new/obj/item/implant/exile(H) implant.implant(H) H.set_species(/datum/species/skeleton) -/obj/effect/mob_spawn/human/zombie - name = "rotting corpse" - mob_name = "zombie" - mob_species = /datum/species/zombie - assignedrole = "Zombie" - -/obj/effect/mob_spawn/human/zombie/alive - death = FALSE - roundstart = FALSE - icon = 'icons/effects/blood.dmi' - icon_state = "remains" - short_desc = "By unknown powers, your rotting remains have been resurrected!" - flavour_text = "Walk this mortal plain and terrorize all living adventurers who dare cross your path." - use_cooldown = TRUE - /obj/effect/mob_spawn/human/abductor name = "abductor" mob_name = "alien" @@ -584,25 +565,6 @@ uniform = /obj/item/clothing/under/color/grey shoes = /obj/item/clothing/shoes/combat - -//For ghost bar. -/obj/effect/mob_spawn/human/alive/space_bar_patron - name = "Bar cryogenics" - mob_name = "Bar patron" - random = TRUE - permanent = TRUE - uses = -1 - outfit = /datum/outfit/spacebartender - assignedrole = "Space Bar Patron" - -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user) - var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No") - if(despawn != "Yes" || !loc || !Adjacent(user)) - return - user.visible_message("[user.name] climbs back into cryosleep...") - qdel(user) - /datum/outfit/cryobartender name = "Cryogenic Bartender" uniform = /obj/item/clothing/under/rank/civilian/bartender diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index 724aa39b410..f62053e356d 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -90,7 +90,7 @@ var/mob/living/current_wizard = null var/next_check = 0 var/cooldown = 600 - var/faction = ROLE_WIZARD + var/faction = FACTION_WIZARD var/braindead_check = 0 /obj/structure/academy_wizard_spawner/New() @@ -125,7 +125,7 @@ if(!current_wizard) return - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", ROLE_WIZARD, null, ROLE_WIZARD, 50, current_wizard) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", ROLE_WIZARD, /datum/role_preference/midround_ghost/wizard, 10 SECONDS, current_wizard) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) @@ -133,6 +133,7 @@ current_wizard.ghostize(FALSE) // on the off chance braindead defender gets back in current_wizard.key = C.key else + current_wizard.playable_bantype = ROLE_WIZARD current_wizard.ghostize(FALSE,SENTIENCE_FORCE) /obj/structure/academy_wizard_spawner/proc/summon_wizard() @@ -313,7 +314,7 @@ A.setup_master(user) servant_mind.transfer_to(H) - var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, null, ROLE_WIZARD, 50, H) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, /datum/role_preference/midround_ghost/wizard, 10 SECONDS, H) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant") diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index 12c18edec71..1eabeb89289 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -577,7 +577,7 @@ icon_state = "sleeper" roundstart = FALSE death = FALSE - faction = ROLE_SYNDICATE + faction = FACTION_SYNDICATE outfit = /datum/outfit/snowsyndie short_desc = "You are a syndicate operative recently awoken from cryostasis in an underground outpost." flavour_text = "You are a syndicate operative recently awoken from cryostasis in an underground outpost. Monitor Nanotrasen communications and record information. All intruders should be \ diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 401e4131f8b..1acd467413c 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -24,10 +24,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/tip_delay = 500 //tip delay in milliseconds //Antag preferences - var/list/be_special = list() //Special role selection - var/tmp/old_be_special = 0 //Bitflag version of be_special, used to update old savefiles and nothing more - //If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were, - //autocorrected this round, not that you'd need to check that. + var/list/role_preferences = list() //Special role selection var/UI_style = null var/outline_color = COLOR_BLUE_GRAY @@ -135,11 +132,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/list/dat = list("
") dat += "Character Settings" + dat += "Antagonist Preferences" dat += "Game Preferences" var/shop_name = "[CONFIG_GET(string/metacurrency_name)] Shop" dat += "[shop_name]" dat += "OOC Preferences" - dat += "Roleplay Settings" //NSV13 - Roleplay Tab + dat += "Roleplay Settings" //NSV13 - Roleplay Tab dat += "
" @@ -598,7 +596,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if (1) // Game Preferences - dat += "
" + dat += "" + // left box + dat += "" // left box closed + // right box + dat += "" + // right box closed + dat += "" + dat += "" + dat += "
" dat += "

General Settings

" dat += "UI Style: [UI_style]
" dat += "Outline: [toggles & PREFTOGGLE_OUTLINE_ENABLED ? "Enabled" : "Disabled"]
" @@ -652,8 +652,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
" dat += "Income Updates: [(chat_toggles & CHAT_BANKCARD) ? "Allowed" : "Muted"]
" - dat += "
" + dat += "
" + dat += "

Graphics Settings

" dat += "FPS: [clientfps]
" dat += "Parallax (Fancy Space): " @@ -705,35 +708,98 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(CONFIG_GET(flag/preference_map_voting)) dat += "Preferred Map: [p_map]
" - dat += "
" - - dat += "

Special Role Settings

" - - if(is_banned_from(user.ckey, ROLE_SYNDICATE)) - dat += "You are banned from antagonist roles.
" - src.be_special = list() + dat += "
Customize Keybinds
" - for (var/i in GLOB.special_roles) - if(is_banned_from(user.ckey, i)) - dat += "Be [capitalize(i)]: BANNED
" + if(4) // antagonist preferences window + dat += "
" + var/name + var/unspaced_slots = 0 + for(var/datum/character_save/CS as anything in character_saves) + unspaced_slots++ + if(unspaced_slots > 4) + dat += "
" + unspaced_slots = 0 + name = CS.real_name + if(!name) + name = "Character [CS.slot_number]" + if(CS.slot_locked) + dat += "[name] (Locked) " else - var/days_remaining = null - if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age - var/mode_path = GLOB.special_roles[i] - var/datum/game_mode/temp_mode = new mode_path - days_remaining = temp_mode.get_remaining_days(user.client) - - if(days_remaining) - dat += "Be [capitalize(i)]: \[IN [days_remaining] DAYS]
" - else - dat += "Be [capitalize(i)]: [(i in be_special) ? "Enabled" : "Disabled"]
" - dat += "
" - dat += "Midround Antagonist: [(toggles & PREFTOGGLE_MIDROUND_ANTAG) ? "Enabled" : "Disabled"]
" + dat += "[name] " + dat += "
" + dat += "" + // + dat += "" + // left box closed + + // + // -------------------------------------------- + // Midround antagonists + ghostspawn roles + dat += "" + // right box closed - dat += "" // i hate myself for this - dat += "" - dat += "
" + // -------------------------------------------- + // warning pannel + var/ban_antagonists = is_banned_from(parent.ckey, BAN_ROLE_ALL_ANTAGONISTS) + var/ban_forced_antagonists = is_banned_from(parent.ckey, BAN_ROLE_FORCED_ANTAGONISTS) + var/ban_ghost = is_banned_from(parent.ckey, BAN_ROLE_ALL_GHOST) + if(ban_antagonists || ban_forced_antagonists || ban_ghost) + dat += "

Notification

" + if(ban_antagonists) + dat += "You are banned from all antagonist roles.
\ + Show Info
" + if(ban_forced_antagonists) + dat += "You are banned from all forced antagonist roles (such as brainwashing).
\ + Show Info
" + if(ban_ghost) + dat += "You are banned from all non-antagonist ghost roles.
\ + Show Info
" + // -------------------------------------------- + // Antagonist roles + dat += "

Antagonists

" + for (var/typepath in GLOB.role_preference_entries) + var/datum/role_preference/pref = GLOB.role_preference_entries[typepath] + if(pref.category != ROLE_PREFERENCE_CATEGORY_ANAGONIST) + continue + var/ban_key = initial(pref.antag_datum.banning_key) + if(is_banned_from(parent.ckey, ban_key)) + dat += "[pref.name]: BANNED
" + else + dat += "[pref.name] \ +
- Character: [parent.role_preference_enabled(typepath) ? "Enabled" : "Disabled"]\ +
- Global: Enable\ + Disable
" + dat += "
" + dat += "

Midrounds (Living)

" + for (var/typepath in GLOB.role_preference_entries) + var/datum/role_preference/pref = GLOB.role_preference_entries[typepath] + if(pref.category != ROLE_PREFERENCE_CATEGORY_MIDROUND_LIVING) + continue + var/ban_key = initial(pref.antag_datum.banning_key) + if(is_banned_from(parent.ckey, ban_key)) + dat += "[pref.name]: BANNED
" + else + dat += "[pref.name] \ +
- Character: [parent.role_preference_enabled(typepath) ? "Enabled" : "Disabled"]\ +
- Global: Enable\ + Disable
" + dat += "

Midrounds (Ghost)

" + for (var/typepath in GLOB.role_preference_entries) + var/datum/role_preference/pref = GLOB.role_preference_entries[typepath] + if(pref.category != ROLE_PREFERENCE_CATEGORY_MIDROUND_GHOST) + continue + var/ban_key = initial(pref.antag_datum.banning_key) + if(is_banned_from(parent.ckey, ban_key)) + dat += "[pref.name]: BANNED
" + else + dat += "[pref.name]: [parent.role_preference_enabled(typepath) ? "Enabled" : "Disabled"]
" + dat += "
Customize Keybinds
" + dat += "
" if(2) //Loadout var/list/type_blacklist = list() @@ -890,7 +956,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "" dat += "" - if(4) //NSV13 - Roleplay Tab - Start + if(5) + dat += "Character Settings" //NSV13 - Roleplay Tab - Start dat += "
" var/name var/unspaced_slots = 0 @@ -2005,12 +2072,33 @@ GLOBAL_LIST_EMPTY(preferences_datums) toggles ^= PREFTOGGLE_DEADMIN_POSITION_SILICON - if("be_special") - var/be_special_type = href_list["be_special_type"] - if(be_special_type in be_special) - be_special -= be_special_type - else - be_special += be_special_type + if("role_preferences") + var/role_preference_type = href_list["role_preference_type"] + var/role_preference_path = text2path(role_preference_type) + var/datum/role_preference/role_pref = GLOB.role_preference_entries[role_preference_path] + if(istype(role_pref)) + var/list/prefsource = role_pref.per_character ? active_character.role_preferences_character : role_preferences + var/current = prefsource["[role_preference_type]"] + if(isnum(current)) + prefsource["[role_preference_type]"] = !current + else // not set, we assume it's on, so turn it off. + prefsource["[role_preference_type]"] = FALSE + + if("role_preferences_enableall") + var/role_preference_type = href_list["role_preference_type"] + var/role_preference_path = text2path(role_preference_type) + var/datum/role_preference/role_pref = GLOB.role_preference_entries[role_preference_path] + if(istype(role_pref) && role_pref.per_character) + for(var/datum/character_save/CS in character_saves) + CS.role_preferences_character["[role_preference_type]"] = TRUE + + if("role_preferences_disableall") + var/role_preference_type = href_list["role_preference_type"] + var/role_preference_path = text2path(role_preference_type) + var/datum/role_preference/role_pref = GLOB.role_preference_entries[role_preference_path] + if(istype(role_pref) && role_pref.per_character) + for(var/datum/character_save/CS in character_saves) + CS.role_preferences_character["[role_preference_type]"] = FALSE if("name") active_character.be_random_name = !active_character.be_random_name @@ -2052,9 +2140,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("pull_requests") chat_toggles ^= CHAT_PULLR - if("allow_midround_antag") - toggles ^= PREFTOGGLE_MIDROUND_ANTAG - if("parallaxup") parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1) if (parent && parent.mob && parent.mob.hud_used) diff --git a/code/modules/client/preferences2/character_save.dm b/code/modules/client/preferences2/character_save.dm index 59fc38cad52..2647311ca59 100644 --- a/code/modules/client/preferences2/character_save.dm +++ b/code/modules/client/preferences2/character_save.dm @@ -71,6 +71,7 @@ var/list/equipped_gear = list() var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants var/uplink_spawn_loc = UPLINK_PDA + var/list/role_preferences_character = list() //Nsv13 squads - we CM now var/preferred_squad = "Able" //NSV13 - Pilots @@ -181,6 +182,11 @@ SAFE_READ_QUERY(39, medical_record) //NSV13 - Stop + // Role prefs + var/role_preferences_character_tmp + SAFE_READ_QUERY(40, role_preferences_character_tmp) //NSV13 - Moved from 32 to 40 due to Roleplaying stuff + role_preferences_character = json_decode(role_preferences_character_tmp) + //Sanitize. Please dont put query reads below this point. Please. @@ -261,6 +267,14 @@ job_preferences -= j all_quirks = SANITIZE_LIST(all_quirks) + role_preferences_character = SANITIZE_LIST(role_preferences_character) + // Remove any invalid entries + for(var/preference in role_preferences_character) + var/path = text2path(preference) + var/datum/role_preference/entry = GLOB.role_preference_entries[path] + if(istype(entry) && entry.per_character) + continue + role_preferences_character -= preference //NSV13 - Roleplay Stuff - Start flavor_text = html_decode(strip_html(flavor_text)) @@ -373,7 +387,8 @@ silicon_flavor_text, general_record, security_record, - medical_record + medical_record, + role_preferences ) VALUES ( :slot, :ckey, @@ -414,7 +429,8 @@ :silicon_flavor_text, :general_record, :security_record, - :medical_record + :medical_record, + :role_preferences ) "}, list( // Now for the above but in a fucking monsterous list @@ -457,7 +473,8 @@ "silicon_flavor_text" = silicon_flavor_text, "general_record" = general_record, "security_record" = security_record, - "medical_record" = medical_record + "medical_record" = medical_record, + "role_preferences" = json_encode(role_preferences_character) )) if(!insert_query.warn_execute()) diff --git a/code/modules/client/preferences2/preferences2.dm b/code/modules/client/preferences2/preferences2.dm index a57181f360e..fe6967c60c5 100644 --- a/code/modules/client/preferences2/preferences2.dm +++ b/code/modules/client/preferences2/preferences2.dm @@ -84,7 +84,7 @@ READPREF_JSONDEC(ignoring, PREFERENCE_TAG_IGNORING) READPREF_JSONDEC(key_bindings, PREFERENCE_TAG_KEYBINDS) READPREF_JSONDEC(purchased_gear, PREFERENCE_TAG_PURCHASED_GEAR) - READPREF_JSONDEC(be_special, PREFERENCE_TAG_BE_SPECIAL) + READPREF_JSONDEC(role_preferences, PREFERENCE_TAG_ROLE_PREFERENCES) //Sanitize asaycolor = sanitize_ooccolor(sanitize_hexcolor(asaycolor, 6, TRUE, initial(asaycolor))) @@ -104,7 +104,14 @@ ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit)) ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION) ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION) - be_special = SANITIZE_LIST(be_special) + role_preferences = SANITIZE_LIST(role_preferences) + // Remove any invalid entries + for(var/preference in role_preferences) + var/path = text2path(preference) + var/datum/role_preference/entry = GLOB.role_preference_entries[path] + if(istype(entry) && !entry.per_character) + continue + role_preferences -= preference pda_theme = sanitize_inlist(pda_theme, GLOB.ntos_device_themes_default_content, initial(pda_theme)) pda_color = sanitize_hexcolor(pda_color, 6, TRUE, initial(pda_color)) @@ -166,7 +173,7 @@ PREP_WRITEPREF_JSONENC(ignoring, PREFERENCE_TAG_IGNORING) PREP_WRITEPREF_JSONENC(key_bindings, PREFERENCE_TAG_KEYBINDS) PREP_WRITEPREF_JSONENC(purchased_gear, PREFERENCE_TAG_PURCHASED_GEAR) - PREP_WRITEPREF_JSONENC(be_special, PREFERENCE_TAG_BE_SPECIAL) + PREP_WRITEPREF_JSONENC(role_preferences, PREFERENCE_TAG_ROLE_PREFERENCES) // QuerySelect can execute many queries at once. That name is dumb but w/e SSdbcore.QuerySelect(write_queries, TRUE, TRUE) @@ -220,7 +227,8 @@ silicon_flavor_text, general_record, security_record, - medical_record + medical_record, + role_preferences FROM [format_table_name("characters")] WHERE ckey=:ckey "}, list("ckey" = parent.ckey)) diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 6ca7eb5fad4..56f84d923e5 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -78,15 +78,6 @@ prefs.save_preferences() SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Arrivalrattle", "[!(prefs.toggles & PREFTOGGLE_DISABLE_ARRIVALRATTLE) ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, maybe you should rethink where your life went so wrong. -/client/verb/togglemidroundantag() - set name = "Toggle Midround Antagonist" - set category = "Preferences" - set desc = "Midround Antagonist" - prefs.toggles ^= PREFTOGGLE_MIDROUND_ANTAG - prefs.save_preferences() - to_chat(usr, "You will [(prefs.toggles & PREFTOGGLE_MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.") - SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Midround Antag", "[prefs.toggles & PREFTOGGLE_MIDROUND_ANTAG ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - /client/verb/toggletitlemusic() set name = "Hear/Silence Lobby Music" set category = "Preferences" diff --git a/code/modules/clothing/outfits/vr.dm b/code/modules/clothing/outfits/vr.dm index fa02a1aa264..bfd90cf8825 100644 --- a/code/modules/clothing/outfits/vr.dm +++ b/code/modules/clothing/outfits/vr.dm @@ -33,7 +33,7 @@ W.implant(H) var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H) E.implant(H) - H.faction |= ROLE_SYNDICATE + H.faction |= FACTION_SYNDICATE H.update_icons() /obj/item/paper/fluff/vr/fluke_ops diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm index b089c96b5f5..e521dc6d02d 100755 --- a/code/modules/events/abductor.dm +++ b/code/modules/events/abductor.dm @@ -15,7 +15,7 @@ fakeable = FALSE //Nothing to fake here /datum/round_event/ghost_role/abductor/spawn_role() - var/list/mob/dead/observer/candidates = get_candidates(ROLE_ABDUCTOR, null, ROLE_ABDUCTOR) + var/list/mob/dead/observer/candidates = get_candidates(ROLE_ABDUCTOR, /datum/role_preference/midround_ghost/abductor) if(candidates.len < 2) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 3ff8a552a02..b3579514588 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -62,7 +62,7 @@ message_admins("An event attempted to spawn an alien but no suitable vents were found. Shutting down.") return MAP_ERROR - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_ALIEN, /datum/role_preference/midround_ghost/xenomorph) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 662cab5c991..0869a6f35ee 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -22,7 +22,7 @@ /datum/round_event/ghost_role/blob/spawn_role() if(!GLOB.blobstart.len) return MAP_ERROR - var/list/candidates = get_candidates(ROLE_BLOB, null, ROLE_BLOB) + var/list/candidates = get_candidates(ROLE_BLOB, /datum/role_preference/midround_ghost/blob) if(!candidates.len) return NOT_ENOUGH_PLAYERS var/mob/dead/observer/new_blob = pick(candidates) diff --git a/code/modules/events/creep_awakening.dm b/code/modules/events/creep_awakening.dm index 1b5643bc53f..b45b45ada95 100644 --- a/code/modules/events/creep_awakening.dm +++ b/code/modules/events/creep_awakening.dm @@ -10,7 +10,7 @@ /datum/round_event/obsessed/start() for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list)) - if(!H.client || !(ROLE_OBSESSED in H.client.prefs.be_special)) + if(!H.client?.should_include_for_role(ROLE_OBSESSED, /datum/role_preference/midround_living/obsessed)) continue if(H.stat == DEAD) continue diff --git a/code/modules/events/devil.dm b/code/modules/events/devil.dm index 9073171c98c..7000d2b3366 100644 --- a/code/modules/events/devil.dm +++ b/code/modules/events/devil.dm @@ -19,7 +19,7 @@ return MAP_ERROR //selecting a candidate player - var/list/candidates = get_candidates(ROLE_DEVIL, null, ROLE_DEVIL) + var/list/candidates = get_candidates(ROLE_DEVIL, /datum/role_preference/midround_ghost/devil) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/fugitive_spawning.dm b/code/modules/events/fugitive_spawning.dm index 29b3e3149a3..5dd61663786 100644 --- a/code/modules/events/fugitive_spawning.dm +++ b/code/modules/events/fugitive_spawning.dm @@ -22,7 +22,7 @@ return MAP_ERROR var/turf/landing_turf = pick(possible_spawns) var/list/possible_backstories = list() - var/list/candidates = get_candidates(ROLE_TRAITOR, null, ROLE_TRAITOR) + var/list/candidates = get_candidates(ROLE_TRAITOR, /datum/role_preference/midround_ghost/fugitive) if(candidates.len >= 1) //solo refugees if(prob(30)) possible_backstories.Add("waldo") //less common as it comes with magicks and is kind of immershun shattering diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm index 67ef4002e73..70546de1fa9 100644 --- a/code/modules/events/ghost_role.dm +++ b/code/modules/events/ghost_role.dm @@ -55,14 +55,14 @@ // players could be found, and just runtime if anything else happens return TRUE -/datum/round_event/ghost_role/proc/get_candidates(jobban, gametypecheck, be_special) +/datum/round_event/ghost_role/proc/get_candidates(banning_key, role_preference, poll_ignore = null) // Returns a list of candidates in priority order, with candidates from // `priority_candidates` first, and ghost roles randomly shuffled and // appended after var/list/mob/dead/observer/regular_candidates // don't get their hopes up if(priority_candidates.len < minimum_required) - regular_candidates = pollGhostCandidates("Do you wish to be considered for the special role of '[role_name]'?", jobban, gametypecheck, be_special) + regular_candidates = pollGhostCandidates("Do you wish to be considered for the special role of '[role_name]'?", banning_key, role_preference, ignore_category = poll_ignore) else regular_candidates = list() diff --git a/code/modules/events/holiday/xmas.dm b/code/modules/events/holiday/xmas.dm index 6a75c1cf380..f887ab485d7 100644 --- a/code/modules/events/holiday/xmas.dm +++ b/code/modules/events/holiday/xmas.dm @@ -86,7 +86,7 @@ priority_announce("Santa is coming to town!", "Unknown Transmission", SSstation.announcer.get_rand_alert_sound()) /datum/round_event/santa/start() - var/list/candidates = pollGhostCandidates("Santa is coming to town! Do you want to be Santa?", poll_time=150) + var/list/candidates = pollGhostCandidates("Santa is coming to town! Do you want to be Santa?", poll_time = 15 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) santa = new /mob/living/carbon/human(pick(GLOB.blobstart)) diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm index f0311378d3f..03ef2578f3b 100644 --- a/code/modules/events/nightmare.dm +++ b/code/modules/events/nightmare.dm @@ -12,7 +12,7 @@ fakeable = FALSE /datum/round_event/ghost_role/nightmare/spawn_role() - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_NIGHTMARE, /datum/role_preference/midround_ghost/nightmare) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/operative.dm b/code/modules/events/operative.dm index e655d8b0e33..bea4dad09d1 100644 --- a/code/modules/events/operative.dm +++ b/code/modules/events/operative.dm @@ -11,7 +11,7 @@ fakeable = FALSE /datum/round_event/ghost_role/operative/spawn_role() - var/list/candidates = get_candidates(ROLE_OPERATIVE, null, ROLE_OPERATIVE) + var/list/candidates = get_candidates(ROLE_OPERATIVE, /datum/role_preference/midround_ghost/nuclear_operative) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index a4764953150..6a6b5e564ff 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -65,7 +65,7 @@ GLOBAL_VAR_INIT(pirates_spawned, FALSE) if(!skip_answer_check && threat?.answered == PIRATE_RESPONSE_PAY) return - var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_TRAITOR) + var/list/candidates = pollGhostCandidates("Do you wish to be considered for pirate crew?", ROLE_SPACE_PIRATE, /datum/role_preference/midround_ghost/space_pirate, 15 SECONDS) shuffle_inplace(candidates) var/datum/map_template/shuttle/pirate/default/ship = new diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm index 06cfa5e5843..7139a65377a 100644 --- a/code/modules/events/sentience.dm +++ b/code/modules/events/sentience.dm @@ -40,7 +40,7 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( /datum/round_event/ghost_role/sentience/spawn_role() var/list/mob/dead/observer/candidates - candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + candidates = get_candidates(ROLE_SENTIENT_ANIMAL, null) // find our chosen mob to breathe life into // Mobs have to be simple animals, mindless, on station, and NOT holograms. diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index 731cda46c4a..95e7f509cfd 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -17,7 +17,7 @@ priority_announce("It appears a lifeform with magical traces is approaching [station_name()], please stand-by.", "Lifesign Alert", SSstation.announcer.get_rand_alert_sound()) /datum/round_event/ghost_role/space_dragon/spawn_role() - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_SPACE_DRAGON, /datum/role_preference/midround_ghost/space_dragon) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/events/special_antag_event.dm b/code/modules/events/special_antag_event.dm index 6fbe7b39e73..50b1932d2eb 100644 --- a/code/modules/events/special_antag_event.dm +++ b/code/modules/events/special_antag_event.dm @@ -3,9 +3,10 @@ typepath = /datum/round_event/create_special_antag auto_add = FALSE //Antagonist data - var/antagonist_datum = /datum/antagonist/special + var/datum/antagonist/antagonist_datum = /datum/antagonist/special var/antag_name //The datum of the antag E.G. /datum/antagonist/special/undercover - var/preference_type = ROLE_TRAITOR + var/preference_type = /datum/role_preference/antagonist/traitor + var/banning_key = BAN_ROLE_ALL_ANTAGONISTS var/protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CAPTAIN, JOB_NAME_MASTERATARMS) //NSV13 - MPs, XO, MAA /datum/round_event_control/spawn_special_antagonist/runEvent() @@ -13,6 +14,7 @@ E.antag_datum = antagonist_datum E.role_name = antag_name E.preference_type = preference_type + E.banning_key = banning_key E.protected_jobs = protected_jobs E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) E.control = src @@ -34,15 +36,16 @@ /datum/round_event/create_special_antag fakeable = FALSE var/role_name - var/antag_datum //The datum of the antag E.G. /datum/antagonist/special/undercover - var/preference_type = ROLE_TRAITOR + var/datum/antagonist/antag_datum //The datum of the antag E.G. /datum/antagonist/special/undercover + var/banning_key = BAN_ROLE_ALL_ANTAGONISTS + var/preference_type = /datum/role_preference/antagonist/traitor var/protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_DETECTIVE, JOB_NAME_HEADOFSECURITY, JOB_NAME_HEADOFPERSONNEL, JOB_NAME_CHIEFMEDICALOFFICER, JOB_NAME_CHIEFENGINEER, JOB_NAME_RESEARCHDIRECTOR, JOB_NAME_CAPTAIN, JOB_NAME_MASTERATARMS) //NSV13 - XO, MAA, MP /datum/round_event/create_special_antag/start() for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list)) - if(!H.client || !(preference_type in H.client.prefs.be_special) || !(H.client.prefs.toggles & PREFTOGGLE_MIDROUND_ANTAG)) + if(!H.client) continue - if(is_banned_from(H, list(preference_type))) + if(!H.client.should_include_for_role(initial(antag_datum.banning_key), preference_type)) continue if(H.stat == DEAD) continue diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index 1c8ef95baae..f69d962ce0c 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -10,7 +10,7 @@ if(!ishuman(M.current)) continue var/mob/living/carbon/human/W = M.current - var/list/candidates = pollGhostCandidates("Would you like to be an imposter wizard?", ROLE_WIZARD) + var/list/candidates = pollGhostCandidates("Would you like to be an imposter wizard?", ROLE_WIZARD, /datum/role_preference/midround_ghost/wizard, ignore_category = POLL_IGNORE_WIZARD_HELPER) if(!candidates) return //Sad Trombone var/mob/dead/observer/C = pick(candidates) diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index 81e5588b5f2..afe3167fe08 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -178,7 +178,7 @@ qdel(src) /obj/item/reagent_containers/food/snacks/monkeycube/syndicate - faction = list("neutral", ROLE_SYNDICATE) + faction = list("neutral", FACTION_SYNDICATE) /obj/item/reagent_containers/food/snacks/monkeycube/gorilla name = "gorilla cube" diff --git a/code/modules/guardian/guardian.dm b/code/modules/guardian/guardian.dm index ba180d60701..3de93224483 100644 --- a/code/modules/guardian/guardian.dm +++ b/code/modules/guardian/guardian.dm @@ -581,7 +581,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians /mob/living/simple_animal/hostile/guardian/proc/ResetMe() set waitfor = FALSE - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [summoner?.current?.name]'s [real_name]?", ROLE_HOLOPARASITE, null, FALSE, 10 SECONDS) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [summoner?.current?.name]'s [real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) key = C.key @@ -674,7 +674,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians return G.next_reset = world.time + GUARDIAN_RESET_COOLDOWN to_chat(src, "You attempt to reset [G.real_name]'s personality...") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", ROLE_HOLOPARASITE, null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) to_chat(G, "Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.") diff --git a/code/modules/guardian/guardianbuilder.dm b/code/modules/guardian/guardianbuilder.dm index 4492b08cacd..e5a97fa23ee 100644 --- a/code/modules/guardian/guardianbuilder.dm +++ b/code/modules/guardian/guardianbuilder.dm @@ -225,7 +225,7 @@ used = FALSE return FALSE // IMPORTANT - if we're debugging, the user gets thrown into the stand - var/list/mob/dead/observer/candidates = debug_mode ? list(user) : pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_HOLOPARASITE, null, FALSE, 100, POLL_IGNORE_HOLOPARASITE) + var/list/mob/dead/observer/candidates = debug_mode ? list(user) : pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) var/mob/living/simple_animal/hostile/guardian/G = new(user, theme, guardian_color) diff --git a/code/modules/guardian/standarrow.dm b/code/modules/guardian/standarrow.dm index c2e6b3457c5..583ee3fc2b4 100644 --- a/code/modules/guardian/standarrow.dm +++ b/code/modules/guardian/standarrow.dm @@ -161,7 +161,7 @@ G.name = new_name /obj/item/stand_arrow/proc/get_stand(mob/living/carbon/H, datum/guardian_stats/stats) - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Guardian Spirit of [H.real_name]?", ROLE_HOLOPARASITE, null, FALSE, 100, POLL_IGNORE_HOLOPARASITE) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Guardian Spirit of [H.real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) var/mob/living/simple_animal/hostile/guardian/G = new(H, GUARDIAN_MAGIC, rgb(rand(1, 255), rand(1, 255), rand(1, 255))) diff --git a/code/modules/jobs/jobs.dm b/code/modules/jobs/jobs.dm index 81c921f6ef1..3a28fde67a2 100644 --- a/code/modules/jobs/jobs.dm +++ b/code/modules/jobs/jobs.dm @@ -175,7 +175,7 @@ GLOBAL_LIST_INIT(exp_jobsmap, list( GLOBAL_LIST_INIT(exp_specialmap, list( EXP_TYPE_LIVING = list(), // all living mobs EXP_TYPE_ANTAG = list(), - EXP_TYPE_SPECIAL = list("Lifebringer","Ash Walker","Exile","Servant Golem","Free Golem","Hermit","Translocated Vet","Escaped Prisoner","Hotel Staff","SuperFriend","Space Syndicate","Ancient Crew","Space Doctor","Space Bartender","Beach Bum","Skeleton","Zombie","Space Bar Patron","Lavaland Syndicate",JOB_NAME_PAI,"Ghost Role"), // Ghost roles + EXP_TYPE_SPECIAL = list("Lifebringer","Ash Walker","Exile","Servant Golem","Free Golem","Hermit","Translocated Vet","Escaped Prisoner","Hotel Staff","SuperFriend","Space Syndicate","Ancient Crew","Space Doctor","Beach Bum","Skeleton","Zombie","Lavaland Syndicate",JOB_NAME_PAI,"Ghost Role"), // Ghost roles EXP_TYPE_GHOST = list() // dead people, observers )) GLOBAL_PROTECT(exp_jobsmap) diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 19d1d67f1c6..25fb54ec741 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -513,9 +513,7 @@ if(client.prefs.active_character.joblessrole != RETURNTOLOBBY) return TRUE // If they have antags enabled, they're potentially doing this on purpose instead of by accident. Notify admins if so. - var/has_antags = FALSE - if(client.prefs.be_special.len > 0) - has_antags = TRUE + var/has_antags = (length(client.prefs.role_preferences) + length(client.prefs.active_character?.role_preferences_character)) > 0 if(!length(client.prefs.active_character.job_preferences)) if(!ineligible_for_roles) to_chat(src, "You have no jobs enabled, along with return to lobby if job is unavailable. This makes you ineligible for any round start role, please update your job preferences.") diff --git a/code/modules/mob/dead/observer/notificationprefs.dm b/code/modules/mob/dead/observer/notificationprefs.dm deleted file mode 100644 index 6370747ad46..00000000000 --- a/code/modules/mob/dead/observer/notificationprefs.dm +++ /dev/null @@ -1,53 +0,0 @@ -/mob/dead/observer/verb/show_notificationprefs() - set category = "Ghost" - set name = "Notification preferences" - set desc = "Notification preferences" - - var/datum/notificationpanel/panel = new(usr) - - panel.ui_interact(usr) - - - -/datum/notificationpanel - var/client/user - -/datum/notificationpanel/New(user) - if (ismob(user)) - var/mob/M = user - if (!M.client) - CRASH("Ghost role notification panel attempted to open to a mob without a client") - src.user = M.client - else - src.user = user - - -/datum/notificationpanel/ui_state(mob/user) - return GLOB.observer_state - -/datum/notificationpanel/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "NotificationPreferences") - ui.open() - -/datum/notificationpanel/ui_data(mob/user) - . = list() - .["ignore"] = list() - for(var/key in GLOB.poll_ignore_desc) - .["ignore"] += list(list( - "key" = key, - "enabled" = (user.ckey in GLOB.poll_ignore[key]), - "desc" = GLOB.poll_ignore_desc[key] - )) - - -/datum/notificationpanel/ui_act(action, params) - if(..()) - return - switch (action) - if ("toggle_ignore") - var/key = params["key"] - if (key && islist(GLOB.poll_ignore[key])) - GLOB.poll_ignore[key] ^= list(user.ckey) - . = TRUE diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 6d6396d172f..fbae9c34847 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -3,7 +3,7 @@ icon = 'icons/mob/alien.dmi' gender = FEMALE //All xenos are girls!! dna = null - faction = list(ROLE_ALIEN) + faction = list(FACTION_ALIEN) ventcrawler = VENTCRAWLER_ALWAYS sight = SEE_MOBS see_in_dark = 4 diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index 3fd29dfdfe0..6d4ada4ce49 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -115,12 +115,12 @@ var/recent_queen_death = 0 //Indicates if the queen died recently, aliens are heavily weakened while this is active. /obj/item/organ/alien/hivenode/Insert(mob/living/carbon/M, special = 0) - M.faction |= ROLE_ALIEN + M.faction |= FACTION_ALIEN ADD_TRAIT(M, TRAIT_XENO_IMMUNE, "xeno immune") return ..() /obj/item/organ/alien/hivenode/Remove(mob/living/carbon/M, special = 0) - M.faction -= ROLE_ALIEN + M.faction -= FACTION_ALIEN REMOVE_TRAIT(M, TRAIT_XENO_IMMUNE, "xeno immune") return ..() diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 1aee89c7515..dc4a6ac2b9e 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -90,7 +90,7 @@ bursting = TRUE - var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA) + var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, /datum/role_preference/midround_ghost/xenomorph, 10 SECONDS, POLL_IGNORE_ALIEN_LARVA) // separate poll from xeno event spawns if(QDELETED(src) || QDELETED(owner)) return diff --git a/code/modules/mob/living/living_sentience.dm b/code/modules/mob/living/living_sentience.dm index 2e349cbcd38..d778bac1562 100644 --- a/code/modules/mob/living/living_sentience.dm +++ b/code/modules/mob/living/living_sentience.dm @@ -1,15 +1,19 @@ //WHY ISN'T THIS COMPONENT +/// The ban type to check if somebody attempts to play this "playable mob" +/mob/living/var/playable_bantype + /mob/living/ghostize(can_reenter_corpse, sentience_retention) . = ..() switch(sentience_retention) if (SENTIENCE_RETAIN) if (playable) //so the alert goes through for observing ghosts - set_playable() + set_playable(playable_bantype) if (SENTIENCE_FORCE) - set_playable() + set_playable(playable_bantype) if (SENTIENCE_ERASE) playable = FALSE + playable_bantype = null /mob/living/attack_ghost(mob/user) . = ..() @@ -34,6 +38,10 @@ if(key) to_chat(user, "Someone else already took [name].") return TRUE + if(!SSticker.HasRoundStarted()) + return + if(!user?.client?.can_take_ghost_spawner(playable_bantype, TRUE, flags_1 & ADMIN_SPAWNED_1)) + return key = user.key log_game("[key_name(src)] took control of [name].") remove_from_spawner_menu() @@ -41,10 +49,11 @@ to_chat(src, "[get_spawner_flavour_text()]") return TRUE -/mob/living/proc/set_playable() +/mob/living/proc/set_playable(ban_type = null, poll_ignore_key = null) playable = TRUE + playable_bantype = ban_type if (!key) //check if there is nobody already inhibiting this mob - notify_ghosts("[name] can be controlled", null, enter_link="(Click to play)", source=src, action=NOTIFY_ATTACK, ignore_key = name) + notify_ghosts("[name] can be controlled", null, enter_link="(Click to play)", source=src, action=NOTIFY_ATTACK, ignore_key = poll_ignore_key) LAZYADD(GLOB.mob_spawners["[name]"], src) GLOB.poi_list |= src SSmobs.update_spawners() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 1fd3611725a..dc57aca536b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -904,7 +904,7 @@ /mob/living/silicon/robot/modules/syndicate icon_state = "synd_sec" - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) bubble_icon = "syndibot" req_access = list(ACCESS_SYNDICATE) lawupdate = FALSE diff --git a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm index b873ae66255..9f666beb24f 100644 --- a/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm +++ b/code/modules/mob/living/simple_animal/bot/SuperBeepsky.dm @@ -24,7 +24,7 @@ desc = "The Syndicate sends their regards." emagged = 2 noloot = TRUE - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) /mob/living/simple_animal/bot/secbot/grievous/nullcrate/ComponentInitialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm index b5dd3f01af4..c82610ca84f 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm @@ -47,12 +47,6 @@ /obj/effect/mob_spawn/drone/attack_ghost(mob/user) if(is_banned_from(user.ckey, ROLE_DRONE) || QDELETED(src) || QDELETED(user)) return - if(CONFIG_GET(flag/use_age_restriction_for_jobs)) - if(!isnum_safe(user.client.player_age)) //apparently what happens when there's no DB connected. just don't let anybody be a drone without admin intervention - return - if(user.client.player_age < DRONE_MINIMUM_AGE) - to_chat(user, "You're too new to play as a drone! Please try again in [DRONE_MINIMUM_AGE - user.client.player_age] days.") - return if(!SSticker.mode) to_chat(user, "Can't become a drone before the game has started.") return diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index 057facfda3e..0d22d332ef3 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -18,7 +18,7 @@ health = 30 maxHealth = 120 //If you murder other drones and cannibalize them you can get much stronger initial_language_holder = /datum/language_holder/drone/syndicate - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) speak_emote = list("hisses") bubble_icon = "syndibot" heavy_emp_damage = 10 diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 80f89524fb8..08c9c2448b6 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -462,7 +462,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/mob/living/simple_animal/hostile/guardian/G = input(src, "Pick the guardian you wish to reset", "Guardian Reset") as null|anything in sortNames(guardians) if(G) to_chat(src, "You attempt to reset [G.real_name]'s personality...") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", ROLE_PAI, null, FALSE, 100) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as [src.real_name]'s [G.real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) to_chat(G, "Your user reset you, and your body was taken over by a ghost. Looks like they weren't happy with your performance.") @@ -540,7 +540,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians return used = TRUE to_chat(user, "[use_message]") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_HOLOPARASITE) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_HOLOPARASITE, null, 10 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 3cd5f245d6a..c85b891ea68 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -24,7 +24,7 @@ attack_sound = 'sound/weapons/bladeslice.ogg' atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 15 - faction = list(ROLE_ALIEN) + faction = list(FACTION_ALIEN) status_flags = CANPUSH minbodytemp = 0 see_in_dark = 8 diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index f17d40a8148..3cb408d47c7 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -144,7 +144,7 @@ gender = FEMALE speak_emote = list("squeaks") gold_core_spawnable = NO_SPAWN - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) AIStatus = AI_OFF /// Keeping track of the nuke disk for the functionality of storing it. var/obj/item/disk/nuclear/disky diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 484f5249ecb..b3758fc7464 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -156,7 +156,7 @@ While using this makes the system rely on OnFire, it still gives options for tim addtimer(CALLBACK(src, PROC_REF(spawn_elite)), 30) return visible_message("Something within [src] stirs...") - var/list/candidates = pollCandidatesForMob("Do you want to play as a lavaland elite?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, src, POLL_IGNORE_SENTIENCE_POTION) + var/list/candidates = pollCandidatesForMob("Do you want to play as a lavaland elite?", ROLE_LAVALAND_ELITE, null, 10 SECONDS, src) if(candidates.len) audible_message("The stirring sounds increase in volume!") elitemind = pick(candidates) diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 9d75eb659f7..af8d6db1272 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -40,7 +40,7 @@ loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier) atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 15 - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) check_friendly_fire = 1 status_flags = CANPUSH del_on_death = TRUE @@ -287,7 +287,7 @@ environment_smash = ENVIRONMENT_SMASH_NONE attacktext = "cuts" attack_sound = 'sound/weapons/bladeslice.ogg' - faction = list(ROLE_SYNDICATE) + faction = list(FACTION_SYNDICATE) atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 mob_size = MOB_SIZE_TINY diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm index c365014d62f..e4f104a8afb 100644 --- a/code/modules/mob/living/simple_animal/hostile/wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm @@ -20,7 +20,7 @@ a_intent = INTENT_HARM atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) unsuitable_atmos_damage = 15 - faction = list(ROLE_WIZARD) + faction = list(FACTION_WIZARD) status_flags = CANPUSH retreat_distance = 3 //out of fireball range diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 6e449acdfdd..fd3cd1dd0c7 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -113,7 +113,7 @@ . = ..() set_nutrition(SLIME_DEFAULT_NUTRITION) if(transformeffects & SLIME_EFFECT_LIGHT_PINK) - set_playable() + set_playable(ROLE_SENTIENCE) /mob/living/simple_animal/slime/Destroy() set_target(null) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 157565c96aa..c6e307add8b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -490,15 +490,17 @@ log_admin("[key_name(usr)] has offered control of ([key_name(M)]) to ghosts.") message_admins("[key_name_admin(usr)] has offered control of ([ADMIN_LOOKUPFLW(M)]) to ghosts") var/poll_message = "Do you want to play as [M.real_name]?" + var/ban_key = BAN_ROLE_ALL_ANTAGONISTS if(M.mind && M.mind.assigned_role) poll_message = "[poll_message] Job:[M.mind.assigned_role]." if(M.mind && M.mind.special_role) poll_message = "[poll_message] Status:[M.mind.special_role]." else if(M.mind) - var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist/) + var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist) if(A) poll_message = "[poll_message] Status:[A.name]." - var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, ROLE_PAI, null, FALSE, 100, M) + ban_key = A.banning_key + var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, ban_key, null, 10 SECONDS, M, ignore_category = FALSE) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index 8b8ea63bc9c..a3b656b5f09 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -45,7 +45,7 @@ Contents: return MAP_ERROR //selecting a candidate player - var/list/candidates = get_candidates(ROLE_NINJA, null, ROLE_NINJA) + var/list/candidates = get_candidates(ROLE_NINJA, /datum/role_preference/midround_ghost/ninja) if(!candidates.len) return NOT_ENOUGH_PLAYERS diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 9f42c08f3a4..d165cdd8943 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -583,15 +583,17 @@ /obj/item/projectile/magic/wipe/proc/possession_test(var/mob/living/carbon/M) var/datum/brain_trauma/special/imaginary_friend/trapped_owner/trauma = M.gain_trauma(/datum/brain_trauma/special/imaginary_friend/trapped_owner) var/poll_message = "Do you want to play as [M.real_name]?" + var/ban_key = BAN_ROLE_ALL_ANTAGONISTS if(M.mind?.assigned_role) poll_message = "[poll_message] Job:[M.mind.assigned_role]." if(M.mind?.special_role) poll_message = "[poll_message] Status:[M.mind.special_role]." else if(M.mind) - var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist/) + var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist) if(A) poll_message = "[poll_message] Status:[A.name]." - var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, ROLE_PAI, null, FALSE, 100, M) + ban_key = A.banning_key + var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, ban_key, null, 10 SECONDS, M, ignore_category = FALSE) if(M.stat == DEAD)//boo. return if(LAZYLEN(candidates)) diff --git a/code/modules/religion/rites.dm b/code/modules/religion/rites.dm index 345cbcad35d..d9fc56a01e8 100644 --- a/code/modules/religion/rites.dm +++ b/code/modules/religion/rites.dm @@ -395,8 +395,7 @@ var/turf/altar_turf = get_turf(religious_tool) new /obj/effect/temp_visual/cult/blood/long(altar_turf) new /obj/effect/temp_visual/dir_setting/curse/long(altar_turf) - var/list/jobbans = list(ROLE_BRAINWASHED, ROLE_DEATHSQUAD, ROLE_DRONE, ROLE_LAVALAND, ROLE_MIND_TRANSFER, ROLE_POSIBRAIN, ROLE_SENTIENCE) - var/list/candidates = pollGhostCandidates("Do you wish to be resurrected as a Holy Summoned Undead?", jobbans, null, FALSE,) + var/list/candidates = pollGhostCandidates("Do you wish to be resurrected as a Holy Summoned Undead?", ROLE_HOLY_SUMMONED, null, FALSE) if(!length(candidates)) to_chat(user, "The soul pool is empty...") new /obj/effect/gibspawner/human/bodypartless(altar_turf) @@ -558,8 +557,7 @@ var/turf/altar_turf = get_turf(religious_tool) new /obj/effect/temp_visual/bluespace_fissure/long(altar_turf) user.visible_message("A tear in reality appears above the altar!") - var/list/jobbans = list(ROLE_BRAINWASHED, ROLE_DEATHSQUAD, ROLE_DRONE, ROLE_LAVALAND, ROLE_MIND_TRANSFER, ROLE_POSIBRAIN, ROLE_SENTIENCE) - var/list/candidates = pollGhostCandidates("Do you wish to be summoned as a Holy Carp?", jobbans, null, FALSE) + var/list/candidates = pollGhostCandidates("Do you wish to be summoned as a Holy Carp?", ROLE_HOLY_SUMMONED, null, FALSE) if(!length(candidates)) new /obj/effect/gibspawner/generic(altar_turf) user.visible_message("The carp pool was not strong enough to bring forth a space carp.") diff --git a/code/modules/research/xenobiology/crossbreeding/warping.dm b/code/modules/research/xenobiology/crossbreeding/warping.dm index 87fda9a828e..2ae9c6b746d 100644 --- a/code/modules/research/xenobiology/crossbreeding/warping.dm +++ b/code/modules/research/xenobiology/crossbreeding/warping.dm @@ -713,7 +713,7 @@ GLOBAL_DATUM(blue_storage, /obj/item/storage/backpack/holding/bluespace) return to_chat(user, "The rune is trying to repair [host.name]'s soul!") - var/list/candidates = pollCandidatesForMob("Do you want to replace the soul of [host.name]?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, host, POLL_IGNORE_SHADE)//todo: fix desc + var/list/candidates = pollCandidatesForMob("Do you want to replace the soul of [host.name]?", ROLE_SENTIENCE, null, 5 SECONDS, host, POLL_IGNORE_SHADE) if(length(candidates) && !host.key) //check if anyone wanted to play as the dead person and check if no one's in control of the body one last time. var/mob/dead/observer/ghost = pick(candidates) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 221e42c019c..dfa8e98894e 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -748,7 +748,7 @@ to_chat(user, "You offer [src] to [SM]...") being_used = TRUE - var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]? (Sentience Potion)", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, SM, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm + var/list/candidates = pollCandidatesForMob("Do you want to play as [SM.name]? (Sentience Potion)", ROLE_SENTIENCE, null, 5 SECONDS, SM) if(length(candidates)) var/mob/dead/observer/C = pick(candidates) SM.key = C.key diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 7e1e2b1c871..be12c9f2f6c 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -115,6 +115,7 @@ outfit = /datum/outfit/lavaland_syndicate assignedrole = "Lavaland Syndicate" use_cooldown = TRUE + banType = ROLE_LAVALAND_SYNDICATE /obj/effect/mob_spawn/human/lavaland_syndicate/special(mob/living/new_spawn) new_spawn.grant_language(/datum/language/codespeak) @@ -133,7 +134,7 @@ implants = list(/obj/item/implant/weapons_auth) /datum/outfit/lavaland_syndicate/post_equip(mob/living/carbon/human/H) - H.faction |= ROLE_SYNDICATE + H.faction |= FACTION_SYNDICATE /obj/effect/mob_spawn/human/lavaland_syndicate/comms name = "Syndicate Comms Agent" diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index b8f42696f2d..ea141a15cdc 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -465,6 +465,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) back = /obj/item/storage/backpack/satchel/leather suit = /obj/item/clothing/suit/toggle/labcoat use_cooldown = TRUE + banType = ROLE_HOTEL_STAFF /obj/item/paper/crumpled/docslogs name = "Research Logs" diff --git a/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/assassination.dm b/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/assassination.dm index c49e6cc64ce..88ae992e973 100644 --- a/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/assassination.dm +++ b/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/assassination.dm @@ -35,7 +35,7 @@ /datum/orbital_objective/assassination/generate_objective_stuff(turf/chosen_turf) var/mob/living/carbon/human/created_human = new(chosen_turf) //Maybe polling ghosts would be better than the shintience code - created_human.set_playable() + created_human.set_playable(ROLE_SURVIVALIST) created_human.mind_initialize() //Remove nearby dangers for(var/mob/living/simple_animal/hostile/SA in range(10, created_human)) diff --git a/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/vip_extraction.dm b/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/vip_extraction.dm index de86fe6ff67..c9d288670df 100644 --- a/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/vip_extraction.dm +++ b/code/modules/shuttle/super_cruise/orbital_poi_generator/objective_types/vip_extraction.dm @@ -36,7 +36,7 @@ /datum/orbital_objective/vip_recovery/generate_objective_stuff(turf/chosen_turf) var/mob/living/carbon/human/created_human = new(chosen_turf) //Maybe polling ghosts would be better than the shintience code - created_human.set_playable() + created_human.set_playable(ROLE_EXPLORATION_VIP) created_human.mind_initialize() //Remove nearby dangers for(var/mob/living/simple_animal/hostile/SA in range(10, created_human)) diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 29ddd49e9f9..5cdee0bd98b 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -29,7 +29,7 @@ . = ..() /obj/machinery/computer/shuttle_flight/syndicate/allowed(mob/M) - if(issilicon(M) && !(ROLE_SYNDICATE in M.faction)) + if(issilicon(M) && !(FACTION_SYNDICATE in M.faction)) return FALSE return ..() diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index edf8ab0bad3..77c992afe94 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -57,8 +57,10 @@ #include "create_and_destroy.dm" #endif +#include "antag_datums.dm" #include "dynamic_ruleset_sanity.dm" #include "keybinding_init.dm" +#include "gamemode_sanity.dm" #include "reagent_id_typos.dm" #include "reagent_recipe_collisions.dm" #include "spawn_humans.dm" diff --git a/code/modules/unit_tests/antag_datums.dm b/code/modules/unit_tests/antag_datums.dm new file mode 100644 index 00000000000..fdea39f2ea3 --- /dev/null +++ b/code/modules/unit_tests/antag_datums.dm @@ -0,0 +1,15 @@ +/// Verifies that antag datums have banning_keys. +/datum/unit_test/antag_datum_sanity + +/datum/unit_test/antag_datum_sanity/Run() + for (var/datum/antagonist/antag as anything in subtypesof(/datum/antagonist)) + if(ispath(antag, /datum/antagonist/custom)) + continue + var/name = initial(antag.name) + if (!name || name == "Antagonist") + Fail("[antag] has no name set!") + if (!initial(antag.banning_key)) + Fail("[antag] has no banning_key set!") + var/category = initial(antag.antagpanel_category) + if (initial(antag.show_in_antagpanel) && (!category || category == "Uncategorized")) + Fail("[antag] shows in the antag panel, but has no category set!") diff --git a/code/modules/unit_tests/dynamic_ruleset_sanity.dm b/code/modules/unit_tests/dynamic_ruleset_sanity.dm index 61200a29bb3..84a111a0745 100644 --- a/code/modules/unit_tests/dynamic_ruleset_sanity.dm +++ b/code/modules/unit_tests/dynamic_ruleset_sanity.dm @@ -10,6 +10,17 @@ Fail("[ruleset] has a scaling_cost, but is also a lone/highlander ruleset.") else if (!has_scaling_cost && !is_lone) Fail("[ruleset] has no scaling cost, but is also not a lone/highlander ruleset.") + var/name = initial(ruleset.name) + if(!name) + Fail("[ruleset] has no name!") + if(name == "Extended" || name == "Meteor") // These rulesets don't spawn antags and are exempt. + continue + var/datum/antagonist/antag_datum = initial(ruleset.antag_datum) + if (!ispath(antag_datum, /datum/antagonist) || !initial(antag_datum.banning_key)) + Fail("[ruleset] has no antag_datum with a banning key!") + var/role_pref = initial(ruleset.role_preference) + if (!role_pref || !ispath(role_pref, /datum/role_preference)) + Fail("[ruleset] has no role preference!") for (var/datum/dynamic_ruleset/midround/ruleset as anything in subtypesof(/datum/dynamic_ruleset/midround) - /datum/dynamic_ruleset/midround/from_ghosts) var/midround_ruleset_style = initial(ruleset.midround_ruleset_style) diff --git a/code/modules/unit_tests/gamemode_sanity.dm b/code/modules/unit_tests/gamemode_sanity.dm new file mode 100644 index 00000000000..2ac7e458f0b --- /dev/null +++ b/code/modules/unit_tests/gamemode_sanity.dm @@ -0,0 +1,20 @@ +/// Verifies that gamemodes have various fields +/datum/unit_test/gamemode_sanity + +/datum/unit_test/gamemode_sanity/Run() + for (var/datum/game_mode/mode as anything in subtypesof(/datum/game_mode)) + var/name = initial(mode.name) + if (!name) + Fail("[mode] has no name set!") + var/config_tag = initial(mode.config_tag) + if (!config_tag) + Fail("[mode] has no config_tag set!") + // These gamemodes don't spawn antags directly and are exempt. + if(!initial(mode.required_enemies) && !initial(mode.recommended_enemies)) + continue + var/datum/antagonist/antag_datum = initial(mode.antag_datum) + if (!ispath(antag_datum, /datum/antagonist) || !initial(antag_datum.banning_key)) + Fail("[mode] has no antag_datum with a banning key!") + var/role_pref = initial(mode.role_preference) + if (!role_pref || !ispath(role_pref, /datum/role_preference)) + Fail("[mode] has no role_preference set!") diff --git a/code/modules/xenoarchaeology/traits/xenoartifact_minors.dm b/code/modules/xenoarchaeology/traits/xenoartifact_minors.dm index 8ba217223f2..97efac692b7 100644 --- a/code/modules/xenoarchaeology/traits/xenoartifact_minors.dm +++ b/code/modules/xenoarchaeology/traits/xenoartifact_minors.dm @@ -131,7 +131,7 @@ man.key = M.ckey /datum/xenoartifact_trait/minor/sentient/proc/get_canidate(obj/item/xenoartifact/X, mob/M) - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the maleviolent force inside the [X.name]?", ROLE_SENTIENCE, null, FALSE, 8 SECONDS, POLL_IGNORE_SENTIENCE_POTION) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the maleviolent force inside the [X.name]?", ROLE_SENTIENT_XENOARTIFACT, null, 8 SECONDS) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) setup_sentience(X, C.ckey) @@ -197,6 +197,7 @@ short_desc = "You're a maleviolent sentience, possesing an ancient alien artifact." flavour_text = "Return to your master..." use_cooldown = TRUE + banType = ROLE_SENTIENT_XENOARTIFACT invisibility = 101 var/obj/item/xenoartifact/artifact diff --git a/config/dbconfig.txt b/config/dbconfig.txt index 17550ca61b1..6d1e40ed08e 100644 --- a/config/dbconfig.txt +++ b/config/dbconfig.txt @@ -3,11 +3,11 @@ ## administration, and the in game library. ## Should SQL be enabled? Uncomment to enable -#SQL_ENABLED +SQL_ENABLED ## Server the MySQL database can be found at. ## Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. -ADDRESS localhost +ADDRESS 127.0.0.1 ## MySQL server port (default is 3306). PORT 3306 diff --git a/config/dynamic.json b/config/dynamic.json index 55cd5dc0f04..f7a22b96803 100644 --- a/config/dynamic.json +++ b/config/dynamic.json @@ -7,20 +7,9 @@ "weight": 5, "required_candidates": 1, "minimum_required_age": 0, - "requirements": [ - 10, - 10, - 10, - 10, - 10, - 10, - 10, - 10, - 10, - 10 - ], + "requirements": [8, 8, 8, 8, 8, 8, 8, 8, 8, 8], "antag_cap": { - "denominator": 24 + "denominator": 38 }, "protected_roles": [ "Security Officer", @@ -29,9 +18,7 @@ "Head of Security", "Captain" ], - "restricted_roles": [ - "Cyborg" - ] + "restricted_roles": ["Cyborg"] } }, "Midround": {}, diff --git a/html/admin/banpanel.css b/html/admin/banpanel.css index f19ef6e1ba2..86fe6f84e33 100644 --- a/html/admin/banpanel.css +++ b/html/admin/banpanel.css @@ -1,7 +1,7 @@ .middle { - margin-left: 5px; - margin-right: 5px; - max-width: 125px; + margin-left: 5px; + margin-right: 5px; + max-width: 125px; } .right { @@ -70,10 +70,18 @@ background-color: #6eaa2c; } -.ghostandotherroles { +.ghostroles { background-color: #5c00e6; } .antagonistpositions { - background-color: #6d3f40; + background-color: #6d3f40; +} + +.forcedantagonistpositions { + background-color: #064d10; +} + +.other { + background-color: #cf7474; } diff --git a/nsv13.dme b/nsv13.dme index 08d24ee8f07..54578d4e2ae 100644 --- a/nsv13.dme +++ b/nsv13.dme @@ -1777,6 +1777,13 @@ #include "code\modules\antagonists\revenant\revenant_blight.dm" #include "code\modules\antagonists\revenant\revenant_spawn_event.dm" #include "code\modules\antagonists\revolution\revolution.dm" +#include "code\modules\antagonists\role_preference\_role_preference.dm" +#include "code\modules\antagonists\role_preference\role_antagonists.dm" +#include "code\modules\antagonists\role_preference\role_changeling.dm" +#include "code\modules\antagonists\role_preference\role_midrounds.dm" +#include "code\modules\antagonists\role_preference\role_operative.dm" +#include "code\modules\antagonists\role_preference\role_traitor.dm" +#include "code\modules\antagonists\role_preference\role_wizard.dm" #include "code\modules\antagonists\roundstart_special\special_antagonist.dm" #include "code\modules\antagonists\roundstart_special\undercover\undercover.dm" #include "code\modules\antagonists\santa\santa.dm" @@ -2506,7 +2513,6 @@ #include "code\modules\mob\dead\new_player\sprite_accessories.dm" #include "code\modules\mob\dead\observer\login.dm" #include "code\modules\mob\dead\observer\logout.dm" -#include "code\modules\mob\dead\observer\notificationprefs.dm" #include "code\modules\mob\dead\observer\observer.dm" #include "code\modules\mob\dead\observer\observer_movement.dm" #include "code\modules\mob\dead\observer\orbit.dm" @@ -3844,6 +3850,9 @@ #include "nsv13\code\modules\antagonists\simple_teamchat.dm" #include "nsv13\code\modules\antagonists\boarders\boarders.dm" #include "nsv13\code\modules\antagonists\boarders\pirate_boarders.dm" +#include "nsv13\code\modules\antagonists\ghostship\ghost_ship.dm" +#include "nsv13\code\modules\antagonists\role_preference\role_antagonists.dm" +#include "nsv13\code\modules\antagonists\role_preference\role_midrounds.dm" #include "nsv13\code\modules\atmospherics\gasmixtures\reactions.dm" #include "nsv13\code\modules\atmospherics\machinery\components\binary_devices\constrictor.dm" #include "nsv13\code\modules\atmospherics\machinery\components\unary_devices\outlet_injector.dm" diff --git a/nsv13/code/controllers/subsystem/overmap_mode.dm b/nsv13/code/controllers/subsystem/overmap_mode.dm index a634ee5957e..c0690a54508 100644 --- a/nsv13/code/controllers/subsystem/overmap_mode.dm +++ b/nsv13/code/controllers/subsystem/overmap_mode.dm @@ -659,7 +659,7 @@ SUBSYSTEM_DEF(overmap_mode) if("Cancel") return if("Open") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [initial(target_ship.faction)] [initial(target_ship.name)]?", ROLE_GHOSTSHIP, null, null, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [initial(target_ship.faction)] [initial(target_ship.name)]?", ROLE_GHOSTSHIP, /datum/role_preference/midround_ghost/ghost_ship, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) target_ghost = C diff --git a/nsv13/code/game/gamemodes/bloodling.dm b/nsv13/code/game/gamemodes/bloodling.dm index 87706ff243f..a075a456632 100644 --- a/nsv13/code/game/gamemodes/bloodling.dm +++ b/nsv13/code/game/gamemodes/bloodling.dm @@ -2,7 +2,8 @@ name = "bloodling" config_tag = "bloodling" report_type = "bloodling" - antag_flag = ROLE_BLOODLING + role_preference = /datum/role_preference/antagonist/bloodling + antag_datum = /datum/antagonist/bloodling false_report_weight = 10 restricted_jobs = list("AI", "Cyborg") protected_jobs = list(JOB_NAME_SECURITYOFFICER, JOB_NAME_WARDEN, JOB_NAME_HEADOFSECURITY, JOB_NAME_CAPTAIN, JOB_NAME_BRIGPHYSICIAN) @@ -108,19 +109,21 @@ Helper proc to spawn the lil' blood alien creature in a vent! Adapted from alien if(master) //There's already a master return if(bloodlings.len < bloodling_amount) - if(ROLE_BLOODLING in character.client.prefs.be_special) - if(!is_banned_from(character.ckey, list(ROLE_BLOODLING, ROLE_SYNDICATE)) && !QDELETED(character)) - if(age_check(character.client)) - if(!(character.job in restricted_jobs)) - if(!master) //Make him the master - master = spawn_bloodling() - if(!master) - return FALSE //yeah okay your shit map doesn't support bloodling RIP - master.key = character.client.ckey - bloodlings += master.mind - qdel(character) //Bye! - //Otherwise, make him a new thrall... - character.mind.add_antag_datum(/datum/antagonist/changeling/bloodling_thrall) + if(!QDELETED(character) && character.client?.should_include_for_role( + banning_key = initial(antag_datum.banning_key), + role_preference_key = role_preference, + req_hours = initial(antag_datum.required_living_playtime), + )) + if(!(character.job in restricted_jobs)) if(!(character.job in restricted_jobs)) + if(!master) //Make him the master + master = spawn_bloodling() + if(!master) + return FALSE //yeah okay your shit map doesn't support bloodling RIP + master.key = character.client.ckey + bloodlings += master.mind + qdel(character) //Bye! + //Otherwise, make him a new thrall... + character.mind.add_antag_datum(/datum/antagonist/changeling/bloodling_thrall) /datum/game_mode/bloodling/generate_report() diff --git a/nsv13/code/game/gamemodes/pvp/pvp.dm b/nsv13/code/game/gamemodes/pvp/pvp.dm index e2e82902605..703a8eb2491 100644 --- a/nsv13/code/game/gamemodes/pvp/pvp.dm +++ b/nsv13/code/game/gamemodes/pvp/pvp.dm @@ -16,8 +16,8 @@ GLOBAL_LIST_EMPTY(syndi_crew_leader_spawns) required_players = 24 //40 // 40 to make 20 v 20 required_enemies = 12 //20 recommended_enemies = 15 - antag_flag = ROLE_SYNDI_CREW - enemy_minimum_age = 0 + role_preference = /datum/role_preference/antagonist/pvp + antag_datum = /datum/antagonist/nukeop/syndi_crew announce_span = "danger" announce_text = "The Syndicate are planning an all out assault!\n\ diff --git a/nsv13/code/game/gamemodes/pvp/roles.dm b/nsv13/code/game/gamemodes/pvp/roles.dm index 91c2b025464..98dfa96d77f 100644 --- a/nsv13/code/game/gamemodes/pvp/roles.dm +++ b/nsv13/code/game/gamemodes/pvp/roles.dm @@ -53,7 +53,7 @@ /datum/antagonist/nukeop/syndi_crew name = "Syndicate crew" nukeop_outfit = /datum/outfit/syndicate/no_crystals/syndi_crew - job_rank = ROLE_SYNDI_CREW + banning_key = ROLE_SYNDI_CREW tips = "galactic_conquest" give_objectives = FALSE //Their objective is to win the game @@ -230,7 +230,7 @@ Singleton to handle conquest roles. This exists to populate the roles list and n /datum/antagonist/nukeop/syndi_crew/strategist name = "Syndicate Strategist" nukeop_outfit = /datum/outfit/syndicate/no_crystals/syndi_crew/strategist - job_rank = ROLE_SYNDI_CREW + banning_key = ROLE_SYNDI_CREW /datum/outfit/syndicate/no_crystals/syndi_crew/strategist name = "Syndicate Strategist" @@ -383,7 +383,7 @@ Singleton to handle conquest roles. This exists to populate the roles list and n /datum/antagonist/nukeop/syndi_crew/clown name = "Syndicate Clown" nukeop_outfit = /datum/outfit/syndicate/clownop/no_crystals/jojo_reference - job_rank = ROLE_SYNDI_CREW + banning_key = ROLE_SYNDI_CREW /datum/antagonist/nukeop/syndi_crew/clown/give_alias() owner.current.fully_replace_character_name(owner.current.real_name, owner.current.client.prefs.active_character.custom_names["clown"]) diff --git a/nsv13/code/game/objects/effects/spawners/custom_ghost_role_spawners.dm b/nsv13/code/game/objects/effects/spawners/custom_ghost_role_spawners.dm index 8eadc64edbc..4bee8db8109 100644 --- a/nsv13/code/game/objects/effects/spawners/custom_ghost_role_spawners.dm +++ b/nsv13/code/game/objects/effects/spawners/custom_ghost_role_spawners.dm @@ -29,7 +29,7 @@ . = ..() var/area/A = get_area(src) if(A) - notify_ghosts("A Syndicate Crewmember is about to thaw from cryo on \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_SYNDICATE) + notify_ghosts("A Syndicate Crewmember is about to thaw from cryo on \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE) /obj/effect/mob_spawn/human/nsv13/nt_prisoner/ name = "a prisoner stasis pod" diff --git a/nsv13/code/modules/antagonists/bloodling.dm b/nsv13/code/modules/antagonists/bloodling.dm index 69c3dc87153..e30d74b9320 100644 --- a/nsv13/code/modules/antagonists/bloodling.dm +++ b/nsv13/code/modules/antagonists/bloodling.dm @@ -283,6 +283,7 @@ Infestation! If given a human, it makes them a changeling thrall. If given any o var/antag_hud_type = ANTAG_HUD_BLOODLING var/antag_hud_name = "bloodling_thrall" var/component_type = /datum/component/bloodling + banning_key = ROLE_BLOODLING /datum/antagonist/bloodling/greet() to_chat(owner.current, "We are the master!") @@ -813,7 +814,7 @@ Depending on what creature the entity gives life to, this can be EXTREMELY stron refund_biomass(user, biomass_cost) return FALSE - var/list/candidates = pollCandidatesForMob("Do you want to play as a bloodling minion?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm + var/list/candidates = pollCandidatesForMob("Do you want to play as a bloodling minion?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M) // see poll_ignore.dm if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) var/datum/component/bloodling/B = user.GetComponent(/datum/component/bloodling) diff --git a/nsv13/code/modules/antagonists/ghostship/ghost_ship.dm b/nsv13/code/modules/antagonists/ghostship/ghost_ship.dm new file mode 100644 index 00000000000..000247bb89c --- /dev/null +++ b/nsv13/code/modules/antagonists/ghostship/ghost_ship.dm @@ -0,0 +1,8 @@ +/datum/antagonist/ghost_ship + name = "Ghost Ship" + show_name_in_check_antagonists = TRUE + show_in_antagpanel = FALSE + show_in_roundend = FALSE + banning_key = ROLE_GHOSTSHIP + +///Used for tracking and because the role_preferences needs an antag_datum to point at. diff --git a/nsv13/code/modules/antagonists/role_preference/role_antagonists.dm b/nsv13/code/modules/antagonists/role_preference/role_antagonists.dm new file mode 100644 index 00000000000..b46cee28337 --- /dev/null +++ b/nsv13/code/modules/antagonists/role_preference/role_antagonists.dm @@ -0,0 +1,7 @@ +/datum/role_preference/antagonist/bloodling + name = "Bloodling" + antag_datum = /datum/antagonist/bloodling + +/datum/role_preference/antagonist/pvp + name = "Galactic Conquest" + antag_datum = /datum/antagonist/nukeop/syndi_crew diff --git a/nsv13/code/modules/antagonists/role_preference/role_midrounds.dm b/nsv13/code/modules/antagonists/role_preference/role_midrounds.dm new file mode 100644 index 00000000000..38bf28a2bc9 --- /dev/null +++ b/nsv13/code/modules/antagonists/role_preference/role_midrounds.dm @@ -0,0 +1,7 @@ +/datum/role_preference/midround_ghost/ghost_ship + name = "Ghost Ship" + antag_datum = /datum/antagonist/ghost_ship + +/datum/role_preference/midround_ghost/boarder + name = "Boarder" + antag_datum = /datum/antagonist/traitor/boarder diff --git a/nsv13/code/modules/cargo/objective_cargo.dm b/nsv13/code/modules/cargo/objective_cargo.dm index 231b2242a96..15a86587059 100644 --- a/nsv13/code/modules/cargo/objective_cargo.dm +++ b/nsv13/code/modules/cargo/objective_cargo.dm @@ -42,7 +42,7 @@ /obj/structure/closet/crate/large/freight_objective/proc/poll_for_ghost_sentience() for ( var/mob/living/simple_animal/M in contents ) if ( rand( 1, 20 ) == 20 ) // Random sentient mob event! - var/list/candidates = pollCandidatesForMob("Do you want to play as [M]?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M, POLL_IGNORE_SENTIENCE_POTION) + var/list/candidates = pollCandidatesForMob("Do you want to play as [M]?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, M) M.AIStatus = AI_ON // Keep the mob asleep unless the poll receives no candidates if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) diff --git a/nsv13/code/modules/overmap/ai-skynet.dm b/nsv13/code/modules/overmap/ai-skynet.dm index eab22f31145..ef7f5a28f00 100644 --- a/nsv13/code/modules/overmap/ai-skynet.dm +++ b/nsv13/code/modules/overmap/ai-skynet.dm @@ -716,7 +716,7 @@ Adding tasks is easy! Just define a datum for it. var/target_location = locate(rand(round(world.maxx/2) + 10, world.maxx - 39), rand(40, world.maxy - 39), OM.z) var/obj/structure/overmap/selected_ship = pick(ship_list) var/target_ghost - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [initial(selected_ship.faction)] [initial(selected_ship.name)]?", ROLE_GHOSTSHIP, null, null, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [initial(selected_ship.faction)] [initial(selected_ship.name)]?", ROLE_GHOSTSHIP, /datum/role_preference/midround_ghost/ghost_ship, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) target_ghost = C diff --git a/nsv13/code/modules/overmap/boarding/boarding.dm b/nsv13/code/modules/overmap/boarding/boarding.dm index 5b96c56c9ed..cdad8f74b11 100644 --- a/nsv13/code/modules/overmap/boarding/boarding.dm +++ b/nsv13/code/modules/overmap/boarding/boarding.dm @@ -34,7 +34,7 @@ //20 or more players? You're allowed "real" boarders. if(player_check >= min_players_for_ghosts) // Remove the low pop boarder camping - candidates = pollCandidatesForMob("Do you want to play as a boarding team member?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 10 SECONDS, src) + candidates = pollCandidatesForMob("Do you want to play as a boarding team member?", ROLE_OPERATIVE, /datum/role_preference/midround_ghost/boarder, 10 SECONDS, src) //No candidates? Well! Guess you get to deal with some KNPCs :)))))) if(!length(candidates)) return spawn_knpcs(amount, faction_selection) diff --git a/nsv13/code/modules/overmap/boarding/ghost_role_spawners.dm b/nsv13/code/modules/overmap/boarding/ghost_role_spawners.dm index 307cbf05edd..ed63d498484 100644 --- a/nsv13/code/modules/overmap/boarding/ghost_role_spawners.dm +++ b/nsv13/code/modules/overmap/boarding/ghost_role_spawners.dm @@ -1,3 +1,25 @@ +/obj/effect/mob_spawn/human/syndicate + name = "Syndicate Operative" + roundstart = FALSE + death = FALSE + icon = 'icons/obj/machines/sleeper.dmi' + icon_state = "sleeper_s" + outfit = /datum/outfit/syndicate_empty + assignedrole = "Space Syndicate" //I know this is really dumb, but Syndicate operative is nuke ops + +/datum/outfit/syndicate_empty + name = "Syndicate Operative Empty" + uniform = /obj/item/clothing/under/syndicate + shoes = /obj/item/clothing/shoes/combat + gloves = /obj/item/clothing/gloves/combat + ears = /obj/item/radio/headset/syndicate/alt + back = /obj/item/storage/backpack + implants = list(/obj/item/implant/weapons_auth) + id = /obj/item/card/id/syndicate + +/datum/outfit/syndicate_empty/post_equip(mob/living/carbon/human/H) + H.faction |= FACTION_SYNDICATE + /datum/outfit/syndicate_empty/boarding/captain name = "Syndicate Captain (Boarding)" id = /obj/item/card/id/syndicate/nuke_leader diff --git a/nsv13/code/modules/overmap/overmap_ghosts.dm b/nsv13/code/modules/overmap/overmap_ghosts.dm index 5f0f1f385ee..56b960f254a 100644 --- a/nsv13/code/modules/overmap/overmap_ghosts.dm +++ b/nsv13/code/modules/overmap/overmap_ghosts.dm @@ -16,7 +16,7 @@ if("Cancel") return if("Open") - var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [src.faction] [src.name]?", ROLE_GHOSTSHIP, null, null, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you wish to pilot a [src.faction] [src.name]?", ROLE_GHOSTSHIP, /datum/role_preference/midround_ghost/ghost_ship, 20 SECONDS, POLL_IGNORE_GHOSTSHIP) if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) target_ghost = C @@ -84,6 +84,10 @@ ghost.hud_type = /datum/hud //Mostly blank hud ghost.key = target.key + //More or less a modified version of how the morph antag gets the antag datum. + if(ghost.mind) + ghost.mind.add_antag_datum(/datum/antagonist/ghost_ship) + //Allows player to hear hails mobs_in_ship += ghost diff --git a/tgui/packages/tgui/interfaces/NotificationPreferences.js b/tgui/packages/tgui/interfaces/NotificationPreferences.js deleted file mode 100644 index 91d992ee420..00000000000 --- a/tgui/packages/tgui/interfaces/NotificationPreferences.js +++ /dev/null @@ -1,41 +0,0 @@ -import { useBackend } from '../backend'; -import { Section, Button } from '../components'; -import { Window } from '../layouts'; - -export const NotificationPreferences = (props, context) => { - const { act, data } = useBackend(context); - - const ignoresPreSort = data.ignore || []; - const ignores = ignoresPreSort.sort((a, b) => { - const descA = a.desc.toLowerCase(); - const descB = b.desc.toLowerCase(); - if (descA < descB) { - return -1; - } - if (descA > descB) { - return 1; - } - return 0; - }); - - return ( - - -
- {ignores.map(ignore => ( -
-
-
- ); -};