diff --git a/baystation12.dme b/baystation12.dme index 1cbd9ee410c..82badb93616 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -978,8 +978,8 @@ #include "code\modules\client\preferences_toggles.dm" #include "code\modules\client\ui_style.dm" #include "code\modules\client\preference_setup\preference_setup.dm" -#include "code\modules\client\preference_setup\antagonism\01_basic.dm" -#include "code\modules\client\preference_setup\antagonism\02_candidacy.dm" +#include "code\modules\client\preference_setup\antagonism\01_candidacy.dm" +#include "code\modules\client\preference_setup\antagonism\02_setup.dm" #include "code\modules\client\preference_setup\general\01_basic.dm" #include "code\modules\client\preference_setup\general\02_language.dm" #include "code\modules\client\preference_setup\general\03_body.dm" diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index d117d0df5c7..94288982684 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -9,44 +9,9 @@ #define SEC_LEVEL_RED 2 #define SEC_LEVEL_DELTA 3 -#define BE_TRAITOR 0x1 -#define BE_OPERATIVE 0x2 -#define BE_CHANGELING 0x4 -#define BE_WIZARD 0x8 -#define BE_MALF 0x10 -#define BE_REV 0x20 -#define BE_ALIEN 0x40 -#define BE_AI 0x80 -#define BE_CULTIST 0x100 -#define BE_MONKEY 0x200 -#define BE_NINJA 0x400 -#define BE_RAIDER 0x800 -#define BE_PLANT 0x1000 -#define BE_MUTINEER 0x2000 -#define BE_PAI 0x4000 -#define BE_LOYALIST 0x8000 - -var/list/be_special_flags = list( - "Traitor" = BE_TRAITOR, - "Operative" = BE_OPERATIVE, - "Changeling" = BE_CHANGELING, - "Wizard" = BE_WIZARD, - "Malf AI" = BE_MALF, - "Revolutionary" = BE_REV, - "Loyalist" = BE_LOYALIST, - "Xenomorph" = BE_ALIEN, - "Positronic Brain" = BE_AI, - "Cultist" = BE_CULTIST, - "Monkey" = BE_MONKEY, - "Ninja" = BE_NINJA, - "Raider" = BE_RAIDER, - "Diona" = BE_PLANT, - "Mutineer" = BE_MUTINEER, - "pAI" = BE_PAI -) - -#define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE)))) - +#define BE_PLANT "BE_PLANT" +#define BE_SYNTH "BE_SYNTH" +#define BE_PAI "BE_PAI" // Antagonist datum flags. #define ANTAG_OVERRIDE_JOB 0x1 // Assigned job is set to MODE when spawning. diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index cf955a022c7..2a4dc372d92 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -330,12 +330,11 @@ proc/isInSight(var/atom/A, var/atom/B) // Same as above but for alien candidates. /proc/get_alien_candidates() - var/list/candidates = list() //List of candidate KEYS to assume control of the new larva ~Carn var/i = 0 while(candidates.len <= 0 && i < 5) for(var/mob/dead/observer/G in player_list) - if(G.client.prefs.be_special & BE_ALIEN) + if(MODE_XENOMORPH in G.client.prefs.be_special_role) if(((G.client.inactivity/10)/60) <= ALIEN_SELECT_AFK_BUFFER + i) // the most active players are more likely to become an alien if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD)) candidates += G.key diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm index 36f5216045a..2eb8d2d23fc 100644 --- a/code/game/antagonist/alien/xenomorph.dm +++ b/code/game/antagonist/alien/xenomorph.dm @@ -2,7 +2,6 @@ var/datum/antagonist/xenos/xenomorphs /datum/antagonist/xenos id = MODE_XENOMORPH - role_type = BE_ALIEN role_text = "Xenomorph" role_text_plural = "Xenomorphs" mob_path = /mob/living/carbon/alien/larva diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 32f40ad985d..2dd934d1f04 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -14,7 +14,7 @@ // Role data. var/id = "traitor" // Unique datum identifier. - var/role_type = BE_TRAITOR // Preferences option for this role. + var/role_type // Preferences option for this role. Defaults to the id if unset var/role_text = "Traitor" // special_role text. var/role_text_plural = "Traitors" // As above but plural. @@ -72,6 +72,9 @@ /datum/antagonist/New() ..() + if(!role_type) + role_type = id + cur_max = hard_cap get_starting_locations() if(!role_text_plural) diff --git a/code/game/antagonist/outsider/actors.dm b/code/game/antagonist/outsider/actors.dm index 7d5deb39e76..d9e8d422700 100644 --- a/code/game/antagonist/outsider/actors.dm +++ b/code/game/antagonist/outsider/actors.dm @@ -2,8 +2,7 @@ var/datum/antagonist/actor/actor /datum/antagonist/actor id = MODE_ACTOR - bantype = "operative" - role_type = BE_OPERATIVE + bantype = "actor" role_text = "NanoTrasen Actor" role_text_plural = "NanoTrasen Actors" welcome_text = "You've been hired to entertain people through the power of television!" diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index ca0b39aaefe..2abdb5db3d4 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -2,7 +2,6 @@ var/datum/antagonist/deathsquad/deathsquad /datum/antagonist/deathsquad id = MODE_DEATHSQUAD - role_type = BE_OPERATIVE role_text = "Death Commando" role_text_plural = "Death Commandos" welcome_text = "You work in the service of corporate Asset Protection, answering directly to the Board of Directors." diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm index e8517dbf4e8..5408a8a889d 100644 --- a/code/game/antagonist/outsider/ert.dm +++ b/code/game/antagonist/outsider/ert.dm @@ -3,7 +3,6 @@ var/datum/antagonist/ert/ert /datum/antagonist/ert id = MODE_ERT bantype = "Emergency Response Team" - role_type = BE_OPERATIVE role_text = "Emergency Responder" role_text_plural = "Emergency Responders" welcome_text = "As member of the Emergency Response Team, you answer only to your leader and company officials." @@ -41,6 +40,6 @@ var/datum/antagonist/ert/ert player.equip_to_slot_or_del(new /obj/item/clothing/shoes/swat(src), slot_shoes) player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves) player.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(src), slot_glasses) - + create_id(role_text, player) return 1 diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm index e2c44aef70f..82415de808a 100644 --- a/code/game/antagonist/outsider/mercenary.dm +++ b/code/game/antagonist/outsider/mercenary.dm @@ -2,7 +2,6 @@ var/datum/antagonist/mercenary/mercs /datum/antagonist/mercenary id = MODE_MERCENARY - role_type = BE_OPERATIVE role_text = "Mercenary" bantype = "operative" antag_indicator = "synd" diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm index 09dc15b5949..eeead17be7f 100644 --- a/code/game/antagonist/outsider/ninja.dm +++ b/code/game/antagonist/outsider/ninja.dm @@ -2,7 +2,6 @@ var/datum/antagonist/ninja/ninjas /datum/antagonist/ninja id = MODE_NINJA - role_type = BE_NINJA role_text = "Ninja" role_text_plural = "Ninja" bantype = "ninja" diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm index 8ab342bbf24..26648a34f04 100644 --- a/code/game/antagonist/outsider/raider.dm +++ b/code/game/antagonist/outsider/raider.dm @@ -2,7 +2,6 @@ var/datum/antagonist/raider/raiders /datum/antagonist/raider id = MODE_RAIDER - role_type = BE_RAIDER role_text = "Raider" role_text_plural = "Raiders" bantype = "raider" diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm index f6741cafa07..292277b1a27 100644 --- a/code/game/antagonist/outsider/wizard.dm +++ b/code/game/antagonist/outsider/wizard.dm @@ -2,7 +2,6 @@ var/datum/antagonist/wizard/wizards /datum/antagonist/wizard id = MODE_WIZARD - role_type = BE_WIZARD role_text = "Space Wizard" role_text_plural = "Space Wizards" bantype = "wizard" diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm index dad7ed81a26..2fe9581cbda 100644 --- a/code/game/antagonist/station/changeling.dm +++ b/code/game/antagonist/station/changeling.dm @@ -1,6 +1,5 @@ /datum/antagonist/changeling id = MODE_CHANGELING - role_type = BE_CHANGELING role_text = "Changeling" role_text_plural = "Changelings" bantype = "changeling" diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm index aba2115d152..cc6314c7519 100644 --- a/code/game/antagonist/station/cultist.dm +++ b/code/game/antagonist/station/cultist.dm @@ -13,7 +13,6 @@ var/datum/antagonist/cultist/cult bantype = "cultist" restricted_jobs = list("Chaplain","AI", "Cyborg", "Internal Affairs Agent", "Head of Security", "Captain") protected_jobs = list("Security Officer", "Warden", "Detective") - role_type = BE_CULTIST feedback_tag = "cult_objective" antag_indicator = "cult" welcome_text = "You have a talisman in your possession; one that will help you start the cult on this station. Use it well and remember - there are others." diff --git a/code/game/antagonist/station/loyalist.dm b/code/game/antagonist/station/loyalist.dm index fddf0c37960..f8b5ec49946 100644 --- a/code/game/antagonist/station/loyalist.dm +++ b/code/game/antagonist/station/loyalist.dm @@ -2,7 +2,6 @@ var/datum/antagonist/loyalists/loyalists /datum/antagonist/loyalists id = MODE_LOYALIST - role_type = BE_LOYALIST role_text = "Head Loyalist" role_text_plural = "Loyalists" bantype = "loyalist" diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm index 96e37529915..ca0011f8d72 100644 --- a/code/game/antagonist/station/revolutionary.dm +++ b/code/game/antagonist/station/revolutionary.dm @@ -2,7 +2,6 @@ var/datum/antagonist/revolutionary/revs /datum/antagonist/revolutionary id = MODE_REVOLUTIONARY - role_type = BE_REV role_text = "Head Revolutionary" role_text_plural = "Revolutionaries" bantype = "revolutionary" diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm index 4240708cc22..ea99bf14afb 100644 --- a/code/game/antagonist/station/rogue_ai.dm +++ b/code/game/antagonist/station/rogue_ai.dm @@ -2,7 +2,6 @@ var/datum/antagonist/rogue_ai/malf /datum/antagonist/rogue_ai id = MODE_MALFUNCTION - role_type = BE_MALF role_text = "Rampant AI" role_text_plural = "Rampant AIs" mob_path = /mob/living/silicon/ai diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 83085fdda99..2a3c361bc99 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -435,7 +435,7 @@ var/global/list/additional_antag_types = list() continue if(istype(player, /mob/new_player)) continue - if(!role || (player.client.prefs.be_special & role)) + if(!role || (role in player.client.prefs.be_special_role)) log_debug("[player.key] had [antag_id] enabled, so we are drafting them.") candidates |= player.mind else @@ -446,7 +446,7 @@ var/global/list/additional_antag_types = list() // Get a list of all the people who want to be the antagonist for this round for(var/mob/new_player/player in players) - if(!role || (player.client.prefs.be_special & role)) + if(!role || (role in player.client.prefs.be_special_role)) log_debug("[player.key] had [antag_id] enabled, so we are drafting them.") candidates += player.mind players -= player diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 7bf949e217f..53b6627f076 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -91,7 +91,7 @@ var/global/datum/controller/occupations/job_master if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age)) Debug("FOC character not old enough, Player: [player]") continue - if(flag && (!player.client.prefs.be_special & flag)) + if(flag && !(flag in player.client.prefs.be_special_role)) Debug("FOC flag failed, Player: [player], Flag: [flag], ") continue if(player.client.prefs.GetJobDepartment(job, level) & job.flag) diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 3cbacf9e501..613e9c7241a 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -52,6 +52,8 @@ var/list/whitelist = list() //todo: admin aliens /proc/is_alien_whitelisted(mob/M, var/species) + if(!M || !species) + return 0 if(!config.usealienwhitelist) return 1 if(istype(species,/datum/species) || istype(species,/datum/language)) diff --git a/code/game/objects/structures/alien/egg.dm b/code/game/objects/structures/alien/egg.dm index c16c1a182e8..5d32f9685f6 100644 --- a/code/game/objects/structures/alien/egg.dm +++ b/code/game/objects/structures/alien/egg.dm @@ -30,7 +30,7 @@ progress++ if(progress >= MAX_PROGRESS) for(var/mob/M in dead_mob_list) - if(istype(M,/mob/dead) && M.client && M.client.prefs && (M.client.prefs.be_special & BE_ALIEN)) + if(istype(M,/mob/dead) && M.client && M.client.prefs && (MODE_XENOMORPH in M.client.prefs.be_special_role)) M << "An alien is ready to hatch! ([ghost_follow_link(src, M)]) (spawn)" processing_objects -= src update_icon() diff --git a/code/modules/client/preference_setup/antagonism/01_candidacy.dm b/code/modules/client/preference_setup/antagonism/01_candidacy.dm new file mode 100644 index 00000000000..449a5ceb747 --- /dev/null +++ b/code/modules/client/preference_setup/antagonism/01_candidacy.dm @@ -0,0 +1,84 @@ +var/list/private_valid_special_roles + +/datum/category_item/player_setup_item/antagonism/candidacy + name = "Candidacy" + sort_order = 1 + +/datum/category_item/player_setup_item/antagonism/candidacy/load_character(var/savefile/S) + S["be_special"] >> pref.be_special_role + +/datum/category_item/player_setup_item/antagonism/candidacy/save_character(var/savefile/S) + S["be_special"] << pref.be_special_role + +/datum/category_item/player_setup_item/antagonism/candidacy/sanitize_character() + if(!istype(pref.be_special_role)) + pref.be_special_role = list() + + for(var/role in pref.be_special_role) + if(!(role in valid_special_roles())) + pref.be_special_role -= role + +/datum/category_item/player_setup_item/antagonism/candidacy/content(var/mob/user) + . += "Special Role Availability:
" + . += "" + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + . += "" + + var/list/ghost_traps = get_ghost_traps() + for(var/ghost_trap_key in ghost_traps) + var/datum/ghosttrap/ghost_trap = ghost_traps[ghost_trap_key] + if(!ghost_trap.list_as_special_role) + continue + + . += "" + . += "
[antag.role_text]: " + if(jobban_isbanned(preference_mob(), antag.bantype)) + . += "\[BANNED\]
" + else if(antag.role_type in pref.be_special_role) + . += "Yes / No
" + else + . += "Yes / No
" + . += "
[(ghost_trap.ghost_trap_role)]: " + if(banned_from_ghost_role(preference_mob(), ghost_trap)) + . += "\[BANNED\]
" + else if(ghost_trap.pref_check in pref.be_special_role) + . += "Yes / No
" + else + . += "Yes / No
" + . += "
" + +/datum/category_item/player_setup_item/proc/banned_from_ghost_role(var/mob, var/datum/ghosttrap/ghost_trap) + for(var/ban_type in ghost_trap.ban_checks) + if(jobban_isbanned(mob, ban_type)) + return 1 + return 0 + +/datum/category_item/player_setup_item/antagonism/candidacy/OnTopic(var/href,var/list/href_list, var/mob/user) + if(href_list["add_special"]) + if(!(href_list["add_special"] in valid_special_roles())) + return TOPIC_HANDLED + pref.be_special_role |= href_list["add_special"] + return TOPIC_REFRESH + + if(href_list["del_special"]) + pref.be_special_role -= href_list["del_special"] + return TOPIC_REFRESH + + return ..() + +/datum/category_item/player_setup_item/antagonism/candidacy/proc/valid_special_roles() + if(!(private_valid_special_roles && private_valid_special_roles.len)) + private_valid_special_roles = list() + for(var/antag_type in all_antag_types) + var/datum/antagonist/antag = all_antag_types[antag_type] + private_valid_special_roles += antag.role_type + + var/list/ghost_traps = get_ghost_traps() + for(var/ghost_trap_key in ghost_traps) + var/datum/ghosttrap/ghost_trap = ghost_traps[ghost_trap_key] + if(!ghost_trap.list_as_special_role) + continue + private_valid_special_roles += ghost_trap.pref_check + + return private_valid_special_roles diff --git a/code/modules/client/preference_setup/antagonism/02_candidacy.dm b/code/modules/client/preference_setup/antagonism/02_candidacy.dm deleted file mode 100644 index 82d44027afe..00000000000 --- a/code/modules/client/preference_setup/antagonism/02_candidacy.dm +++ /dev/null @@ -1,54 +0,0 @@ -var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm --rastaf -//some autodetection here. -// TODO: Update to new antagonist system. - "traitor" = IS_MODE_COMPILED("traitor"), // 0 - "operative" = IS_MODE_COMPILED("nuclear"), // 1 - "changeling" = IS_MODE_COMPILED("changeling"), // 2 - "wizard" = IS_MODE_COMPILED("wizard"), // 3 - "malf AI" = IS_MODE_COMPILED("malfunction"), // 4 - "revolutionary" = IS_MODE_COMPILED("revolution"), // 5 - "alien candidate" = 1, //always show // 6 - "positronic brain" = 1, // 7 - "cultist" = IS_MODE_COMPILED("cult"), // 8 - "infested monkey" = IS_MODE_COMPILED("monkey"), // 9 - "ninja" = "true", // 10 - "raider" = IS_MODE_COMPILED("heist"), // 11 - "diona" = 1, // 12 - "loyalist" = IS_MODE_COMPILED("revolution"), // 13 - "pAI candidate" = 1, // -- TLE // 14 -) - -/datum/category_item/player_setup_item/antagonism/candidacy - name = "Candidacy" - sort_order = 2 - -/datum/category_item/player_setup_item/antagonism/candidacy/load_character(var/savefile/S) - S["be_special"] >> pref.be_special - -/datum/category_item/player_setup_item/antagonism/candidacy/save_character(var/savefile/S) - S["be_special"] << pref.be_special - -/datum/category_item/player_setup_item/antagonism/candidacy/sanitize_character() - pref.be_special = sanitize_integer(pref.be_special, 0, 65535, initial(pref.be_special)) - -/datum/category_item/player_setup_item/antagonism/candidacy/content(var/mob/user) - if(jobban_isbanned(user, "Syndicate")) - . += "You are banned from antagonist roles." - pref.be_special = 0 - else - var/n = 0 - for (var/i in special_roles) - if(special_roles[i]) //if mode is available on the server - if(jobban_isbanned(user, i) || (i == "positronic brain" && jobban_isbanned(user, "AI") && jobban_isbanned(user, "Cyborg")) || (i == "pAI candidate" && jobban_isbanned(user, "pAI"))) - . += "Be [i]: \[BANNED]
" - else - . += "Be [i]: [pref.be_special&(1<
" - n++ - -/datum/category_item/player_setup_item/antagonism/candidacy/OnTopic(var/href,var/list/href_list, var/mob/user) - if(href_list["be_special"]) - var/num = text2num(href_list["be_special"]) - pref.be_special ^= (1<> pref.uplinklocation @@ -16,9 +16,9 @@ var/global/list/uplink_locations = list("PDA", "Headset", "None") pref.uplinklocation = sanitize_inlist(pref.uplinklocation, uplink_locations, initial(pref.uplinklocation)) /datum/category_item/player_setup_item/antagonism/basic/content(var/mob/user) - . +="Uplink Type : [pref.uplinklocation]" - . +="
" - . +="Exploitable information:
" + . +="Antag Setup:
" + . +="Uplink Type: [pref.uplinklocation]
" + . +="Exploitable information:
" if(jobban_isbanned(user, "Records")) . += "You are banned from using character records.
" else diff --git a/code/modules/client/preference_setup/preference_setup.dm b/code/modules/client/preference_setup/preference_setup.dm index 13df4a05e01..90a15851dc4 100644 --- a/code/modules/client/preference_setup/preference_setup.dm +++ b/code/modules/client/preference_setup/preference_setup.dm @@ -19,7 +19,7 @@ category_item_type = /datum/category_item/player_setup_item/occupation /datum/category_group/player_setup_category/appearance_preferences - name = "Antagonism" + name = "Roles" sort_order = 4 category_item_type = /datum/category_item/player_setup_item/antagonism diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index a5a037ee811..6c5eaeb0544 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -17,7 +17,7 @@ datum/preferences //game-preferences var/lastchangelog = "" //Saved changlog filesize to detect if there was a change var/ooccolor = "#010000" //Whatever this is set to acts as 'reset' color and is thus unusable as an actual custom color - var/be_special = 0 //Special role selection + var/list/be_special_role = list() //Special role selection var/UI_style = "Midnight" var/toggles = TOGGLES_DEFAULT var/UI_style_color = "#ffffff" diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm index 09ee55b1736..b2d0958dbd5 100644 --- a/code/modules/client/preferences_toggles.dm +++ b/code/modules/client/preferences_toggles.dm @@ -145,15 +145,3 @@ src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) feedback_add_details("admin_verb","TAmbi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - -//be special -/client/verb/toggle_be_special(role in be_special_flags) - set name = "Toggle SpecialRole Candidacy" - set category = "Preferences" - set desc = "Toggles which special roles you would like to be a candidate for, during events." - var/role_flag = be_special_flags[role] - if(!role_flag) return - prefs.be_special ^= role_flag - prefs.save_preferences() - src << "You will [(prefs.be_special & role_flag) ? "now" : "no longer"] be considered for [role] events (where possible)." - feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/ghosttrap/trap.dm b/code/modules/ghosttrap/trap.dm index c6afe7ac987..92eb1d0f1c5 100644 --- a/code/modules/ghosttrap/trap.dm +++ b/code/modules/ghosttrap/trap.dm @@ -3,12 +3,17 @@ var/list/ghost_traps -proc/get_ghost_trap(var/trap_key) +/proc/get_ghost_trap(var/trap_key) if(!ghost_traps) populate_ghost_traps() return ghost_traps[trap_key] -proc/populate_ghost_traps() +/proc/get_ghost_traps() + if(!ghost_traps) + populate_ghost_traps() + return ghost_traps + +/proc/populate_ghost_traps() ghost_traps = list() for(var/traptype in typesof(/datum/ghosttrap)) var/datum/ghosttrap/G = new traptype @@ -18,14 +23,20 @@ proc/populate_ghost_traps() var/object = "positronic brain" var/minutes_since_death = 0 // If non-zero the ghost must have been dead for this many minutes to be allowed to spawn var/list/ban_checks = list("AI","Cyborg") - var/pref_check = BE_AI + var/pref_check = BE_SYNTH var/ghost_trap_message = "They are occupying a positronic brain now." var/ghost_trap_role = "Positronic Brain" + var/can_set_own_name = TRUE + var/list_as_special_role = TRUE // If true, this entry will be listed as a special role in the character setup + + var/list/request_timeouts + +/datum/ghosttrap/New() + request_timeouts = list() + ..() // Check for bans, proper atom types, etc. -/datum/ghosttrap/proc/assess_candidate(var/mob/dead/observer/candidate) - if(!istype(candidate) || !candidate.client || !candidate.ckey) - return 0 +/datum/ghosttrap/proc/assess_candidate(var/mob/dead/observer/candidate, var/mob/target) if(!candidate.MayRespawn(1, minutes_since_death)) return 0 if(islist(ban_checks)) @@ -36,9 +47,13 @@ proc/populate_ghost_traps() return 1 // Print a message to all ghosts with the right prefs/lack of bans. -/datum/ghosttrap/proc/request_player(var/mob/target, var/request_string) - if(!target) - return +/datum/ghosttrap/proc/request_player(var/mob/target, var/request_string, var/request_timeout) + if(request_timeout) + request_timeouts[target] = world.time + request_timeout + target.destruction.register(src, /datum/ghosttrap/proc/target_destroyed) + else + request_timeouts -= target + for(var/mob/dead/observer/O in player_list) if(!O.MayRespawn()) continue @@ -46,10 +61,13 @@ proc/populate_ghost_traps() for(var/bantype in ban_checks) if(jobban_isbanned(O, "[bantype]")) continue - if(pref_check && !(O.client.prefs.be_special & pref_check)) + if(pref_check && !(pref_check in O.client.prefs.be_special_role)) continue if(O.client) - O << "[request_string]Click here if you wish to play as this option." + O << "[request_string] (Occupy) ([ghost_follow_link(target, O)])" + +/datum/ghosttrap/proc/target_destroyed(var/destroyed_target) + request_timeouts -= destroyed_target // Handles a response to request_player(). /datum/ghosttrap/Topic(href, href_list) @@ -60,7 +78,15 @@ proc/populate_ghost_traps() var/mob/target = locate(href_list["target"]) // So much BYOND magic. if(!target || !candidate) return - if(candidate == usr && assess_candidate(candidate) && !target.ckey) + if(candidate != usr) + return + if(request_timeouts[target] && world.time > request_timeouts[target]) + candidate << "This occupation request is no longer valid." + return + if(target.key) + candidate << "The target is already occupied." + return + if(assess_candidate(candidate, target)) transfer_personality(candidate,target) return 1 @@ -93,12 +119,17 @@ proc/populate_ghost_traps() // Allows people to set their own name. May or may not need to be removed for posibrains if people are dumbasses. /datum/ghosttrap/proc/set_new_name(var/mob/target) + if(!can_set_own_name) + return + var/newname = sanitizeSafe(input(target,"Enter a name, or leave blank for the default name.", "Name change","") as text, MAX_NAME_LEN) if (newname != "") target.real_name = newname target.name = target.real_name -// Doona pods and walking mushrooms. +/*********************************** +* Diona pods and walking mushrooms * +***********************************/ /datum/ghosttrap/plant object = "living plant" ban_checks = list("Dionaea") @@ -111,4 +142,47 @@ proc/populate_ghost_traps() // This is a hack, replace with some kind of species blurb proc. if(istype(target,/mob/living/carbon/alien/diona)) target << "You are \a [target], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders." - target << "Too much darkness will send you into shock and starve you, but light will help you heal." \ No newline at end of file + target << "Too much darkness will send you into shock and starve you, but light will help you heal." + +/***************** +* Cortical Borer * +*****************/ +/datum/ghosttrap/borer + object = "cortical borer" + ban_checks = list("Borer") + pref_check = MODE_BORER + ghost_trap_message = "They are occupying a borer now." + ghost_trap_role = "Cortical Borer" + can_set_own_name = FALSE + list_as_special_role = FALSE + +/datum/ghosttrap/borer/welcome_candidate(var/mob/target) + target << "You are a cortical borer! You are a brain slug that worms its way \ + into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, \ + your host and your eventual spawn safe and warm." + target << "You can speak to your victim with say, to other borers with say [target.get_language_prefix()]x, and use your Abilities tab to access powers." + +/******************** +* Maintenance Drone * +*********************/ +/datum/ghosttrap/drone + object = "maintenance drone" + pref_check = BE_PAI + ghost_trap_message = "They are occupying a maintenance drone now." + ghost_trap_role = "Maintenance Drone" + can_set_own_name = FALSE + list_as_special_role = FALSE + +/datum/ghosttrap/drone/New() + minutes_since_death = DRONE_SPAWN_DELAY + ..() + +datum/ghosttrap/drone/assess_candidate(var/mob/dead/observer/candidate, var/mob/target) + . = ..() + if(. && !target.can_be_possessed_by(candidate)) + return 0 + +datum/ghosttrap/drone/transfer_personality(var/mob/candidate, var/mob/living/silicon/robot/drone/drone) + if(!assess_candidate(candidate)) + return 0 + drone.transfer_personality(candidate.client) diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index 88462acb47a..3c2ee048a7f 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -4,7 +4,7 @@ if(!host || !istype(host)) return var/datum/ghosttrap/plant/P = get_ghost_trap("living plant") - P.request_player(host, "Someone is harvesting [display_name]. ") + P.request_player(host, "Someone is harvesting \a [display_name].") spawn(75) if(!host.ckey && !host.client) diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 5bb14920823..5350ec6403f 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -16,63 +16,14 @@ /obj/item/device/mmi/digital/posibrain/attack_self(mob/user as mob) if(brainmob && !brainmob.key && searching == 0) //Start the process of searching for a new user. - user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process." + user << "You carefully locate the manual activation switch and start the positronic brain's boot process." icon_state = "posibrain-searching" src.searching = 1 - src.request_player() + var/datum/ghosttrap/G = get_ghost_trap("positronic brain") + G.request_player(brainmob, "Someone is requesting a personality for a positronic brain.", 60 SECONDS) spawn(600) reset_search() -/obj/item/device/mmi/digital/posibrain/proc/request_player() - for(var/mob/dead/observer/O in player_list) - if(!O.MayRespawn()) - continue - if(jobban_isbanned(O, "AI") && jobban_isbanned(O, "Cyborg")) - continue - if(O.client) - if(O.client.prefs.be_special & BE_AI) - question(O.client) - -/obj/item/device/mmi/digital/posibrain/proc/question(var/client/C) - spawn(0) - if(!C) return - var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round") - if(response == "Yes") - response = alert(C, "Are you sure you want to play as a positronic brain?", "Positronic brain request", "Yes", "No") - if(!C || brainmob.key || 0 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located. - if(response == "Yes") - transfer_personality(C.mob) - else if (response == "Never for this round") - C.prefs.be_special ^= BE_AI - - -/obj/item/device/mmi/digital/posibrain/transfer_identity(var/mob/living/carbon/H) - ..() - if(brainmob.mind) - brainmob.mind.assigned_role = "Positronic Brain" - brainmob << "You feel slightly disoriented. That's normal when you're just a metal cube." - icon_state = "posibrain-occupied" - return - -/obj/item/device/mmi/digital/posibrain/proc/transfer_personality(var/mob/candidate) - announce_ghost_joinleave(candidate, 0, "They are occupying a positronic brain now.") - src.searching = 0 - src.brainmob.mind = candidate.mind - src.brainmob.ckey = candidate.ckey - src.brainmob.mind.reset() - src.name = "positronic brain ([src.brainmob.name])" - src.brainmob << "You are a positronic brain, brought into existence on [station_name()]." - src.brainmob << "As a synthetic intelligence, you answer to all crewmembers, as well as the AI." - src.brainmob << "Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm." - src.brainmob << "Use say [candidate.get_language_prefix()]b to speak to other artificial intelligences." - src.brainmob.mind.assigned_role = "Positronic Brain" - - var/turf/T = get_turf_or_move(src.loc) - for (var/mob/M in viewers(T)) - M.show_message("\blue The positronic brain chimes quietly.") - icon_state = "posibrain-occupied" - /obj/item/device/mmi/digital/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer. - if(src.brainmob && src.brainmob.key) return src.searching = 0 @@ -80,7 +31,19 @@ var/turf/T = get_turf_or_move(src.loc) for (var/mob/M in viewers(T)) - M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") + M.show_message("The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?") + +/obj/item/device/mmi/digital/posibrain/attack_ghost(var/mob/dead/observer/user) + if(!searching || (src.brainmob && src.brainmob.key)) + return + + var/datum/ghosttrap/G = get_ghost_trap("positronic brain") + if(!G.assess_candidate(user)) + return + var/response = alert(user, "Are you sure you wish to possess this [src]?", "Possess [src]", "Yes", "No") + if(response == "Yes") + G.transfer_personality(user, brainmob) + return /obj/item/device/mmi/digital/posibrain/examine(mob/user) if(!..(user)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 3099c654375..ffe29a519d5 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -827,8 +827,11 @@ default behaviour is: if(deaf >= 0) ear_deaf = deaf -/mob/living/proc/can_be_possessed_by(var/mob/dead/observer/possessor) - if(!istype(possessor)) +/mob/proc/can_be_possessed_by(var/mob/dead/observer/possessor) + return istype(possessor) && possessor.client + +/mob/living/can_be_possessed_by(var/mob/dead/observer/possessor) + if(!..()) return 0 if(!possession_candidate) possessor << "That animal cannot be possessed." diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index 91a10bf3e50..1bae59372f7 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -357,7 +357,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates else asked.Remove(O.key) if(O.client) - if(O.client.prefs.be_special & BE_PAI) + if(BE_PAI in O.client.prefs.be_special_role) question(O.client) /datum/paiController/proc/question(var/client/C) @@ -370,4 +370,4 @@ var/datum/paiController/paiController // Global handler for pAI candidates if(response == "Yes") recruitWindow(C.mob) else if (response == "Never for this round") - C.prefs.be_special ^= BE_PAI + C.prefs.be_special_role -= BE_PAI diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 9346b63c16a..af4d59c3db2 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -60,11 +60,14 @@ var/list/mob_hat_cache = list() holder_type = /obj/item/weapon/holder/drone /mob/living/silicon/robot/drone/can_be_possessed_by(var/mob/dead/observer/possessor) - if(!istype(possessor)) + if(!istype(possessor) || !possessor.client || !possessor.ckey) return 0 if(!config.allow_drone_spawn) src << "Playing as drones is not currently permitted." return 0 + if(too_many_active_drones()) + src << "The maximum number of active drones has been reached.." + return 0 if(jobban_isbanned(possessor,"Cyborg")) usr << "You are banned from playing synthetics and cannot spawn as a drone." return 0 @@ -161,7 +164,7 @@ var/list/mob_hat_cache = list() if(hat) return hat = new_hat - new_hat.loc = src + new_hat.forceMove(src) updateicon() //Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..(). @@ -196,12 +199,7 @@ var/list/mob_hat_cache = list() return user.visible_message("\The [user] swipes \his ID card through \the [src], attempting to reboot it.", ">You swipe your ID card through \the [src], attempting to reboot it.") - var/drones = 0 - for(var/mob/living/silicon/robot/drone/D in world) - if(D.key && D.client) - drones++ - if(drones < config.max_maint_drones) - request_player() + request_player() return else @@ -304,28 +302,13 @@ var/list/mob_hat_cache = list() //Reboot procs. /mob/living/silicon/robot/drone/proc/request_player() - for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, "Cyborg")) - continue - if(O.client) - if(O.client.prefs.be_special & BE_PAI) - question(O.client) - -/mob/living/silicon/robot/drone/proc/question(var/client/C) - spawn(0) - if(!C || jobban_isbanned(C,"Cyborg")) return - var/response = alert(C, "Someone is attempting to reboot a maintenance drone. Would you like to play as one?", "Maintenance drone reboot", "Yes", "No", "Never for this round") - if(!C || ckey) - return - if(response == "Yes") - transfer_personality(C) - else if (response == "Never for this round") - C.prefs.be_special ^= BE_PAI + if(too_many_active_drones()) + return + var/datum/ghosttrap/G = get_ghost_trap("maintenance drone") + G.request_player(src, "Someone is attempting to reboot a maintenance drone.", 30 SECONDS) /mob/living/silicon/robot/drone/proc/transfer_personality(var/client/player) - if(!player) return - src.ckey = player.ckey if(player.mob && player.mob.mind) @@ -361,3 +344,10 @@ var/list/mob_hat_cache = list() /mob/living/silicon/robot/drone/construction/updatename() real_name = "construction drone ([rand(100,999)])" name = real_name + +/proc/too_many_active_drones() + var/drones = 0 + for(var/mob/living/silicon/robot/drone/D in mob_list) + if(D.key && D.client) + drones++ + return drones >= config.max_maint_drones diff --git a/code/modules/mob/living/simple_animal/borer/borer.dm b/code/modules/mob/living/simple_animal/borer/borer.dm index d8606524e21..7836493722d 100644 --- a/code/modules/mob/living/simple_animal/borer/borer.dm +++ b/code/modules/mob/living/simple_animal/borer/borer.dm @@ -173,41 +173,8 @@ //Procs for grabbing players. /mob/living/simple_animal/borer/proc/request_player() - for(var/mob/dead/observer/O in player_list) - if(jobban_isbanned(O, "Borer")) - continue - if(O.client) - if(O.client.prefs.be_special & BE_ALIEN) - question(O.client) - -/mob/living/simple_animal/borer/proc/question(var/client/C) - spawn(0) - if(!C) return - var/response = alert(C, "A cortical borer needs a player. Are you interested?", "Cortical borer request", "Yes", "No", "Never for this round") - if(!C || ckey) - return - if(response == "Yes") - transfer_personality(C) - else if (response == "Never for this round") - C.prefs.be_special ^= BE_ALIEN - -/mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate) - - if(!candidate || !candidate.mob || !candidate.mob.mind) - return - - src.mind = candidate.mob.mind - candidate.mob.mind.current = src - src.ckey = candidate.ckey - - if(src.mind) - src.mind.assigned_role = "Cortical Borer" - src.mind.special_role = "Cortical Borer" - - src << "You are a cortical borer! You are a brain slug that worms its way \ - into the head of its victim. Use stealth, persuasion and your powers of mind control to keep you, \ - your host and your eventual spawn safe and warm." - src << "You can speak to your victim with say, to other borers with say :x, and use your Abilities tab to access powers." + var/datum/ghosttrap/G = get_ghost_trap("cortical borer") + G.request_player(src, "A cortical borer needs a player.") /mob/living/simple_animal/borer/cannot_use_vents() - return \ No newline at end of file + return