mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
@@ -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"
|
||||
@@ -247,6 +252,7 @@
|
||||
#include "code\game\dna\genes\powers.dm"
|
||||
#include "code\game\gamemodes\events.dm"
|
||||
#include "code\game\gamemodes\game_mode.dm"
|
||||
#include "code\game\gamemodes\game_mode_latespawn.dm"
|
||||
#include "code\game\gamemodes\gameticker.dm"
|
||||
#include "code\game\gamemodes\intercept_report.dm"
|
||||
#include "code\game\gamemodes\objective.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")
|
||||
|
||||
@@ -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"]]
|
||||
|
||||
72
code/game/antagonist/_antagonist_setup.dm
Normal file
72
code/game/antagonist/_antagonist_setup.dm
Normal file
@@ -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()
|
||||
@@ -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 "<a href='?src=\ref[src];move_to_spawn=\ref[player.current]'>\[move to vent\]</a>"
|
||||
|
||||
/datum/antagonist/xenos/random_spawn()
|
||||
/datum/antagonist/xenos/attempt_random_spawn()
|
||||
if(config.aliens_allowed) ..()
|
||||
|
||||
/datum/antagonist/xenos/proc/get_vents()
|
||||
|
||||
@@ -33,8 +33,9 @@
|
||||
var/nuke_spawn_loc
|
||||
|
||||
var/list/valid_species = list("Unathi","Tajara","Skrell","Human") // Used for setting appearance.
|
||||
var/list/starting_locations = list()
|
||||
var/list/current_antagonists = list()
|
||||
var/list/pending_antagonists = list()
|
||||
var/list/starting_locations = list()
|
||||
var/list/global_objectives = list()
|
||||
var/list/restricted_jobs = list()
|
||||
var/list/protected_jobs = list()
|
||||
@@ -42,209 +43,70 @@
|
||||
|
||||
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)
|
||||
candidates = list() // Clear.
|
||||
candidates = ticker.mode.get_players_for_role(role_type, id)
|
||||
// Prune restricted jobs and status. Broke it up for readability.
|
||||
for(var/datum/mind/player in candidates)
|
||||
if(ghosts_only && !istype(player.current, /mob/dead))
|
||||
candidates -= player
|
||||
else if(player.special_role)
|
||||
candidates -= player
|
||||
else if (player in pending_antagonists)
|
||||
candidates -= player
|
||||
else if(!can_become_antag(player))
|
||||
candidates -= player
|
||||
return candidates
|
||||
|
||||
var/dat = "<tr><td><b>[role_text]:</b>"
|
||||
var/extra = get_extra_panel_options(player)
|
||||
if(is_antagonist(player))
|
||||
dat += "<a href='?src=\ref[player];remove_antagonist=[id]'>\[-\]</a>"
|
||||
dat += "<a href='?src=\ref[player];equip_antagonist=[id]'>\[equip\]</a>"
|
||||
if(starting_locations && starting_locations.len)
|
||||
dat += "<a href='?src=\ref[player];move_antag_to_spawn=[id]'>\[move to spawn\]</a>"
|
||||
if(extra) dat += "[extra]"
|
||||
/datum/antagonist/proc/attempt_random_spawn()
|
||||
attempt_spawn(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
|
||||
|
||||
/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player)
|
||||
if(!can_late_spawn())
|
||||
return
|
||||
if(!istype(player)) player = get_candidates(is_latejoin_template())
|
||||
player.current << "<span class='danger'><i>You have been selected this round as an antagonist!</i></span>"
|
||||
if(istype(player.current, /mob/dead))
|
||||
create_default(player.current)
|
||||
else
|
||||
dat += "<a href='?src=\ref[player];add_antagonist=[id]'>\[+\]</a>"
|
||||
dat += "</td></tr>"
|
||||
|
||||
return dat
|
||||
|
||||
/datum/antagonist/proc/get_extra_panel_options()
|
||||
add_antagonist(player,0,1,0,1,1)
|
||||
return
|
||||
|
||||
/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/attempt_spawn(var/ghosts_only)
|
||||
|
||||
/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)
|
||||
// Get the raw list of potential players.
|
||||
update_current_antag_max()
|
||||
candidates = get_candidates(ghosts_only)
|
||||
|
||||
/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 our boundaries.
|
||||
if(!candidates.len)
|
||||
return 0
|
||||
|
||||
var/text = "<br><font size = 2><b>The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:</b></font>"
|
||||
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 += "<font color='green'><B>Success!</B></font>"
|
||||
feedback_add_details(feedback_tag,"[O.type]|SUCCESS")
|
||||
else
|
||||
text += "<font color='red'>Fail.</font>"
|
||||
feedback_add_details(feedback_tag,"[O.type]|FAIL")
|
||||
failed = 1
|
||||
num++
|
||||
//Grab candidates randomly until we have enough.
|
||||
while(candidates.len)
|
||||
var/datum/mind/player = pick(candidates)
|
||||
pending_antagonists |= player
|
||||
candidates -= player
|
||||
return 1
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
if(failed)
|
||||
text += "<br><font color='red'><B>The [role_text] has failed.</B></font>"
|
||||
else
|
||||
text += "<br><font color='green'><B>The [role_text] was successful!</B></font>"
|
||||
|
||||
if(global_objectives && global_objectives.len)
|
||||
text += "<BR/><FONT size = 2>Their objectives were:<FONT>"
|
||||
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 = "<br><b>Objective [num]:</b> [O.explanation_text] "
|
||||
if(append_success)
|
||||
if(O.check_completion())
|
||||
text += "<font color='green'><B>Success!</B></font>"
|
||||
else
|
||||
text += "<font color='red'>Fail.</font>"
|
||||
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 = "<br><b>[ply.name]</b> (<b>[ply.key]</b>) as \a <b>[role]</b> ("
|
||||
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 <b>[ply.current.real_name]</b>"
|
||||
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 += "<br>[purchases]"
|
||||
|
||||
return text
|
||||
|
||||
/datum/antagonist/proc/update_all_icons()
|
||||
if(!antag_indicator)
|
||||
/datum/antagonist/proc/finalize_spawn()
|
||||
if(!pending_antagonists || !pending_antagonists.len)
|
||||
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)
|
||||
|
||||
|
||||
for(var/datum/mind/player in pending_antagonists)
|
||||
if(can_become_antag(player) && !player.special_role)
|
||||
add_antagonist(player,0,0,1)
|
||||
pending_antagonists.Cut()
|
||||
31
code/game/antagonist/antagonist_add.dm
Normal file
31
code/game/antagonist/antagonist_add.dm
Normal file
@@ -0,0 +1,31 @@
|
||||
/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.current)
|
||||
return 0
|
||||
if(player in current_antagonists)
|
||||
return 0
|
||||
if(!can_become_antag(player, ignore_role))
|
||||
return 0
|
||||
|
||||
current_antagonists |= player
|
||||
if(flags & ANTAG_OVERRIDE_JOB)
|
||||
player.assigned_role = "MODE"
|
||||
|
||||
if(istype(player.current, /mob/dead))
|
||||
create_default(player.current)
|
||||
else
|
||||
create_antagonist(player, move_to_spawn, do_not_announce, preserve_appearance)
|
||||
if(!do_not_equip)
|
||||
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 << "<span class='danger'><font size = 3>You are no longer a [role_text]!</font></span>"
|
||||
current_antagonists -= player
|
||||
player.special_role = null
|
||||
update_icons_removed(player)
|
||||
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
|
||||
return 1
|
||||
return 0
|
||||
@@ -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 << "<span class='danger'><font size=3>You are a [role_text]!</font></span>"
|
||||
if(leader_welcome_text && player.current == leader)
|
||||
player.current << "<span class='notice'>[leader_welcome_text]</span>"
|
||||
else
|
||||
player.current << "<span class='notice'>[welcome_text]</span>"
|
||||
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(get_turf(source))
|
||||
else
|
||||
M = new /mob/living/carbon/human(get_turf(source))
|
||||
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: <b>[code]</b>"
|
||||
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("<B>Nuclear Bomb Code</B>: [code]", 0, 0)
|
||||
code_owner.current << "The nuclear authorization code is: <B>[code]</B>"
|
||||
|
||||
else
|
||||
world << "<spam class='danger'>Could not spawn nuclear bomb. Contact a developer.</span>"
|
||||
return
|
||||
|
||||
spawned_nuke = code
|
||||
return code
|
||||
|
||||
/datum/antagonist/proc/greet(var/datum/mind/player)
|
||||
|
||||
// Basic intro text.
|
||||
player.current << "<span class='danger'><font size=3>You are a [role_text]!</font></span>"
|
||||
if(leader_welcome_text && player == leader)
|
||||
player.current << "<span class='notice'>[leader_welcome_text]</span>"
|
||||
else
|
||||
player.current << "<span class='notice'>[welcome_text]</span>"
|
||||
|
||||
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)
|
||||
17
code/game/antagonist/antagonist_equip.dm
Normal file
17
code/game/antagonist/antagonist_equip.dm
Normal file
@@ -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
|
||||
@@ -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()
|
||||
@@ -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,15 @@
|
||||
if(antag_type == id || antag_type == role_text)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/antagonist/proc/is_votable()
|
||||
return (flags & ANTAG_VOTABLE)
|
||||
|
||||
/datum/antagonist/proc/can_late_spawn()
|
||||
update_current_antag_max()
|
||||
if(get_antag_count() >= cur_max)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/antagonist/proc/is_latejoin_template()
|
||||
return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
|
||||
@@ -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 ""
|
||||
@@ -12,8 +23,6 @@
|
||||
for(var/datum/objective/O in global_objectives)
|
||||
if(!O.completed && !O.check_completion())
|
||||
result = 0
|
||||
else
|
||||
O.completed = 1 //Will this break anything?
|
||||
if(result && victory_text)
|
||||
world << "<span class='danger'><font size = 3>[victory_text]</span>"
|
||||
if(victory_feedback_tag) feedback_set_details("round_end_result","[victory_feedback_tag]")
|
||||
|
||||
61
code/game/antagonist/antagonist_panel.dm
Normal file
61
code/game/antagonist/antagonist_panel.dm
Normal file
@@ -0,0 +1,61 @@
|
||||
/datum/antagonist/proc/get_panel_entry(var/datum/mind/player)
|
||||
|
||||
var/dat = "<tr><td><b>[role_text]:</b>"
|
||||
var/extra = get_extra_panel_options(player)
|
||||
if(is_antagonist(player))
|
||||
dat += "<a href='?src=\ref[player];remove_antagonist=[id]'>\[-\]</a>"
|
||||
dat += "<a href='?src=\ref[player];equip_antagonist=[id]'>\[equip\]</a>"
|
||||
if(starting_locations && starting_locations.len)
|
||||
dat += "<a href='?src=\ref[player];move_antag_to_spawn=[id]'>\[move to spawn\]</a>"
|
||||
if(extra) dat += "[extra]"
|
||||
else
|
||||
dat += "<a href='?src=\ref[player];add_antagonist=[id]'>\[+\]</a>"
|
||||
dat += "</td></tr>"
|
||||
|
||||
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 = "<br><table cellspacing=5><tr><td><B>[role_text_plural]</B></td><td></td></tr>"
|
||||
for(var/datum/mind/player in current_antagonists)
|
||||
var/mob/M = player.current
|
||||
dat += "<tr>"
|
||||
if(M)
|
||||
dat += "<td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>"
|
||||
if(!M.client) dat += " <i>(logged out)</i>"
|
||||
if(M.stat == DEAD) dat += " <b><font color=red>(DEAD)</font></b>"
|
||||
dat += "</td>"
|
||||
dat += "<td>\[<A href='?src=\ref[caller];priv_msg=\ref[M]'>PM</A>\]\[<A href='?src=\ref[caller];traitor=\ref[M]'>TP</A>\]</td>"
|
||||
else
|
||||
dat += "<td><i>Mob not found!</i></td>"
|
||||
dat += "</tr>"
|
||||
dat += "</table>"
|
||||
|
||||
if(flags & ANTAG_HAS_NUKE)
|
||||
dat += "<br><table><tr><td><B>Nuclear disk(s)</B></td></tr>"
|
||||
for(var/obj/item/weapon/disk/nuclear/N in world)
|
||||
dat += "<tr><td>[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 <a href='?src=\ref[caller];adminplayeropts=\ref[M]'>[M.real_name]</a> "
|
||||
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])</td></tr>"
|
||||
dat += "</table>"
|
||||
dat += get_additional_check_antag_output(caller)
|
||||
dat += "<hr>"
|
||||
return dat
|
||||
|
||||
//Overridden elsewhere.
|
||||
/datum/antagonist/proc/get_additional_check_antag_output(var/datum/admins/caller)
|
||||
return ""
|
||||
29
code/game/antagonist/antagonist_place.dm
Normal file
29
code/game/antagonist/antagonist_place.dm
Normal file
@@ -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)
|
||||
88
code/game/antagonist/antagonist_print.dm
Normal file
88
code/game/antagonist/antagonist_print.dm
Normal file
@@ -0,0 +1,88 @@
|
||||
/datum/antagonist/proc/print_player_summary()
|
||||
|
||||
if(!current_antagonists.len)
|
||||
return 0
|
||||
|
||||
var/text = "<br><font size = 2><b>The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:</b></font>"
|
||||
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.check_completion())
|
||||
text += "<font color='green'><B>Success!</B></font>"
|
||||
feedback_add_details(feedback_tag,"[O.type]|SUCCESS")
|
||||
else
|
||||
text += "<font color='red'>Fail.</font>"
|
||||
feedback_add_details(feedback_tag,"[O.type]|FAIL")
|
||||
failed = 1
|
||||
num++
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
if(failed)
|
||||
text += "<br><font color='red'><B>The [role_text] has failed.</B></font>"
|
||||
else
|
||||
text += "<br><font color='green'><B>The [role_text] was successful!</B></font>"
|
||||
|
||||
if(global_objectives && global_objectives.len)
|
||||
text += "<BR/><FONT size = 2>Their objectives were:<FONT>"
|
||||
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 = "<br><b>Objective [num]:</b> [O.explanation_text] "
|
||||
if(append_success)
|
||||
if(O.check_completion())
|
||||
text += "<font color='green'><B>Success!</B></font>"
|
||||
else
|
||||
text += "<font color='red'>Fail.</font>"
|
||||
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 = "<br><b>[ply.name]</b> (<b>[ply.key]</b>) as \a <b>[role]</b> ("
|
||||
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 <b>[ply.current.real_name]</b>"
|
||||
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 += "<br>[purchases]"
|
||||
|
||||
return text
|
||||
@@ -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 << "<span class='danger'><i>You have been selected this round as an antagonist!</i></span>"
|
||||
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 << "<span class='danger'><font size = 3>You are no longer a [role_text]!</font></span>"
|
||||
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
|
||||
71
code/game/antagonist/antagonist_update.dm
Normal file
71
code/game/antagonist/antagonist_update.dm
Normal file
@@ -0,0 +1,71 @@
|
||||
/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()
|
||||
var/main_type
|
||||
if(ticker && ticker.mode)
|
||||
if(ticker.mode.antag_tag && ticker.mode.antag_tag == id)
|
||||
main_type = 1
|
||||
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)
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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("<B>Directive:</B> <span class='danger'>[directive]</span><br>")
|
||||
player << "<b>Remember your directive:</b> [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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -10,6 +10,7 @@ var/datum/antagonist/wizard/wizards
|
||||
welcome_text = "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.<br>In your pockets you will find a teleport scroll. Use it as needed."
|
||||
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
|
||||
max_antags = 1
|
||||
max_antags_round = 1
|
||||
|
||||
/datum/antagonist/wizard/New()
|
||||
..()
|
||||
@@ -58,7 +59,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("<B>Remember:</B> do not forget to prepare your spells.")
|
||||
wizard.current.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
|
||||
wizard.current.name = wizard.current.real_name
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/datum/antagonist/changeling/get_special_objective_text(var/datum/mind/player)
|
||||
return "<br><b>Changeling ID:</b> [player.changeling.changelingID].<br><b>Genomes Absorbed:</b> [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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 += "<br><table cellspacing=5><tr><td><B>Revolutionaries</B></td><td></td></tr>"
|
||||
for(var/datum/mind/N in ticker.mode.head_revolutionaries)
|
||||
var/mob/M = N.current
|
||||
if(!M)
|
||||
dat += "<tr><td><i>Head Revolutionary not found!</i></td></tr>"
|
||||
else
|
||||
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a> <b>(Leader)</b>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
|
||||
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
|
||||
for(var/datum/mind/N in ticker.mode.revolutionaries)
|
||||
var/mob/M = N.current
|
||||
if(M)
|
||||
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
|
||||
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td></tr>"
|
||||
dat += "</table><table cellspacing=5><tr><td><B>Target(s)</B></td><td></td><td><B>Location</B></td></tr>"
|
||||
for(var/datum/mind/N in ticker.mode.get_living_heads())
|
||||
var/mob/M = N.current
|
||||
if(M)
|
||||
dat += "<tr><td><a href='?src=\ref[src];adminplayeropts=\ref[M]'>[M.real_name]</a>[M.client ? "" : " <i>(logged out)</i>"][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>"
|
||||
dat += "<td><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>"
|
||||
var/turf/mob_loc = get_turf(M)
|
||||
dat += "<td>[mob_loc.loc]</td></tr>"
|
||||
else
|
||||
dat += "<tr><td><i>Head not found!</i></td></tr>"
|
||||
*/
|
||||
|
||||
/datum/antagonist/revolutionary/create_global_objectives()
|
||||
if(!..())
|
||||
return
|
||||
@@ -166,7 +196,7 @@ var/datum/antagonist/revolutionary/revs
|
||||
if(choice == "Yes!")
|
||||
M << "<span class='notice'>You join the revolution!</span>"
|
||||
src << "<span class='notice'>[M] joins the revolution!</span>"
|
||||
revs.add_antagonist(M.mind)
|
||||
revs.add_antagonist(M.mind, 0, 0, 1)
|
||||
else if(choice == "No!")
|
||||
M << "<span class='danger'>You reject this traitorous cause!</span>"
|
||||
src << "<span class='danger'>\The [M] does not support the revolution!</span>"
|
||||
|
||||
@@ -18,7 +18,7 @@ var/datum/antagonist/traitor/traitors
|
||||
/datum/antagonist/traitor/Topic(href, href_list)
|
||||
if (..())
|
||||
return
|
||||
if(href_list["spawn_uplink"]) spawn_uplink(href_list["spawn_uplink"])
|
||||
if(href_list["spawn_uplink"]) spawn_uplink(locate(href_list["spawn_uplink"]))
|
||||
|
||||
/datum/antagonist/traitor/create_objectives(var/datum/mind/traitor)
|
||||
if(!..())
|
||||
|
||||
@@ -42,17 +42,10 @@ var/global/list/additional_antag_types = list()
|
||||
|
||||
var/antag_tag // First (main) antag template to spawn.
|
||||
var/list/antag_templates // Extra antagonist types to include.
|
||||
|
||||
var/list/latejoin_templates = list()
|
||||
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
|
||||
var/antag_prob = 0 // Likelihood of a new antagonist spawning.
|
||||
var/antag_count = 0 // Current number of antagonists.
|
||||
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
|
||||
|
||||
var/list/living_antag_templates = list() // Currently selected antag types that do not require a ghosted player.
|
||||
var/list/ghost_antag_templates = list() // Inverse of above.
|
||||
var/list/antag_candidates = list() // Living antag candidates.
|
||||
var/list/ghost_candidates = list() // Observing antag candidates.
|
||||
|
||||
var/station_was_nuked = 0 // See nuclearbomb.dm and malfunction.dm.
|
||||
var/explosion_in_progress = 0 // Sit back and relax
|
||||
var/waittime_l = 600 // Lower bound on time before intercept arrives (in tenths of seconds)
|
||||
@@ -272,7 +265,6 @@ var/global/list/additional_antag_types = list()
|
||||
EMajor.delay_modifier = event_delay_mod_major
|
||||
|
||||
///post_setup()
|
||||
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
|
||||
/datum/game_mode/proc/post_setup()
|
||||
|
||||
refresh_event_modifiers()
|
||||
@@ -287,7 +279,9 @@ var/global/list/additional_antag_types = list()
|
||||
|
||||
if(antag_templates && antag_templates.len)
|
||||
for(var/datum/antagonist/antag in antag_templates)
|
||||
antag.finalize()
|
||||
antag.finalize_spawn()
|
||||
if(antag.is_latejoin_template())
|
||||
latejoin_templates |= antag
|
||||
|
||||
if(emergency_shuttle && auto_recall_shuttle)
|
||||
emergency_shuttle.auto_recall = 1
|
||||
@@ -336,67 +330,6 @@ var/global/list/additional_antag_types = list()
|
||||
)
|
||||
command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission")
|
||||
|
||||
///process()
|
||||
///Called by the gameticker
|
||||
/datum/game_mode/proc/process()
|
||||
|
||||
if(emergency_shuttle.departed)
|
||||
return
|
||||
|
||||
if(!round_autoantag || !antag_templates || !antag_templates.len)
|
||||
return
|
||||
|
||||
var/player_count = 0
|
||||
antag_count = 0
|
||||
antag_candidates = list()
|
||||
|
||||
for(var/mob/living/player in mob_list)
|
||||
if(player.client)
|
||||
player_count += 1
|
||||
if(player.mind)
|
||||
if(player.stat == 2) // observing
|
||||
ghost_candidates |= player
|
||||
else
|
||||
if(player.mind.special_role)
|
||||
antag_count += 1
|
||||
else
|
||||
antag_candidates |= player
|
||||
|
||||
antag_prob = min(100,max(0,(player_count - 5 * 10) * 5)) // This is arbitrary, probably needs adjusting.
|
||||
|
||||
var/datum/antagonist/spawn_antag
|
||||
var/datum/mind/candidate
|
||||
|
||||
var/from_ghosts
|
||||
if(prob(antag_prob))
|
||||
if(ghost_candidates.len && ghost_antag_templates.len && prob(50))
|
||||
spawn_antag = pick(ghost_antag_templates)
|
||||
candidate = pick(ghost_candidates)
|
||||
from_ghosts = 1
|
||||
else if(antag_candidates.len && living_antag_templates.len)
|
||||
spawn_antag = pick(living_antag_templates)
|
||||
candidate = pick(antag_candidates)
|
||||
else
|
||||
return // Failed :(
|
||||
else
|
||||
return
|
||||
|
||||
if(spawn_antag.can_become_antag(candidate))
|
||||
spawn_antag.attempt_late_spawn(candidate, from_ghosts)
|
||||
|
||||
/datum/game_mode/proc/latespawn(mob/living/carbon/human/character)
|
||||
|
||||
if(emergency_shuttle.departed || !character.mind)
|
||||
return
|
||||
|
||||
var/datum/antagonist/spawn_antag
|
||||
if(prob(antag_prob) && round_autoantag && living_antag_templates.len)
|
||||
spawn_antag = pick(living_antag_templates)
|
||||
if(spawn_antag && spawn_antag.can_become_antag(character.mind))
|
||||
spawn_antag.attempt_late_spawn(character.mind)
|
||||
|
||||
return 0
|
||||
|
||||
/datum/game_mode/proc/check_finished()
|
||||
if(emergency_shuttle.returned() || station_was_nuked)
|
||||
return 1
|
||||
@@ -623,13 +556,10 @@ var/global/list/additional_antag_types = list()
|
||||
|
||||
if(antag_templates && antag_templates.len)
|
||||
for(var/datum/antagonist/antag in antag_templates)
|
||||
if(antag.flags & ANTAG_OVERRIDE_JOB)
|
||||
ghost_antag_templates |= antag
|
||||
else if(antag.flags & ANTAG_RANDSPAWN)
|
||||
living_antag_templates |= antag
|
||||
else
|
||||
antag_templates -= antag
|
||||
world << "<span class='danger'>[antag.role_text_plural] are invalid for additional roundtype antags!</span>"
|
||||
if(antag.flags & (ANTAG_OVERRIDE_JOB|ANTAG_RANDSPAWN))
|
||||
continue
|
||||
antag_templates -= antag
|
||||
world << "<span class='danger'>[antag.role_text_plural] are invalid for additional roundtype antags!</span>"
|
||||
|
||||
newscaster_announcements = pick(newscaster_standard_feeds)
|
||||
|
||||
|
||||
43
code/game/gamemodes/game_mode_latespawn.dm
Normal file
43
code/game/gamemodes/game_mode_latespawn.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates)
|
||||
var/list/usable_templates = list()
|
||||
for(var/datum/antagonist/A in supplied_templates)
|
||||
if(A.can_late_spawn())
|
||||
usable_templates |= A
|
||||
return usable_templates
|
||||
|
||||
///process()
|
||||
///Called by the gameticker
|
||||
/datum/game_mode/proc/process()
|
||||
try_latespawn()
|
||||
|
||||
/datum/game_mode/proc/latespawn(var/mob/living/carbon/human/character)
|
||||
if(!character.mind)
|
||||
return
|
||||
try_latespawn(character.mind)
|
||||
return 0
|
||||
|
||||
/datum/game_mode/proc/try_latespawn(var/datum/mind/player, var/latejoin_only)
|
||||
|
||||
if(emergency_shuttle.departed || !round_autoantag)
|
||||
return
|
||||
|
||||
if(!prob(get_antag_prob()))
|
||||
return
|
||||
|
||||
var/list/usable_templates
|
||||
if(latejoin_only && latejoin_templates.len)
|
||||
usable_templates = get_usable_templates(latejoin_templates)
|
||||
else if (antag_templates.len)
|
||||
usable_templates = get_usable_templates(antag_templates)
|
||||
else
|
||||
return
|
||||
if(usable_templates.len)
|
||||
var/datum/antagonist/spawn_antag = pick(usable_templates)
|
||||
spawn_antag.attempt_late_spawn(player)
|
||||
|
||||
/datum/game_mode/proc/get_antag_prob()
|
||||
var/player_count = 0
|
||||
for(var/mob/living/M in mob_list)
|
||||
if(M.client)
|
||||
player_count += 1
|
||||
return min(100,max(0,(player_count - 5 * 10) * 5))
|
||||
@@ -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
|
||||
|
||||
@@ -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 << "<span class='warning'>You cannot join the response team at this time.</span>"
|
||||
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 << "<font color=red><b>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
|
||||
|
||||
@@ -1164,7 +1164,7 @@ proc/admin_notice(var/message, var/rights)
|
||||
out += "<b>Core antag id:</b> <a href='?src=\ref[ticker.mode];debug_antag=[ticker.mode.antag_tag]'>[ticker.mode.antag_tag]</a>.</br>"
|
||||
|
||||
if(ticker.mode.round_autoantag)
|
||||
out += "<b>Autotraitor <a href='?src=\ref[ticker.mode];toggle=autotraitor'>enabled</a></b> ([ticker.mode.antag_prob]% spawn chance)"
|
||||
out += "<b>Autotraitor <a href='?src=\ref[ticker.mode];toggle=autotraitor'>enabled</a></b> ([ticker.mode.get_antag_prob()]% spawn chance)"
|
||||
if(ticker.mode.antag_scaling_coeff)
|
||||
out += " (scaling with <a href='?src=\ref[ticker.mode];set=antag_scaling'>[ticker.mode.antag_scaling_coeff]</a>)"
|
||||
out += "<br/>"
|
||||
|
||||
@@ -410,43 +410,11 @@
|
||||
dat += "Launching now..."
|
||||
|
||||
dat += "<a href='?src=\ref[src];delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
|
||||
|
||||
//todo
|
||||
|
||||
dat += "<hr>"
|
||||
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 += "</body></html>"
|
||||
usr << browse(dat, "window=roundstatus;size=400x500")
|
||||
else
|
||||
alert("The game hasn't started yet!")
|
||||
|
||||
/proc/check_role_table(name, list/members, admins, show_objectives=1)
|
||||
var/txt = "<br><table cellspacing=5><tr><td><b>[name]</b></td><td></td></tr>"
|
||||
for(var/datum/mind/M in members)
|
||||
txt += check_role_table_row(M.current, admins, show_objectives)
|
||||
txt += "</table>"
|
||||
return txt
|
||||
|
||||
/proc/check_role_table_row(mob/M, admins=src, show_objectives)
|
||||
if (!istype(M))
|
||||
return "<tr><td><i>Not found!</i></td></tr>"
|
||||
|
||||
var/txt = {"
|
||||
<tr>
|
||||
<td>
|
||||
<a href='?src=\ref[admins];adminplayeropts=\ref[M]'>[M.real_name]</a>
|
||||
[M.client ? "" : " <i>(logged out)</i>"]
|
||||
[M.is_dead() ? " <b><font color='red'>(DEAD)</font></b>" : ""]
|
||||
</td>
|
||||
<td>
|
||||
<a href='?src=\ref[usr];priv_msg=\ref[M]'>PM</a>
|
||||
</td>
|
||||
"}
|
||||
|
||||
if (show_objectives)
|
||||
txt += {"
|
||||
<td>
|
||||
<a href='?src=\ref[admins];traitor=\ref[M]'>Show Objective</a>
|
||||
</td>
|
||||
"}
|
||||
|
||||
txt += "</tr>"
|
||||
return txt
|
||||
|
||||
@@ -1734,13 +1734,13 @@
|
||||
feedback_add_details("admin_secrets_fun_used","Aliens")
|
||||
log_admin("[key_name(usr)] spawned an alien infestation", 1)
|
||||
message_admins("\blue [key_name_admin(usr)] attempted an alien infestation", 1)
|
||||
xenomorphs.random_spawn()
|
||||
xenomorphs.attempt_random_spawn()
|
||||
if("borers")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","Borers")
|
||||
log_admin("[key_name(usr)] spawned a cortical borer infestation.", 1)
|
||||
message_admins("\blue [key_name_admin(usr)] spawned a cortical borer infestation.", 1)
|
||||
borers.random_spawn()
|
||||
borers.attempt_random_spawn()
|
||||
|
||||
if("power")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
@@ -2046,7 +2046,7 @@
|
||||
if("aliens")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","AL")
|
||||
if(xenomorphs.random_spawn())
|
||||
if(xenomorphs.attempt_random_spawn())
|
||||
message_admins("[key_name_admin(usr)] has spawned aliens", 1)
|
||||
if("spiders")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
@@ -2644,4 +2644,4 @@ mob/living/carbon/human/can_centcom_reply()
|
||||
return istype(l_ear, /obj/item/device/radio/headset) || istype(r_ear, /obj/item/device/radio/headset)
|
||||
|
||||
mob/living/silicon/ai/can_centcom_reply()
|
||||
return common_radio != null && !check_unable(2)
|
||||
return common_radio != null && !check_unable(2)
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
valid_types |= antag
|
||||
if(valid_types.len)
|
||||
var/datum/antagonist/antag = pick(valid_types)
|
||||
antag.random_spawn()
|
||||
antag.attempt_random_spawn()
|
||||
|
||||
@@ -257,12 +257,13 @@
|
||||
lawupdate = 0
|
||||
src << "<b>Systems rebooted</b>. Loading base pattern maintenance protocol... <b>loaded</b>."
|
||||
full_law_reset()
|
||||
src << "<br><b>You are a maintenance drone, a tiny-brained robotic repair machine</b>."
|
||||
welcome_drone()
|
||||
|
||||
/mob/living/silicon/robot/drone/proc/welcome_drone()
|
||||
src << "<b>You are a maintenance drone, a tiny-brained robotic repair machine</b>."
|
||||
src << "You have no individual will, no personality, and no drives or urges other than your laws."
|
||||
src << "Use <b>:d</b> to talk to other drones and <b>say</b> to speak silently to your nearby fellows."
|
||||
src << "Remember, you are <b>lawed against interference with the crew</b>. Also remember, <b>you DO NOT take orders from the AI.</b>"
|
||||
src << "<b>Don't invade their worksites, don't steal their resources, don't tell them about the changeling in the toilets.</b>"
|
||||
src << "<b>If a crewmember has noticed you, <i>you are probably breaking your third law</i></b>."
|
||||
src << "Use <b>:d</b> to talk to other drones and <b>say</b> to speak silently to your nearby fellows."
|
||||
|
||||
/mob/living/silicon/robot/drone/start_pulling(var/atom/movable/AM)
|
||||
|
||||
@@ -293,6 +294,12 @@
|
||||
can_pull_size = 5
|
||||
can_pull_mobs = 1
|
||||
|
||||
/mob/living/silicon/robot/drone/construction/welcome_drone()
|
||||
src << "<b>You are a construction drone, an autonomous engineering and fabrication system.</b>."
|
||||
src << "You are assigned to a Sol Central construction project. The name is irrelevant. Your task is to complete construction and subsystem integration as soon as possible."
|
||||
src << "Use <b>:d</b> to talk to other drones and <b>say</b> to speak silently to your nearby fellows."
|
||||
src << "<b>You do not follow orders from anyone; not the AI, not humans, and not other synthetics.</b>."
|
||||
|
||||
/mob/living/silicon/robot/drone/construction/init()
|
||||
..()
|
||||
flavor_text = "It's a bulky construction drone stamped with a Sol Central glyph."
|
||||
|
||||
@@ -815,18 +815,6 @@ var/list/be_special_flags = list(
|
||||
#define APPEARANCE_ALL_HAIR (APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR)
|
||||
#define APPEARANCE_ALL 511
|
||||
|
||||
// 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.
|
||||
// Mode/antag template macros.
|
||||
#define MODE_BORER "borer"
|
||||
#define MODE_XENOMORPH "xeno"
|
||||
|
||||
Reference in New Issue
Block a user