From e38e6b8fa44f45d367fc4f218a9ee4ab8d760253 Mon Sep 17 00:00:00 2001 From: AnturK Date: Fri, 19 Jan 2018 15:43:23 +0100 Subject: [PATCH] Antag Panel / Check antagonists Refactor (#34236) * Antag Panel & Friends Refactor * Prettfying * Removes abduction also blob from default configs. * Ninja fixes * Ninjafix * First draft of the new check_antags * I love coding without compiler * Yes * Fixes * Check_antags part 2 * Fixes and cleanup * Okay should be good now. * Adds simple no move & no tc syndie for events * Integrates toggle objective pr * Why i even bother. * Offer mob shows all antags * Some minor visual stuff * Proper name for the helper --- code/__DEFINES/antagonists.dm | 2 - code/__DEFINES/role_preferences.dm | 2 +- code/__HELPERS/roundend.dm | 7 +- code/datums/antagonists/abductor.dm | 49 +- code/datums/antagonists/antag_datum.dm | 101 ++- code/datums/antagonists/blob.dm | 10 +- code/datums/antagonists/brother.dm | 38 +- code/datums/antagonists/changeling.dm | 38 +- code/datums/antagonists/clockcult.dm | 48 +- code/datums/antagonists/cult.dm | 36 +- code/datums/antagonists/datum_traitor.dm | 44 +- code/datums/antagonists/devil.dm | 44 +- code/datums/antagonists/internal_affairs.dm | 14 +- code/datums/antagonists/monkey.dm | 55 +- code/datums/antagonists/ninja.dm | 72 +- code/datums/antagonists/nukeop.dm | 63 +- code/datums/antagonists/pirate.dm | 3 + code/datums/antagonists/revolution.dm | 110 ++- code/datums/antagonists/wizard.dm | 9 + code/datums/datumvars.dm | 22 - code/datums/diseases/transformation.dm | 2 +- code/datums/mind.dm | 809 ++---------------- code/game/gamemodes/antag_spawner.dm | 11 +- code/game/gamemodes/antag_team.dm | 14 +- code/game/gamemodes/brother/traitor_bro.dm | 5 +- code/game/gamemodes/changeling/changeling.dm | 2 +- .../gamemodes/changeling/powers/absorb.dm | 6 +- code/game/gamemodes/clock_cult/clock_cult.dm | 27 + .../clock_structures/eminence_spire.dm | 3 +- code/game/gamemodes/cult/cult.dm | 2 +- code/game/gamemodes/cult/cult_comms.dm | 1 + .../miniantags/abduction/abduction.dm | 92 +- code/game/gamemodes/miniantags/morph/morph.dm | 1 - .../gamemodes/miniantags/revenant/revenant.dm | 1 - .../miniantags/slaughter/slaughterevent.dm | 1 - code/game/gamemodes/revolution/revolution.dm | 2 +- code/game/gamemodes/traitor/traitor.dm | 8 +- code/game/machinery/wishgranter.dm | 1 - code/game/objects/items/devices/doorCharge.dm | 2 +- code/modules/admin/admin.dm | 7 +- code/modules/admin/antag_panel.dm | 217 +++++ code/modules/admin/check_antagonists.dm | 212 +++++ code/modules/admin/player_panel.dm | 340 +------- code/modules/admin/secrets.dm | 2 +- code/modules/admin/topic.dm | 20 +- code/modules/admin/verbs/one_click_antag.dm | 3 - code/modules/admin/verbs/onlyone.dm | 1 - .../awaymissions/mission_code/wildwest.dm | 1 - code/modules/events/abductor.dm | 18 +- code/modules/events/holiday/vday.dm | 6 - code/modules/events/nightmare.dm | 1 - .../modules/events/wizard/departmentrevolt.dm | 3 +- code/modules/events/wizard/greentext.dm | 2 - code/modules/events/wizard/imposter.dm | 2 +- code/modules/mob/living/silicon/robot/life.dm | 1 - code/modules/mob/mob.dm | 1 - code/modules/mob/mob_helpers.dm | 4 + code/modules/ninja/ninja_event.dm | 35 +- code/modules/power/singularity/narsie.dm | 2 + .../reagents/chemistry/recipes/others.dm | 1 - .../spells/spell_types/rightandwrong.dm | 4 +- config/game_options.txt | 7 - tgstation.dme | 2 + 63 files changed, 1218 insertions(+), 1431 deletions(-) create mode 100644 code/modules/admin/antag_panel.dm create mode 100644 code/modules/admin/check_antagonists.dm diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index 1fba96b1eb09..7fab07159518 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -4,8 +4,6 @@ #define ANTAG_DATUM_CLOCKCULT_SILENT /datum/antagonist/clockcult/silent #define ANTAG_DATUM_DEVIL /datum/antagonist/devil #define ANTAG_DATUM_NINJA /datum/antagonist/ninja -#define ANTAG_DATUM_NINJA_FRIENDLY /datum/antagonist/ninja/friendly -#define ANTAG_DATUM_NINJA_RANDOM /datum/antagonist/ninja/randomAllegiance/ #define ANTAG_DATUM_TRAITOR /datum/antagonist/traitor #define ANTAG_DATUM_TRAITOR_HUMAN /datum/antagonist/traitor/human #define ANTAG_DATUM_TRAITOR_AI /datum/antagonist/traitor/AI diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 5b48890ce676..1d3300bbf8c1 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -42,7 +42,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_NINJA, ROLE_MONKEY = /datum/game_mode/monkey, ROLE_REVENANT, - ROLE_ABDUCTOR = /datum/game_mode/abduction, + ROLE_ABDUCTOR, ROLE_DEVIL = /datum/game_mode/devil, ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult )) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 1966fa8219db..5ff7cd9e496a 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -26,6 +26,9 @@ var/list/team_ids = list() for(var/datum/antagonist/A in GLOB.antagonists) + if(!A.owner) + continue + var/list/antag_info = list() antag_info["key"] = A.owner.key antag_info["name"] = A.owner.name @@ -41,8 +44,6 @@ team_ids[T] = team_gid++ antag_info["team"]["id"] = team_ids[T] - if(!A.owner) - continue if(A.objectives.len) for(var/datum/objective/O in A.objectives) var/result = O.check_completion() ? "SUCCESS" : "FAIL" @@ -368,6 +369,8 @@ var/list/all_antagonists = list() for(var/datum/antagonist/A in GLOB.antagonists) + if(!A.owner) + continue all_teams |= A.get_team() all_antagonists += A diff --git a/code/datums/antagonists/abductor.dm b/code/datums/antagonists/abductor.dm index a98acf054e8f..fde8d0059b60 100644 --- a/code/datums/antagonists/abductor.dm +++ b/code/datums/antagonists/abductor.dm @@ -1,24 +1,33 @@ +#define ABDUCTOR_MAX_TEAMS 4 + /datum/antagonist/abductor name = "Abductor" roundend_category = "abductors" + antagpanel_category = "Abductor" job_rank = ROLE_ABDUCTOR + show_in_antagpanel = FALSE //should only show subtypes var/datum/team/abductor_team/team var/sub_role var/outfit var/landmark_type var/greet_text + /datum/antagonist/abductor/agent + name = "Abductor Agent" sub_role = "Agent" outfit = /datum/outfit/abductor/agent landmark_type = /obj/effect/landmark/abductor/agent greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve." + show_in_antagpanel = TRUE /datum/antagonist/abductor/scientist + name = "Abductor Scientist" sub_role = "Scientist" outfit = /datum/outfit/abductor/scientist landmark_type = /obj/effect/landmark/abductor/scientist greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve." + show_in_antagpanel = TRUE /datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team) if(!new_team) @@ -33,6 +42,7 @@ /datum/antagonist/abductor/on_gain() SSticker.mode.abductors += owner owner.special_role = "[name] [sub_role]" + owner.assigned_role = "[name] [sub_role]" owner.objectives += team.objectives finalize_abductor() return ..() @@ -72,11 +82,48 @@ var/datum/species/abductor/A = H.dna.species A.scientist = TRUE +/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin) + var/list/current_teams = list() + for(var/datum/team/abductor_team/T in get_all_teams(/datum/team/abductor_team)) + current_teams[T.name] = T + var/choice = input(admin,"Add to which team ?") as null|anything in (current_teams + "new team") + if (choice == "new team") + team = new + else if(choice in current_teams) + team = current_teams[choice] + else + return + new_owner.add_antag_datum(src) + log_admin("[key_name(usr)] made [key_name(new_owner.current)] [name] on [choice]!") + message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner.current)] [name] on [choice] !") + +/datum/antagonist/abductor/get_admin_commands() + . = ..() + .["Equip"] = CALLBACK(src,.proc/admin_equip) + +/datum/antagonist/abductor/proc/admin_equip(mob/admin) + if(!ishuman(owner.current)) + to_chat(admin, "This only works on humans!") + return + var/mob/living/carbon/human/H = owner.current + var/gear = alert(admin,"Agent or Scientist Gear","Gear","Agent","Scientist") + if(gear) + if(gear=="Agent") + H.equipOutfit(/datum/outfit/abductor/agent) + else + H.equipOutfit(/datum/outfit/abductor/scientist) /datum/team/abductor_team member_name = "abductor" var/team_number var/list/datum/mind/abductees = list() + var/static/team_count = 1 + +/datum/team/abductor_team/New() + ..() + team_number = team_count++ + name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names + add_objective(new/datum/objective/experiment) /datum/team/abductor_team/is_solo() return FALSE @@ -105,10 +152,10 @@ return result.Join("
") - /datum/antagonist/abductee name = "Abductee" roundend_category = "abductees" + antagpanel_category = "Abductee" /datum/antagonist/abductee/on_gain() give_objective() diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm index 9b5dbb6d7584..6140dc67978d 100644 --- a/code/datums/antagonists/antag_datum.dm +++ b/code/datums/antagonists/antag_datum.dm @@ -12,12 +12,15 @@ GLOBAL_LIST_EMPTY(antagonists) var/job_rank var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted. var/list/objectives = list() + var/antag_memory = ""//These will be removed with antag datum + + //Antag panel properties + var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind + var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED -/datum/antagonist/New(datum/mind/new_owner) +/datum/antagonist/New() GLOB.antagonists += src typecache_datum_blacklist = typecacheof(typecache_datum_blacklist) - if(new_owner) - owner = new_owner /datum/antagonist/Destroy() GLOB.antagonists -= src @@ -36,6 +39,11 @@ GLOBAL_LIST_EMPTY(antagonists) if(is_type_in_typecache(src, A.typecache_datum_blacklist)) return FALSE +//This will be called in add_antag_datum before owner assignment. +//Should return antag datum without owner. +/datum/antagonist/proc/specialization(datum/mind/new_owner) + return src + /datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body) remove_innate_effects(old_body) apply_innate_effects(new_body) @@ -131,18 +139,82 @@ GLOBAL_LIST_EMPTY(antagonists) /datum/antagonist/proc/roundend_report_footer() return + +//ADMIN TOOLS + +//Called when using admin tools to give antag status +/datum/antagonist/proc/admin_add(datum/mind/new_owner,mob/admin) + message_admins("[key_name_admin(admin)] made [new_owner.current] into [name].") + log_admin("[key_name(admin)] made [new_owner.current] into [name].") + new_owner.add_antag_datum(src) + +//Called when removing antagonist using admin tools +/datum/antagonist/proc/admin_remove(mob/user) + if(!user) + return + message_admins("[key_name_admin(user)] has removed [name] antagonist status from [owner.current].") + log_admin("[key_name(user)] has removed [name] antagonist status from [owner.current].") + on_removal() + +//gamemode/proc/is_mode_antag(antagonist/A) => TRUE/FALSE + +//Additional data to display in antagonist panel section +//nuke disk code, genome count, etc +/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() + +/datum/antagonist/Topic(href,href_list) + if(!check_rights(R_ADMIN)) + return + //Antag memory edit + if (href_list["memory_edit"]) + edit_memory(usr) + owner.traitor_panel() + return + + //Some commands might delete/modify this datum clearing or changing owner + var/datum/mind/persistent_owner = owner + + var/commands = get_admin_commands() + for(var/admin_command in commands) + if(href_list["command"] == admin_command) + var/datum/callback/C = commands[admin_command] + C.Invoke(usr) + persistent_owner.traitor_panel() + return + +/datum/antagonist/proc/edit_memory(mob/user) + var/new_memo = copytext(trim(input(user,"Write new memory", "Memory", antag_memory) as null|message),1,MAX_MESSAGE_LEN) + if (isnull(new_memo)) + return + antag_memory = new_memo + //Should probably be on ticker or job ss ? /proc/get_antagonists(antag_type,specific = FALSE) . = list() for(var/datum/antagonist/A in GLOB.antagonists) - if(!specific && istype(A,antag_type) || specific && A.type == antag_type) + if(!A.owner) + continue + if(!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type) . += A.owner - - //This datum will autofill the name with special_role //Used as placeholder for minor antagonists, please create proper datums for these /datum/antagonist/auto_custom + show_in_antagpanel = FALSE + antagpanel_category = "Other" /datum/antagonist/auto_custom/on_gain() ..() @@ -156,5 +228,20 @@ GLOBAL_LIST_EMPTY(antagonists) already_registered_objectives |= A.objectives objectives = owner.objectives - already_registered_objectives +/datum/antagonist/auto_custom/antag_listing_name() + return ..() + "([name])" + //This one is created by admin tools for custom objectives -/datum/antagonist/custom \ No newline at end of file +/datum/antagonist/custom + antagpanel_category = "Custom" + +/datum/antagonist/custom/admin_add(datum/mind/new_owner,mob/admin) + var/custom_name = stripped_input(admin, "Custom antagonist name:", "Custom antag", "Antagonist") + if(custom_name) + name = custom_name + else + return + ..() + +/datum/antagonist/custom/antag_listing_name() + return ..() + "([name])" \ No newline at end of file diff --git a/code/datums/antagonists/blob.dm b/code/datums/antagonists/blob.dm index 5689e6a5679e..964bc9931160 100644 --- a/code/datums/antagonists/blob.dm +++ b/code/datums/antagonists/blob.dm @@ -1,6 +1,7 @@ /datum/antagonist/blob name = "Blob" roundend_category = "blobs" + antagpanel_category = "Blob" job_rank = ROLE_BLOB var/datum/action/innate/blobpop/pop_action @@ -56,4 +57,11 @@ var/mob/camera/blob/B = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob) owner.mind.transfer_to(B) old_body.gib() - B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE) \ No newline at end of file + B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE) + +/datum/antagonist/blob/antag_listing_status() + . = ..() + if(owner && owner.current) + var/mob/camera/blob/B = owner.current + if(istype(B)) + . += "(Progress: [B.blobs_legit.len]/[B.blobwincount])" \ No newline at end of file diff --git a/code/datums/antagonists/brother.dm b/code/datums/antagonists/brother.dm index b06c75e4fa34..e4c43ef78858 100644 --- a/code/datums/antagonists/brother.dm +++ b/code/datums/antagonists/brother.dm @@ -1,12 +1,10 @@ /datum/antagonist/brother name = "Brother" + antagpanel_category = "Brother" job_rank = ROLE_BROTHER var/special_role = "blood brother" var/datum/team/brother_team/team -/datum/antagonist/brother/New(datum/mind/new_owner) - return ..() - /datum/antagonist/brother/create_team(datum/team/brother_team/new_team) if(!new_team) return @@ -36,7 +34,7 @@ if(!owner.current || !team || !team.meeting_area) return to_chat(owner.current, "Your designated meeting area: [team.meeting_area]") - owner.store_memory("Meeting Area: [team.meeting_area]") + antag_memory += "Meeting Area: [team.meeting_area]
" /datum/antagonist/brother/greet() var/brother_text = "" @@ -56,15 +54,42 @@ /datum/antagonist/brother/proc/finalize_brother() SSticker.mode.update_brother_icons_added(owner) +/datum/antagonist/brother/admin_add(datum/mind/new_owner,mob/admin) + //show list of possible brothers + var/list/candidates = list() + for(var/mob/living/L in GLOB.alive_mob_list) + if(!L.mind || L.mind == new_owner || !can_be_owned(L.mind)) + continue + candidates[L.mind.name] = L.mind + + var/choice = input(admin,"Choose the blood brother.", "Brother") as null|anything in candidates + if(!choice) + return + var/datum/mind/bro = candidates[choice] + var/datum/team/brother_team/T = new + T.add_member(new_owner) + T.add_member(bro) + T.pick_meeting_area() + T.forge_brother_objectives() + new_owner.add_antag_datum(ANTAG_DATUM_BROTHER,T) + bro.add_antag_datum(ANTAG_DATUM_BROTHER, T) + T.update_name() + message_admins("[key_name_admin(admin)] made [new_owner.current] and [bro.current] into blood brothers.") + log_admin("[key_name(admin)] made [new_owner.current] and [bro.current] into blood brothers.") /datum/team/brother_team name = "brotherhood" member_name = "blood brother" var/meeting_area + var/static/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library") /datum/team/brother_team/is_solo() return FALSE +/datum/team/brother_team/proc/pick_meeting_area() + meeting_area = pick(meeting_areas) + meeting_areas -= meeting_area + /datum/team/brother_team/proc/update_name() var/list/last_names = list() for(var/datum/mind/M in members) @@ -122,4 +147,7 @@ else add_objective(new/datum/objective/assassinate, TRUE) else - add_objective(new/datum/objective/steal, TRUE) \ No newline at end of file + add_objective(new/datum/objective/steal, TRUE) + +/datum/team/brother_team/antag_listing_name() + return "[name] blood brothers" \ No newline at end of file diff --git a/code/datums/antagonists/changeling.dm b/code/datums/antagonists/changeling.dm index 53d0c37143ec..5d4e34cd9706 100644 --- a/code/datums/antagonists/changeling.dm +++ b/code/datums/antagonists/changeling.dm @@ -5,6 +5,7 @@ /datum/antagonist/changeling name = "Changeling" roundend_category = "changelings" + antagpanel_category = "Changeling" job_rank = ROLE_CHANGELING var/you_are_greet = TRUE @@ -40,11 +41,6 @@ var/static/list/all_powers = typecacheof(/obj/effect/proc_holder/changeling,TRUE) -/datum/antagonist/changeling/New() - . = ..() - generate_name() - create_actions() - /datum/antagonist/changeling/Destroy() QDEL_NULL(cellular_emporium) QDEL_NULL(emporium_action) @@ -68,6 +64,8 @@ emporium_action = new(cellular_emporium) /datum/antagonist/changeling/on_gain() + generate_name() + create_actions() reset_powers() create_initial_profile() if(give_objectives) @@ -340,6 +338,9 @@ owner.announce_objectives() +/datum/antagonist/changeling/farewell() + to_chat(owner.current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!") + /datum/antagonist/changeling/proc/forge_team_objectives() if(GLOB.changeling_team_objective_type) var/datum/objective/changeling_team_objective/team_objective = new GLOB.changeling_team_objective_type @@ -436,6 +437,25 @@ hud.leave_hud(owner.current) set_antag_hud(owner.current, null) +/datum/antagonist/changeling/admin_add(datum/mind/new_owner,mob/admin) + . = ..() + to_chat(new_owner.current, "Our powers have awoken. A flash of memory returns to us...we are [changelingID], a changeling!") + +/datum/antagonist/changeling/get_admin_commands() + . = ..() + if(stored_profiles.len && (owner.current.real_name != first_prof.name)) + .["Transform to initial appearance."] = CALLBACK(src,.proc/admin_restore_appearance) + +/datum/antagonist/changeling/proc/admin_restore_appearance(mob/admin) + if(!stored_profiles.len || !iscarbon(owner.current)) + to_chat(admin, "Resetting DNA failed!") + else + var/mob/living/carbon/C = owner.current + first_prof.dna.transfer_identity(C, transfer_SE=1) + C.real_name = first_prof.name + C.updateappearance(mutcolor_update=1) + C.domutcheck() + // Profile /datum/changelingprofile @@ -509,4 +529,10 @@ else parts += "The changeling has failed." - return parts.Join("
") \ No newline at end of file + return parts.Join("
") + +/datum/antagonist/changeling/antag_listing_name() + return ..() + "([changelingID])" + +/datum/antagonist/changeling/xenobio/antag_listing_name() + return ..() + "(Xenobio)" \ No newline at end of file diff --git a/code/datums/antagonists/clockcult.dm b/code/datums/antagonists/clockcult.dm index 48f9b5342552..6b57e3d0dcaa 100644 --- a/code/datums/antagonists/clockcult.dm +++ b/code/datums/antagonists/clockcult.dm @@ -2,6 +2,7 @@ /datum/antagonist/clockcult name = "Clock Cultist" roundend_category = "clock cultists" + antagpanel_category = "Clockcult" job_rank = ROLE_SERVANT_OF_RATVAR var/datum/action/innate/hierophant/hierophant_network = new() var/datum/team/clockcult/clock_team @@ -9,6 +10,7 @@ /datum/antagonist/clockcult/silent silent = TRUE + show_in_antagpanel = FALSE //internal /datum/antagonist/clockcult/Destroy() qdel(hierophant_network) @@ -21,6 +23,8 @@ if(!new_team && make_team) //TODO blah blah same as the others, allow multiple for(var/datum/antagonist/clockcult/H in GLOB.antagonists) + if(!H.owner) + continue if(H.clock_team) clock_team = H.clock_team return @@ -33,28 +37,7 @@ /datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner) . = ..() if(.) - if(iscyborg(new_owner.current)) - var/mob/living/silicon/robot/R = new_owner.current - if(R.deployed) - var/mob/living/silicon/ai/AI = R.mainframe - R.undeploy() - to_chat(AI, "Anomaly Detected. Returned to core!") //The AI needs to be in its core to properly be converted . = is_eligible_servant(new_owner.current) - if(!silent && new_owner.current) - if(.) - to_chat(new_owner.current, "The world before you suddenly glows a brilliant yellow. [issilicon(new_owner.current) ? "You cannot compute this truth!" : \ - "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and all at once it comes to you.
\ - Ratvar, the Clockwork Justiciar, [GLOB.ratvar_awakens ? "has been freed from his eternal prison" : "lies in exile, derelict and forgotten in an unseen realm"].
") - flash_color(new_owner.current, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 50) - else - new_owner.current.visible_message("[new_owner.current] seems to resist an unseen force!", null, null, 7, new_owner.current) - to_chat(new_owner.current, "The world before you suddenly glows a brilliant yellow. [issilicon(new_owner.current) ? "You cannot compute this truth!" : \ - "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and the sound \ - is a meaningless cacophony.
\ - You see an abomination of rusting parts[GLOB.ratvar_awakens ? ", and it is here.
It is too late" : \ - " in an endless grey void.
It cannot be allowed to escape"].
") - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 40, TRUE, frequency = 100000, pressure_affected = FALSE) - flash_color(new_owner.current, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 5) /datum/antagonist/clockcult/greet() if(!owner.current || silent) @@ -85,7 +68,7 @@ to_chat(current, "You can communicate with other servants by using the Hierophant Network action button in the upper left.") ..() to_chat(current, "This is Ratvar's will: [CLOCKCULT_OBJECTIVE]") - owner.memory += "Ratvar's will: [CLOCKCULT_OBJECTIVE]
" //Memorize the objectives + antag_memory += "Ratvar's will: [CLOCKCULT_OBJECTIVE]
" //Memorize the objectives /datum/antagonist/clockcult/apply_innate_effects(mob/living/mob_override) . = ..() @@ -178,13 +161,32 @@ owner.current.visible_message("[owner] seems to have remembered their true allegiance!", ignored_mob = owner.current) to_chat(owner, "A cold, cold darkness flows through your mind, extinguishing the Justiciar's light and all of your memories as his servant.") owner.current.log_message("Has renounced the cult of Ratvar!", INDIVIDUAL_ATTACK_LOG) - owner.wipe_memory() owner.special_role = null if(iscyborg(owner.current)) to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.") . = ..() +/datum/antagonist/clockcult/admin_add(datum/mind/new_owner,mob/admin) + add_servant_of_ratvar(new_owner.current, TRUE) + message_admins("[key_name_admin(admin)] has made [new_owner.current] into a servant of Ratvar.") + log_admin("[key_name(admin)] has made [new_owner.current] into a servant of Ratvar.") + +/datum/antagonist/clockcult/admin_remove(mob/user) + remove_servant_of_ratvar(owner.current, TRUE) + message_admins("[key_name_admin(user)] has removed clockwork servant status from [owner.current].") + log_admin("[key_name(user)] has removed clockwork servant status from [owner.current].") + +/datum/antagonist/clockcult/get_admin_commands() + . = ..() + .["Give slab"] = CALLBACK(src,.proc/admin_give_slab) + +/datum/antagonist/clockcult/proc/admin_give_slab(mob/admin) + if(!SSticker.mode.equip_servant(owner.current)) + to_chat(admin, "Failed to outfit [owner.current]!") + else + to_chat(admin, "Successfully gave [owner.current] servant equipment!") + /datum/team/clockcult name = "Clockcult" var/list/objective diff --git a/code/datums/antagonists/cult.dm b/code/datums/antagonists/cult.dm index cccc442c4d3d..6089e8d1f077 100644 --- a/code/datums/antagonists/cult.dm +++ b/code/datums/antagonists/cult.dm @@ -3,6 +3,7 @@ /datum/antagonist/cult name = "Cultist" roundend_category = "cultists" + antagpanel_category = "Cult" var/datum/action/innate/cult/comm/communion = new var/datum/action/innate/cult/mastervote/vote = new job_rank = ROLE_CULTIST @@ -18,6 +19,8 @@ if(!new_team) //todo remove this and allow admin buttons to create more than one cult for(var/datum/antagonist/cult/H in GLOB.antagonists) + if(!H.owner) + continue if(H.cult_team) cult_team = H.cult_team return @@ -127,7 +130,6 @@ /datum/antagonist/cult/on_removal() remove_objectives() - owner.wipe_memory() SSticker.mode.cult -= owner SSticker.mode.update_cult_icons_removed(owner) if(!silent) @@ -138,11 +140,36 @@ owner.current.client.images -= cult_team.blood_target_image . = ..() +/datum/antagonist/cult/admin_add(datum/mind/new_owner,mob/admin) + give_equipment = FALSE + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has cult'ed [new_owner.current].") + log_admin("[key_name(admin)] has cult'ed [new_owner.current].") + +/datum/antagonist/cult/admin_remove(mob/user) + message_admins("[key_name_admin(user)] has decult'ed [owner.current].") + log_admin("[key_name(user)] has decult'ed [owner.current].") + SSticker.mode.remove_cultist(owner,silent=TRUE) //disgusting + +/datum/antagonist/cult/get_admin_commands() + . = ..() + .["Tome"] = CALLBACK(src,.proc/admin_give_tome) + .["Amulet"] = CALLBACK(src,.proc/admin_give_amulet) + +/datum/antagonist/cult/proc/admin_give_tome(mob/admin) + if(equip_cultist(owner.current,1)) + to_chat(admin, "Spawning tome failed!") + +/datum/antagonist/cult/proc/admin_give_amulet(mob/admin) + if (equip_cultist(owner.current)) + to_chat(admin, "Spawning amulet failed!") + /datum/antagonist/cult/master + ignore_implant = TRUE + show_in_antagpanel = FALSE //Feel free to add this later var/datum/action/innate/cult/master/finalreck/reckoning = new var/datum/action/innate/cult/master/cultmark/bloodmark = new var/datum/action/innate/cult/master/pulse/throwing = new - ignore_implant = TRUE /datum/antagonist/cult/master/Destroy() QDEL_NULL(reckoning) @@ -296,4 +323,7 @@ parts += "The cultists were:" parts += printplayerlist(members) - return "
[parts.Join("
")]
" \ No newline at end of file + return "
[parts.Join("
")]
" + +/datum/team/cult/is_gamemode_hero() + return SSticker.mode.name == "cult" \ No newline at end of file diff --git a/code/datums/antagonists/datum_traitor.dm b/code/datums/antagonists/datum_traitor.dm index 420dae46503b..23cf95e6aea8 100644 --- a/code/datums/antagonists/datum_traitor.dm +++ b/code/datums/antagonists/datum_traitor.dm @@ -1,8 +1,9 @@ /datum/antagonist/traitor name = "Traitor" roundend_category = "traitors" + antagpanel_category = "Traitor" job_rank = ROLE_TRAITOR - var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only + var/should_specialise = TRUE //do we split into AI and human, set to true on inital assignment only var/ai_datum = ANTAG_DATUM_TRAITOR_AI var/human_datum = ANTAG_DATUM_TRAITOR_HUMAN var/special_role = "traitor" @@ -10,23 +11,28 @@ var/give_objectives = TRUE var/should_give_codewords = TRUE + + /datum/antagonist/traitor/human + show_in_antagpanel = FALSE + should_specialise = FALSE var/should_equip = TRUE -/datum/antagonist/traitor/AI -/datum/antagonist/traitor/proc/specialise() - silent = TRUE - if(owner.current && isAI(owner.current)) - owner.add_antag_datum(ai_datum) - else - owner.add_antag_datum(human_datum) - on_removal() +/datum/antagonist/traitor/AI + show_in_antagpanel = FALSE + should_specialise = FALSE + +/datum/antagonist/traitor/specialization(datum/mind/new_owner) + if(should_specialise) + if(new_owner.current && isAI(new_owner.current)) + return new ai_datum() + else + return new human_datum() + else + return ..() /datum/antagonist/traitor/on_gain() - if(should_specialise) - specialise() - return SSticker.mode.traitors += owner owner.special_role = special_role if(give_objectives) @@ -49,8 +55,6 @@ traitor_mob.dna.add_mutation(CLOWNMUT) /datum/antagonist/traitor/on_removal() - if(should_specialise) - return ..()//we never did any of this anyway SSticker.mode.traitors -= owner for(var/O in objectives) owner.objectives -= O @@ -79,6 +83,7 @@ /datum/antagonist/traitor/proc/forge_traitor_objectives() return + /datum/antagonist/traitor/human/forge_traitor_objectives() var/is_hijacker = prob(10) var/martyr_chance = prob(20) @@ -229,8 +234,8 @@ to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]") to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]") - traitor_mob.mind.store_memory("Code Phrase: [GLOB.syndicate_code_phrase]") - traitor_mob.mind.store_memory("Code Response: [GLOB.syndicate_code_response]") + antag_memory += "Code Phrase: [GLOB.syndicate_code_phrase]
" + antag_memory += "Code Response: [GLOB.syndicate_code_response]
" to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") @@ -249,7 +254,7 @@ return /datum/antagonist/traitor/human/equip(var/silent = FALSE) - owner.equip_traitor(employer, silent) + owner.equip_traitor(employer, silent, src) /datum/antagonist/traitor/human/proc/assign_exchange_role() //set faction @@ -339,4 +344,7 @@ /datum/antagonist/traitor/roundend_report_footer() return "
The code phrases were: [GLOB.syndicate_code_phrase]
\ - The code responses were: [GLOB.syndicate_code_response]
" \ No newline at end of file + The code responses were: [GLOB.syndicate_code_response]
" + +/datum/antagonist/traitor/is_gamemode_hero() + return SSticker.mode.name == "traitor" \ No newline at end of file diff --git a/code/datums/antagonists/devil.dm b/code/datums/antagonists/devil.dm index 97e0d8c18aa7..858b2d1ef11a 100644 --- a/code/datums/antagonists/devil.dm +++ b/code/datums/antagonists/devil.dm @@ -87,6 +87,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", /datum/antagonist/devil name = "Devil" roundend_category = "devils" + antagpanel_category = "Devil" job_rank = ROLE_DEVIL //Don't delete upon mind destruction, otherwise soul re-selling will break. delete_on_mind_deletion = FALSE @@ -111,17 +112,35 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", /obj/effect/proc_holder/spell/targeted/summon_dancefloor)) var/ascendable = FALSE +/datum/antagonist/devil/can_be_owned(datum/mind/new_owner) + . = ..() + return . && (ishuman(new_owner.current) || iscyborg(new_owner.current)) -/datum/antagonist/devil/New() - ..() - truename = randomDevilName() - ban = randomdevilban() - bane = randomdevilbane() - obligation = randomdevilobligation() - banish = randomdevilbanish() - GLOB.allDevils[lowertext(truename)] = src +/datum/antagonist/devil/get_admin_commands() + . = ..() + .["Toggle ascendable"] = CALLBACK(src,.proc/admin_toggle_ascendable) +/datum/antagonist/devil/proc/admin_toggle_ascendable(mob/admin) + ascendable = !ascendable + message_admins("[key_name_admin(admin)] set [owner.current] devil ascendable to [ascendable]") + log_admin("[key_name_admin(admin)] set [owner.current] devil ascendable to [ascendable])") + +/datum/antagonist/devil/admin_add(datum/mind/new_owner,mob/admin) + switch(alert(admin,"Should the devil be able to ascend",,"Yes","No","Cancel")) + if("Yes") + ascendable = TRUE + if("No") + ascendable = FALSE + else + return + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has devil'ed [new_owner.current]. [ascendable ? "(Ascendable)":""]") + log_admin("[key_name(admin)] has devil'ed [new_owner.current]. [ascendable ? "(Ascendable)":""]") + +/datum/antagonist/devil/antag_listing_name() + return ..() + "([truename])" + /proc/devilInfo(name) if(GLOB.allDevils[lowertext(name)]) return GLOB.allDevils[lowertext(name)] @@ -480,7 +499,14 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", .=..() /datum/antagonist/devil/on_gain() - owner.store_memory("Your devilic true name is [truename]
[GLOB.lawlorify[LAW][ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[GLOB.lawlorify[LAW][bane]]
[GLOB.lawlorify[LAW][obligation]]
[GLOB.lawlorify[LAW][banish]]
") + truename = randomDevilName() + ban = randomdevilban() + bane = randomdevilbane() + obligation = randomdevilobligation() + banish = randomdevilbanish() + GLOB.allDevils[lowertext(truename)] = src + + antag_memory += "Your devilic true name is [truename]
[GLOB.lawlorify[LAW][ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[GLOB.lawlorify[LAW][bane]]
[GLOB.lawlorify[LAW][obligation]]
[GLOB.lawlorify[LAW][banish]]
" if(issilicon(owner.current)) var/mob/living/silicon/robot_devil = owner.current var/laws = list("You may not use violence to coerce someone into selling their soul.", "You may not directly and knowingly physically harm a devil, other than yourself.", GLOB.lawlorify[LAW][ban], GLOB.lawlorify[LAW][obligation], "Accomplish your objectives at all costs.") diff --git a/code/datums/antagonists/internal_affairs.dm b/code/datums/antagonists/internal_affairs.dm index b06d8ea068d8..e06d8983e363 100644 --- a/code/datums/antagonists/internal_affairs.dm +++ b/code/datums/antagonists/internal_affairs.dm @@ -5,32 +5,31 @@ #define TRAITOR_AGENT_ROLE "Syndicate External Affairs Agent" /datum/antagonist/traitor/internal_affairs + name = "Internal Affairs Agent" human_datum = ANTAG_DATUM_IAA_HUMAN ai_datum = ANTAG_DATUM_IAA_AI - - + antagpanel_category = "IAA" /datum/antagonist/traitor/AI/internal_affairs name = "Internal Affairs Agent" employer = "Nanotrasen" special_role = "internal affairs agent" + antagpanel_category = "IAA" var/syndicate = FALSE var/last_man_standing = FALSE var/list/datum/mind/targets_stolen - -/datum/antagonist/traitor/AI/internal_affairs/custom - silent = TRUE - should_give_codewords = FALSE - give_objectives = FALSE + /datum/antagonist/traitor/human/internal_affairs name = "Internal Affairs Agent" employer = "Nanotrasen" special_role = "internal affairs agent" + antagpanel_category = "IAA" var/syndicate = FALSE var/last_man_standing = FALSE var/list/datum/mind/targets_stolen + /datum/antagonist/traitor/human/internal_affairs/proc/give_pinpointer() if(owner && owner.current) owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer) @@ -292,6 +291,7 @@ /datum/antagonist/traitor/AI/internal_affairs/greet() greet_iaa() + /datum/antagonist/traitor/human/internal_affairs/greet() greet_iaa() diff --git a/code/datums/antagonists/monkey.dm b/code/datums/antagonists/monkey.dm index d2c5d5e7620b..4d218b612cbe 100644 --- a/code/datums/antagonists/monkey.dm +++ b/code/datums/antagonists/monkey.dm @@ -7,7 +7,15 @@ name = "Monkey" job_rank = ROLE_MONKEY roundend_category = "monkeys" + antagpanel_category = "Monkey" var/datum/team/monkey/monkey_team + var/monkey_only = TRUE + +/datum/antagonist/monkey/can_be_owned(datum/mind/new_owner) + return ..() && (!monkey_only || ismonkey(new_owner.current)) + +/datum/antagonist/monkey/get_team() + return monkey_team /datum/antagonist/monkey/on_gain() . = ..() @@ -29,13 +37,15 @@ SEND_SOUND(owner.current, sound('sound/ambience/antag/monkey.ogg')) /datum/antagonist/monkey/on_removal() - . = ..() owner.special_role = null SSticker.mode.ape_infectees -= owner - var/datum/disease/D = (/datum/disease/transformation/jungle_fever in owner.current.viruses) + var/datum/disease/transformation/jungle_fever/D = locate() in owner.current.viruses if(D) - D.cure() + D.remove_virus() + qdel(D) + + . = ..() /datum/antagonist/monkey/create_team(datum/team/monkey/new_team) if(!new_team) @@ -50,15 +60,45 @@ stack_trace("Wrong team type passed to [type] initialization.") monkey_team = new_team -/datum/antagonist/monkey/get_team() - return monkey_team - /datum/antagonist/monkey/proc/forge_objectives() objectives |= monkey_team.objectives owner.objectives |= objectives +/datum/antagonist/monkey/admin_remove(mob/admin) + var/mob/living/carbon/monkey/M = owner.current + if(istype(M)) + switch(alert(admin, "Humanize?", "Humanize", "Yes", "No")) + if("Yes") + if(admin == M) + admin = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + else + M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + if("No") + //nothing + else + return + . = ..() + /datum/antagonist/monkey/leader name = "Monkey Leader" + monkey_only = FALSE + +/datum/antagonist/monkey/leader/admin_add(datum/mind/new_owner,mob/admin) + var/mob/living/carbon/human/H = new_owner.current + if(istype(H)) + switch(alert(admin, "Monkeyize?", "Monkeyize", "Yes", "No")) + if("Yes") + if(admin == H) + admin = H.monkeyize() + else + H.monkeyize() + if("No") + //nothing + else + return + new_owner.add_antag_datum(src) + log_admin("[key_name(admin)] made [key_name(new_owner.current)] a monkey leader!") + message_admins("[key_name_admin(admin)] made [key_name_admin(new_owner.current)] a monkey leader!") /datum/antagonist/monkey/leader/on_gain() . = ..() @@ -68,11 +108,12 @@ owner.special_role = "Monkey Leader" /datum/antagonist/monkey/leader/on_removal() - . = ..() SSticker.mode.ape_leaders -= owner var/obj/item/organ/heart/H = new H.Insert(owner.current, drop_if_replaced = FALSE) //replace freedom heart with normal heart + . = ..() + /datum/antagonist/monkey/leader/greet() to_chat(owner, "You are the Jungle Fever patient zero!!") to_chat(owner, "You have been planted onto this station by the Animal Rights Consortium.") diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm index 8201cd879d16..3d46d3ef0538 100644 --- a/code/datums/antagonists/ninja.dm +++ b/code/datums/antagonists/ninja.dm @@ -1,31 +1,27 @@ /datum/antagonist/ninja name = "Ninja" + antagpanel_category = "Ninja" job_rank = ROLE_NINJA - var/helping_station = 0 + var/helping_station = FALSE var/give_objectives = TRUE + var/give_equipment = TRUE -/datum/antagonist/ninja/friendly - helping_station = 1 -/datum/antagonist/ninja/friendly/noobjective - give_objectives = FALSE +/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override) + var/mob/living/M = mob_override || owner.current + update_ninja_icons_added(M) -/datum/antagonist/ninja/New(datum/mind/new_owner) - if(new_owner && !ishuman(new_owner.current))//It's fine if we aren't passed a mind, but if we are, they have to be human. - throw EXCEPTION("Only humans and/or humanoids may be ninja'ed") - ..(new_owner) - -/datum/antagonist/ninja/randomAllegiance/New(datum/mind/new_owner) - ..(new_owner) - helping_station = rand(0,1) +/datum/antagonist/ninja/remove_innate_effects(mob/living/mob_override) + var/mob/living/M = mob_override || owner.current + update_ninja_icons_removed(M) /datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current) return H.equipOutfit(/datum/outfit/ninja) /datum/antagonist/ninja/proc/addMemories() - owner.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!") - owner.store_memory("Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!") - owner.store_memory("Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.") + antag_memory += "I am an elite mercenary assassin of the mighty Spider Clan. A SPACE NINJA!
" + antag_memory += "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!
" + antag_memory += "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.
" /datum/antagonist/ninja/proc/addObjectives(quantity = 6) var/list/possible_targets = list() @@ -103,11 +99,6 @@ datum.on_removal() return TRUE -/proc/add_ninja(mob/living/carbon/human/H, type = ANTAG_DATUM_NINJA_RANDOM) - if(!H || !H.mind) - return FALSE - return H.mind.add_antag_datum(type) - /proc/is_ninja(mob/living/M) return M && M.mind && M.mind.has_antag_datum(ANTAG_DATUM_NINJA) @@ -123,3 +114,42 @@ if(give_objectives) addObjectives() addMemories() + if(give_equipment) + equip_space_ninja(owner.current) + . = ..() + +/datum/antagonist/ninja/admin_add(datum/mind/new_owner,mob/admin) + var/adj + switch(input("What kind of ninja?", "Ninja") as null|anything in list("Random","Syndicate","Nanotrasen","No objectives")) + if("Random") + helping_station = pick(TRUE,FALSE) + adj = "" + if("Syndicate") + helping_station = FALSE + adj = "syndie" + if("Nanotrasen") + helping_station = TRUE + adj = "friendly" + if("No objectives") + give_objectives = FALSE + adj = "objectiveless" + else + return + new_owner.assigned_role = "Space Ninja" + new_owner.special_role = "Space Ninja" + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has [adj] ninja'ed [new_owner.current].") + log_admin("[key_name(admin)] has [adj] ninja'ed [new_owner.current].") + +/datum/antagonist/ninja/antag_listing_name() + return ..() + "(Ninja)" + +/datum/antagonist/ninja/proc/update_ninja_icons_added(var/mob/living/carbon/human/ninja) + var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA] + ninjahud.join_hud(ninja) + set_antag_hud(ninja, "ninja") + +/datum/antagonist/ninja/proc/update_ninja_icons_removed(var/mob/living/carbon/human/ninja) + var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA] + ninjahud.leave_hud(ninja) + set_antag_hud(ninja, null) \ No newline at end of file diff --git a/code/datums/antagonists/nukeop.dm b/code/datums/antagonists/nukeop.dm index 99d273ac977d..5fac18c6f702 100644 --- a/code/datums/antagonists/nukeop.dm +++ b/code/datums/antagonists/nukeop.dm @@ -11,6 +11,7 @@ /datum/antagonist/nukeop name = "Nuclear Operative" roundend_category = "syndicate operatives" //just in case + antagpanel_category = "NukeOp" job_rank = ROLE_OPERATIVE var/datum/team/nuclear/nuke_team var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team. @@ -85,7 +86,7 @@ /datum/antagonist/nukeop/proc/memorize_code() if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code) - owner.store_memory("[nuke_team.tracked_nuke] Code: [nuke_team.memorized_code]", 0, 0) + antag_memory += "[nuke_team.tracked_nuke] Code: [nuke_team.memorized_code]
" to_chat(owner, "The nuclear authorization code is: [nuke_team.memorized_code]") else to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.") @@ -107,6 +108,8 @@ if(!new_team) if(!always_new_team) for(var/datum/antagonist/nukeop/N in GLOB.antagonists) + if(!N.owner) + continue if(N.nuke_team) nuke_team = N.nuke_team return @@ -118,6 +121,32 @@ stack_trace("Wrong team type passed to [type] initialization.") nuke_team = new_team +/datum/antagonist/nukeop/admin_add(datum/mind/new_owner,mob/admin) + new_owner.assigned_role = "Syndicate" + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has nuke op'ed [new_owner.current].") + log_admin("[key_name(admin)] has nuke op'ed [new_owner.current].") + +/datum/antagonist/nukeop/get_admin_commands() + . = ..() + .["Send to base"] = CALLBACK(src,.proc/admin_send_to_base) + .["Tell code"] = CALLBACK(src,.proc/admin_tell_code) + +/datum/antagonist/nukeop/proc/admin_send_to_base(mob/admin) + owner.current.forceMove(pick(GLOB.nukeop_start)) + +/datum/antagonist/nukeop/proc/admin_tell_code(mob/admin) + var/code + for (var/obj/machinery/nuclearbomb/bombue in GLOB.machines) + if (length(bombue.r_code) <= 5 && bombue.r_code != initial(bombue.r_code)) + code = bombue.r_code + break + if (code) + antag_memory += "Syndicate Nuclear Bomb Code: [code]
" + to_chat(owner.current, "The nuclear authorization code is: [code]") + else + to_chat(admin, "No valid nuke found!") + /datum/antagonist/nukeop/leader name = "Nuclear Operative Leader" nukeop_outfit = /datum/outfit/syndicate/leader @@ -201,6 +230,10 @@ stack_trace("Station self destruct ot found during lone op team creation.") nuke_team.memorized_code = null +/datum/antagonist/nukeop/reinforcement + send_to_spawnpoint = FALSE + nukeop_outfit = /datum/outfit/syndicate/no_crystals + /datum/team/nuclear var/syndicate_name var/obj/machinery/nuclearbomb/tracked_nuke @@ -316,3 +349,31 @@ parts += text return "
[parts.Join("
")]
" + +/datum/team/nuclear/antag_listing_name() + if(syndicate_name) + return "[syndicate_name] Syndicates" + else + return "Syndicates" + +/datum/team/nuclear/antag_listing_entry() + var/disk_report = "Nuclear Disk(s)
" + disk_report += "" + for(var/obj/item/disk/nuclear/N in GLOB.poi_list) + disk_report += "" + disk_report += "
[N.name], " + var/atom/disk_loc = N.loc + while(!isturf(disk_loc)) + if(ismob(disk_loc)) + var/mob/M = disk_loc + disk_report += "carried by [M.real_name] " + if(isobj(disk_loc)) + var/obj/O = disk_loc + disk_report += "in \a [O.name] " + disk_loc = disk_loc.loc + disk_report += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])FLW
" + var/common_part = ..() + return common_part + disk_report + +/datum/team/nuclear/is_gamemode_hero() + return SSticker.mode.name == "nuclear emergency" \ No newline at end of file diff --git a/code/datums/antagonists/pirate.dm b/code/datums/antagonists/pirate.dm index 9bf20a4bf58b..cdd871ff352d 100644 --- a/code/datums/antagonists/pirate.dm +++ b/code/datums/antagonists/pirate.dm @@ -2,6 +2,7 @@ name = "Space Pirate" job_rank = ROLE_TRAITOR roundend_category = "space pirates" + antagpanel_category = "Pirate" var/datum/team/pirate/crew /datum/antagonist/pirate/greet() @@ -15,6 +16,8 @@ /datum/antagonist/pirate/create_team(datum/team/pirate/new_team) if(!new_team) for(var/datum/antagonist/pirate/P in GLOB.antagonists) + if(!P.owner) + continue if(P.crew) crew = P.crew return diff --git a/code/datums/antagonists/revolution.dm b/code/datums/antagonists/revolution.dm index 3209b9221c71..b0637f236117 100644 --- a/code/datums/antagonists/revolution.dm +++ b/code/datums/antagonists/revolution.dm @@ -4,16 +4,20 @@ /datum/antagonist/rev name = "Revolutionary" roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen + antagpanel_category = "Revolution" job_rank = ROLE_REV var/hud_type = "rev" var/datum/team/revolution/rev_team /datum/antagonist/rev/can_be_owned(datum/mind/new_owner) . = ..() - if(new_owner.assigned_role in GLOB.command_positions) - return FALSE - if(new_owner.unconvertable) - return FALSE + if(.) + if(new_owner.assigned_role in GLOB.command_positions) + return FALSE + if(new_owner.unconvertable) + return FALSE + if(new_owner.current && new_owner.current.isloyal()) + return FALSE /datum/antagonist/rev/apply_innate_effects(mob/living/mob_override) var/mob/living/M = mob_override || owner.current @@ -26,9 +30,6 @@ /datum/antagonist/rev/proc/equip_rev() return -/datum/antagonist/rev/New() - . = ..() - /datum/antagonist/rev/on_gain() . = ..() create_objectives() @@ -47,6 +48,8 @@ if(!new_team) //For now only one revolution at a time for(var/datum/antagonist/rev/head/H in GLOB.antagonists) + if(!H.owner) + continue if(H.rev_team) rev_team = H.rev_team return @@ -73,12 +76,73 @@ var/datum/mind/old_owner = owner silent = TRUE owner.remove_antag_datum(/datum/antagonist/rev) - var/datum/antagonist/rev/head/new_revhead = new(old_owner) + var/datum/antagonist/rev/head/new_revhead = new() new_revhead.silent = TRUE old_owner.add_antag_datum(new_revhead,old_team) new_revhead.silent = FALSE to_chat(old_owner, "You have proved your devotion to revolution! You are a head revolutionary now!") +/datum/antagonist/rev/get_admin_commands() + . = ..() + .["Promote"] = CALLBACK(src,.proc/admin_promote) + +/datum/antagonist/rev/proc/admin_promote(mob/admin) + var/datum/mind/O = owner + promote() + message_admins("[key_name_admin(admin)] has head-rev'ed [O].") + log_admin("[key_name(admin)] has head-rev'ed [O].") + +/datum/antagonist/rev/head/admin_add(datum/mind/new_owner,mob/admin) + give_flash = TRUE + give_hud = TRUE + remove_clumsy = TRUE + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has head-rev'ed [new_owner.current].") + log_admin("[key_name(admin)] has head-rev'ed [new_owner.current].") + to_chat(new_owner.current, "You are a member of the revolutionaries' leadership now!") + +/datum/antagonist/rev/head/get_admin_commands() + . = ..() + . -= "Promote" + .["Take flash"] = CALLBACK(src,.proc/admin_take_flash) + .["Give flash"] = CALLBACK(src,.proc/admin_give_flash) + .["Repair flash"] = CALLBACK(src,.proc/admin_repair_flash) + .["Demote"] = CALLBACK(src,.proc/admin_demote) + +/datum/antagonist/rev/head/proc/admin_take_flash(mob/admin) + var/list/L = owner.current.get_contents() + var/obj/item/device/assembly/flash/flash = locate() in L + if (!flash) + to_chat(admin, "Deleting flash failed!") + return + qdel(flash) + +/datum/antagonist/rev/head/proc/admin_give_flash(mob/admin) + //This is probably overkill but making these impact state annoys me + var/old_give_flash = give_flash + var/old_give_hud = give_hud + var/old_remove_clumsy = remove_clumsy + give_flash = TRUE + give_hud = FALSE + remove_clumsy = FALSE + equip_rev() + give_flash = old_give_flash + give_hud = old_give_hud + remove_clumsy = old_remove_clumsy + +/datum/antagonist/rev/head/proc/admin_repair_flash(mob/admin) + var/list/L = owner.current.get_contents() + var/obj/item/device/assembly/flash/flash = locate() in L + if (!flash) + to_chat(admin, "Repairing flash failed!") + else + flash.crit_fail = 0 + flash.update_icon() + +/datum/antagonist/rev/head/proc/admin_demote(datum/mind/target,mob/user) + message_admins("[key_name_admin(user)] has demoted [owner.current] from head revolutionary.") + log_admin("[key_name(user)] has demoted [owner.current] from head revolutionary.") + demote() /datum/antagonist/rev/head name = "Head Revolutionary" @@ -87,6 +151,9 @@ var/give_flash = FALSE var/give_hud = TRUE +/datum/antagonist/rev/head/antag_listing_name() + return ..() + "(Leader)" + /datum/antagonist/rev/proc/update_rev_icons_added(mob/living/M) var/datum/atom_hud/antag/revhud = GLOB.huds[ANTAG_HUD_REV] revhud.join_hud(M) @@ -105,8 +172,6 @@ var/mob/living/carbon/C = candidate //Check to see if the potential rev is implanted if(!istype(C)) //Can't convert simple animals return FALSE - if(C.isloyal()) - return FALSE return TRUE /datum/antagonist/rev/proc/add_revolutionary(datum/mind/rev_mind,stun = TRUE) @@ -127,7 +192,7 @@ var/old_team = rev_team silent = TRUE owner.remove_antag_datum(/datum/antagonist/rev/head) - var/datum/antagonist/rev/new_rev = new /datum/antagonist/rev(old_owner) + var/datum/antagonist/rev/new_rev = new /datum/antagonist/rev() new_rev.silent = TRUE old_owner.add_antag_datum(new_rev,old_team) new_rev.silent = FALSE @@ -279,4 +344,25 @@ result += "" - return result.Join() \ No newline at end of file + return result.Join() + +/datum/team/revolution/antag_listing_entry() + var/common_part = ..() + var/heads_report = "Heads of Staff
" + heads_report += "" + for(var/datum/mind/N in SSjob.get_living_heads()) + var/mob/M = N.current + if(M) + heads_report += "" + heads_report += "" + heads_report += "" + var/turf/mob_loc = get_turf(M) + heads_report += "" + else + heads_report += "" + heads_report += "" + heads_report += "
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW[mob_loc.loc]
[N.name]([N.key])Head body destroyed!PM
" + return common_part + heads_report + +/datum/team/revolution/is_gamemode_hero() + return SSticker.mode.name == "revolution" \ No newline at end of file diff --git a/code/datums/antagonists/wizard.dm b/code/datums/antagonists/wizard.dm index e856a6642f66..c4f029e5e3b6 100644 --- a/code/datums/antagonists/wizard.dm +++ b/code/datums/antagonists/wizard.dm @@ -6,6 +6,7 @@ /datum/antagonist/wizard name = "Space Wizard" roundend_category = "wizards/witches" + antagpanel_category = "Wizard" job_rank = ROLE_WIZARD var/give_objectives = TRUE var/strip = TRUE //strip before equipping @@ -167,6 +168,14 @@ update_wiz_icons_removed(M) M.faction -= "wizard" + +/datum/antagonist/wizard/get_admin_commands() + . = ..() + .["Send to Lair"] = CALLBACK(src,.proc/admin_send_to_lair) + +/datum/antagonist/wizard/proc/admin_send_to_lair(mob/admin) + owner.current.forceMove(pick(GLOB.wizardstart)) + /datum/antagonist/wizard/apprentice name = "Wizard Apprentice" hud_version = "apprentice" diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 1df8d60d3948..8f8fa8f1f0a4 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -740,28 +740,6 @@ src.give_disease(M) href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["ninja"]) - if(!check_rights(R_FUN)) - return - - var/mob/living/carbon/human/M = locate(href_list["ninja"]) in GLOB.carbon_list - if(!istype(M)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - if(tgalert(usr, "Are you sure you want to make [M] into a ninja?", "Confirmation", "Yes", "No") == "No") - return - - if(!M.mind) - M.mind_initialize() - - var/datum/antagonist/ninja/hiyah = M.mind.has_antag_datum(/datum/antagonist/ninja) - if(!hiyah) - hiyah = add_ninja(M) - if(hiyah) - hiyah.equip_space_ninja() - href_list["datumrefresh"] = href_list["ninja"] - else if(href_list["gib"]) if(!check_rights(R_FUN)) return diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 06e091d9029b..17aebc46299d 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -88,7 +88,7 @@ stage5 = list("You feel like monkeying around.") /datum/disease/transformation/jungle_fever/do_disease_transformation(mob/living/carbon/affected_mob) - if(affected_mob.mind && !is_monkey(affected_mob)) + if(affected_mob.mind && !is_monkey(affected_mob.mind)) add_monkey(affected_mob.mind) if(ishuman(affected_mob)) var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 1722673fc26c..d47a25ee55f4 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -140,10 +140,16 @@ if(!istype(A)) return else - A = new datum_type_or_instance(src, team) + A = new datum_type_or_instance() + //Choose snowflake variation if antagonist handles it + var/datum/antagonist/S = A.specialization(src) + if(S && S != A) + qdel(A) + A = S if(!A.can_be_owned(src)) qdel(A) return + A.owner = src LAZYADD(antag_datums, A) A.create_team(team) var/datum/team/antag_team = A.get_team() @@ -242,7 +248,7 @@ SSticker.mode.update_traitor_icons_removed(src) SSticker.mode.update_cult_icons_removed(src) -/datum/mind/proc/equip_traitor(var/employer = "The Syndicate", var/silent = FALSE) +/datum/mind/proc/equip_traitor(employer = "The Syndicate", silent = FALSE, datum/antagonist/uplink_owner) if(!current) return var/mob/living/carbon/human/traitor_mob = current @@ -289,27 +295,32 @@ . = 0 else uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key) - + var/unlock_note + if(uplink_loc == R) R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ)) if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.") - traitor_mob.mind.store_memory("Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name]).") - + unlock_note = "Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name])." else if(uplink_loc == PDA) PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]" if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.") - traitor_mob.mind.store_memory("Uplink Passcode: [PDA.lock_code] ([PDA.name]).") + unlock_note = "Uplink Passcode: [PDA.lock_code] ([PDA.name])." else if(uplink_loc == P) P.traitor_unlock_degrees = rand(1, 360) if(!silent) to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.") - traitor_mob.mind.store_memory("Uplink Degrees: [P.traitor_unlock_degrees] ([P.name]).") + unlock_note = "Uplink Degrees: [P.traitor_unlock_degrees] ([P.name])." + + if(uplink_owner) + uplink_owner.antag_memory += unlock_note + "
" + else + traitor_mob.mind.store_memory(unlock_note) //Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does. @@ -326,7 +337,7 @@ else if(is_nuclear_operative(creator)) var/datum/antagonist/nukeop/converter = creator.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE) - var/datum/antagonist/nukeop/N = new(src) + var/datum/antagonist/nukeop/N = new() N.send_to_spawnpoint = FALSE N.nukeop_outfit = null add_antag_datum(N,converter.nuke_team) @@ -347,6 +358,10 @@ var/output = "[current.real_name]'s Memories:
" output += memory + + for(var/datum/antagonist/A in antag_datums) + output += A.antag_memory + if(objectives.len) output += "Objectives:" var/obj_count = 1 @@ -364,396 +379,21 @@ else if(objectives.len || memory) to_chat(recipient, "[output]") -/datum/mind/proc/edit_memory() - if(!SSticker.HasRoundStarted()) - alert("Not before round-start!", "Alert") - return - if(QDELETED(src) || QDELETED(current)) - alert("This mind doesn't have a mob, or is deleted! For some reason!", "Edit Memory") - return - - var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
" - out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
" - out += "Assigned role: [assigned_role]. Edit
" - out += "Faction and special role: [special_role]
" - - var/list/sections = list( - "traitor", // "traitorchan", - "changeling", - "nuclear", - "wizard", - "revolution", - "cult", - "clockcult", - "abductor", - "devil", - "ninja", - "monkey" - ) - var/text = "" - - /** TRAITOR ***/ - text = "traitor" - if (SSticker.mode.config_tag=="traitor" || SSticker.mode.config_tag=="traitorchan" || SSticker.mode.config_tag=="traitorbro") - text = uppertext(text) - text = "[text]: " - if (src in SSticker.mode.traitors) - text += "TRAITOR | loyal" - if (objectives.len==0) - text += "
Objectives are empty! Randomize!" - else - text += "traitor | LOYAL" - - if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["traitor"] = text - - - if(ishuman(current) || ismonkey(current)) - - /** BROTHER **/ - text = "brother" - if(SSticker.mode.config_tag == "traitorbro") - text = uppertext(text) - text = "[text]: " - if(src in SSticker.mode.brothers) - text += "Brother | no" - - if(current && current.client && (ROLE_BROTHER in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["brother"] = text - - /** CHANGELING ***/ - text = "changeling" - if (SSticker.mode.config_tag=="changeling" || SSticker.mode.config_tag=="traitorchan") - text = uppertext(text) - text = "[text]: " - var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) - if(C) - text += "[C.name] | No" - if (objectives.len==0) - text += "
Objectives are empty! Randomize!" - if(C.stored_profiles.len && (current.real_name != C.first_prof.name) ) - text += "
Transform to initial appearance." - else - text += "yes | NO" - - if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["changeling"] = text - - - /** MONKEY ***/ - text = "monkey" - if (SSticker.mode.config_tag=="monkey") - text = uppertext(text) - text = "[text]: " - if (ishuman(current)) - if(is_monkey_leader(src)) - text += "healthy | infected LEADER | human | other" - else - text += "healthy | infected | leader | HUMAN | other" - else if(ismonkey(current)) - var/found = FALSE - for(var/datum/disease/transformation/jungle_fever/JF in current.viruses) - found = TRUE - break - - var/isLeader = is_monkey_leader(src) - - if(isLeader) - text += "healthy | infected LEADER | human | other" - else if(found) - text += "healthy | INFECTED | leader | human | other" - else - text += "HEALTHY | infected | leader | human | other" - - else - text += "healthy | infected | leader | human | OTHER" - - if(current && current.client && (ROLE_MONKEY in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["monkey"] = text - - if(ishuman(current)) - - /** NUCLEAR ***/ - text = "nuclear" - if (SSticker.mode.config_tag=="nuclear") - text = uppertext(text) - text = "[text]: " - var/datum/antagonist/nukeop/N = has_antag_datum(/datum/antagonist/nukeop,TRUE) - if(N) - text += "OPERATIVE | nanotrasen" - text += "
To shuttle, undress, dress up." - var/code - for (var/obj/machinery/nuclearbomb/bombue in GLOB.machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - text += " Code is [code]. tell the code." - else - text += "operative | NANOTRASEN" - - if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["nuclear"] = text - - - /** WIZARD ***/ - text = "wizard" - if (SSticker.mode.config_tag=="wizard") - text = uppertext(text) - text = "[text]: " - if (has_antag_datum(/datum/antagonist/wizard)) - text += "YES | no" - text += "
To lair, undress" - else - text += "yes | NO" - - if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["wizard"] = text - - - /** REVOLUTION ***/ - text = "revolution" - if (SSticker.mode.config_tag=="revolution") - text = uppertext(text) - text = "[text]: " - if (assigned_role in GLOB.command_positions) - text += "HEAD | not mindshielded | employee | headrev | rev" - else if (has_antag_datum(/datum/antagonist/rev/head)) - var/datum/antagonist/rev/head = has_antag_datum(/datum/antagonist/rev/head) - var/last_healthy_headrev = TRUE - for(var/datum/mind/I in head.rev_team.head_revolutionaries()) - if(I == src) - continue - var/mob/M = I.current - if(M && is_station_level(M.z) && !M.stat) - last_healthy_headrev = FALSE - break - text += "head | not mindshielded | employee | [last_healthy_headrev ? "LAST " : ""]HEADREV | rev" - text += "
Flash: give" - - var/list/L = current.get_contents() - var/obj/item/device/assembly/flash/flash = locate() in L - if (flash) - if(!flash.crit_fail) - text += " | take." - else - text += " | take | repair." - else - text += "." - - text += " Reequip (gives traitor uplink)." - if (objectives.len==0) - text += "
Objectives are empty! Set to kill all heads." - else if(current.isloyal()) - text += "head | MINDSHIELDED | employee | headrev | rev" - else if (has_antag_datum(/datum/antagonist/rev)) - text += "head | not mindshielded | employee | headrev | REV" - else - text += "head | not mindshielded | EMPLOYEE | headrev | rev" - - if(current && current.client && (ROLE_REV in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["revolution"] = text - - /** ABDUCTION **/ - text = "abductor" - if(SSticker.mode.config_tag == "abductor") - text = uppertext(text) - text = "[text]: " - if(src in SSticker.mode.abductors) - text += "Abductor | human" - text += " | undress | equip" - - if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["abductor"] = text - - - /** DEVIL ***/ - text = "devil" - if(SSticker.mode.config_tag == "devil") - text = uppertext(text) - text = "[text]: " - var/datum/antagonist/devil/devilinfo = has_antag_datum(ANTAG_DATUM_DEVIL) - if(devilinfo) - if(!devilinfo.ascendable) - text += "DEVIL | ascendable devil | sintouched | human" - else - text += "DEVIL | ASCENDABLE DEVIL | sintouched | human" - else if(src in SSticker.mode.sintouched) - text += "devil | ascendable devil | SINTOUCHED | human" - else - text += "devil | ascendable devil | sintouched | HUMAN" - - if(current && current.client && (ROLE_DEVIL in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - sections["devil"] = text - - - /** NINJA ***/ - text = "ninja" - if(SSticker.mode.config_tag == "ninja") - text = uppertext(text) - text = "[text]: " - var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA) - if(ninjainfo) - if(ninjainfo.helping_station) - text += "employee | syndicate | NANOTRASEN | EQUIP" - else - text += "employee | SYNDICATE | nanotrasen | EQUIP" - else - text += "EMPLOYEE | syndicate | nanotrasen | random allegiance" - if(current && current.client && (ROLE_NINJA in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - sections["ninja"] = text - - - if(!issilicon(current)) - /** CULT ***/ - text = "cult" - if (SSticker.mode.config_tag=="cult") - text = uppertext(text) - text = "[text]: " - if(iscultist(current)) - text += "not mindshielded | employee | CULTIST" - text += "
Give tome | amulet." - else if(is_convertable_to_cult(current)) - text += "not mindshielded | EMPLOYEE | cultist" - else - text += "[!current.isloyal() ? "not mindshielded" : "MINDSHIELDED"] | EMPLOYEE | cannot serve Nar-Sie" - - if(current && current.client && (ROLE_CULTIST in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["cult"] = text - - - if(ishuman(current) || issilicon(current)) - /** CLOCKWORK CULT **/ - text = "clockwork cult" - if(SSticker.mode.config_tag == "clockwork cult") - text = uppertext(text) - text = "[text]: " - if(is_servant_of_ratvar(current)) - text += "not mindshielded | employee | SERVANT" - text += "
Equip" - else if(is_eligible_servant(current)) - text += "not mindshielded | EMPLOYEE | servant" - else - text += "[!current.isloyal() ? "not mindshielded" : "MINDSHIELDED"] | EMPLOYEE | cannot serve Ratvar" - - if(current && current.client && (ROLE_SERVANT_OF_RATVAR in current.client.prefs.be_special)) - text += " | Enabled in Prefs" - else - text += " | Disabled in Prefs" - - sections["clockcult"] = text - - - /** SILICON ***/ - if(issilicon(current)) - text = "silicon" - var/mob/living/silicon/robot/robot = current - if (istype(robot) && robot.emagged) - text += "
Cyborg: Is emagged! Unemag!
0th law: [robot.laws.zeroth]" - var/mob/living/silicon/ai/ai = current - if (istype(ai) && ai.connected_robots.len) - var/n_e_robots = 0 - for (var/mob/living/silicon/robot/R in ai.connected_robots) - if (R.emagged) - n_e_robots++ - text += "
[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. Unemag" - if (SSticker.mode.config_tag == "traitorchan") - if (sections["traitor"]) - out += sections["traitor"]+"
" - if (sections["changeling"]) - out += sections["changeling"]+"

" - sections -= "traitor" - sections -= "changeling" - else - if (sections[SSticker.mode.config_tag]) - out += sections[SSticker.mode.config_tag]+"

" - sections -= SSticker.mode.config_tag - for (var/i in sections) - if (sections[i]) - out += sections[i]+"
" - - - if(((src in SSticker.mode.traitors) || is_nuclear_operative(current)) && ishuman(current)) - text = "Uplink: give" - var/datum/component/uplink/U = find_syndicate_uplink() - if(U) - text += " | take" - if (check_rights(R_FUN, 0)) - text += ", [U.telecrystals] TC" - else - text += ", [U.telecrystals] TC" - text += "." //hiel grammar - out += text - - out += "

" - - out += "Memory:
" - out += memory - out += "
Edit memory
" - out += "Objectives:
" - if (objectives.len == 0) - out += "EMPTY
" - else - var/obj_count = 1 - for(var/datum/objective/objective in objectives) - out += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" - obj_count++ - out += "Add objective

" - - out += "Announce objectives

" - - var/datum/browser/popup = new(usr, "edit_memory", "", 600, 600) - popup.set_content(out) - popup.open() - //usr << browse(out, "window=edit_memory[src];size=575x600") - - /datum/mind/Topic(href, href_list) if(!check_rights(R_ADMIN)) return + var/self_antagging = usr == current + + if(href_list["add_antag"]) + add_antag_wrapper(text2path(href_list["add_antag"]),usr) + if(href_list["remove_antag"]) + var/datum/antagonist/A = locate(href_list["remove_antag"]) in antag_datums + if(!istype(A)) + to_chat(usr,"Invalid antagonist ref to be removed.") + return + A.admin_remove(usr) + if (href_list["role_edit"]) var/new_role = input("Select new role", "Assigned role", assigned_role) as null|anything in get_all_jobs() if (!new_role) @@ -771,8 +411,6 @@ var/objective_pos var/def_value - - var/datum/antagonist/target_antag if (href_list["obj_edit"]) @@ -786,7 +424,7 @@ objective_pos = A.objectives.Find(objective) break - if(!target_antag) //Shouldn't happen + if(!target_antag) //Shouldn't happen anymore stack_trace("objective without antagonist found") objective_pos = objectives.Find(objective) @@ -796,19 +434,25 @@ if(!def_value)//If it's a custom objective, it will be an empty string. def_value = "custom" else - switch(antag_datums.len) - if(0) - target_antag = add_antag_datum(/datum/antagonist/custom) - if(1) - target_antag = antag_datums[1] - else - var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)" - if (QDELETED(target)) - return - else if(target == "(new custom antag)") + //We're adding this objective + if(href_list["target_antag"]) + var/datum/antagonist/X = locate(href_list["target_antag"]) in antag_datums + if(X) + target_antag = X + if(!target_antag) + switch(antag_datums.len) + if(0) target_antag = add_antag_datum(/datum/antagonist/custom) + if(1) + target_antag = antag_datums[1] else - target_antag = target + var/datum/antagonist/target = input("Which antagonist gets the objective:", "Antagonist", def_value) as null|anything in antag_datums + "(new custom antag)" + if (QDELETED(target)) + return + else if(target == "(new custom antag)") + target_antag = add_antag_datum(/datum/antagonist/custom) + else + target_antag = target var/new_obj_type = input("Select objective type:", "Objective type", def_value) as null|anything in list("assassinate", "maroon", "debrain", "protect", "destroy", "prevent", "hijack", "escape", "survive", "martyr", "steal", "download", "nuclear", "capture", "absorb", "custom") if (!new_obj_type) @@ -957,344 +601,6 @@ objective.completed = !objective.completed log_admin("[key_name(usr)] toggled the win state for [current]'s objective: [objective.explanation_text]") - else if (href_list["revolution"]) - switch(href_list["revolution"]) - if("clear") - remove_rev() - message_admins("[key_name_admin(usr)] has de-rev'ed [current].") - log_admin("[key_name(usr)] has de-rev'ed [current].") - if("rev") - if(has_antag_datum(/datum/antagonist/rev/head)) - var/datum/antagonist/rev/head/head = has_antag_datum(/datum/antagonist/rev/head) - head.demote() - else if(!has_antag_datum(/datum/antagonist/rev)) - add_antag_datum(/datum/antagonist/rev) - special_role = "Revolutionary" - message_admins("[key_name_admin(usr)] has rev'ed [current].") - log_admin("[key_name(usr)] has rev'ed [current].") - else - return - - if("headrev") - if(has_antag_datum(/datum/antagonist/rev)) - var/datum/antagonist/rev/rev = has_antag_datum(/datum/antagonist/rev) - rev.promote() - else if(!has_antag_datum(/datum/antagonist/rev/head)) - //what about the team here. - var/datum/antagonist/rev/head/new_head = new /datum/antagonist/rev/head(src) - new_head.give_flash = TRUE - new_head.give_hud = TRUE - new_head.remove_clumsy = TRUE - add_antag_datum(new_head) - to_chat(current, "You are a member of the revolutionaries' leadership now!") - else - return - special_role = "Head Revolutionary" - message_admins("[key_name_admin(usr)] has head-rev'ed [current].") - log_admin("[key_name(usr)] has head-rev'ed [current].") - - if("flash") - var/datum/antagonist/rev/head/head = has_antag_datum(/datum/antagonist/rev/head) - if(!head.equip_rev()) - to_chat(usr, "Spawning flash failed!") - - if("takeflash") - var/list/L = current.get_contents() - var/obj/item/device/assembly/flash/flash = locate() in L - if (!flash) - to_chat(usr, "Deleting flash failed!") - qdel(flash) - - if("repairflash") - var/list/L = current.get_contents() - var/obj/item/device/assembly/flash/flash = locate() in L - if (!flash) - to_chat(usr, "Repairing flash failed!") - else - flash.crit_fail = 0 - flash.update_icon() - - - - else if (href_list["cult"]) - switch(href_list["cult"]) - if("clear") - remove_cultist() - message_admins("[key_name_admin(usr)] has de-cult'ed [current].") - log_admin("[key_name(usr)] has de-cult'ed [current].") - if("cultist") - if(!(src in SSticker.mode.cult)) - SSticker.mode.add_cultist(src, 0) - message_admins("[key_name_admin(usr)] has cult'ed [current].") - log_admin("[key_name(usr)] has cult'ed [current].") - if("tome") - var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) - if (C.equip_cultist(current,1)) - to_chat(usr, "Spawning tome failed!") - - if("amulet") - var/datum/antagonist/cult/C = has_antag_datum(/datum/antagonist/cult,TRUE) - if (C.equip_cultist(current)) - to_chat(usr, "Spawning amulet failed!") - - else if(href_list["clockcult"]) - switch(href_list["clockcult"]) - if("clear") - remove_servant_of_ratvar(current, TRUE) - message_admins("[key_name_admin(usr)] has removed clockwork servant status from [current].") - log_admin("[key_name(usr)] has removed clockwork servant status from [current].") - if("servant") - if(!is_servant_of_ratvar(current)) - add_servant_of_ratvar(current, TRUE) - message_admins("[key_name_admin(usr)] has made [current] into a servant of Ratvar.") - log_admin("[key_name(usr)] has made [current] into a servant of Ratvar.") - if("slab") - if(!SSticker.mode.equip_servant(current)) - to_chat(usr, "Failed to outfit [current]!") - else - to_chat(usr, "Successfully gave [current] servant equipment!") - - else if (href_list["wizard"]) - switch(href_list["wizard"]) - if("clear") - remove_wizard() - log_admin("[key_name(usr)] has de-wizard'ed [current].") - if("wizard") - if(!has_antag_datum(/datum/antagonist/wizard)) - special_role = "Wizard" - add_antag_datum(/datum/antagonist/wizard) - message_admins("[key_name_admin(usr)] has wizard'ed [current].") - log_admin("[key_name(usr)] has wizard'ed [current].") - if("lair") - current.forceMove(pick(GLOB.wizardstart)) - - else if (href_list["changeling"]) - switch(href_list["changeling"]) - if("clear") - remove_antag_datum(/datum/antagonist/changeling) - special_role = null - to_chat(current, "You grow weak and lose your powers! You are no longer a changeling and are stuck in your current form!") - message_admins("[key_name_admin(usr)] has de-changeling'ed [current].") - log_admin("[key_name(usr)] has de-changeling'ed [current].") - if("changeling") - var/datum/antagonist/changeling/C = make_Changling() - to_chat(current, "Our powers have awoken. A flash of memory returns to us...we are [C.changelingID], a changeling!") - message_admins("[key_name_admin(usr)] has changeling'ed [current].") - log_admin("[key_name(usr)] has changeling'ed [current].") - if("autoobjectives") - var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) - if(C) - C.forge_objectives() - to_chat(usr, "The objectives for changeling [key] have been generated. You can edit them and anounce manually.") - if("initialdna") - var/datum/antagonist/changeling/ling = has_antag_datum(/datum/antagonist/changeling) - if( !ling || !ling.stored_profiles.len || !iscarbon(current)) - to_chat(usr, "Resetting DNA failed!") - else - var/mob/living/carbon/C = current - ling.first_prof.dna.transfer_identity(C, transfer_SE=1) - C.real_name = ling.first_prof.name - C.updateappearance(mutcolor_update=1) - C.domutcheck() - - else if (href_list["nuclear"]) - switch(href_list["nuclear"]) - if("clear") - remove_nukeop() - to_chat(current, "You have been brainwashed! You are no longer a syndicate operative!") - message_admins("[key_name_admin(usr)] has de-nuke op'ed [current].") - log_admin("[key_name(usr)] has de-nuke op'ed [current].") - if("nuclear") - if(!has_antag_datum(/datum/antagonist/nukeop,TRUE)) - add_antag_datum(/datum/antagonist/nukeop) - special_role = "Syndicate" - assigned_role = "Syndicate" - message_admins("[key_name_admin(usr)] has nuke op'ed [current].") - log_admin("[key_name(usr)] has nuke op'ed [current].") - if("lair") - current.forceMove(pick(GLOB.nukeop_start)) - if("tellcode") - var/code - for (var/obj/machinery/nuclearbomb/bombue in GLOB.machines) - if (length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN") - code = bombue.r_code - break - if (code) - store_memory("Syndicate Nuclear Bomb Code: [code]", 0, 0) - to_chat(current, "The nuclear authorization code is: [code]") - else - to_chat(usr, "No valid nuke found!") - - else if (href_list["traitor"]) - switch(href_list["traitor"]) - if("clear") - to_chat(current, "You have been brainwashed!") - remove_traitor() - message_admins("[key_name_admin(usr)] has de-traitor'ed [current].") - log_admin("[key_name(usr)] has de-traitor'ed [current].") - SSticker.mode.update_traitor_icons_removed(src) - - if("traitor") - if(!(src in SSticker.mode.traitors)) - message_admins("[key_name_admin(usr)] has traitor'ed [current].") - log_admin("[key_name(usr)] has traitor'ed [current].") - make_Traitor() - - if("autoobjectives") - var/datum/antagonist/traitor/traitordatum = has_antag_datum(ANTAG_DATUM_TRAITOR) - if(!traitordatum) - message_admins("[key_name_admin(usr)] has traitor'ed [current] as part of autoobjectives.") - log_admin("[key_name(usr)] has traitor'ed [current] as part of autoobjectives.") - make_Traitor() - else - log_admin("[key_name(usr)] has forged objectives for [current] as part of autoobjectives.") - traitordatum.forge_traitor_objectives() - to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and anounce manually.") - - else if(href_list["devil"]) - var/datum/antagonist/devil/devilinfo = has_antag_datum(ANTAG_DATUM_DEVIL) - switch(href_list["devil"]) - if("clear") - if(src in SSticker.mode.devils) - remove_devil(current) - message_admins("[key_name_admin(usr)] has de-devil'ed [current].") - log_admin("[key_name(usr)] has de-devil'ed [current].") - if(src in SSticker.mode.sintouched) - SSticker.mode.sintouched -= src - message_admins("[key_name_admin(usr)] has de-sintouch'ed [current].") - log_admin("[key_name(usr)] has de-sintouch'ed [current].") - if("devil") - if(devilinfo) - devilinfo.ascendable = FALSE - message_admins("[key_name_admin(usr)] has made [current] unable to ascend as a devil.") - log_admin("[key_name(usr)] has made [current] unable to ascend as a devil.") - return - if(!ishuman(current) && !iscyborg(current)) - to_chat(usr, "This only works on humans and cyborgs!") - return - add_devil(current, FALSE) - message_admins("[key_name_admin(usr)] has devil'ed [current].") - log_admin("[key_name(usr)] has devil'ed [current].") - if("ascendable_devil") - if(devilinfo) - devilinfo.ascendable = TRUE - message_admins("[key_name_admin(usr)] has made [current] able to ascend as a devil.") - log_admin("[key_name(usr)] has made [current] able to ascend as a devil.") - return - if(!ishuman(current) && !iscyborg(current)) - to_chat(usr, "This only works on humans and cyborgs!") - return - add_devil(current, TRUE) - message_admins("[key_name_admin(usr)] has devil'ed [current]. The devil has been marked as ascendable.") - log_admin("[key_name(usr)] has devil'ed [current]. The devil has been marked as ascendable.") - if("sintouched") - if(ishuman(current)) - var/mob/living/carbon/human/H = current - H.influenceSin() - message_admins("[key_name_admin(usr)] has sintouch'ed [current].") - else - to_chat(usr, "This only works on humans!") - return - else if(href_list["ninja"]) - var/datum/antagonist/ninja/ninjainfo = has_antag_datum(ANTAG_DATUM_NINJA) - switch(href_list["ninja"]) - if("clear") - remove_ninja(current) - message_admins("[key_name_admin(usr)] has de-ninja'ed [current].") - log_admin("[key_name(usr)] has de-ninja'ed [current].") - if("equip") - ninjainfo.equip_space_ninja() - return - if("nanotrasen") - add_ninja(current, ANTAG_DATUM_NINJA_FRIENDLY) - message_admins("[key_name_admin(usr)] has friendly ninja'ed [current].") - log_admin("[key_name(usr)] has friendly ninja'ed [current].") - if("syndicate") - add_ninja(current, ANTAG_DATUM_NINJA) - message_admins("[key_name_admin(usr)] has syndie ninja'ed [current].") - log_admin("[key_name(usr)] has syndie ninja'ed [current].") - if("random") - add_ninja(current) - message_admins("[key_name_admin(usr)] has random ninja'ed [current].") - log_admin("[key_name(usr)] has random ninja'ed [current].") - else if(href_list["abductor"]) - switch(href_list["abductor"]) - if("clear") - to_chat(usr, "Not implemented yet. Sorry!") - //SSticker.mode.update_abductor_icons_removed(src) - if("equip") - if(!ishuman(current)) - to_chat(usr, "This only works on humans!") - return - - var/mob/living/carbon/human/H = current - var/gear = alert("Agent or Scientist Gear","Gear","Agent","Scientist") - if(gear) - if(gear=="Agent") - H.equipOutfit(/datum/outfit/abductor/agent) - else - H.equipOutfit(/datum/outfit/abductor/scientist) - - else if (href_list["monkey"]) - var/mob/living/L = current - if (L.notransform) - return - switch(href_list["monkey"]) - if("healthy") - if (check_rights(R_ADMIN)) - var/mob/living/carbon/human/H = current - var/mob/living/carbon/monkey/M = current - if (istype(H)) - log_admin("[key_name(usr)] attempting to monkeyize [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to monkeyize [key_name_admin(current)]") - src = null - M = H.monkeyize() - src = M.mind - else if (istype(M) && length(M.viruses)) - for(var/thing in M.viruses) - var/datum/disease/D = thing - D.cure(FALSE) - if("leader") - if(check_rights(R_ADMIN, 0)) - add_monkey_leader(src) - log_admin("[key_name(usr)] made [key_name(current)] a monkey leader!") - message_admins("[key_name_admin(usr)] made [key_name_admin(current)] a monkey leader!") - if("infected") - if(check_rights(R_ADMIN, 0)) - var/mob/living/carbon/human/H = current - var/mob/living/carbon/monkey/M = current - add_monkey(src) - if (istype(H)) - log_admin("[key_name(usr)] attempting to monkeyize and infect [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to monkeyize and infect [key_name_admin(current)]") - src = null - M = H.monkeyize() - src = M.mind - current.ForceContractDisease(new /datum/disease/transformation/jungle_fever) - else if (istype(M)) - current.ForceContractDisease(new /datum/disease/transformation/jungle_fever) - if("human") - if (check_rights(R_ADMIN, 0)) - var/mob/living/carbon/human/H = current - var/mob/living/carbon/monkey/M = current - if (istype(M)) - for(var/datum/disease/transformation/jungle_fever/JF in M.viruses) - JF.cure(0) - stoplag() //because deleting of virus is doing throught spawn(0) //What - remove_monkey(src) - log_admin("[key_name(usr)] attempting to humanize [key_name(current)]") - message_admins("[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]") - H = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) - if(H) - src = H.mind - - else if (href_list["brother"]) - switch(href_list["brother"]) - if("clear") - remove_brother() - log_admin("[key_name(usr)] has de-brother'ed [current].") - SSticker.mode.update_brother_icons_removed(src) - else if (href_list["silicon"]) switch(href_list["silicon"]) if("unemag") @@ -1340,7 +646,10 @@ else if (href_list["obj_announce"]) announce_objectives() - edit_memory() + //Something in here might have changed your mob + if(self_antagging && (!usr || !usr.client) && current.client) + usr = current + traitor_panel() /datum/mind/proc/announce_objectives() var/obj_count = 1 @@ -1363,9 +672,7 @@ /datum/mind/proc/make_Traitor() if(!(has_antag_datum(ANTAG_DATUM_TRAITOR))) - var/datum/antagonist/traitor/T = new(src) - T.should_specialise = TRUE - add_antag_datum(T) + add_antag_datum(/datum/antagonist/traitor) /datum/mind/proc/make_Changling() var/datum/antagonist/changeling/C = has_antag_datum(/datum/antagonist/changeling) @@ -1389,7 +696,7 @@ to_chat(current, "Assist your new bretheren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.") /datum/mind/proc/make_Rev() - var/datum/antagonist/rev/head/head = new(src) + var/datum/antagonist/rev/head/head = new() head.give_flash = TRUE head.give_hud = TRUE add_antag_datum(head) diff --git a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm index 3b8937d9fb4c..8d4c1cf5ba95 100644 --- a/code/game/gamemodes/antag_spawner.dm +++ b/code/game/gamemodes/antag_spawner.dm @@ -73,8 +73,8 @@ C.prefs.copy_to(M) M.key = C.key var/datum/mind/app_mind = M.mind - - var/datum/antagonist/wizard/apprentice/app = new(app_mind) + + var/datum/antagonist/wizard/apprentice/app = new() app.master = user app.school = kind @@ -136,7 +136,7 @@ C.prefs.copy_to(M) M.key = C.key - var/datum/antagonist/nukeop/new_op = new(M.mind) + var/datum/antagonist/nukeop/new_op = new() new_op.send_to_spawnpoint = FALSE new_op.nukeop_outfit = /datum/outfit/syndicate/no_crystals @@ -187,8 +187,8 @@ R.real_name = R.name R.key = C.key - - var/datum/antagonist/nukeop/new_borg = new(R.mind) + + var/datum/antagonist/nukeop/new_borg = new() new_borg.send_to_spawnpoint = FALSE R.mind.add_antag_datum(new_borg,creator_op.nuke_team) R.mind.special_role = "Syndicate Cyborg" @@ -235,7 +235,6 @@ S.key = C.key S.mind.assigned_role = S.name S.mind.special_role = S.name - SSticker.mode.traitors += S.mind var/datum/objective/assassinate/new_objective if(user) new_objective = new /datum/objective/assassinate diff --git a/code/game/gamemodes/antag_team.dm b/code/game/gamemodes/antag_team.dm index 372ee26dfad6..56ca7c76e224 100644 --- a/code/game/gamemodes/antag_team.dm +++ b/code/game/gamemodes/antag_team.dm @@ -31,4 +31,16 @@ report += "The [member_name]s were:" report += printplayerlist(members) - return report.Join("
") \ No newline at end of file + return report.Join("
") + +//Get all teams [of type team_type] +//TODO move these to some antag helpers file with get_antagonists +/proc/get_all_teams(team_type) + . = list() + for(var/V in GLOB.antagonists) + var/datum/antagonist/A = V + if(!A.owner) + continue + var/datum/team/T = A.get_team() + if(!team_type || istype(T,team_type)) + . |= T diff --git a/code/game/gamemodes/brother/traitor_bro.dm b/code/game/gamemodes/brother/traitor_bro.dm index 5052fa0cf5be..1634983a1b50 100644 --- a/code/game/gamemodes/brother/traitor_bro.dm +++ b/code/game/gamemodes/brother/traitor_bro.dm @@ -18,8 +18,6 @@ var/const/min_team_size = 2 traitors_required = FALSE //Only teams are possible - var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library") - /datum/game_mode/traitor/bros/pre_setup() if(CONFIG_GET(flag/protect_roles_from_antagonist)) restricted_jobs += protected_jobs @@ -51,8 +49,7 @@ /datum/game_mode/traitor/bros/post_setup() for(var/datum/team/brother_team/team in pre_brother_teams) - team.meeting_area = pick(meeting_areas) - meeting_areas -= team.meeting_area + team.pick_meeting_area() team.forge_brother_objectives() for(var/datum/mind/M in team.members) M.add_antag_datum(ANTAG_DATUM_BROTHER, team) diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index ad76d41d473f..491378c5de29 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -70,7 +70,7 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th for(var/datum/mind/changeling in changelings) log_game("[changeling.key] (ckey) has been selected as a changeling") - var/datum/antagonist/changeling/new_antag = new(changeling) + var/datum/antagonist/changeling/new_antag = new() new_antag.team_mode = TRUE changeling.add_antag_datum(new_antag) ..() diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm index 56003d91ebf4..bd641757806d 100644 --- a/code/game/gamemodes/changeling/powers/absorb.dm +++ b/code/game/gamemodes/changeling/powers/absorb.dm @@ -78,12 +78,12 @@ recent_speech[spoken_memory] = say_log[spoken_memory] if(recent_speech.len) - user.mind.store_memory("Some of [target]'s speech patterns, we should study these to better impersonate them!") + changeling.antag_memory += "Some of [target]'s speech patterns, we should study these to better impersonate them!
" to_chat(user, "Some of [target]'s speech patterns, we should study these to better impersonate them!") for(var/spoken_memory in recent_speech) - user.mind.store_memory("\"[recent_speech[spoken_memory]]\"") + changeling.antag_memory += "\"[recent_speech[spoken_memory]]\"
" to_chat(user, "\"[recent_speech[spoken_memory]]\"") - user.mind.store_memory("We have no more knowledge of [target]'s speech patterns.") + changeling.antag_memory += "We have no more knowledge of [target]'s speech patterns.
" to_chat(user, "We have no more knowledge of [target]'s speech patterns.") diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index f5484e91f51b..c7765b19bfe5 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -74,8 +74,35 @@ Credit where due: var/datum/antagonist/clockcult/C = new update_type(L.mind) C.make_team = create_team C.show_in_roundend = create_team //tutorial scarabs begone + + if(iscyborg(L)) + var/mob/living/silicon/robot/R = L + if(R.deployed) + var/mob/living/silicon/ai/AI = R.mainframe + R.undeploy() + to_chat(AI, "Anomaly Detected. Returned to core!") //The AI needs to be in its core to properly be converted + . = L.mind.add_antag_datum(C) + if(!silent && L) + if(.) + to_chat(L, "The world before you suddenly glows a brilliant yellow. [issilicon(L) ? "You cannot compute this truth!" : \ + "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and all at once it comes to you.
\ + Ratvar, the Clockwork Justiciar, [GLOB.ratvar_awakens ? "has been freed from his eternal prison" : "lies in exile, derelict and forgotten in an unseen realm"].
") + flash_color(L, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 50) + else + L.visible_message("[L] seems to resist an unseen force!", null, null, 7, L) + to_chat(L, "The world before you suddenly glows a brilliant yellow. [issilicon(L) ? "You cannot compute this truth!" : \ + "Your mind is racing!"] You hear the whooshing steam and cl[pick("ank", "ink", "unk", "ang")]ing cogs of a billion billion machines, and the sound \ + is a meaningless cacophony.
\ + You see an abomination of rusting parts[GLOB.ratvar_awakens ? ", and it is here.
It is too late" : \ + " in an endless grey void.
It cannot be allowed to escape"].
") + L.playsound_local(get_turf(L), 'sound/ambience/antag/clockcultalr.ogg', 40, TRUE, frequency = 100000, pressure_affected = FALSE) + flash_color(L, flash_color = list("#BE8700", "#BE8700", "#BE8700", rgb(0,0,0)), flash_time = 5) + + + + /proc/remove_servant_of_ratvar(mob/L, silent = FALSE) if(!L || !L.mind) return diff --git a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm index 2edaba3b2389..2fa682ff5c42 100644 --- a/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm +++ b/code/game/gamemodes/clock_cult/clock_structures/eminence_spire.dm @@ -38,7 +38,8 @@ /obj/structure/destructible/clockwork/eminence_spire/attack_ghost(mob/user) if(!IsAdminGhost(user)) return - var/datum/antagonist/clockcult/random_cultist = locate() in GLOB.antagonists //if theres no cultists new team without eminence will be created anyway. + + var/datum/antagonist/clockcult/random_cultist = locate() in get_antagonists(/datum/antagonist/clockcult) //if theres no cultists new team without eminence will be created anyway. if(random_cultist && random_cultist.clock_team && random_cultist.clock_team.eminence) to_chat(user, "There's already an Eminence - too late!") return diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 35e8c3cb4e42..42939460730f 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -99,7 +99,7 @@ if (!istype(cult_mind)) return 0 - var/datum/antagonist/cult/new_cultist = new(cult_mind) + var/datum/antagonist/cult/new_cultist = new() new_cultist.give_equipment = equip if(cult_mind.add_antag_datum(new_cultist)) diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index b809f2419c95..be029c31788e 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -338,6 +338,7 @@ return ..() /datum/action/innate/cult/master/pulse/Destroy() + PM.attached_action = null //What the fuck is even going on here. QDEL_NULL(PM) return ..() diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index f9e8f8d75253..ff4d80cd6e9c 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -1,92 +1,6 @@ /datum/game_mode var/list/datum/mind/abductors = list() -/datum/game_mode/abduction - name = "abduction" - config_tag = "abduction" - antag_flag = ROLE_ABDUCTOR - false_report_weight = 1 - recommended_enemies = 2 - required_players = 15 - maximum_players = 50 - var/max_teams = 4 - var/list/datum/team/abductor_team/abductor_teams = list() - var/finished = FALSE - var/static/team_count = 0 - -/datum/game_mode/abduction/announce() - to_chat(world, "The current game mode is - Abduction!") - to_chat(world, "There are alien abductors sent to [station_name()] to perform nefarious experiments!") - to_chat(world, "Abductors - kidnap the crew and replace their organs with experimental ones.") - to_chat(world, "Crew - don't get abducted and stop the abductors.") - -/datum/game_mode/abduction/pre_setup() - var/num_teams = max(1, min(max_teams, round(num_players() / CONFIG_GET(number/abductor_scaling_coeff)))) - var/possible_teams = max(1, round(antag_candidates.len / 2)) - num_teams = min(num_teams, possible_teams) - - for(var/i = 1 to num_teams) - if(!make_abductor_team()) - return FALSE - return TRUE - -/datum/game_mode/abduction/proc/make_abductor_team(datum/mind/agent, datum/mind/scientist) - team_count++ //TODO: Fix the edge case of abductor game mode rolling twice+ and failing to setup on first time. - var/team_number = team_count - - if(team_number > max_teams) - return //or should it try to stuff them in anway ? - - var/datum/team/abductor_team/team = new - team.team_number = team_number - team.name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names - team.add_objective(new/datum/objective/experiment) - - if(antag_candidates.len < (!agent + !scientist)) - return - - if(!scientist) - scientist = pick(antag_candidates) - antag_candidates -= scientist - team.members |= scientist - scientist.assigned_role = "Abductor Scientist" - scientist.special_role = "Abductor Scientist" - log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.") - - if(!agent) - agent = pick(antag_candidates) - antag_candidates -= agent - team.members |= agent - agent.assigned_role = "Abductor Agent" - agent.special_role = "Abductor Agent" - log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.") - - abductor_teams += team - return team - -/datum/game_mode/abduction/post_setup() - for(var/datum/team/abductor_team/team in abductor_teams) - post_setup_team(team) - return ..() - -//Used for create antag buttons -/datum/game_mode/abduction/proc/post_setup_team(datum/team/abductor_team/team) - for(var/datum/mind/M in team.members) - if(M.assigned_role == "Abductor Scientist") - M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, team) - else - M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_AGENT, team) - -/datum/game_mode/abduction/check_finished() - if(!finished) - for(var/datum/team/abductor_team/team in abductor_teams) - for(var/datum/objective/O in team.objectives) - if(O.check_completion()) - SSshuttle.emergency.request(null, set_coefficient = 0.5) - finished = TRUE - return ..() - return ..() - // LANDMARKS /obj/effect/landmark/abductor var/team_number = 1 @@ -118,8 +32,4 @@ /datum/game_mode/proc/update_abductor_icons_removed(datum/mind/alien_mind) var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR] hud.leave_hud(alien_mind.current) - set_antag_hud(alien_mind.current, null) - -/datum/game_mode/abduction/generate_report() - return "Nearby spaceships report crewmembers having been [pick("kidnapped", "abducted", "captured")] and [pick("tortured", "experimented on", "probed", "implanted")] by mysterious \ - grey humanoids, before being sent back. Be advised that the kidnapped crewmembers behave strangely upon return to duties." + set_antag_hud(alien_mind.current, null) \ No newline at end of file diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index 158ba09d43c8..6d0759c52bdc 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -226,7 +226,6 @@ player_mind.transfer_to(S) player_mind.assigned_role = "Morph" player_mind.special_role = "Morph" - SSticker.mode.traitors |= player_mind player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) SEND_SOUND(S, sound('sound/magic/mutate.ogg')) diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index 002e1b3809c3..0719072077f2 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -86,7 +86,6 @@ to_chat(src, "Objective #2: [objective2.explanation_text]") mind.assigned_role = "revenant" mind.special_role = "Revenant" - SSticker.mode.traitors |= mind //Necessary for announcing mind.add_antag_datum(/datum/antagonist/auto_custom) AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null)) AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null)) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm index e62665f21bd7..4ac480b3452e 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughterevent.dm @@ -37,7 +37,6 @@ player_mind.transfer_to(S) player_mind.assigned_role = "Slaughter Demon" player_mind.special_role = "Slaughter Demon" - SSticker.mode.traitors |= player_mind player_mind.add_antag_datum(/datum/antagonist/auto_custom) to_chat(S, S.playstyle_string) to_chat(S, "You are currently not currently in the same plane of existence as the station. Blood Crawl near a blood pool to manifest.") diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 71947fc682b7..4c78ecca909a 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -96,7 +96,7 @@ for(var/datum/mind/rev_mind in headrev_candidates) log_game("[rev_mind.key] (ckey) has been selected as a head rev") - var/datum/antagonist/rev/head/new_head = new(rev_mind) + var/datum/antagonist/rev/head/new_head = new() new_head.give_flash = TRUE new_head.give_hud = TRUE new_head.remove_clumsy = TRUE diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 42c96cb5c0ee..09e31810f167 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -61,8 +61,7 @@ /datum/game_mode/traitor/post_setup() for(var/datum/mind/traitor in pre_traitors) - var/datum/antagonist/traitor/new_antag = new antag_datum(traitor) - new_antag.should_specialise = TRUE + var/datum/antagonist/traitor/new_antag = new antag_datum() addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100)) if(!exchange_blue) exchange_blue = -1 //Block latejoiners from getting exchange objectives @@ -82,8 +81,7 @@ 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(character) - new_antag.should_specialise = TRUE + var/datum/antagonist/traitor/new_antag = new antag_datum() character.add_antag_datum(new_antag) /datum/game_mode/traitor/generate_report() @@ -98,4 +96,4 @@ /datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.leave_hud(traitor_mind.current) - set_antag_hud(traitor_mind.current, null) + set_antag_hud(traitor_mind.current, null) \ No newline at end of file diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index 59465cf5b2e8..6f0c281730c2 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -39,7 +39,6 @@ user.dna.add_mutation(COLDRES) user.dna.add_mutation(TK) - SSticker.mode.traitors += user.mind user.mind.special_role = "Avatar of the Wish Granter" var/datum/objective/hijack/hijack = new diff --git a/code/game/objects/items/devices/doorCharge.dm b/code/game/objects/items/devices/doorCharge.dm index cf11b2c94122..2fc3770f1ccf 100644 --- a/code/game/objects/items/devices/doorCharge.dm +++ b/code/game/objects/items/devices/doorCharge.dm @@ -35,7 +35,7 @@ /obj/item/device/doorCharge/examine(mob/user) ..() - if(user.mind in SSticker.mode.traitors) //No nuke ops because the device is excluded from nuclear + if(user.mind && user.mind.has_antag_datum(/datum/antagonist/traitor)) //No nuke ops because the device is excluded from nuclear to_chat(user, "A small explosive device that can be used to sabotage airlocks to cause an explosion upon opening. To apply, remove the airlock's maintenance panel and place it within.") else to_chat(user, "A small, suspicious object that feels lukewarm when held.") diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 4c7b8c5b4036..fc4e04f97e2d 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -48,7 +48,10 @@ body += "

\[ " body += "VV - " - body += "TP - " + if(M.mind) + body += "TP - " + else + body += "Init Mind - " body += "PM - " body += "SM - " body += "FLW - " @@ -649,7 +652,7 @@ to_chat(usr, "This mob has no mind!") return - M.mind.edit_memory() + M.mind.traitor_panel() SSblackbox.record_feedback("tally", "admin_verb", 1, "Traitor Panel") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/antag_panel.dm b/code/modules/admin/antag_panel.dm new file mode 100644 index 000000000000..7546fa85423e --- /dev/null +++ b/code/modules/admin/antag_panel.dm @@ -0,0 +1,217 @@ +GLOBAL_VAR(antag_prototypes) + +//Things to do somewhere in the future (If you're reading this feel free to do any of these) +//Add HrefTokens to these +//Make this template or at least remove + "
" with joins where you can grasp the big picture. +//Span classes for the headers, wrap sections in div's and style them. +//Move common admin commands to /mob (maybe integrate with vv dropdown so the list is one thing with some flag where to show it) +//Move objective initialization/editing stuff from mind to objectives and completely remove mind.objectives + +/proc/cmp_antagpanel(datum/antagonist/A,datum/antagonist/B) + var/a_cat = initial(A.antagpanel_category) + var/b_cat = initial(B.antagpanel_category) + if(!a_cat && !b_cat) + return sorttext(initial(A.name),initial(B.name)) + return sorttext(b_cat,a_cat) + +/datum/mind/proc/add_antag_wrapper(antag_type,mob/user) + var/datum/antagonist/new_antag = new antag_type() + new_antag.admin_add(src,user) + //If something gone wrong/admin-add assign another antagonist due to whatever clean it up + if(!new_antag.owner) + qdel(new_antag) + +/proc/listtrim(list/L) + for(var/x in L) + if(istext(x) && !x) + L -= x + return L + +/datum/antagonist/proc/antag_panel() + var/list/commands = list() + for(var/command in get_admin_commands()) + commands += "[command]" + var/command_part = commands.Join(" | ") + var/data_part = antag_panel_data() + var/objective_part = antag_panel_objectives() + var/memory_part = antag_panel_memory() + + var/list/parts = listtrim(list(command_part,data_part,objective_part,memory_part)) + + return parts.Join("
") + +/datum/antagonist/proc/antag_panel_objectives() + var/result = "Objectives:
" + if (objectives.len == 0) + result += "EMPTY
" + else + var/obj_count = 1 + for(var/datum/objective/objective in objectives) + result += "[obj_count]: [objective.explanation_text] Edit Delete [objective.completed ? "Mark as incomplete" : "Mark as complete"]
" + obj_count++ + result += "Add objective
" + result += "Announce objectives
" + return result + +/datum/antagonist/proc/antag_panel_memory() + var/out = "Memory:
" + out += antag_memory + out += "
Edit memory
" + return out + +/datum/mind/proc/get_common_admin_commands() + var/common_commands = "Common Commands:" + if(ishuman(current)) + common_commands += "undress" + else if(iscyborg(current)) + var/mob/living/silicon/robot/R = current + if(R.emagged) + common_commands += "Unemag" + else if(isAI(current)) + var/mob/living/silicon/ai/A = current + if (A.connected_robots.len) + for (var/mob/living/silicon/robot/R in A.connected_robots) + if (R.emagged) + common_commands += "Unemag slaved cyborgs" + break + return common_commands + +/datum/mind/proc/get_special_statuses() + var/list/result = list() + if(!current) + result += "No body!" + if(current && current.isloyal()) + result += "Mindshielded" + //Move these to mob + if(iscyborg(current)) + var/mob/living/silicon/robot/robot = current + if (robot.emagged) + result += "Emagged" + return result.Join(" | ") + +/datum/mind/proc/traitor_panel() + if(!SSticker.HasRoundStarted()) + alert("Not before round-start!", "Alert") + return + if(QDELETED(src)) + alert("This mind doesn't have a mob, or is deleted! For some reason!", "Edit Memory") + return + + var/out = "[name][(current && (current.real_name!=name))?" (as [current.real_name])":""]
" + out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
" + out += "Assigned role: [assigned_role]. Edit
" + out += "Faction and special role: [special_role]
" + + var/special_statuses = get_special_statuses() + if(length(special_statuses)) + out += get_special_statuses() + "
" + + if(!GLOB.antag_prototypes) + GLOB.antag_prototypes = list() + for(var/antag_type in subtypesof(/datum/antagonist)) + var/datum/antagonist/A = new antag_type + var/cat_id = A.antagpanel_category + if(!GLOB.antag_prototypes[cat_id]) + GLOB.antag_prototypes[cat_id] = list(A) + else + GLOB.antag_prototypes[cat_id] += A + sortTim(GLOB.antag_prototypes,/proc/cmp_text_asc,associative=TRUE) + + var/list/sections = list() + var/list/priority_sections = list() + + for(var/antag_category in GLOB.antag_prototypes) + var/category_header = "[antag_category]:" + var/list/antag_header_parts = list(category_header) + + var/datum/antagonist/current_antag + var/list/possible_admin_antags = list() + + for(var/datum/antagonist/prototype in GLOB.antag_prototypes[antag_category]) + var/datum/antagonist/A = has_antag_datum(prototype.type) + if(A) + //We got the antag + if(!current_antag) + current_antag = A + else + continue //Let's skip subtypes of what we already shown. + else if(prototype.show_in_antagpanel) + if(prototype.can_be_owned(src)) + possible_admin_antags += "[prototype.name]" + else + possible_admin_antags += "[prototype.name]" + else + //We don't have it and it shouldn't be shown as an option to be added. + continue + + if(!current_antag) //Show antagging options + if(possible_admin_antags.len) + antag_header_parts += "None" + antag_header_parts += possible_admin_antags + else + //If there's no antags to show in this category skip the section completely + continue + else //Show removal and current one + priority_sections |= antag_category + antag_header_parts += "[current_antag.name]" + antag_header_parts += "Remove" + + + //We aren't antag of this category, grab first prototype to check the prefs (This is pretty vague but really not sure how else to do this) + var/datum/antagonist/pref_source = current_antag + if(!pref_source) + for(var/datum/antagonist/prototype in GLOB.antag_prototypes[antag_category]) + if(!prototype.show_in_antagpanel) + continue + pref_source = prototype + break + if(pref_source.job_rank) + antag_header_parts += pref_source.enabled_in_preferences(src) ? "Enabled in Prefs" : "Disabled in Prefs" + + //Traitor : None | Traitor | IAA + // Command1 | Command2 | Command3 + // Secret Word : Banana + // Objectives: + // 1.Do the thing [a][b] + // [a][b] + // Memory: + // Uplink Code: 777 Alpha + var/cat_section = antag_header_parts.Join(" | ") + "
" + if(current_antag) + cat_section += current_antag.antag_panel() + sections[antag_category] = cat_section + + for(var/s in priority_sections) + out += sections[s] + for(var/s in sections - priority_sections) + out += sections[s] + + out += "
" + + //Uplink + if(ishuman(current)) + var/uplink_info = "Uplink:" + var/datum/component/uplink/U = find_syndicate_uplink() + if(U) + uplink_info += "take" + if (check_rights(R_FUN, 0)) + uplink_info += ", [U.telecrystals] TC" + else + uplink_info += ", [U.telecrystals] TC" + else + uplink_info += "give" + uplink_info += "." //hiel grammar + + out += uplink_info + "
" + //Common Memory + var/common_memory = "Common Memory:" + common_memory += memory + common_memory += "Edit Memory" + out += common_memory + "
" + //Other stuff + out += get_common_admin_commands() + + var/datum/browser/panel = new(usr, "traitorpanel", "", 600, 600) + panel.set_content(out) + panel.open() + return \ No newline at end of file diff --git a/code/modules/admin/check_antagonists.dm b/code/modules/admin/check_antagonists.dm new file mode 100644 index 000000000000..f1ad21ded3bc --- /dev/null +++ b/code/modules/admin/check_antagonists.dm @@ -0,0 +1,212 @@ +//I wish we had interfaces sigh, and i'm not sure giving team and antag common root is a better solution here + +//Name shown on antag list +/datum/antagonist/proc/antag_listing_name() + if(!owner) + return "Unassigned" + if(owner.current) + return "[owner.current.real_name]" + else + return "[owner.name]" + +//Whatever interesting things happened to the antag admins should know about +//Include additional information about antag in this part +/datum/antagonist/proc/antag_listing_status() + if(!owner) + return "(Unassigned)" + if(!owner.current) + return "(Body destroyed)" + else + if(owner.current.stat == DEAD) + return "(DEAD)" + else if(!owner.current.client) + return "(No client)" + +//Builds the common FLW PM TP commands part +//Probably not going to be overwritten by anything but you never know +/datum/antagonist/proc/antag_listing_commands() + if(!owner) + return + var/list/parts = list() + parts += "PM" + if(owner.current) //There's body to follow + parts += "FLW" + else + parts += "" + parts += "Show Objective" + return parts //Better as one cell or two/three + +//Builds table row for the antag +// Jim (Status) FLW PM TP +/datum/antagonist/proc/antag_listing_entry() + var/list/parts = list() + parts += antag_listing_name() + parts += antag_listing_status() + parts += antag_listing_commands() + return "[parts.Join("")]" + + +/datum/team/proc/get_team_antags(antag_type,specific = FALSE) + . = list() + for(var/datum/antagonist/A in GLOB.antagonists) + if(A.get_team() == src && (!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type)) + . += A + +//Builds section for the team +/datum/team/proc/antag_listing_entry() + //NukeOps: + // Jim (Status) FLW PM TP + // Joe (Status) FLW PM TP + //Disk: + // Deep Space FLW + var/list/parts = list() + parts += "[antag_listing_name()]
" + parts += "" + for(var/datum/antagonist/A in get_team_antags()) + parts += A.antag_listing_entry() + parts += "
" + parts += antag_listing_footer() + return parts.Join() + +/datum/team/proc/antag_listing_name() + return name + +/datum/team/proc/antag_listing_footer() + return + +//Moves them to the top of the list if TRUE +/datum/antagonist/proc/is_gamemode_hero() + return FALSE + +/datum/team/proc/is_gamemode_hero() + return FALSE + +/datum/admins/proc/build_antag_listing() + var/list/sections = list() + var/list/priority_sections = list() + + var/list/all_teams = list() + var/list/all_antagonists = list() + + for(var/datum/antagonist/A in GLOB.antagonists) + if(!A.owner) + continue + all_teams |= A.get_team() + all_antagonists += A + + for(var/datum/team/T in all_teams) + for(var/datum/antagonist/X in all_antagonists) + if(X.get_team() == T) + all_antagonists -= X + if(T.is_gamemode_hero()) + priority_sections += T.antag_listing_entry() + else + sections += T.antag_listing_entry() + + sortTim(all_antagonists, /proc/cmp_antag_category) + + var/current_category + var/list/current_section = list() + for(var/i in 1 to all_antagonists.len) + var/datum/antagonist/current_antag = all_antagonists[i] + var/datum/antagonist/next_antag + if(i < all_antagonists.len) + next_antag = all_antagonists[i+1] + if(!current_category) + current_category = current_antag.roundend_category + current_section += "[capitalize(current_category)]
" + current_section += "" + current_section += current_antag.antag_listing_entry() // Name - (Traitor) - FLW | PM | TP + + if(!next_antag || next_antag.roundend_category != current_antag.roundend_category) //End of section + current_section += "
" + if(current_antag.is_gamemode_hero()) + priority_sections += current_section.Join() + else + sections += current_section.Join() + current_section.Cut() + current_category = null + var/list/all_sections = priority_sections + sections + return all_sections.Join("
") + +/datum/admins/proc/check_antagonists() + if (SSticker.HasRoundStarted()) + var/dat = "Round Status

Round Status

" + if(SSticker.mode.replacementmode) + dat += "Former Game Mode: [SSticker.mode.name]
" + dat += "Replacement Game Mode: [SSticker.mode.replacementmode.name]
" + else + dat += "Current Game Mode: [SSticker.mode.name]
" + dat += "Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]
" + dat += "Emergency shuttle
" + if(EMERGENCY_IDLE_OR_RECALLED) + dat += "Call Shuttle
" + else + var/timeleft = SSshuttle.emergency.timeLeft() + if(SSshuttle.emergency.mode == SHUTTLE_CALL) + dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
" + dat += "Send Back
" + else + dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
" + dat += "Continuous Round Status
" + dat += "[CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]" + if(CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag]) + dat += ", [CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag] ? "creating replacement antagonists" : "not creating new antagonists"]
" + else + dat += "
" + if(CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag]) + dat += "Time limit: [CONFIG_GET(number/midround_antag_time_check)] minutes into round
" + dat += "Living crew limit: [CONFIG_GET(number/midround_antag_life_check) * 100]% of crew alive
" + dat += "If limits past: [SSticker.mode.round_ends_with_antag_death ? "End The Round" : "Continue As Extended"]
" + dat += "End Round Now
" + dat += "[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]" + var/connected_players = GLOB.clients.len + var/lobby_players = 0 + var/observers = 0 + var/observers_connected = 0 + var/living_players = 0 + var/living_players_connected = 0 + var/living_players_antagonist = 0 + var/brains = 0 + var/other_players = 0 + var/living_skipped = 0 + var/drones = 0 + for(var/mob/M in GLOB.mob_list) + if(M.ckey) + if(isnewplayer(M)) + lobby_players++ + continue + else if(M.stat != DEAD && M.mind && !isbrain(M)) + if(isdrone(M)) + drones++ + continue + if(is_centcom_level(M.z)) + living_skipped++ + continue + living_players++ + if(M.mind.special_role) + living_players_antagonist++ + if(M.client) + living_players_connected++ + else if(M.stat == DEAD || isobserver(M)) + observers++ + if(M.client) + observers_connected++ + else if(isbrain(M)) + brains++ + else + other_players++ + dat += "
Players:|[connected_players - lobby_players] ingame|[connected_players] connected|[lobby_players] lobby|" + dat += "
Living Players:|[living_players_connected] active|[living_players - living_players_connected] disconnected|[living_players_antagonist] antagonists|" + dat += "
SKIPPED \[On centcom Z-level\]: [living_skipped] living players|[drones] living drones|" + dat += "
Dead/Observing players:|[observers_connected] active|[observers - observers_connected] disconnected|[brains] brains|" + if(other_players) + dat += "
[other_players] players in invalid state or the statistics code is bugged!" + dat += "

" + + dat += build_antag_listing() + + dat += "" + usr << browse(dat, "window=roundstatus;size=500x500") + else + alert("The game hasn't started yet!") \ No newline at end of file diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index e38f857cd469..6e15da69ef82 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -307,342 +307,4 @@ "} - usr << browse(dat, "window=players;size=600x480") - -/datum/admins/proc/check_antagonists() - if (SSticker.HasRoundStarted()) - var/dat = "Round Status

Round Status

" - if(SSticker.mode.replacementmode) - dat += "Former Game Mode: [SSticker.mode.name]
" - dat += "Replacement Game Mode: [SSticker.mode.replacementmode.name]
" - else - dat += "Current Game Mode: [SSticker.mode.name]
" - dat += "Round Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]
" - dat += "Emergency shuttle
" - if(EMERGENCY_IDLE_OR_RECALLED) - dat += "Call Shuttle
" - else - var/timeleft = SSshuttle.emergency.timeLeft() - if(SSshuttle.emergency.mode == SHUTTLE_CALL) - dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
" - dat += "Send Back
" - else - dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]
" - dat += "Continuous Round Status
" - dat += "[CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]" - if(CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag]) - dat += ", [CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag] ? "creating replacement antagonists" : "not creating new antagonists"]
" - else - dat += "
" - if(CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag]) - dat += "Time limit: [CONFIG_GET(number/midround_antag_time_check)] minutes into round
" - dat += "Living crew limit: [CONFIG_GET(number/midround_antag_life_check) * 100]% of crew alive
" - dat += "If limits past: [SSticker.mode.round_ends_with_antag_death ? "End The Round" : "Continue As Extended"]
" - dat += "End Round Now
" - dat += "[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]" - var/connected_players = GLOB.clients.len - var/lobby_players = 0 - var/observers = 0 - var/observers_connected = 0 - var/living_players = 0 - var/living_players_connected = 0 - var/living_players_antagonist = 0 - var/brains = 0 - var/other_players = 0 - var/living_skipped = 0 - var/drones = 0 - for(var/mob/M in GLOB.mob_list) - if(M.ckey) - if(isnewplayer(M)) - lobby_players++ - continue - else if(M.stat != DEAD && M.mind && !isbrain(M)) - if(isdrone(M)) - drones++ - continue - if(is_centcom_level(M.z)) - living_skipped++ - continue - living_players++ - if(M.mind.special_role) - living_players_antagonist++ - if(M.client) - living_players_connected++ - else if((M.stat == DEAD )||(isobserver(M))) - observers++ - if(M.client) - observers_connected++ - else if(isbrain(M)) - brains++ - else - other_players++ - dat += "
Players:|[connected_players - lobby_players] ingame|[connected_players] connected|[lobby_players] lobby|" - dat += "
Living Players:|[living_players_connected] active|[living_players - living_players_connected] disconnected|[living_players_antagonist] antagonists|" - dat += "
SKIPPED \[On centcom Z-level\]: [living_skipped] living players|[drones] living drones|" - dat += "
Dead/Observing players:|[observers_connected] active|[observers - observers_connected] disconnected|[brains] brains|" - if(other_players) - dat += "
[other_players] players in invalid state or the statistics code is bugged!" - dat += "
" - - var/list/nukeops = get_antagonists(/datum/antagonist/nukeop) - if(nukeops.len) - dat += "
" - for(var/datum/mind/N in nukeops) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Syndicates
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
[N.name]([N.key]) Nuclear Operative Body destroyed!PM

" - for(var/obj/item/disk/nuclear/N in GLOB.poi_list) - dat += "" - dat += "
Nuclear Disk(s)
[N.name], " - var/atom/disk_loc = N.loc - while(!isturf(disk_loc)) - if(ismob(disk_loc)) - var/mob/M = disk_loc - dat += "carried by [M.real_name] " - if(isobj(disk_loc)) - var/obj/O = disk_loc - dat += "in \a [O.name] " - disk_loc = disk_loc.loc - dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])
" - - var/list/revs = get_antagonists(/datum/antagonist/rev) - if(revs.len > 0) - dat += "
" - for(var/datum/mind/N in get_antagonists(/datum/antagonist/rev/head)) - var/mob/M = N.current - if(!M) - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "" - for(var/datum/mind/N in get_antagonists(/datum/antagonist/rev,TRUE)) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "
Revolutionaries
[N.name]([N.key])Head Revolutionary body destroyed!PM
[M.real_name] (Leader)[M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
" - for(var/datum/mind/N in SSjob.get_living_heads()) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "" - var/turf/mob_loc = get_turf(M) - dat += "" - else - dat += "" - dat += "" - dat += "
Target(s)Location
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW[mob_loc.loc]
[N.name]([N.key])Head body destroyed!PM
" - - - var/list/lings = get_antagonists(/datum/antagonist/changeling) - if(lings.len > 0) - dat += "
" - for(var/datum/mind/changeling in lings) - var/datum/antagonist/changeling/lingantag = changeling.has_antag_datum(/datum/antagonist/changeling) - var/mob/M = changeling.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Changelings
[lingantag.changelingID]([lingantag.name]) as [M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[changeling.name]([changeling.key])Changeling body destroyed!PM
" - - if(SSticker.mode.wizards.len > 0) - dat += "
" - for(var/datum/mind/wizard in SSticker.mode.wizards) - var/mob/M = wizard.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Wizards
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[wizard.name]([wizard.key])Wizard body destroyed!
PM
" - - if(SSticker.mode.apprentices.len > 0) - dat += "
" - for(var/datum/mind/apprentice in SSticker.mode.apprentices) - var/mob/M = apprentice.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Apprentice
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[apprentice.name]([apprentice.key])Apprentice body destroyed!!
PM
" - - if(SSticker.mode.cult.len) - dat += "
" - for(var/datum/mind/N in SSticker.mode.cult) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "
Cultists
[M.real_name][N.has_antag_datum(ANTAG_DATUM_CULT_MASTER) ? " \[Master\]" : ""][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
" - - if(SSticker.mode.servants_of_ratvar.len) - dat += "
" - for(var/datum/mind/N in SSticker.mode.servants_of_ratvar) - var/mob/M = N.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "
Servants of Ratvar
[M.real_name][M.client ? "" : " (ghost)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
" - - if(SSticker.mode.traitors.len > 0) - dat += "
" - for(var/datum/mind/traitor in SSticker.mode.traitors) - var/mob/M = traitor.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Traitors
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[traitor.name]([traitor.key])Traitor body destroyed!PM
" - - if(SSticker.mode.brother_teams.len > 0) - dat += "
" - for(var/datum/team/brother_team/team in SSticker.mode.brother_teams) - for(var/datum/mind/brother in team.members) - var/mob/M = brother.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Brothers
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[brother.name]([brother.key])Brother body destroyed!PM
" - - if(SSticker.mode.abductors.len) - dat += "
" - for(var/datum/mind/abductor in SSticker.mode.abductors) - var/mob/M = abductor.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Abductors
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[abductor.name]([abductor.key])Abductor body destroyed!
PM
" - dat += "
" - for(var/obj/machinery/abductor/experiment/E in GLOB.machines) - for(var/datum/mind/abductee in E.abductee_minds) - var/mob/M = abductee.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Abductees
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLWShow Objective
[abductee.name]([abductee.key])Abductee body destroyed!PM
" - - if(SSticker.mode.devils.len) - dat += "
" - for(var/X in SSticker.mode.devils) - var/datum/mind/devil = X - var/mob/M = devil.current - var/datum/antagonist/devil/devilinfo = devil.has_antag_datum(ANTAG_DATUM_DEVIL) - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
devils
[M.real_name] : [devilinfo.truename][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMShow Objective
Show all devil info
[devil.name] : [devilinfo.truename] ([devil.key])devil body destroyed!
PM
" - - if(SSticker.mode.sintouched.len) - dat += "
" - for(var/X in SSticker.mode.sintouched) - var/datum/mind/sintouched = X - var/mob/M = sintouched.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
sintouched
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMShow Objective
[sintouched.name]([sintouched.key])sintouched body destroyed!
PM
" - - var/list/blob_minds = list() - for(var/mob/camera/blob/B in GLOB.mob_list) - blob_minds |= B.mind - if(blob_minds.len) - dat += "
" - for(var/datum/mind/blob in blob_minds) - var/mob/camera/blob/M = blob.current - if(M) - dat += "" - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Blob
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
Progress: [M.blobs_legit.len]/[M.blobwincount]
[blob.name]([blob.key])Blob not found!PM
" - - - var/list/pirates = get_antagonists(/datum/antagonist/pirate) - if(pirates.len > 0) - dat += "
" - for(var/datum/mind/N in pirates) - var/mob/M = N.current - if(!M) - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "" - dat += "
Pirates
[N.name]([N.key])No body.PM
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
" - - if(istype(SSticker.mode, /datum/game_mode/monkey)) - var/datum/game_mode/monkey/mode = SSticker.mode - dat += "
" - - for(var/datum/mind/eek in mode.ape_infectees) - var/mob/M = eek.current - if(M) - dat += "" - dat += "" - dat += "" - else - dat += "" - dat += "" - dat += "
Monkey
[M.real_name][M.client ? "" : " (No Client)"][M.stat == DEAD ? " (DEAD)" : ""]PMFLW
[eek.name]([eek.key])Monkey not found!PM
" - - - dat += "" - usr << browse(dat, "window=roundstatus;size=420x500") - else - alert("The game hasn't started yet!") + usr << browse(dat, "window=players;size=600x480") \ No newline at end of file diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 42cd5bc7a532..8cb66d09eb86 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -344,7 +344,7 @@ continue if(is_special_character(H)) continue - var/datum/antagonist/traitor/human/T = new(H.mind) + var/datum/antagonist/traitor/human/T = new() T.give_objectives = FALSE var/datum/objective/new_objective = new new_objective.owner = H diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 635cfda90ca8..e0ba3a637843 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1888,10 +1888,24 @@ var/mob/M = locate(href_list["traitor"]) if(!ismob(M)) - to_chat(usr, "This can only be used on instances of type /mob.") + var/datum/mind/D = M + if(!istype(D)) + to_chat(usr, "This can only be used on instances of type /mob and /mind") + return + else + D.traitor_panel() + else + show_traitor_panel(M) + + else if(href_list["initmind"]) + if(!check_rights(R_ADMIN)) return - show_traitor_panel(M) - + var/mob/M = locate(href_list["initmind"]) + if(!ismob(M) || M.mind) + to_chat(usr, "This can only be used on instances on mindless mobs") + return + M.mind_initialize() + else if(href_list["create_object"]) if(!check_rights(R_SPAWN)) return diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 9035a343172e..11b4775f111b 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -306,7 +306,6 @@ door.open() //Assign antag status and the mission - SSticker.mode.traitors += Commando.mind Commando.mind.special_role = "deathsquad" var/datum/objective/missionobj = new @@ -361,7 +360,6 @@ newmob.equipOutfit(/datum/outfit/centcom_official) //Assign antag status and the mission - SSticker.mode.traitors += newmob.mind newmob.mind.special_role = "official" var/datum/objective/missionobj = new @@ -469,7 +467,6 @@ door.open() //Assign antag status and the mission - SSticker.mode.traitors += ERTOperative.mind ERTOperative.mind.special_role = "ERT" var/datum/objective/missionobj = new diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index d09041aaf334..b2f865294870 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -26,7 +26,6 @@ GLOBAL_VAR_INIT(highlander, FALSE) addtimer(CALLBACK(src, .proc/only_one), 420) /mob/living/carbon/human/proc/make_scottish() - SSticker.mode.traitors += mind mind.special_role = "highlander" dna.species.species_traits |= NOGUNS //nice try jackass diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index 1fe8baba012c..666b7bbbafef 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -113,7 +113,6 @@ if("To Kill") to_chat(user, "Your wish is granted, but at a terrible cost...") to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.") - SSticker.mode.traitors += user.mind user.mind.special_role = "traitor" var/datum/objective/hijack/hijack = new diff --git a/code/modules/events/abductor.dm b/code/modules/events/abductor.dm index c7e9baf779c8..ca1922a3a937 100755 --- a/code/modules/events/abductor.dm +++ b/code/modules/events/abductor.dm @@ -4,7 +4,7 @@ weight = 10 max_occurrences = 1 min_players = 20 - gamemode_blacklist = list("nuclear","wizard","revolution","abduction") + gamemode_blacklist = list("nuclear","wizard","revolution") /datum/round_event/ghost_role/abductor minimum_required = 2 @@ -17,20 +17,18 @@ if(candidates.len < 2) return NOT_ENOUGH_PLAYERS - var/datum/game_mode/abduction/GM - if(SSticker.mode.config_tag == "abduction") - GM = SSticker.mode - else - GM = new - var/mob/living/carbon/human/agent = makeBody(pick_n_take(candidates)) var/mob/living/carbon/human/scientist = makeBody(pick_n_take(candidates)) - var/team = GM.make_abductor_team(agent.mind, scientist.mind) - if(!team) + var/datum/team/abductor_team/T = new + if(T.team_number > ABDUCTOR_MAX_TEAMS) return MAP_ERROR + + log_game("[scientist.mind.key] (ckey) has been selected as [T.name] abductor scientist.") + log_game("[agent.mind.key] (ckey) has been selected as [T.name] abductor agent.") - GM.post_setup_team(team) + scientist.mind.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, T) + agent.mind.add_antag_datum(ANTAG_DATUM_ABDUCTOR_AGENT, T) spawned_mobs += list(agent, scientist) return SUCCESSFUL_SPAWN diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm index abb5a0639dd4..0084cb7ea5b9 100644 --- a/code/modules/events/holiday/vday.dm +++ b/code/modules/events/holiday/vday.dm @@ -46,17 +46,11 @@ var/datum/objective/martyr/normiesgetout = new normiesgetout.owner = L.mind L.mind.special_role = "heartbreaker" - SSticker.mode.traitors |= L.mind L.mind.objectives += normiesgetout - L.mind.add_antag_datum(/datum/antagonist/auto_custom) /proc/forge_valentines_objective(mob/living/lover,mob/living/date) - - SSticker.mode.traitors |= lover.mind lover.mind.special_role = "valentine" - - var/datum/objective/protect/protect_objective = new /datum/objective/protect protect_objective.owner = lover.mind protect_objective.target = date.mind diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm index 76188cb5b7a5..94014027fd69 100644 --- a/code/modules/events/nightmare.dm +++ b/code/modules/events/nightmare.dm @@ -34,7 +34,6 @@ player_mind.transfer_to(S) player_mind.assigned_role = "Nightmare" player_mind.special_role = "Nightmare" - SSticker.mode.traitors += player_mind player_mind.add_antag_datum(/datum/antagonist/auto_custom) S.set_species(/datum/species/shadow/nightmare) playsound(S, 'sound/magic/ethereal_exit.ogg', 50, 1, -1) diff --git a/code/modules/events/wizard/departmentrevolt.dm b/code/modules/events/wizard/departmentrevolt.dm index 3227f81d5833..22fe7d91d4f4 100644 --- a/code/modules/events/wizard/departmentrevolt.dm +++ b/code/modules/events/wizard/departmentrevolt.dm @@ -38,11 +38,10 @@ for(var/mob/living/carbon/human/H in GLOB.carbon_list) if(H.mind) var/datum/mind/M = H.mind - if(M.assigned_role && !(M in SSticker.mode.traitors)) + if(M.assigned_role && !(M.has_antag_datum(/datum/antagonist))) for(var/job in jobs_to_revolt) if(M.assigned_role == job) citizens += H - SSticker.mode.traitors += M M.special_role = "separatist" M.add_antag_datum(/datum/antagonist/auto_custom) H.log_message("Was made into a separatist, long live [nation]!", INDIVIDUAL_ATTACK_LOG) diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm index 9ac7d8919171..156ecea2ec4c 100644 --- a/code/modules/events/wizard/greentext.dm +++ b/code/modules/events/wizard/greentext.dm @@ -60,8 +60,6 @@ /obj/item/greentext/process() if(new_holder && is_centcom_level(new_holder.z))//you're winner! to_chat(new_holder, "At last it feels like victory is assured!") - if(!(new_holder in SSticker.mode.traitors)) - SSticker.mode.traitors += new_holder.mind new_holder.mind.special_role = "winner" var/datum/objective/O = new /datum/objective("Succeed") O.completed = 1 //YES! diff --git a/code/modules/events/wizard/imposter.dm b/code/modules/events/wizard/imposter.dm index 4b2147bd9edc..0ab0e6c2e894 100644 --- a/code/modules/events/wizard/imposter.dm +++ b/code/modules/events/wizard/imposter.dm @@ -27,7 +27,7 @@ var/datum/antagonist/wizard/master = M.has_antag_datum(/datum/antagonist/wizard) if(!master.wiz_team) master.create_wiz_team() - var/datum/antagonist/wizard/apprentice/imposter/imposter = new(I.mind) + var/datum/antagonist/wizard/apprentice/imposter/imposter = new() imposter.master = M imposter.wiz_team = master.wiz_team master.wiz_team.add_member(imposter) diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index dedadd4d2a99..c08dd83f99be 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -47,7 +47,6 @@ if(mind) if(!mind.special_role) mind.special_role = "traitor" - SSticker.mode.traitors += mind mind.add_antag_datum(/datum/antagonist/auto_custom) // ???? diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e6d788e72617..03ab7c9c57ed 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -982,7 +982,6 @@ .["Toggle Godmode"] = "?_src_=vars;[HrefToken()];godmode=[REF(src)]" .["Drop Everything"] = "?_src_=vars;[HrefToken()];drop_everything=[REF(src)]" .["Regenerate Icons"] = "?_src_=vars;[HrefToken()];regenerateicons=[REF(src)]" - .["Make Space Ninja"] = "?_src_=vars;[HrefToken()];ninja=[REF(src)]" .["Show player panel"] = "?_src_=vars;[HrefToken()];mob_player_panel=[REF(src)]" .["Toggle Build Mode"] = "?_src_=vars;[HrefToken()];build_mode=[REF(src)]" .["Assume Direct Control"] = "?_src_=vars;[HrefToken()];direct_control=[REF(src)]" diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index c2cf2505d0ef..999a6090eb82 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -448,6 +448,10 @@ It's fairly easy to fix if dealing with single letters but not so much with comp 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/) + if(A) + poll_message = "[poll_message] Status:[A.name]." var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, "pAI", null, FALSE, 100, M) var/mob/dead/observer/theghost = null diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm index b26d01d880cd..2b12adb4a8c1 100644 --- a/code/modules/ninja/ninja_event.dm +++ b/code/modules/ninja/ninja_event.dm @@ -28,7 +28,6 @@ Contents: /datum/round_event/ghost_role/ninja/setup() helping_station = rand(0,1) - /datum/round_event/ghost_role/ninja/kill() if(!success_spawn && control) control.occurrences-- @@ -57,22 +56,21 @@ Contents: var/key = selected_candidate.key //Prepare ninja player mind - var/datum/mind/Mind = create_ninja_mind(key) + var/datum/mind/Mind = new /datum/mind(key) + Mind.assigned_role = "Space Ninja" + Mind.special_role = "Space Ninja" Mind.active = 1 - //generate objectives - You'll generally get 6 objectives (Ninja is meant to be hardmode!) - - //spawn the ninja and assign the candidate var/mob/living/carbon/human/Ninja = create_space_ninja(spawn_loc) Mind.transfer_to(Ninja) - var/datum/antagonist/ninja/ninjadatum = add_ninja(Ninja) - ninjadatum.equip_space_ninja() + var/datum/antagonist/ninja/ninjadatum = new + ninjadatum.helping_station = pick(TRUE,FALSE) + Mind.add_antag_datum(ninjadatum) if(Ninja.mind != Mind) //something has gone wrong! throw EXCEPTION("Ninja created with incorrect mind") - SSticker.mode.update_ninja_icons_added(Ninja) spawned_mobs += Ninja message_admins("[key_name_admin(Ninja)] has been made into a ninja by an event.") log_game("[key_name(Ninja)] was spawned as a ninja by an event.") @@ -88,23 +86,4 @@ Contents: A.real_name = "[pick(GLOB.ninja_titles)] [pick(GLOB.ninja_names)]" A.copy_to(new_ninja) new_ninja.dna.update_dna_identity() - return new_ninja - - -/proc/create_ninja_mind(key) - var/datum/mind/Mind = new /datum/mind(key) - Mind.assigned_role = "Space Ninja" - Mind.special_role = "Space Ninja" - SSticker.mode.traitors |= Mind //Adds them to current traitor list. TODO : Remove this in admin tools refeactor. - return Mind - - -/datum/game_mode/proc/update_ninja_icons_added(var/mob/living/carbon/human/ninja) - var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA] - ninjahud.join_hud(ninja) - set_antag_hud(ninja, "ninja") - -/datum/game_mode/proc/update_ninja_icons_removed(datum/mind/ninja_mind) - var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA] - ninjahud.leave_hud(ninja_mind.current) - set_antag_hud(ninja_mind.current, null) + return new_ninja \ No newline at end of file diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 88497a0672d8..0fa143979630 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -49,6 +49,8 @@ GLOB.cult_narsie = src var/list/all_cults = list() for(var/datum/antagonist/cult/C in GLOB.antagonists) + if(!C.owner) + continue all_cults |= C.cult_team for(var/datum/team/cult/T in all_cults) deltimer(T.blood_target_reset_timer) diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index cc49efe71245..5999911cb101 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -323,7 +323,6 @@ D.Devolve() /datum/chemical_reaction/mix_virus/neuter_virus - name = "Neuter Virus" id = "neutervirus" required_reagents = list("formaldehyde" = 1) diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm index d696571bb90a..1c76ac47915b 100644 --- a/code/modules/spells/spell_types/rightandwrong.dm +++ b/code/modules/spells/spell_types/rightandwrong.dm @@ -93,7 +93,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) if(iswizard(H) || H.mind.special_role == "survivalist") return - if(prob(GLOB.summon_guns_triggered) && !(H.mind in SSticker.mode.traitors)) + if(prob(GLOB.summon_guns_triggered) && !(H.mind.has_antag_datum(/datum/antagonist))) SSticker.mode.traitors += H.mind var/datum/objective/steal_five_of_type/summon_guns/guns = new @@ -125,7 +125,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) if(iswizard(H) || H.mind.special_role == "survivalist") return - if(prob(GLOB.summon_magic_triggered) && !(H.mind in SSticker.mode.traitors)) + if(prob(GLOB.summon_magic_triggered) && !(H.mind.has_antag_datum(/datum/antagonist))) var/datum/objective/steal_five_of_type/summon_magic/magic = new magic.owner = H.mind H.mind.objectives += magic diff --git a/config/game_options.txt b/config/game_options.txt index 36ac3a606777..babab059a287 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -112,8 +112,6 @@ CONTINUOUS CULT CONTINUOUS CLOCKWORK_CULT CONTINUOUS CHANGELING CONTINUOUS WIZARD -CONTINUOUS BLOB -CONTINUOUS ABDUCTION #CONTINUOUS MONKEY ##Note: do not toggle continuous off for these modes, as they have no antagonists and would thus end immediately! @@ -136,8 +134,6 @@ MIDROUND_ANTAG CULT MIDROUND_ANTAG CLOCKWORK_CULT MIDROUND_ANTAG CHANGELING MIDROUND_ANTAG WIZARD -MIDROUND_ANTAG BLOB -MIDROUND_ANTAG ABDUCTION #MIDROUND_ANTAG MONKEY ## Uncomment these for overrides of the minimum / maximum number of players in a round type. @@ -176,9 +172,6 @@ MIDROUND_ANTAG ABDUCTION #MIN_POP WIZARD 20 #MAX_POP WIZARD -1 -#MIN_POP BLOB 25 -#MAX_POP BLOB -1 - #MIN_POP MONKEY 20 #MAX_POP MONKEY -1 diff --git a/tgstation.dme b/tgstation.dme index 13d7056572eb..f8898039a69c 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -1113,8 +1113,10 @@ #include "code\modules\admin\admin_ranks.dm" #include "code\modules\admin\admin_verbs.dm" #include "code\modules\admin\adminmenu.dm" +#include "code\modules\admin\antag_panel.dm" #include "code\modules\admin\banjob.dm" #include "code\modules\admin\chat_commands.dm" +#include "code\modules\admin\check_antagonists.dm" #include "code\modules\admin\create_mob.dm" #include "code\modules\admin\create_object.dm" #include "code\modules\admin\create_poll.dm"