diff --git a/baystation12.dme b/baystation12.dme
index edec632f08..88966c957f 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -212,12 +212,17 @@
#include "code\game\skincmd.dm"
#include "code\game\sound.dm"
#include "code\game\supplyshuttle.dm"
+#include "code\game\antagonist\_antagonist_setup.dm"
#include "code\game\antagonist\antagonist.dm"
-#include "code\game\antagonist\antagonist_build.dm"
-#include "code\game\antagonist\antagonist_globals.dm"
+#include "code\game\antagonist\antagonist_add.dm"
+#include "code\game\antagonist\antagonist_create.dm"
+#include "code\game\antagonist\antagonist_equip.dm"
#include "code\game\antagonist\antagonist_helpers.dm"
#include "code\game\antagonist\antagonist_objectives.dm"
-#include "code\game\antagonist\antagonist_spawn.dm"
+#include "code\game\antagonist\antagonist_panel.dm"
+#include "code\game\antagonist\antagonist_place.dm"
+#include "code\game\antagonist\antagonist_print.dm"
+#include "code\game\antagonist\antagonist_update.dm"
#include "code\game\antagonist\alien\borer.dm"
#include "code\game\antagonist\alien\xenomorph.dm"
#include "code\game\antagonist\outsider\commando.dm"
diff --git a/code/controllers/voting.dm b/code/controllers/voting.dm
index f4b88f8850..939dd34e7e 100644
--- a/code/controllers/voting.dm
+++ b/code/controllers/voting.dm
@@ -237,7 +237,7 @@ datum/controller/vote
return 0
for(var/antag_type in all_antag_types)
var/datum/antagonist/antag = all_antag_types[antag_type]
- if(!(antag.id in additional_antag_types) && (antag.flags & ANTAG_VOTABLE))
+ if(!(antag.id in additional_antag_types) && antag.is_votable())
choices.Add(antag.role_text)
choices.Add("None")
if("custom")
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index fac5c75fc3..0e7e42d152 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -143,7 +143,7 @@
if(href_list["add_antagonist"])
var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]]
- if(antag) antag.add_antagonist(src)
+ if(antag) antag.add_antagonist(src, 1, 1, 0, 1, 1) // Ignore equipment and role type for this.
else if(href_list["remove_antagonist"])
var/datum/antagonist/antag = all_antag_types[href_list["remove_antagonist"]]
diff --git a/code/game/antagonist/_antagonist_setup.dm b/code/game/antagonist/_antagonist_setup.dm
new file mode 100644
index 0000000000..ebf22a21c9
--- /dev/null
+++ b/code/game/antagonist/_antagonist_setup.dm
@@ -0,0 +1,72 @@
+/*
+ MODULAR ANTAGONIST SYSTEM
+
+ Attempts to move all the bullshit snowflake antag tracking code into its own system, which
+ has the added bonus of making the display procs consistent. Still needs work/adjustment/cleanup
+ but should be fairly self-explanatory with a review of the procs. Will supply a few examples
+ of common tasks that the system will be expected to perform below. ~Z
+
+ To use:
+ - Get the appropriate datum via get_antag_data("antagonist id")
+ using the id var of the desired /datum/antagonist ie. var/datum/antagonist/A = get_antag_data("traitor")
+ - Call add_antagonist() on the desired target mind ie. A.add_antagonist(mob.mind)
+ - To ignore protected roles, supply a positive second argument.
+ - To skip equipping with appropriate gear, supply a positive third argument.
+*/
+
+// Antagonist datum flags.
+#define ANTAG_OVERRIDE_JOB 1 // Assigned job is set to MODE when spawning.
+#define ANTAG_OVERRIDE_MOB 2 // Mob is recreated from datum mob_type var when spawning.
+#define ANTAG_CLEAR_EQUIPMENT 4 // All preexisting equipment is purged.
+#define ANTAG_CHOOSE_NAME 8 // Antagonists are prompted to enter a name.
+#define ANTAG_IMPLANT_IMMUNE 16 // Cannot be loyalty implanted.
+#define ANTAG_SUSPICIOUS 32 // Shows up on roundstart report.
+#define ANTAG_HAS_LEADER 64 // Generates a leader antagonist.
+#define ANTAG_HAS_NUKE 128 // Will spawn a nuke at supplied location.
+#define ANTAG_RANDSPAWN 256 // Potentially randomly spawns due to events.
+#define ANTAG_VOTABLE 512 // Can be voted as an additional antagonist before roundstart.
+#define ANTAG_SET_APPEARANCE 1024 // Causes antagonists to use an appearance modifier on spawn.
+
+// Globals.
+var/global/list/all_antag_types = list()
+var/global/list/all_antag_spawnpoints = list()
+var/global/list/antag_names_to_ids = list()
+
+// Global procs.
+/proc/get_antag_data(var/antag_type)
+ if(all_antag_types[antag_type])
+ return all_antag_types[antag_type]
+ else
+ for(var/cur_antag_type in all_antag_types)
+ var/datum/antagonist/antag = all_antag_types[cur_antag_type]
+ if(antag && antag.is_type(antag_type))
+ return antag
+
+/proc/clear_antag_roles(var/datum/mind/player, var/implanted)
+ for(var/antag_type in all_antag_types)
+ var/datum/antagonist/antag = all_antag_types[antag_type]
+ if(!implanted || !(antag.flags & ANTAG_IMPLANT_IMMUNE))
+ antag.remove_antagonist(player, 1, implanted)
+
+/proc/update_antag_icons(var/datum/mind/player)
+ for(var/antag_type in all_antag_types)
+ var/datum/antagonist/antag = all_antag_types[antag_type]
+ if(player)
+ antag.update_icons_removed(player)
+ if(antag.is_antagonist(player))
+ antag.update_icons_added(player)
+ else
+ antag.update_all_icons()
+
+/proc/populate_antag_type_list()
+ for(var/antag_type in typesof(/datum/antagonist)-/datum/antagonist)
+ var/datum/antagonist/A = new antag_type
+ all_antag_types[A.id] = A
+ all_antag_spawnpoints[A.landmark_id] = list()
+ antag_names_to_ids[A.role_text] = A.id
+
+/proc/get_antags(var/atype)
+ var/datum/antagonist/antag = all_antag_types[atype]
+ if(antag && islist(antag.current_antagonists))
+ return antag.current_antagonists
+ return list()
\ No newline at end of file
diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm
index 1ab79f26b5..f93409a820 100644
--- a/code/game/antagonist/alien/xenomorph.dm
+++ b/code/game/antagonist/alien/xenomorph.dm
@@ -26,12 +26,12 @@ var/datum/antagonist/xenos/xenomorphs
/datum/antagonist/xenos/Topic(href, href_list)
if (..())
return
- if(href_list["move_to_spawn"]) place_mob(href_list["move_to_spawn"])
+ if(href_list["move_to_spawn"]) place_mob(locate(href_list["move_to_spawn"]))
/datum/antagonist/xenos/get_extra_panel_options(var/datum/mind/player)
return "\[move to vent\]"
-/datum/antagonist/xenos/random_spawn()
+/datum/antagonist/xenos/attempt_random_spawn()
if(config.aliens_allowed) ..()
/datum/antagonist/xenos/proc/get_vents()
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index aad02b1c6c..c7cbde15ab 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -42,209 +42,64 @@
var/default_access = list()
var/id_type = /obj/item/weapon/card/id
+ var/announced
/datum/antagonist/New()
..()
cur_max = max_antags
get_starting_locations()
+ if(!role_text_plural)
+ role_text_plural = role_text
if(config.protect_roles_from_antagonist)
restricted_jobs |= protected_jobs
/datum/antagonist/proc/tick()
return 1
-/datum/antagonist/proc/get_panel_entry(var/datum/mind/player)
+/datum/antagonist/proc/get_candidates(var/ghosts_only)
- var/dat = "
| [role_text]:"
- var/extra = get_extra_panel_options(player)
- if(is_antagonist(player))
- dat += "\[-\]"
- dat += "\[equip\]"
- if(starting_locations && starting_locations.len)
- dat += "\[move to spawn\]"
- if(extra) dat += "[extra]"
- else
- dat += "\[+\]"
- dat += " |
"
+ candidates = list() // Clear.
+ candidates = ticker.mode.get_players_for_role(role_type, id)
+ // Prune restricted jobs and status.
+ for(var/datum/mind/player in candidates)
+ if((ghosts_only && !istype(player.current, /mob/dead)) || player.special_role || (player.assigned_role in restricted_jobs))
+ candidates -= player
+ return candidates
- return dat
+/datum/antagonist/proc/attempt_random_spawn()
+ attempt_spawn(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
-/datum/antagonist/proc/get_extra_panel_options()
- return
+/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player, var/move_to_spawn)
-/datum/antagonist/proc/get_starting_locations()
- if(landmark_id)
- starting_locations = list()
- for(var/obj/effect/landmark/L in landmarks_list)
- if(L.name == landmark_id)
- starting_locations |= get_turf(L)
-
-/datum/antagonist/proc/place_all_mobs()
- if(!starting_locations || !starting_locations.len || !current_antagonists || !current_antagonists.len)
- return
- for(var/datum/mind/player in current_antagonists)
- player.current.loc = pick(starting_locations)
-
-/datum/antagonist/proc/finalize(var/datum/mind/target)
-
- // This will fail if objectives have already been generated.
- create_global_objectives()
-
- if(leader && flags & ANTAG_HAS_NUKE && !spawned_nuke)
- make_nuke(leader)
-
- if(target)
- apply(target)
- create_objectives(target)
- update_icons_added(target)
- greet(target)
- return
-
- for(var/datum/mind/player in current_antagonists)
- apply(player)
- equip(player.current)
- create_objectives(player)
- update_icons_added(player)
- greet(player)
-
- place_all_mobs()
-
- spawn(1)
- if(spawn_announcement)
- if(spawn_announcement_delay)
- sleep(spawn_announcement_delay)
- if(spawn_announcement_sound)
- command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]", new_sound = spawn_announcement_sound)
- else
- command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]")
-
-
-/datum/antagonist/proc/print_player_summary()
-
- if(!current_antagonists.len)
+ update_current_antag_max()
+ if(get_antag_count() >= cur_max)
return 0
- var/text = "
The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:"
- for(var/datum/mind/P in current_antagonists)
- text += print_player_full(P)
- text += get_special_objective_text(P)
- var/failed
- if(!global_objectives.len && P.objectives && P.objectives.len)
- var/num = 1
- for(var/datum/objective/O in P.objectives)
- text += print_objective(O, num)
- if(O.completed) // This is set actively in check_victory()
- text += "Success!"
- feedback_add_details(feedback_tag,"[O.type]|SUCCESS")
- else
- text += "Fail."
- feedback_add_details(feedback_tag,"[O.type]|FAIL")
- failed = 1
- num++
+ player.current << "You have been selected this round as an antagonist!"
+ if(move_to_spawn)
+ place_mob(player.current)
+ add_antagonist(player)
+ equip(player.current)
+ return
- if(!config.objectives_disabled)
- if(failed)
- text += "
The [role_text] has failed."
- else
- text += "
The [role_text] was successful!"
+/datum/antagonist/proc/attempt_spawn(var/ghosts_only)
- if(global_objectives && global_objectives.len)
- text += "
Their objectives were:"
- var/num = 1
- for(var/datum/objective/O in global_objectives)
- text += print_objective(O, num, 1)
- num++
+ // Get the raw list of potential players.
+ update_current_antag_max()
+ candidates = get_candidates(ghosts_only)
- // Display the results.
- world << text
-
-/datum/antagonist/proc/print_objective(var/datum/objective/O, var/num, var/append_success)
- var/text = "
Objective [num]: [O.explanation_text] "
- if(append_success)
- if(O.check_completion())
- text += "Success!"
- else
- text += "Fail."
- return text
-
-/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
- var/role = ply.assigned_role == "MODE" ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]"
- var/text = "
[ply.name] ([ply.key]) as \a [role] ("
- if(ply.current)
- if(ply.current.stat == DEAD)
- text += "died"
- else if(isNotStationLevel(ply.current.z))
- text += "fled the station"
- else
- text += "survived"
- if(ply.current.real_name != ply.name)
- text += " as [ply.current.real_name]"
- else
- text += "body destroyed"
- text += ")"
-
- return text
-
-/datum/antagonist/proc/print_player_full(var/datum/mind/ply)
- var/text = print_player_lite(ply)
-
- var/TC_uses = 0
- var/uplink_true = 0
- var/purchases = ""
- for(var/obj/item/device/uplink/H in world_uplinks)
- if(H && H.uplink_owner && H.uplink_owner == ply)
- TC_uses += H.used_TC
- uplink_true = 1
- var/list/refined_log = new()
- for(var/datum/uplink_item/UI in H.purchase_log)
- var/obj/I = new UI.path
- refined_log.Add("[H.purchase_log[UI]]x\icon[I][UI.name]")
- qdel(I)
- purchases = english_list(refined_log, nothing_text = "")
- if(uplink_true)
- text += " (used [TC_uses] TC)"
- if(purchases)
- text += "
[purchases]"
-
- return text
-
-/datum/antagonist/proc/update_all_icons()
- if(!antag_indicator)
- return
- for(var/datum/mind/antag in current_antagonists)
- if(antag.current && antag.current.client)
- for(var/image/I in antag.current.client.images)
- if(I.icon_state == antag_indicator)
- qdel(I)
- for(var/datum/mind/other_antag in current_antagonists)
- if(other_antag.current)
- antag.current.client.images |= image('icons/mob/mob.dmi', loc = other_antag.current, icon_state = antag_indicator)
-
-/datum/antagonist/proc/update_icons_added(var/datum/mind/player)
- if(!antag_indicator || !player.current)
- return
- spawn(0)
- for(var/datum/mind/antag in current_antagonists)
- if(!antag.current)
- continue
- if(antag.current.client)
- antag.current.client.images |= image('icons/mob/mob.dmi', loc = player.current, icon_state = antag_indicator)
- if(player.current.client)
- player.current.client.images |= image('icons/mob/mob.dmi', loc = antag.current, icon_state = antag_indicator)
-
-/datum/antagonist/proc/update_icons_removed(var/datum/mind/player)
- if(!antag_indicator || !player.current)
- return
- spawn(0)
- for(var/datum/mind/antag in current_antagonists)
- if(antag.current)
- if(antag.current.client)
- for(var/image/I in antag.current.client.images)
- if(I.icon_state == antag_indicator && I.loc == player.current)
- qdel(I)
- if(player.current && player.current.client)
- for(var/image/I in player.current.client.images)
- if(I.icon_state == antag_indicator)
- qdel(I)
+ // Update our boundaries.
+ if(!candidates.len)
+ return 0
+ //Grab candidates randomly until we have enough.
+ while(candidates.len)
+ var/datum/mind/player = pick(candidates)
+ current_antagonists |= player
+ // Update job and role.
+ player.special_role = role_text
+ if(flags & ANTAG_OVERRIDE_JOB)
+ player.assigned_role = "MODE"
+ candidates -= player
+ return 1
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
new file mode 100644
index 0000000000..9a0ef84e8d
--- /dev/null
+++ b/code/game/antagonist/antagonist_add.dm
@@ -0,0 +1,22 @@
+/datum/antagonist/proc/add_antagonist(var/datum/mind/player, var/ignore_role, var/do_not_equip, var/move_to_spawn, var/do_not_announce, var/preserve_appearance)
+ if(!istype(player))
+ return 0
+ if(player in current_antagonists)
+ return 0
+ if(!can_become_antag(player, ignore_role))
+ return 0
+ current_antagonists |= player
+ create_antagonist(player, move_to_spawn, do_not_announce, preserve_appearance)
+ if(!do_not_equip && player.current)
+ equip(player.current)
+ return 1
+
+/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
+ if(player in current_antagonists)
+ player.current << "You are no longer a [role_text]!"
+ current_antagonists -= player
+ player.special_role = null
+ update_icons_removed(player)
+ BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
+ return 1
+ return 0
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_build.dm b/code/game/antagonist/antagonist_create.dm
similarity index 50%
rename from code/game/antagonist/antagonist_build.dm
rename to code/game/antagonist/antagonist_create.dm
index 35af4e6f80..c7387d92a8 100644
--- a/code/game/antagonist/antagonist_build.dm
+++ b/code/game/antagonist/antagonist_create.dm
@@ -1,83 +1,34 @@
-/datum/antagonist/proc/create_objectives(var/datum/mind/player)
- if(config.objectives_disabled)
+/datum/antagonist/proc/create_antagonist(var/datum/mind/target, var/move, var/gag_announcement, var/preserve_appearance)
+
+ if(!target)
+ return
+
+ update_antag_mob(target, preserve_appearance)
+ if(!target.current)
+ remove_antagonist(target)
return 0
- if(global_objectives && global_objectives.len)
- player.objectives |= global_objectives
- return 1
-
-/datum/antagonist/proc/apply(var/datum/mind/player)
-
- if(flags & ANTAG_HAS_LEADER && !leader)
- leader = current_antagonists[1]
-
- // Get the mob.
- if((flags & ANTAG_OVERRIDE_MOB) && (!player.current || (mob_path && !istype(player.current, mob_path))))
- var/mob/holder = player.current
- player.current = new mob_path(get_turf(player.current))
- player.transfer_to(player.current)
- if(holder) qdel(holder)
-
- player.original = player.current
- return player.current
-
-/datum/antagonist/proc/equip(var/mob/living/carbon/human/player)
-
- if(!istype(player))
- return 0
-
- // This could use work.
- if(flags & ANTAG_CLEAR_EQUIPMENT)
- for(var/obj/item/thing in player.contents)
- player.drop_from_inventory(thing)
- if(thing.loc != player)
- qdel(thing)
- return 1
-
- if(flags & ANTAG_SET_APPEARANCE)
- player.change_appearance(APPEARANCE_ALL, player.loc, player, valid_species, state = z_state)
-
-/datum/antagonist/proc/unequip(var/mob/living/carbon/human/player)
- if(!istype(player))
- return 0
- return 1
-
-/datum/antagonist/proc/greet(var/datum/mind/player)
-
- // Basic intro text.
- player.current << "You are a [role_text]!"
- if(leader_welcome_text && player.current == leader)
- player.current << "[leader_welcome_text]"
- else
- player.current << "[welcome_text]"
- show_objectives(player)
-
- // Choose a name, if any.
if(flags & ANTAG_CHOOSE_NAME)
- spawn(5)
- var/newname = sanitize(input(player.current, "You are a [role_text]. Would you like to change your name to something else?", "Name change") as null|text, MAX_NAME_LEN)
- if (newname)
- player.current.real_name = newname
- player.current.name = player.current.real_name
- player.name = player.current.name
- // Update any ID cards.
- update_access(player.current)
+ spawn(1)
+ set_antag_name(target.current)
+ if(move)
+ place_mob(target.current)
+ update_leader()
+ create_objectives(target)
+ update_icons_added(target)
+ greet(target)
+ announce_antagonist_spawn()
- // Clown clumsiness check, I guess downstream might use it.
- if (player.current.mind)
- if (player.current.mind.assigned_role == "Clown")
- player.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself."
- player.current.mutations.Remove(CLUMSY)
- return 1
-
-/datum/antagonist/proc/update_access(var/mob/living/player)
- for(var/obj/item/weapon/card/id/id in player.contents)
- id.name = "[player.real_name]'s ID Card"
- id.registered_name = player.real_name
-
-/datum/antagonist/proc/random_spawn()
- create_global_objectives()
- attempt_spawn(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
- finalize()
+/datum/antagonist/proc/create_default(var/mob/source)
+ var/mob/living/M
+ if(mob_path)
+ M = new mob_path()
+ else
+ M = new /mob/living/carbon/human
+ M.real_name = source.real_name
+ M.name = M.real_name
+ M.ckey = source.ckey
+ add_antagonist(M.mind, 1, 0, 1) // Equip them and move them to spawn.
+ return M
/datum/antagonist/proc/create_id(var/assignment, var/mob/living/carbon/human/player)
@@ -96,7 +47,7 @@
player.equip_to_slot_or_del(R, slot_l_ear)
return R
-/datum/antagonist/proc/make_nuke(var/atom/paper_spawn_loc, var/datum/mind/code_owner)
+/datum/antagonist/proc/create_nuke(var/atom/paper_spawn_loc, var/datum/mind/code_owner)
// Decide on a code.
var/obj/effect/landmark/nuke_spawn = locate(nuke_spawn_loc ? nuke_spawn_loc : "landmark*Nuclear-Bomb")
@@ -109,19 +60,59 @@
if(code)
if(!paper_spawn_loc)
- paper_spawn_loc = get_turf(locate("landmark*Nuclear-Code"))
+ if(leader && leader.current)
+ paper_spawn_loc = get_turf(leader.current)
+ else
+ paper_spawn_loc = get_turf(locate("landmark*Nuclear-Code"))
+
if(paper_spawn_loc)
// Create and pass on the bomb code paper.
var/obj/item/weapon/paper/P = new(paper_spawn_loc)
P.info = "The nuclear authorization code is: [code]"
P.name = "nuclear bomb code"
+ if(leader && leader.current)
+ if(get_turf(P) == get_turf(leader.current) && !(leader.current.l_hand && leader.current.r_hand))
+ leader.current.put_in_hands(P)
+
+ if(!code_owner && leader)
+ code_owner = leader
if(code_owner)
code_owner.store_memory("Nuclear Bomb Code: [code]", 0, 0)
code_owner.current << "The nuclear authorization code is: [code]"
-
else
world << "Could not spawn nuclear bomb. Contact a developer."
return
spawned_nuke = code
return code
+
+/datum/antagonist/proc/greet(var/datum/mind/player)
+
+ // Basic intro text.
+ player.current << "You are a [role_text]!"
+ if(leader_welcome_text && player == leader)
+ player.current << "[leader_welcome_text]"
+ else
+ player.current << "[welcome_text]"
+
+ if((flags & ANTAG_HAS_NUKE) && !spawned_nuke)
+ create_nuke()
+
+ show_objectives(player)
+
+ // Clown clumsiness check, I guess downstream might use it.
+ if (player.current.mind)
+ if (player.current.mind.assigned_role == "Clown")
+ player.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself."
+ player.current.mutations.Remove(CLUMSY)
+ return 1
+
+/datum/antagonist/proc/set_antag_name(var/mob/living/player)
+ // Choose a name, if any.
+ var/newname = sanitize(input(player, "You are a [role_text]. Would you like to change your name to something else?", "Name change") as null|text, MAX_NAME_LEN)
+ if (newname)
+ player.real_name = newname
+ player.name = player.real_name
+ if(player.mind) player.mind.name = player.name
+ // Update any ID cards.
+ update_access(player)
diff --git a/code/game/antagonist/antagonist_equip.dm b/code/game/antagonist/antagonist_equip.dm
new file mode 100644
index 0000000000..2f4bc6da3a
--- /dev/null
+++ b/code/game/antagonist/antagonist_equip.dm
@@ -0,0 +1,17 @@
+/datum/antagonist/proc/equip(var/mob/living/carbon/human/player)
+
+ if(!istype(player))
+ return 0
+
+ // This could use work.
+ if(flags & ANTAG_CLEAR_EQUIPMENT)
+ for(var/obj/item/thing in player.contents)
+ player.drop_from_inventory(thing)
+ if(thing.loc != player)
+ qdel(thing)
+ return 1
+
+/datum/antagonist/proc/unequip(var/mob/living/carbon/human/player)
+ if(!istype(player))
+ return 0
+ return 1
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_globals.dm b/code/game/antagonist/antagonist_globals.dm
deleted file mode 100644
index 02ec5304fc..0000000000
--- a/code/game/antagonist/antagonist_globals.dm
+++ /dev/null
@@ -1,41 +0,0 @@
-var/global/list/all_antag_types = list()
-var/global/list/all_antag_spawnpoints = list()
-var/global/list/antag_names_to_ids = list()
-
-/proc/get_antag_data(var/antag_type)
- if(all_antag_types[antag_type])
- return all_antag_types[antag_type]
- else
- for(var/cur_antag_type in all_antag_types)
- var/datum/antagonist/antag = all_antag_types[cur_antag_type]
- if(antag && antag.is_type(antag_type))
- return antag
-
-/proc/clear_antag_roles(var/datum/mind/player, var/implanted)
- for(var/antag_type in all_antag_types)
- var/datum/antagonist/antag = all_antag_types[antag_type]
- if(!implanted || !(antag.flags & ANTAG_IMPLANT_IMMUNE))
- antag.remove_antagonist(player, 1, implanted)
-
-/proc/update_antag_icons(var/datum/mind/player)
- for(var/antag_type in all_antag_types)
- var/datum/antagonist/antag = all_antag_types[antag_type]
- if(player)
- antag.update_icons_removed(player)
- if(antag.is_antagonist(player))
- antag.update_icons_added(player)
- else
- antag.update_all_icons()
-
-/proc/populate_antag_type_list()
- for(var/antag_type in typesof(/datum/antagonist)-/datum/antagonist)
- var/datum/antagonist/A = new antag_type
- all_antag_types[A.id] = A
- all_antag_spawnpoints[A.landmark_id] = list()
- antag_names_to_ids[A.role_text] = A.id
-
-/proc/get_antags(var/atype)
- var/datum/antagonist/antag = all_antag_types[atype]
- if(antag && islist(antag.current_antagonists))
- return antag.current_antagonists
- return list()
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm
index 92556a817a..bf010b6003 100644
--- a/code/game/antagonist/antagonist_helpers.dm
+++ b/code/game/antagonist/antagonist_helpers.dm
@@ -1,10 +1,11 @@
-/datum/antagonist/proc/can_become_antag(var/datum/mind/player)
+/datum/antagonist/proc/can_become_antag(var/datum/mind/player, var/ignore_role)
if(player.current && jobban_isbanned(player.current, bantype))
return 0
- if(player.assigned_role in protected_jobs)
- return 0
- if(config.protect_roles_from_antagonist && (player.assigned_role in restricted_jobs))
- return 0
+ if(!ignore_role)
+ if(player.assigned_role in protected_jobs)
+ return 0
+ if(config.protect_roles_from_antagonist && (player.assigned_role in restricted_jobs))
+ return 0
return 1
/datum/antagonist/proc/antags_are_dead()
@@ -27,3 +28,6 @@
if(antag_type == id || antag_type == role_text)
return 1
return 0
+
+/datum/antagonist/proc/is_votable()
+ return (flags & ANTAG_VOTABLE)
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_objectives.dm b/code/game/antagonist/antagonist_objectives.dm
index 58997fa68e..010ba565cc 100644
--- a/code/game/antagonist/antagonist_objectives.dm
+++ b/code/game/antagonist/antagonist_objectives.dm
@@ -1,5 +1,16 @@
/datum/antagonist/proc/create_global_objectives()
- return !((global_objectives && global_objectives.len) || config.objectives_disabled)
+ if(config.objectives_disabled)
+ return 0
+ if(global_objectives && global_objectives.len)
+ return 0
+ return 1
+
+/datum/antagonist/proc/create_objectives(var/datum/mind/player)
+ if(config.objectives_disabled)
+ return 0
+ if(create_global_objectives())
+ player.objectives |= global_objectives
+ return 1
/datum/antagonist/proc/get_special_objective_text()
return ""
diff --git a/code/game/antagonist/antagonist_panel.dm b/code/game/antagonist/antagonist_panel.dm
new file mode 100644
index 0000000000..ed8f1d9563
--- /dev/null
+++ b/code/game/antagonist/antagonist_panel.dm
@@ -0,0 +1,61 @@
+/datum/antagonist/proc/get_panel_entry(var/datum/mind/player)
+
+ var/dat = "| [role_text]:"
+ var/extra = get_extra_panel_options(player)
+ if(is_antagonist(player))
+ dat += "\[-\]"
+ dat += "\[equip\]"
+ if(starting_locations && starting_locations.len)
+ dat += "\[move to spawn\]"
+ if(extra) dat += "[extra]"
+ else
+ dat += "\[+\]"
+ dat += " |
"
+
+ return dat
+
+/datum/antagonist/proc/get_extra_panel_options()
+ return
+
+/datum/antagonist/proc/get_check_antag_output(var/datum/admins/caller)
+
+ if(!current_antagonists || !current_antagonists.len)
+ return ""
+
+ var/dat = "
| [role_text_plural] | |
"
+ for(var/datum/mind/player in current_antagonists)
+ var/mob/M = player.current
+ dat += ""
+ if(M)
+ dat += "| [M.real_name]"
+ if(!M.client) dat += " (logged out)"
+ if(M.stat == DEAD) dat += " (DEAD)"
+ dat += " | "
+ dat += "\[PM\]\[TP\] | "
+ else
+ dat += "Mob not found! | "
+ dat += "
"
+ dat += "
"
+
+ if(flags & ANTAG_HAS_NUKE)
+ dat += "
| Nuclear disk(s) |
"
+ for(var/obj/item/weapon/disk/nuclear/N in world)
+ dat += "| [N.name], "
+ var/atom/disk_loc = N.loc
+ while(!istype(disk_loc, /turf))
+ if(istype(disk_loc, /mob))
+ var/mob/M = disk_loc
+ dat += "carried by [M.real_name] "
+ if(istype(disk_loc, /obj))
+ 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]) |
"
+ dat += "
"
+ dat += get_additional_check_antag_output(caller)
+ dat += "
"
+ return dat
+
+//Overridden elsewhere.
+/datum/antagonist/proc/get_additional_check_antag_output(var/datum/admins/caller)
+ return ""
diff --git a/code/game/antagonist/antagonist_place.dm b/code/game/antagonist/antagonist_place.dm
new file mode 100644
index 0000000000..1d69aaa96f
--- /dev/null
+++ b/code/game/antagonist/antagonist_place.dm
@@ -0,0 +1,29 @@
+/datum/antagonist/proc/get_starting_locations()
+ if(landmark_id)
+ starting_locations = list()
+ for(var/obj/effect/landmark/L in landmarks_list)
+ if(L.name == landmark_id)
+ starting_locations |= get_turf(L)
+
+/datum/antagonist/proc/place_all_mobs()
+ if(!starting_locations || !starting_locations.len || !current_antagonists || !current_antagonists.len)
+ return
+ for(var/datum/mind/player in current_antagonists)
+ player.current.loc = pick(starting_locations)
+
+/datum/antagonist/proc/announce_antagonist_spawn()
+ if(spawn_announcement)
+ if(announced)
+ return
+ announced = 1
+ if(spawn_announcement_delay)
+ sleep(spawn_announcement_delay)
+ if(spawn_announcement_sound)
+ command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]", new_sound = spawn_announcement_sound)
+ else
+ command_announcement.Announce("[spawn_announcement]", "[spawn_announcement_title ? spawn_announcement_title : "Priority Alert"]")
+
+/datum/antagonist/proc/place_mob(var/mob/living/mob)
+ if(!starting_locations || !starting_locations.len)
+ return
+ mob.loc = pick(starting_locations)
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm
new file mode 100644
index 0000000000..ae35c22820
--- /dev/null
+++ b/code/game/antagonist/antagonist_print.dm
@@ -0,0 +1,88 @@
+/datum/antagonist/proc/print_player_summary()
+
+ if(!current_antagonists.len)
+ return 0
+
+ var/text = "
The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:"
+ for(var/datum/mind/P in current_antagonists)
+ text += print_player_full(P)
+ text += get_special_objective_text(P)
+ var/failed
+ if(!global_objectives.len && P.objectives && P.objectives.len)
+ var/num = 1
+ for(var/datum/objective/O in P.objectives)
+ text += print_objective(O, num)
+ if(O.completed) // This is set actively in check_victory()
+ text += "Success!"
+ feedback_add_details(feedback_tag,"[O.type]|SUCCESS")
+ else
+ text += "Fail."
+ feedback_add_details(feedback_tag,"[O.type]|FAIL")
+ failed = 1
+ num++
+
+ if(!config.objectives_disabled)
+ if(failed)
+ text += "
The [role_text] has failed."
+ else
+ text += "
The [role_text] was successful!"
+
+ if(global_objectives && global_objectives.len)
+ text += "
Their objectives were:"
+ var/num = 1
+ for(var/datum/objective/O in global_objectives)
+ text += print_objective(O, num, 1)
+ num++
+
+ // Display the results.
+ world << text
+
+/datum/antagonist/proc/print_objective(var/datum/objective/O, var/num, var/append_success)
+ var/text = "
Objective [num]: [O.explanation_text] "
+ if(append_success)
+ if(O.check_completion())
+ text += "Success!"
+ else
+ text += "Fail."
+ return text
+
+/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
+ var/role = ply.assigned_role == "MODE" ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]"
+ var/text = "
[ply.name] ([ply.key]) as \a [role] ("
+ if(ply.current)
+ if(ply.current.stat == DEAD)
+ text += "died"
+ else if(isNotStationLevel(ply.current.z))
+ text += "fled the station"
+ else
+ text += "survived"
+ if(ply.current.real_name != ply.name)
+ text += " as [ply.current.real_name]"
+ else
+ text += "body destroyed"
+ text += ")"
+
+ return text
+
+/datum/antagonist/proc/print_player_full(var/datum/mind/ply)
+ var/text = print_player_lite(ply)
+
+ var/TC_uses = 0
+ var/uplink_true = 0
+ var/purchases = ""
+ for(var/obj/item/device/uplink/H in world_uplinks)
+ if(H && H.uplink_owner && H.uplink_owner == ply)
+ TC_uses += H.used_TC
+ uplink_true = 1
+ var/list/refined_log = new()
+ for(var/datum/uplink_item/UI in H.purchase_log)
+ var/obj/I = new UI.path
+ refined_log.Add("[H.purchase_log[UI]]x\icon[I][UI.name]")
+ qdel(I)
+ purchases = english_list(refined_log, nothing_text = "")
+ if(uplink_true)
+ text += " (used [TC_uses] TC)"
+ if(purchases)
+ text += "
[purchases]"
+
+ return text
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_spawn.dm b/code/game/antagonist/antagonist_spawn.dm
deleted file mode 100644
index c8453663fb..0000000000
--- a/code/game/antagonist/antagonist_spawn.dm
+++ /dev/null
@@ -1,85 +0,0 @@
-/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player, var/move_to_spawn)
-
- update_cur_max()
- if(get_antag_count() >= cur_max)
- return 0
-
- player.current << "You have been selected this round as an antagonist!"
- add_antagonist(player)
- equip(player.current)
- if(move_to_spawn)
- place_mob(player.current)
- return
-
-/datum/antagonist/proc/update_cur_max()
-
- candidates = list()
- var/main_type
- if(ticker && ticker.mode)
- if(ticker.mode.antag_tag && ticker.mode.antag_tag == id)
- main_type = 1
- else
- return list()
-
- cur_max = (main_type ? max_antags_round : max_antags)
- if(ticker.mode.antag_scaling_coeff)
- cur_max = Clamp((ticker.mode.num_players()/ticker.mode.antag_scaling_coeff), 1, cur_max)
-
-/datum/antagonist/proc/attempt_spawn(var/ghosts_only)
-
- // Get the raw list of potential players.
- update_cur_max()
- candidates = get_candidates(ghosts_only)
-
- // Update our boundaries.
- if(!candidates.len)
- return 0
-
- //Grab candidates randomly until we have enough.
- while(candidates.len)
- var/datum/mind/player = pick(candidates)
- current_antagonists |= player
- // Update job and role.
- player.special_role = role_text
- if(flags & ANTAG_OVERRIDE_JOB)
- player.assigned_role = "MODE"
- candidates -= player
- return 1
-
-/datum/antagonist/proc/place_mob(var/mob/living/mob)
- if(!starting_locations || !starting_locations.len)
- return
- mob.loc = pick(starting_locations)
-
-/datum/antagonist/proc/add_antagonist(var/datum/mind/player)
- if(!istype(player))
- return 0
- if(player in current_antagonists)
- return 0
- if(!can_become_antag(player))
- return 0
-
- current_antagonists |= player
- apply(player)
- finalize(player)
- return 1
-
-/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
- if(player in current_antagonists)
- player.current << "You are no longer a [role_text]!"
- current_antagonists -= player
- player.special_role = null
- update_icons_removed(player)
- BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
- return 1
- return 0
-
-/datum/antagonist/proc/get_candidates(var/ghosts_only)
-
- candidates = list() // Clear.
- candidates = ticker.mode.get_players_for_role(role_type, id)
- // Prune restricted jobs and status.
- for(var/datum/mind/player in candidates)
- if((ghosts_only && !istype(player.current, /mob/dead)) || player.special_role || (player.assigned_role in restricted_jobs))
- candidates -= player
- return candidates
\ No newline at end of file
diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm
new file mode 100644
index 0000000000..a06b3e5993
--- /dev/null
+++ b/code/game/antagonist/antagonist_update.dm
@@ -0,0 +1,76 @@
+/datum/antagonist/proc/update_leader()
+ if(!leader && current_antagonists.len && (flags & ANTAG_HAS_LEADER))
+ leader = current_antagonists[1]
+
+/datum/antagonist/proc/update_antag_mob(var/datum/mind/player, var/preserve_appearance)
+
+ // Get the mob.
+ if((flags & ANTAG_OVERRIDE_MOB) && (!player.current || (mob_path && !istype(player.current, mob_path))))
+ var/mob/holder = player.current
+ player.current = new mob_path(get_turf(player.current))
+ player.transfer_to(player.current)
+ if(holder) qdel(holder)
+ player.original = player.current
+ if(!preserve_appearance && (flags & ANTAG_SET_APPEARANCE))
+ spawn(3)
+ var/mob/living/carbon/human/H = player.current
+ if(istype(H)) H.change_appearance(APPEARANCE_ALL, H.loc, H, valid_species, state = z_state)
+ return player.current
+
+/datum/antagonist/proc/update_access(var/mob/living/player)
+ for(var/obj/item/weapon/card/id/id in player.contents)
+ id.name = "[player.real_name]'s ID Card"
+ id.registered_name = player.real_name
+
+/datum/antagonist/proc/update_all_icons()
+ if(!antag_indicator)
+ return
+ for(var/datum/mind/antag in current_antagonists)
+ if(antag.current && antag.current.client)
+ for(var/image/I in antag.current.client.images)
+ if(I.icon_state == antag_indicator)
+ qdel(I)
+ for(var/datum/mind/other_antag in current_antagonists)
+ if(other_antag.current)
+ antag.current.client.images |= image('icons/mob/mob.dmi', loc = other_antag.current, icon_state = antag_indicator)
+
+/datum/antagonist/proc/update_icons_added(var/datum/mind/player)
+ if(!antag_indicator || !player.current)
+ return
+ spawn(0)
+ for(var/datum/mind/antag in current_antagonists)
+ if(!antag.current)
+ continue
+ if(antag.current.client)
+ antag.current.client.images |= image('icons/mob/mob.dmi', loc = player.current, icon_state = antag_indicator)
+ if(player.current.client)
+ player.current.client.images |= image('icons/mob/mob.dmi', loc = antag.current, icon_state = antag_indicator)
+
+/datum/antagonist/proc/update_icons_removed(var/datum/mind/player)
+ if(!antag_indicator || !player.current)
+ return
+ spawn(0)
+ for(var/datum/mind/antag in current_antagonists)
+ if(antag.current)
+ if(antag.current.client)
+ for(var/image/I in antag.current.client.images)
+ if(I.icon_state == antag_indicator && I.loc == player.current)
+ qdel(I)
+ if(player.current && player.current.client)
+ for(var/image/I in player.current.client.images)
+ if(I.icon_state == antag_indicator)
+ qdel(I)
+
+/datum/antagonist/proc/update_current_antag_max()
+
+ candidates = list()
+ var/main_type
+ if(ticker && ticker.mode)
+ if(ticker.mode.antag_tag && ticker.mode.antag_tag == id)
+ main_type = 1
+ else
+ return list()
+
+ cur_max = (main_type ? max_antags_round : max_antags)
+ if(ticker.mode.antag_scaling_coeff)
+ cur_max = Clamp((ticker.mode.num_players()/ticker.mode.antag_scaling_coeff), 1, cur_max)
\ No newline at end of file
diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm
index 73c2c7fd78..9d95fcc4d3 100644
--- a/code/game/antagonist/outsider/deathsquad.dm
+++ b/code/game/antagonist/outsider/deathsquad.dm
@@ -7,7 +7,7 @@ var/datum/antagonist/deathsquad/deathsquad
role_text_plural = "Death Commandos"
welcome_text = "You work in the service of Central Command Asset Protection, answering directly to the Board of Directors."
landmark_id = "Commando"
- flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE
+ flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER
max_antags = 4
max_antags_round = 6
default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)
@@ -23,6 +23,9 @@ var/datum/antagonist/deathsquad/deathsquad
deployed = 1
/datum/antagonist/deathsquad/equip(var/mob/living/carbon/human/player)
+ if(!..())
+ return
+
if (player.mind == leader)
player.equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(player), slot_w_uniform)
else
@@ -49,7 +52,7 @@ var/datum/antagonist/deathsquad/deathsquad
id.icon_state = "centcom"
create_radio(DTH_FREQ, player)
-/datum/antagonist/deathsquad/apply(var/datum/mind/player)
+/datum/antagonist/deathsquad/update_antag_mob(var/datum/mind/player)
..()
@@ -76,9 +79,6 @@ var/datum/antagonist/deathsquad/deathsquad
return
-/datum/antagonist/deathsquad/finalize(var/datum/mind/target)
-
- ..()
-
- if(!deployed)
+/datum/antagonist/deathsquad/create_antagonist()
+ if(..() && !deployed)
deployed = 1
diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm
index 946ff1dfc2..6bcb89a6bf 100644
--- a/code/game/antagonist/outsider/ert.dm
+++ b/code/game/antagonist/outsider/ert.dm
@@ -10,8 +10,13 @@ var/datum/antagonist/ert/ert
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
max_antags = 5
max_antags_round = 5 // ERT mode?
+ landmark_id = "Response Team"
- flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE
+ flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
+
+/datum/antagonist/ert/create_default(var/mob/source)
+ var/mob/living/carbon/human/M = ..()
+ if(istype(M)) M.age = rand(25,45)
/datum/antagonist/ert/New()
..()
diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm
index 72a6a56d62..1ddc6457d9 100644
--- a/code/game/antagonist/outsider/mercenary.dm
+++ b/code/game/antagonist/outsider/mercenary.dm
@@ -7,8 +7,9 @@ var/datum/antagonist/mercenary/mercs
bantype = "operative"
role_text_plural = "Mercenaries"
landmark_id = "Syndicate-Spawn"
+ leader_welcome_text = "You are the leader of the mercenary strikeforce; hail to the chief. Use :t to speak to your underlings."
welcome_text = "To speak on the strike team's private channel use :t."
- flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE | ANTAG_SET_APPEARANCE
+ flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
max_antags = 4
max_antags_round = 6
id_type = /obj/item/weapon/card/id/syndicate
@@ -19,9 +20,10 @@ var/datum/antagonist/mercenary/mercs
/datum/antagonist/mercenary/create_global_objectives()
if(!..())
- return
+ return 0
global_objectives = list()
global_objectives |= new /datum/objective/nuclear
+ return 1
/datum/antagonist/mercenary/equip(var/mob/living/carbon/human/player)
@@ -50,7 +52,7 @@ var/datum/antagonist/mercenary/mercs
if(spawnpos > starting_locations.len)
spawnpos = 1
-/datum/antagonist/mercenary/make_nuke()
+/datum/antagonist/mercenary/create_nuke()
..()
// Create the radio.
var/obj/effect/landmark/uplinkdevice = locate("landmark*Syndicate-Uplink")
diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm
index 4fed41aa13..17083eb89a 100644
--- a/code/game/antagonist/outsider/ninja.dm
+++ b/code/game/antagonist/outsider/ninja.dm
@@ -16,7 +16,7 @@ var/datum/antagonist/ninja/ninjas
..()
ninjas = src
-/datum/antagonist/ninja/random_spawn()
+/datum/antagonist/ninja/attempt_random_spawn()
if(config.ninjas_allowed) ..()
/datum/antagonist/ninja/create_objectives(var/datum/mind/ninja)
@@ -82,7 +82,7 @@ var/datum/antagonist/ninja/ninjas
player.store_memory("Directive: [directive]
")
player << "Remember your directive: [directive]."
-/datum/antagonist/ninja/apply(var/datum/mind/player)
+/datum/antagonist/ninja/update_antag_mob(var/datum/mind/player)
..()
var/ninja_title = pick(ninja_titles)
var/ninja_name = pick(ninja_names)
diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm
index a7949011fc..e17632dccb 100644
--- a/code/game/antagonist/outsider/raider.dm
+++ b/code/game/antagonist/outsider/raider.dm
@@ -8,7 +8,7 @@ var/datum/antagonist/raider/raiders
bantype = "raider"
landmark_id = "voxstart"
welcome_text = "Use :H to talk on your encrypted channel."
- flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
+ flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
max_antags = 6
max_antags_round = 10
id_type = /obj/item/weapon/card/id/syndicate
@@ -83,8 +83,8 @@ var/datum/antagonist/raider/raiders
/datum/antagonist/raider/create_global_objectives()
- if(global_objectives.len)
- return
+ if(!..())
+ return 0
var/i = 1
var/max_objectives = pick(2,2,2,2,3,3,3,4)
@@ -107,6 +107,7 @@ var/datum/antagonist/raider/raiders
i++
global_objectives |= new /datum/objective/heist/preserve_crew
+ return 1
/datum/antagonist/raider/check_victory()
// Totally overrides the base proc.
diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm
index 2923008a7b..93e44974e9 100644
--- a/code/game/antagonist/outsider/wizard.dm
+++ b/code/game/antagonist/outsider/wizard.dm
@@ -58,7 +58,8 @@ var/datum/antagonist/wizard/wizards
wizard.objectives |= hijack_objective
return
-/datum/antagonist/wizard/apply(var/datum/mind/wizard)
+/datum/antagonist/wizard/update_antag_mob(var/datum/mind/wizard)
+ ..()
wizard.store_memory("Remember: do not forget to prepare your spells.")
wizard.current.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
wizard.current.name = wizard.current.real_name
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index 55b67cc29a..f6307b8ae8 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -13,7 +13,7 @@
/datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player)
return "
Changeling ID: [player.changeling.changelingID].
Genomes Absorbed: [player.changeling.absorbedcount]"
-/datum/antagonist/changeling/apply(var/datum/mind/player)
+/datum/antagonist/changeling/update_antag_mob(var/datum/mind/player)
..()
player.current.make_changeling()
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index adaa2b24f5..5c6a3c6782 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -111,8 +111,6 @@ var/datum/antagonist/cultist/cult
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player)
if(!..())
return 0
- if(!istype(player.current, /mob/living/carbon/human))
- return 0
for(var/obj/item/weapon/implant/loyalty/L in player.current)
if(L && (L.imp_in == player.current))
return 0
diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm
index ced1d58b38..59d12b50ad 100644
--- a/code/game/antagonist/station/revolutionary.dm
+++ b/code/game/antagonist/station/revolutionary.dm
@@ -50,13 +50,43 @@ var/datum/antagonist/revolutionary/revs
)
mob.equip_in_one_of_slots(T, slots)
-/datum/antagonist/revolutionary/finalize(var/datum/mind/target)
+/*
+datum/antagonist/revolutionary/finalize(var/datum/mind/target)
if(target)
return ..(target)
current_antagonists |= head_revolutionaries
create_global_objectives()
..()
+/datum/antagonist/revolutionary/get_additional_check_antag_output(var/datum/admins/caller)
+ return ..() //Todo
+
+ Rev extras:
+ dat += "
| Revolutionaries | |
"
+ for(var/datum/mind/N in ticker.mode.head_revolutionaries)
+ var/mob/M = N.current
+ if(!M)
+ dat += "| Head Revolutionary not found! |
"
+ else
+ dat += "| [M.real_name] (Leader)[M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
+ dat += "PM |
"
+ for(var/datum/mind/N in ticker.mode.revolutionaries)
+ var/mob/M = N.current
+ if(M)
+ dat += "| [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
+ dat += "PM |
"
+ dat += "
| Target(s) | | Location |
"
+ for(var/datum/mind/N in ticker.mode.get_living_heads())
+ var/mob/M = N.current
+ if(M)
+ dat += "| [M.real_name][M.client ? "" : " (logged out)"][M.stat == 2 ? " (DEAD)" : ""] | "
+ dat += "PM | "
+ var/turf/mob_loc = get_turf(M)
+ dat += "[mob_loc.loc] |
"
+ else
+ dat += "| Head not found! |
"
+*/
+
/datum/antagonist/revolutionary/create_global_objectives()
if(!..())
return
@@ -166,7 +196,7 @@ var/datum/antagonist/revolutionary/revs
if(choice == "Yes!")
M << "You join the revolution!"
src << "[M] joins the revolution!"
- revs.add_antagonist(M.mind)
+ revs.add_antagonist(M.mind, 0, 0, 1)
else if(choice == "No!")
M << "You reject this traitorous cause!"
src << "\The [M] does not support the revolution!"
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 755887ad83..76ab7b5106 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -285,9 +285,9 @@ var/global/list/additional_antag_types = list()
spawn(rand(100,150))
announce_ert_disabled()
- if(antag_templates && antag_templates.len)
- for(var/datum/antagonist/antag in antag_templates)
- antag.finalize()
+ //if(antag_templates && antag_templates.len)
+ // for(var/datum/antagonist/antag in antag_templates)
+ // antag.finalize()
if(emergency_shuttle && auto_recall_shuttle)
emergency_shuttle.auto_recall = 1
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index d1d2a37ea2..23c6b80b5a 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -697,13 +697,14 @@
/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob)
-
+ /*
if(istype(W, /obj/item/device/mmi))
if(mmi_move_inside(W,user))
user << "[src]-MMI interface initialized successfuly"
else
user << "[src]-MMI interface initialization failed."
return
+ */
if(istype(W, /obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = W
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index 61f6921698..896b79655a 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -38,9 +38,12 @@ var/can_call_ert
trigger_armed_response_team(1)
client/verb/JoinResponseTeam()
+
+ set name = "Join Response Team"
set category = "IC"
if(!MayRespawn(1))
+ usr << "You cannot join the response team at this time."
return
if(istype(usr,/mob/dead/observer) || istype(usr,/mob/new_player))
@@ -50,18 +53,9 @@ client/verb/JoinResponseTeam()
if(jobban_isbanned(usr, "Syndicate") || jobban_isbanned(usr, "Emergency Response Team") || jobban_isbanned(usr, "Security Officer"))
usr << "You are jobbanned from the emergency reponse team!"
return
-
- if(ert.current_antagonists.len > 5) usr << "The emergency response team is already full!"
-
- for (var/obj/effect/landmark/L in landmarks_list) if (L.name == "Commando")
- L.name = null//Reserving the place.
- var/new_name = sanitizeSafe(input(usr, "Pick a name","Name") as null|text, MAX_NAME_LEN)
- if(!new_name)//Somebody changed his mind, place is available again.
- L.name = "Commando"
- return
- create_response_team(L.loc, new_name)
- qdel(L)
-
+ if(ert.current_antagonists.len > 5)
+ usr << "The emergency response team is already full!"
+ ert.create_default(usr)
else
usr << "You need to be an observer or new player to use this."
@@ -130,25 +124,3 @@ proc/trigger_armed_response_team(var/force = 0)
sleep(600 * 5)
send_emergency_team = 0 // Can no longer join the ERT.
-
-/client/proc/create_response_team(obj/spawn_location, commando_name)
-
- var/mob/living/carbon/human/M = new(null)
-
-
- M.real_name = commando_name
- M.name = commando_name
- M.age = rand(25,45)
-
- M.check_dna(M)
- M.dna.ready_dna(M)//Creates DNA.
-
- M.mind = new
- M.mind.current = M
- M.mind.original = M
- if(!(M.mind in ticker.minds))
- ticker.minds += M.mind//Adds them to regular mind list.
- M.loc = spawn_location
- ert.add_antagonist(M.mind)
-
- return M
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 828667aa13..a25d2de043 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -410,43 +410,11 @@
dat += "Launching now..."
dat += "[ticker.delay_end ? "End Round Normally" : "Delay Round End"]
"
-
- //todo
-
+ dat += "
"
+ for(var/antag_type in all_antag_types)
+ var/datum/antagonist/A = all_antag_types[antag_type]
+ dat += A.get_check_antag_output(src)
dat += "