mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-30 15:37:36 +01:00
Refactors objectives, expands team functionality, and custom teams (#22374)
* step 1 * renaming 1 * how could I forget this * renaming 2 * renaming 3 * add matching proc, even if unused can remove later * rename team obj to match * oops * okay more stuff * okay more stuff * fix this stuff * okay more stuff * needs_target = FALSE * OKAY MORE STUFF * OOPS AGAIN. * self-review * more round_end stuff * stuff 119 * yeah fix that too * EVEN MORE CHANGES * grammar * fix * s34n review * fixes custom teams with no antags not showing objs * makes objectives work properly with teams * a
This commit is contained in:
@@ -1618,6 +1618,14 @@
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/datum/team/team
|
||||
if(href_list["team_command"] == "new_custom_team") // this needs to be handled before all the other stuff, as the team doesn't exist yet
|
||||
message_admins("[key_name_admin(usr)] created a new custom team.")
|
||||
log_admin("[key_name(usr)] created a new custom team.")
|
||||
team = new()
|
||||
team.admin_rename_team(usr)
|
||||
check_teams()
|
||||
return
|
||||
|
||||
var/datum/mind/member
|
||||
if(href_list["team"])
|
||||
team = locateUID(href_list["team"])
|
||||
@@ -1646,6 +1654,8 @@
|
||||
show_player_panel(member.current)
|
||||
if("add_objective")
|
||||
team.admin_add_objective(usr)
|
||||
if("announce_objectives")
|
||||
team.admin_announce_objectives(usr)
|
||||
if("remove_objective")
|
||||
var/datum/objective/O = locateUID(href_list["objective"])
|
||||
if(O)
|
||||
@@ -2143,11 +2153,12 @@
|
||||
possible_traitors -= player
|
||||
if(possible_traitors.len)
|
||||
var/datum/mind/newtraitormind = pick(possible_traitors)
|
||||
|
||||
var/datum/objective/assassinate/kill_objective = new()
|
||||
kill_objective.target = H.mind
|
||||
kill_objective.owner = newtraitormind
|
||||
kill_objective.explanation_text = "Assassinate [H.mind.name], the [H.mind.assigned_role]"
|
||||
newtraitormind.objectives += kill_objective
|
||||
newtraitormind.add_mind_objective(kill_objective)
|
||||
|
||||
var/datum/antagonist/traitor/T = new()
|
||||
T.give_objectives = FALSE
|
||||
to_chat(newtraitormind.current, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
|
||||
@@ -3467,16 +3478,14 @@
|
||||
D.implant(hunter_mob)
|
||||
if(killthem)
|
||||
var/datum/objective/assassinate/kill_objective = new
|
||||
kill_objective.owner = hunter_mind
|
||||
kill_objective.target = H.mind
|
||||
kill_objective.explanation_text = "Kill [H.real_name], the [H.mind.assigned_role]."
|
||||
hunter_mind.objectives += kill_objective
|
||||
hunter_mind.add_mind_objective(kill_objective)
|
||||
else
|
||||
var/datum/objective/protect/protect_objective = new
|
||||
protect_objective.owner = hunter_mind
|
||||
protect_objective.target = H.mind
|
||||
protect_objective.explanation_text = "Protect [H.real_name], the [H.mind.assigned_role]."
|
||||
hunter_mind.objectives += protect_objective
|
||||
hunter_mind.add_mind_objective(protect_objective)
|
||||
SSticker.mode.traitors |= hunter_mob.mind
|
||||
to_chat(hunter_mob, "<span class='danger'>ATTENTION:</span> You are now on a mission!")
|
||||
to_chat(hunter_mob, "<b>Goal: <span class='danger'>[killthem ? "MURDER" : "PROTECT"] [H.real_name]</span>, currently in [get_area(H.loc)].</b>");
|
||||
|
||||
@@ -18,15 +18,10 @@
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = SPECIAL_ROLE_TRAITOR
|
||||
|
||||
var/datum/objective/hijack/hijack_objective = new
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
H.mind.add_mind_objective(/datum/objective/hijack)
|
||||
|
||||
to_chat(H, "<B>You are a Highlander. Kill all other Highlanders. There can be only one.</B>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
H.mind.announce_objectives(title = FALSE)
|
||||
|
||||
for(var/obj/item/I in H)
|
||||
if(istype(I, /obj/item/implant))
|
||||
@@ -75,15 +70,10 @@
|
||||
SSticker.mode.traitors += H.mind
|
||||
H.mind.special_role = "[H.real_name] Prime"
|
||||
|
||||
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
|
||||
hijack_objective.owner = H.mind
|
||||
H.mind.objectives += hijack_objective
|
||||
H.mind.add_mind_objective(/datum/objective/hijackclone)
|
||||
|
||||
to_chat(H, "<B>You are the multiverse summoner. Activate your blade to summon copies of yourself from another universe to fight by your side.</B>")
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
to_chat(H, "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]")
|
||||
obj_count++
|
||||
H.mind.announce_objectives(title = FALSE)
|
||||
|
||||
var/obj/item/slot_item_ID = H.get_item_by_slot(slot_wear_id)
|
||||
qdel(slot_item_ID)
|
||||
|
||||
@@ -18,9 +18,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/// Should we replace the role-banned player with a ghost?
|
||||
var/replace_banned = TRUE
|
||||
/// List of objectives connected to this datum.
|
||||
var/list/objectives
|
||||
/// A list of strings which contain [targets][/datum/objective/var/target] of the antagonist's objectives. Used to prevent duplicate objectives.
|
||||
var/list/assigned_targets
|
||||
var/datum/objective_holder/objective_holder
|
||||
/// Antagonist datum specific information that appears in the player's notes. Information stored here will be removed when the datum is removed from the player.
|
||||
var/antag_memory
|
||||
/// The special role that will be applied to the owner's `special_role` var. i.e. `SPECIAL_ROLE_TRAITOR`, `SPECIAL_ROLE_VAMPIRE`.
|
||||
@@ -40,14 +38,10 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
/datum/antagonist/New()
|
||||
GLOB.antagonists += src
|
||||
objectives = list()
|
||||
assigned_targets = list()
|
||||
objective_holder = new(src)
|
||||
|
||||
/datum/antagonist/Destroy(force, ...)
|
||||
for(var/datum/objective/O as anything in objectives)
|
||||
objectives -= O
|
||||
if(!O.team)
|
||||
qdel(O)
|
||||
qdel(objective_holder)
|
||||
remove_owner_from_gamemode()
|
||||
GLOB.antagonists -= src
|
||||
if(!silent)
|
||||
@@ -211,62 +205,44 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
* * explanation_text - the explanation text that will be passed into the objective's `New()` proc
|
||||
* * mob/target_override - a target for the objective
|
||||
*/
|
||||
/datum/antagonist/proc/add_objective(objective_type, explanation_text = "", mob/target_override = null)
|
||||
var/datum/objective/O = new objective_type(explanation_text)
|
||||
/datum/antagonist/proc/add_antag_objective(datum/objective/O, explanation_text, mob/target_override)
|
||||
if(ispath(O))
|
||||
O = new O()
|
||||
if(O.owner)
|
||||
stack_trace("[O], [O.type] was assigned as an objective to [owner] (mind), but already had an owner: [O.owner] (mind). Overriding.")
|
||||
O.owner = owner
|
||||
|
||||
if(!O.needs_target)
|
||||
objectives += O
|
||||
return O
|
||||
|
||||
var/found_valid_target = FALSE
|
||||
|
||||
if(target_override)
|
||||
O.target = target_override
|
||||
found_valid_target = TRUE
|
||||
else
|
||||
var/loops = 5
|
||||
// Steal objectives need snowflake handling here unfortunately.
|
||||
if(istype(O, /datum/objective/steal))
|
||||
var/datum/objective/steal/S = O
|
||||
while(loops--)
|
||||
S.find_target()
|
||||
if(S.steal_target && !("[S.steal_target.name]" in assigned_targets))
|
||||
found_valid_target = TRUE
|
||||
break
|
||||
else
|
||||
while(loops--)
|
||||
O.find_target()
|
||||
if(O.target && !("[O.target]" in assigned_targets))
|
||||
found_valid_target = TRUE
|
||||
break
|
||||
|
||||
if(found_valid_target)
|
||||
// This is its own seperate section in case someone passes a `target_override`.
|
||||
if(istype(O, /datum/objective/steal))
|
||||
var/datum/objective/steal/S = O
|
||||
assigned_targets |= "[S.steal_target.name]"
|
||||
else
|
||||
assigned_targets |= "[O.target]"
|
||||
else
|
||||
O.explanation_text = "Free Objective"
|
||||
O.target = null
|
||||
|
||||
objectives += O
|
||||
return O
|
||||
return objective_holder.add_objective(O, explanation_text, target_override)
|
||||
|
||||
/**
|
||||
* Announces all objectives of this datum, and only this datum.
|
||||
* Complement to add_antag_objective that removes the objective.
|
||||
* Currently unused.
|
||||
*/
|
||||
/datum/antagonist/proc/announce_objectives()
|
||||
if(!length(objectives))
|
||||
return FALSE
|
||||
to_chat(owner.current, "<span class='notice'>Your current objectives:</span>")
|
||||
var/objective_num = 1
|
||||
for(var/objective in objectives)
|
||||
var/datum/objective/O = objective
|
||||
to_chat(owner.current, "<span><B>Objective #[objective_num++]</B>: [O.explanation_text]</span><br>")
|
||||
return TRUE
|
||||
/datum/antagonist/proc/remove_antag_objective(datum/objective/O)
|
||||
return objective_holder.remove_objective(O)
|
||||
|
||||
/**
|
||||
* Do we have any objectives at all, including from a team.
|
||||
* Faster than get_antag_objectives()
|
||||
*/
|
||||
/datum/antagonist/proc/has_antag_objectives(include_team = TRUE)
|
||||
. = FALSE
|
||||
if(include_team)
|
||||
var/datum/team/team = get_team()
|
||||
if(istype(team))
|
||||
. |= team.objective_holder.has_objectives()
|
||||
. |= objective_holder.has_objectives()
|
||||
|
||||
/**
|
||||
* Get all of this antagonist's objectives, including from the team.
|
||||
*/
|
||||
/datum/antagonist/proc/get_antag_objectives(include_team = TRUE)
|
||||
. = list()
|
||||
if(include_team)
|
||||
var/datum/team/team = get_team()
|
||||
if(istype(team))
|
||||
. |= team.objective_holder.get_objectives()
|
||||
. |= objective_holder.get_objectives()
|
||||
|
||||
/**
|
||||
* Proc called when the datum is given to a mind.
|
||||
@@ -278,7 +254,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
give_objectives()
|
||||
if(!silent)
|
||||
greet()
|
||||
announce_objectives()
|
||||
owner.announce_objectives()
|
||||
apply_innate_effects()
|
||||
finalize_antag()
|
||||
if(wiki_page_name)
|
||||
@@ -372,14 +348,14 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
report += printplayer(owner)
|
||||
|
||||
var/objectives_complete = TRUE
|
||||
if(owner.objectives.len)
|
||||
if(objective_holder.has_objectives())
|
||||
report += printobjectives(owner)
|
||||
for(var/datum/objective/objective in owner.objectives)
|
||||
for(var/datum/objective/objective in objective_holder.get_objectives())
|
||||
if(!objective.check_completion())
|
||||
objectives_complete = FALSE
|
||||
break
|
||||
|
||||
if(owner.objectives.len == 0 || objectives_complete)
|
||||
if(objectives_complete)
|
||||
report += "<span class='greentext big'>The [name] was successful!</span>"
|
||||
else
|
||||
report += "<span class='redtext big'>The [name] has failed!</span>"
|
||||
@@ -397,3 +373,4 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
// Called when the owner is cryo'd, for when you want things to happen on cryo and not deletion
|
||||
/datum/antagonist/proc/on_cryo()
|
||||
return
|
||||
|
||||
|
||||
@@ -223,18 +223,19 @@
|
||||
D.mind.assigned_role = D.name
|
||||
D.mind.special_role = D.name
|
||||
SSticker.mode.traitors += D.mind
|
||||
|
||||
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
|
||||
KillDaWiz.owner = D.mind
|
||||
KillDaWiz.target = user.mind
|
||||
KillDaWiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to summon you."
|
||||
D.mind.objectives += KillDaWiz
|
||||
D.mind.add_mind_objective(KillDaWiz)
|
||||
|
||||
var/datum/objective/KillDaCrew = new /datum/objective
|
||||
KillDaCrew.owner = D.mind
|
||||
KillDaCrew.explanation_text = "[objective_verb] everyone else while you're at it."
|
||||
KillDaCrew.completed = TRUE
|
||||
D.mind.objectives += KillDaCrew
|
||||
to_chat(D, "<b>Objective #[1]</b>: [KillDaWiz.explanation_text]")
|
||||
to_chat(D, "<b>Objective #[2]</b>: [KillDaCrew.explanation_text]")
|
||||
D.mind.add_mind_objective(KillDaCrew)
|
||||
|
||||
D.mind.announce_objectives(title = FALSE)
|
||||
|
||||
|
||||
/obj/item/antag_spawner/slaughter_demon/laughter
|
||||
name = "vial of tickles"
|
||||
@@ -302,18 +303,19 @@
|
||||
var/mob/living/simple_animal/hostile/morph/wizard/M = new /mob/living/simple_animal/hostile/morph/wizard(pick(GLOB.xeno_spawn))
|
||||
M.key = C.key
|
||||
M.make_morph_antag(FALSE)
|
||||
|
||||
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
|
||||
KillDaWiz.owner = M.mind
|
||||
KillDaWiz.target = user.mind
|
||||
KillDaWiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to awake you."
|
||||
M.mind.objectives += KillDaWiz
|
||||
M.mind.add_mind_objective(KillDaWiz)
|
||||
|
||||
var/datum/objective/KillDaCrew = new /datum/objective
|
||||
KillDaCrew.owner = M.mind
|
||||
KillDaCrew.explanation_text = "[objective_verb] everyone and everything else while you're at it."
|
||||
KillDaCrew.completed = TRUE
|
||||
M.mind.objectives += KillDaCrew
|
||||
to_chat(M, "<B>Objective #[1]</B>: [KillDaWiz.explanation_text]")
|
||||
to_chat(M, "<B>Objective #[2]</B>: [KillDaCrew.explanation_text]")
|
||||
M.mind.add_mind_objective(KillDaCrew)
|
||||
|
||||
M.mind.announce_objectives(title = FALSE)
|
||||
|
||||
///////////Revenant
|
||||
|
||||
@@ -357,18 +359,18 @@
|
||||
/obj/item/antag_spawner/revenant/spawn_antag(client/C, turf/T, type = "", mob/user)
|
||||
var/mob/living/simple_animal/revenant/M = new /mob/living/simple_animal/revenant(pick(GLOB.xeno_spawn))
|
||||
M.key = C.key
|
||||
|
||||
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
|
||||
KillDaWiz.owner = M.mind
|
||||
KillDaWiz.target = user.mind
|
||||
KillDaWiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to awake you."
|
||||
M.mind.objectives += KillDaWiz
|
||||
M.mind.add_mind_objective(KillDaWiz)
|
||||
|
||||
var/datum/objective/KillDaCrew = new /datum/objective
|
||||
KillDaCrew.owner = M.mind
|
||||
KillDaCrew.explanation_text = "[objective_verb] everyone and everything else while you're at it."
|
||||
KillDaCrew.completed = TRUE
|
||||
M.mind.objectives += KillDaCrew
|
||||
to_chat(M, "<b>Objective #[1]</b>: [KillDaWiz.explanation_text]")
|
||||
to_chat(M, "<b>Objective #[2]</b>: [KillDaCrew.explanation_text]")
|
||||
M.mind.add_mind_objective(KillDaCrew)
|
||||
|
||||
M.mind.announce_objectives(title = FALSE)
|
||||
|
||||
///////////Pulse Demon
|
||||
|
||||
@@ -422,19 +424,16 @@
|
||||
player_mind.transfer_to(demon)
|
||||
player_mind.assigned_role = SPECIAL_ROLE_DEMON
|
||||
player_mind.special_role = SPECIAL_ROLE_DEMON
|
||||
var/i = demon.give_objectives()
|
||||
demon.give_objectives()
|
||||
|
||||
var/datum/objective/assassinate/kill_wiz = new /datum/objective/assassinate
|
||||
kill_wiz.owner = demon.mind
|
||||
kill_wiz.target = user.mind
|
||||
kill_wiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to free you."
|
||||
demon.mind.objectives += kill_wiz
|
||||
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
|
||||
KillDaWiz.target = user.mind
|
||||
KillDaWiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to awake you."
|
||||
demon.mind.add_mind_objective(KillDaWiz)
|
||||
|
||||
var/datum/objective/kill_crew = new /datum/objective
|
||||
kill_crew.owner = demon.mind
|
||||
kill_crew.explanation_text = "[objective_verb] everyone else while you're at it."
|
||||
kill_crew.completed = TRUE
|
||||
demon.mind.objectives += kill_crew
|
||||
var/datum/objective/KillDaCrew = new /datum/objective
|
||||
KillDaCrew.explanation_text = "[objective_verb] everyone and everything else while you're at it."
|
||||
KillDaCrew.completed = TRUE
|
||||
demon.mind.add_mind_objective(KillDaCrew)
|
||||
|
||||
to_chat(demon, "<b>Objective #[i++]</b>: [kill_wiz.explanation_text]")
|
||||
to_chat(demon, "<b>Objective #[i++]</b>: [kill_crew.explanation_text]")
|
||||
demon.mind.announce_objectives(title = FALSE)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
|
||||
#define DEFAULT_TEAM_NAME "Generic Team Name"
|
||||
|
||||
/**
|
||||
* # Antagonist Team
|
||||
*
|
||||
@@ -7,18 +9,20 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
*/
|
||||
/datum/team
|
||||
/// The name of the team.
|
||||
var/name = "Generic Team Name"
|
||||
var/name = DEFAULT_TEAM_NAME
|
||||
/// A list of [minds][/datum/mind] who belong to this team.
|
||||
var/list/members
|
||||
var/list/datum/mind/members
|
||||
/// A list of objectives which all team members share.
|
||||
var/list/objectives
|
||||
var/datum/objective_holder/objective_holder
|
||||
/// Type of antag datum members of this team have. Also given to new members added by admins.
|
||||
var/antag_datum_type
|
||||
/// The name to save objective successes under in the blackboxes. Saves nothing if blank.
|
||||
var/blackbox_save_name
|
||||
|
||||
/datum/team/New(list/starting_members)
|
||||
..()
|
||||
members = list()
|
||||
objectives = list()
|
||||
objective_holder = new(src)
|
||||
if(starting_members && !islist(starting_members))
|
||||
starting_members = list(starting_members)
|
||||
for(var/datum/mind/M as anything in starting_members)
|
||||
@@ -28,7 +32,7 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
/datum/team/Destroy(force = FALSE, ...)
|
||||
for(var/datum/mind/member as anything in members)
|
||||
remove_member(member)
|
||||
QDEL_LIST_CONTENTS(objectives)
|
||||
qdel(objective_holder)
|
||||
members.Cut()
|
||||
GLOB.antagonist_teams -= src
|
||||
return ..()
|
||||
@@ -40,18 +44,21 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
*/
|
||||
/datum/team/proc/add_member(datum/mind/new_member)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
var/datum/antagonist/team_antag = get_antag_datum_from_member(new_member)
|
||||
var/datum/antagonist/antag = get_antag_datum_from_member(new_member) // make sure they have the antag datum
|
||||
members |= new_member
|
||||
team_antag.objectives |= objectives
|
||||
if(!antag) // this team has no antag role, we'll add it directly to their mind team
|
||||
LAZYDISTINCTADD(new_member.teams, src)
|
||||
|
||||
/**
|
||||
* Removes `member` from this team.
|
||||
*/
|
||||
/datum/team/proc/remove_member(datum/mind/member)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
var/datum/antagonist/A = get_antag_datum_from_member(member)
|
||||
members -= member
|
||||
A.objectives -= objectives
|
||||
LAZYREMOVE(member.teams, src)
|
||||
var/datum/antagonist/antag = get_antag_datum_from_member(member)
|
||||
if(!QDELETED(antag))
|
||||
qdel(antag)
|
||||
|
||||
/**
|
||||
* Adds a new member to this team from a list of players in the round.
|
||||
@@ -74,22 +81,17 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
/**
|
||||
* Adds a team objective to each member's matching antag datum.
|
||||
*/
|
||||
/datum/team/proc/add_objective_to_team(datum/objective/O)
|
||||
/datum/team/proc/add_team_objective(datum/objective/O, _explanation_text, mob/target_override)
|
||||
if(ispath(O))
|
||||
O = new O()
|
||||
O.team = src
|
||||
for(var/datum/mind/M as anything in members)
|
||||
var/datum/antagonist/A = get_antag_datum_from_member(M)
|
||||
A.objectives |= O
|
||||
objectives |= O
|
||||
RegisterSignal(O, COMSIG_PARENT_QDELETING, PROC_REF(remove_objective_from_team))
|
||||
return objective_holder.add_objective(O, _explanation_text, target_override)
|
||||
|
||||
/**
|
||||
* Remove a team objective from each member's matching antag datum.
|
||||
*/
|
||||
/datum/team/proc/remove_objective_from_team(datum/objective/O)
|
||||
for(var/datum/mind/M as anything in members)
|
||||
var/datum/antagonist/A = get_antag_datum_from_member(M)
|
||||
A.objectives -= O
|
||||
objectives -= O
|
||||
/datum/team/proc/remove_team_objective(datum/objective/O)
|
||||
. = objective_holder.remove_objective(O)
|
||||
if(!QDELETED(O))
|
||||
qdel(O)
|
||||
|
||||
@@ -105,6 +107,58 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
if(antag_datum_type)
|
||||
return member.add_antag_datum(antag_datum_type, src)
|
||||
|
||||
/**
|
||||
* Special overrides for teams for target exclusion from objectives.
|
||||
*/
|
||||
/datum/team/proc/get_target_excludes()
|
||||
return members
|
||||
|
||||
/**
|
||||
* Displays the roundend stats for teams
|
||||
*/
|
||||
/datum/team/proc/on_round_end()
|
||||
if(!length(members))
|
||||
return
|
||||
var/temp_name = name
|
||||
if(temp_name == DEFAULT_TEAM_NAME || !temp_name)
|
||||
temp_name = "This team"
|
||||
else
|
||||
temp_name = "The [name]"
|
||||
|
||||
var/list/to_send = list("<br><b>[temp_name]'s objectives were:</b>")
|
||||
var/obj_count = 1
|
||||
var/team_win = TRUE
|
||||
for(var/datum/objective/objective in objective_holder.get_objectives())
|
||||
|
||||
var/text_to_add = "<b>Objective #[obj_count++]</b>: [objective.explanation_text] "
|
||||
var/failed = "FAIL"
|
||||
if(objective.check_completion())
|
||||
text_to_add += "<font color='green'><b>Success!</b></font>"
|
||||
failed = "SUCCESS"
|
||||
else
|
||||
text_to_add += "<font color='red'>Fail.</font>"
|
||||
team_win = FALSE
|
||||
to_send += text_to_add
|
||||
|
||||
// handle blackbox stuff
|
||||
if(initial(blackbox_save_name)) // no im not letting admins var edit shit to the blackbox
|
||||
if(istype(objective, /datum/objective/steal))
|
||||
var/datum/objective/steal/S = objective
|
||||
SSblackbox.record_feedback("nested tally", "[initial(blackbox_save_name)]_team_steal_objective", 1, list("Steal [S.steal_target]", failed))
|
||||
else
|
||||
SSblackbox.record_feedback("nested tally", "[initial(blackbox_save_name)]_team_objective", 1, list("[objective.type]", failed))
|
||||
|
||||
if(team_win)
|
||||
to_send += "<font color='green'><B>[temp_name] were successful!</B></font><br/>"
|
||||
if(initial(blackbox_save_name)) // no im not letting admins var edit shit to the blackbox
|
||||
SSblackbox.record_feedback("tally", "[initial(blackbox_save_name)]_team_success", 1, "SUCCESS")
|
||||
else
|
||||
to_send += "<font color='red'><B>[temp_name] failed!</B></font><br/>"
|
||||
if(initial(blackbox_save_name)) // no im not letting admins var edit shit to the blackbox
|
||||
SSblackbox.record_feedback("tally", "[initial(blackbox_save_name)]_team_success", 1, "FAIL")
|
||||
|
||||
to_chat(world, to_send.Join("<br>"))
|
||||
|
||||
/**
|
||||
* Allows admins to send a message to all members of this team.
|
||||
*/
|
||||
@@ -130,22 +184,34 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
var/objective_type = GLOB.admin_objective_list[selected]
|
||||
var/datum/objective/O = new objective_type(team_to_join = src)
|
||||
O.find_target(get_target_excludes()) // Blacklist any team members from being the target.
|
||||
add_objective_to_team(O)
|
||||
add_team_objective(O)
|
||||
|
||||
message_admins("[key_name_admin(user)] added objective [O.type] to the team '[name]'.")
|
||||
log_admin("[key_name(user)] added objective [O.type] to the team '[name]'.")
|
||||
|
||||
/**
|
||||
* Special overrides for teams for target exclusion from objectives.
|
||||
* Allows admins to announce objectives to all team members.
|
||||
*/
|
||||
/datum/team/proc/get_target_excludes()
|
||||
return members
|
||||
/datum/team/proc/admin_announce_objectives(mob/user)
|
||||
// This button is right next to the
|
||||
if(alert(user, "Are you sure you want to announce objectives to all members?", "Are you sure?", "Yes", "No") == "No")
|
||||
return
|
||||
|
||||
|
||||
log_admin("[key_name(usr)] has announced team [src]'s objectives")
|
||||
message_admins("[key_name_admin(usr)] has announced team [src]'s objectives")
|
||||
|
||||
for(var/datum/mind/member in members)
|
||||
if(!member.current || !isliving(member.current))
|
||||
return
|
||||
member.announce_objectives()
|
||||
SEND_SOUND(member.current, sound('sound/ambience/alarm4.ogg'))
|
||||
|
||||
/**
|
||||
* Allows admins to remove a team objective.
|
||||
*/
|
||||
/datum/team/proc/admin_remove_objective(mob/user, datum/objective/O)
|
||||
remove_objective_from_team(O)
|
||||
remove_team_objective(O)
|
||||
message_admins("[key_name_admin(user)] removed objective [O.type] from the team '[name]'.")
|
||||
log_admin("[key_name(user)] removed objective [O.type] from the team '[name]'.")
|
||||
|
||||
@@ -205,8 +271,9 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
/datum/admins/proc/list_teams()
|
||||
var/list/content = list()
|
||||
if(!length(GLOB.antagonist_teams))
|
||||
content += "There are currently no antag teams."
|
||||
for(var/datum/team/T as anything in GLOB.antagonist_teams)
|
||||
content += "There are currently no antag teams.<br/>"
|
||||
content += "<a href='?_src_=holder;team_command=new_custom_team;'>Create new Team</a>"
|
||||
for(var/datum/team/T as anything in GLOB.antagonist_teams) // with multiple teams, this is going to get messy. It should probably be turned into a tabs-like system
|
||||
content += "<h3>[T.name] - [T.type]</h3>"
|
||||
content += "<a href='?_src_=holder;team_command=rename_team;team=[T.UID()]'>Rename Team</a>"
|
||||
content += "<a href='?_src_=holder;team_command=delete_team;team=[T.UID()]'>Delete Team</a>"
|
||||
@@ -216,9 +283,11 @@ GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
// _src_ is T.UID() so it points to `/datum/team/Topic` instead of `/datum/admins/Topic`.
|
||||
content += "<a href='?_src_=[T.UID()];command=[command]'>[command]</a>"
|
||||
content += "<br><br>Objectives:<br><ol>"
|
||||
for(var/datum/objective/O as anything in T.objectives)
|
||||
for(var/datum/objective/O as anything in T.objective_holder.get_objectives())
|
||||
content += "<li>[O.explanation_text] - <a href='?_src_=holder;team_command=remove_objective;team=[T.UID()];objective=[O.UID()]'>Remove</a></li>"
|
||||
content += "</ol><a href='?_src_=holder;team_command=add_objective;team=[T.UID()]'>Add Objective</a><br><br>"
|
||||
content += "</ol><a href='?_src_=holder;team_command=add_objective;team=[T.UID()]'>Add Objective</a><br>"
|
||||
if(T.objective_holder.has_objectives())
|
||||
content += "</ol><a href='?_src_=holder;team_command=announce_objectives;team=[T.UID()]'>Announce Objectives to All Members</a><br><br>"
|
||||
content += "Members: <br><ol>"
|
||||
for(var/datum/mind/M as anything in T.members)
|
||||
content += "<li>[M.name] - <a href='?_src_=holder;team_command=view_member;team=[T.UID()];member=[M.UID()]'>Show Player Panel</a>"
|
||||
|
||||
@@ -149,33 +149,29 @@
|
||||
* If they have two objectives as well as absorb, they must survive rather than escape.
|
||||
*/
|
||||
/datum/antagonist/changeling/give_objectives()
|
||||
var/datum/objective/absorb/absorb = new
|
||||
absorb.gen_amount_goal(6, 8)
|
||||
absorb.owner = owner
|
||||
objectives += absorb
|
||||
add_antag_objective(/datum/objective/absorb)
|
||||
|
||||
if(prob(60))
|
||||
add_objective(/datum/objective/steal)
|
||||
add_antag_objective(/datum/objective/steal)
|
||||
else
|
||||
add_objective(/datum/objective/debrain)
|
||||
add_antag_objective(/datum/objective/debrain)
|
||||
|
||||
var/list/active_ais = active_ais()
|
||||
if(length(active_ais) && prob(4)) // Leaving this at a flat chance for now, problems with the num_players() proc due to latejoin antags.
|
||||
add_objective(/datum/objective/destroy)
|
||||
add_antag_objective(/datum/objective/destroy)
|
||||
else
|
||||
var/datum/objective/assassinate/kill_objective = add_objective(/datum/objective/assassinate)
|
||||
var/datum/objective/assassinate/kill_objective = add_antag_objective(/datum/objective/assassinate)
|
||||
var/mob/living/carbon/human/H = kill_objective.target?.current
|
||||
|
||||
if(!(locate(/datum/objective/escape) in owner.get_all_objectives()) && H && !HAS_TRAIT(H, TRAIT_GENELESS))
|
||||
if(!(locate(/datum/objective/escape) in owner.get_all_objectives(include_team = FALSE)) && H && !HAS_TRAIT(H, TRAIT_GENELESS))
|
||||
var/datum/objective/escape/escape_with_identity/identity_theft = new(assassinate = kill_objective)
|
||||
identity_theft.owner = owner
|
||||
objectives += identity_theft
|
||||
add_antag_objective(identity_theft)
|
||||
|
||||
if(!(locate(/datum/objective/escape) in owner.get_all_objectives()))
|
||||
if(!(locate(/datum/objective/escape) in owner.get_all_objectives(include_team = FALSE)))
|
||||
if(prob(70))
|
||||
add_objective(/datum/objective/escape)
|
||||
add_antag_objective(/datum/objective/escape)
|
||||
else
|
||||
add_objective(/datum/objective/escape/escape_with_identity) // If our kill target has no genes, 30% time pick someone else to steal the identity of
|
||||
add_antag_objective(/datum/objective/escape/escape_with_identity) // If our kill target has no genes, 30% time pick someone else to steal the identity of
|
||||
|
||||
/datum/antagonist/changeling/process()
|
||||
if(!owner || !owner.current)
|
||||
@@ -329,7 +325,7 @@
|
||||
* * datum/dna/new_dna - the DNA to store
|
||||
*/
|
||||
/datum/antagonist/changeling/proc/store_dna(datum/dna/new_dna)
|
||||
for(var/datum/objective/escape/escape_with_identity/E in objectives)
|
||||
for(var/datum/objective/escape/escape_with_identity/E in owner.get_all_objectives()) // this should consider all objectives, in case admins reroll it
|
||||
if(E.target_real_name == new_dna.real_name)
|
||||
protected_dna |= new_dna
|
||||
return
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
message_admins("[key_name_admin(user)] added a mutiny objective to the team '[name]', and no target was found, removing.")
|
||||
log_admin("[key_name_admin(user)] added a mutiny objective to the team '[name]', and no target was found, removing.")
|
||||
|
||||
/datum/team/revolution/on_round_end()
|
||||
return // for now... show nothing. Add this in when revs is added to midround/dynamic. Not showing it currently because its dependent on rev gamemode
|
||||
|
||||
/datum/team/revolution/proc/update_team_objectives()
|
||||
var/list/heads = SSticker.mode.get_all_heads() - get_targetted_head_minds()
|
||||
|
||||
@@ -38,18 +41,18 @@
|
||||
var/datum/objective/mutiny/rev_obj = new
|
||||
rev_obj.target = head_mind
|
||||
rev_obj.explanation_text = "Assassinate or exile [head_mind.name], the [head_mind.assigned_role]."
|
||||
add_objective_to_team(rev_obj)
|
||||
add_team_objective(rev_obj)
|
||||
sanitize_objectives()
|
||||
|
||||
/datum/team/revolution/proc/get_targetted_head_minds()
|
||||
. = list()
|
||||
for(var/datum/objective/mutiny/O in objectives)
|
||||
for(var/datum/objective/mutiny/O in objective_holder.get_objectives())
|
||||
. |= O.target
|
||||
|
||||
/datum/team/revolution/proc/sanitize_objectives()
|
||||
for(var/datum/objective/mutiny/O in objectives)
|
||||
for(var/datum/objective/mutiny/O in objective_holder.get_objectives())
|
||||
if(!O.target) // revs shouldnt have free objectives
|
||||
remove_objective_from_team(O)
|
||||
remove_team_objective(O)
|
||||
. = TRUE
|
||||
|
||||
/datum/team/revolution/proc/check_all_victory()
|
||||
@@ -58,7 +61,7 @@
|
||||
check_heads_victory()
|
||||
|
||||
/datum/team/revolution/proc/check_rev_victory()
|
||||
for(var/datum/objective/mutiny/objective in objectives)
|
||||
for(var/datum/objective/mutiny/objective in objective_holder.get_objectives())
|
||||
if(!(objective.check_completion()))
|
||||
return FALSE
|
||||
|
||||
@@ -139,6 +142,6 @@
|
||||
return FALSE
|
||||
if(!ishuman(rev_mind.current))
|
||||
return FALSE
|
||||
if(rev_mind.current.incapacitated() || HAS_TRAIT(rev_mind.current, TRAIT_HANDS_BLOCKED))
|
||||
if(rev_mind.current.incapacitated() || HAS_TRAIT(rev_mind.current, TRAIT_HANDS_BLOCKED)) // todo for someone else, make sure the rev heads on ON STATION
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/greet_message = ""
|
||||
|
||||
/datum/antagonist/survivalist/give_objectives()
|
||||
add_objective(/datum/objective/survive)
|
||||
add_antag_objective(/datum/objective/survive)
|
||||
|
||||
/datum/antagonist/survivalist/greet()
|
||||
..()
|
||||
@@ -14,7 +14,7 @@
|
||||
greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way."
|
||||
|
||||
/datum/antagonist/survivalist/guns/give_objectives()
|
||||
add_objective(/datum/objective/steal_five_of_type/summon_guns)
|
||||
add_antag_objective(/datum/objective/steal_five_of_type/summon_guns)
|
||||
..()
|
||||
|
||||
/datum/antagonist/survivalist/magic
|
||||
@@ -22,5 +22,5 @@
|
||||
greet_message = "Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way. As a wonderful magician, you should remember that spellbooks don't mean anything if they are used up."
|
||||
|
||||
/datum/antagonist/survivalist/magic/give_objectives()
|
||||
add_objective(/datum/objective/steal_five_of_type/summon_magic)
|
||||
add_antag_objective(/datum/objective/steal_five_of_type/summon_magic)
|
||||
..()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
/datum/antagonist/mindslave/give_objectives()
|
||||
var/explanation_text = "Obey every order from and protect [master.current.real_name], the [master.assigned_role ? master.assigned_role : master.special_role]."
|
||||
add_objective(/datum/objective/protect/mindslave, explanation_text, master)
|
||||
add_antag_objective(/datum/objective/protect/mindslave, explanation_text, master)
|
||||
|
||||
/datum/antagonist/mindslave/greet()
|
||||
var/mob/living/carbon/human/mindslave = owner.current
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
/datum/antagonist/traitor/proc/forge_human_objectives()
|
||||
// Hijack objective.
|
||||
if(prob(10) && !(locate(/datum/objective/hijack) in owner.get_all_objectives()))
|
||||
add_objective(/datum/objective/hijack)
|
||||
add_antag_objective(/datum/objective/hijack)
|
||||
return // Hijack should be their only objective (normally), so return.
|
||||
|
||||
// Will give normal steal/kill/etc. type objectives.
|
||||
@@ -109,15 +109,15 @@
|
||||
|
||||
// Give them an escape objective if they don't have one already.
|
||||
if(!(locate(/datum/objective/escape) in owner.get_all_objectives()) && (!can_succeed_if_dead || prob(80)))
|
||||
add_objective(/datum/objective/escape)
|
||||
add_antag_objective(/datum/objective/escape)
|
||||
|
||||
/**
|
||||
* Create and assign a full set of AI traitor objectives.
|
||||
*/
|
||||
/datum/antagonist/traitor/proc/forge_ai_objectives()
|
||||
add_objective(/datum/objective/block)
|
||||
add_objective(/datum/objective/assassinate)
|
||||
add_objective(/datum/objective/survive)
|
||||
add_antag_objective(/datum/objective/block)
|
||||
add_antag_objective(/datum/objective/assassinate)
|
||||
add_antag_objective(/datum/objective/survive)
|
||||
|
||||
/**
|
||||
* Create and assign a single randomized human traitor objective.
|
||||
@@ -125,15 +125,15 @@
|
||||
/datum/antagonist/traitor/proc/forge_single_human_objective()
|
||||
if(prob(50))
|
||||
if(length(active_ais()) && prob(100 / length(GLOB.player_list)))
|
||||
add_objective(/datum/objective/destroy)
|
||||
add_antag_objective(/datum/objective/destroy)
|
||||
else if(prob(5))
|
||||
add_objective(/datum/objective/debrain)
|
||||
add_antag_objective(/datum/objective/debrain)
|
||||
else if(prob(30))
|
||||
add_objective(/datum/objective/maroon)
|
||||
add_antag_objective(/datum/objective/maroon)
|
||||
else
|
||||
add_objective(/datum/objective/assassinate)
|
||||
add_antag_objective(/datum/objective/assassinate)
|
||||
else
|
||||
add_objective(/datum/objective/steal)
|
||||
add_antag_objective(/datum/objective/steal)
|
||||
|
||||
/**
|
||||
* Give human traitors their uplink, and AI traitors their law 0. Play the traitor an alert sound.
|
||||
|
||||
@@ -329,14 +329,14 @@
|
||||
check_vampire_upgrade(TRUE)
|
||||
|
||||
/datum/antagonist/vampire/give_objectives()
|
||||
add_objective(/datum/objective/blood)
|
||||
add_objective(/datum/objective/assassinate)
|
||||
add_objective(/datum/objective/steal)
|
||||
add_antag_objective(/datum/objective/blood)
|
||||
add_antag_objective(/datum/objective/assassinate)
|
||||
add_antag_objective(/datum/objective/steal)
|
||||
|
||||
if(prob(20)) // 20% chance of getting survive. 80% chance of getting escape.
|
||||
add_objective(/datum/objective/survive)
|
||||
add_antag_objective(/datum/objective/survive)
|
||||
else
|
||||
add_objective(/datum/objective/escape)
|
||||
add_antag_objective(/datum/objective/escape)
|
||||
|
||||
/datum/antagonist/vampire/greet()
|
||||
var/dat
|
||||
|
||||
@@ -340,11 +340,12 @@
|
||||
if(T && T.implanted)
|
||||
qdel(T)
|
||||
visible_message("<span class='warning'>[H] gets an eerie red glow in their eyes!</span>")
|
||||
|
||||
var/datum/objective/protect/protect_objective = new
|
||||
protect_objective.owner = H.mind
|
||||
protect_objective.target = M.mind
|
||||
protect_objective.explanation_text = "Protect [M.real_name]."
|
||||
H.mind.objectives += protect_objective
|
||||
H.mind.add_mind_objective(protect_objective)
|
||||
|
||||
add_attack_logs(M, H, "Vampire-sired")
|
||||
H.mind.make_vampire()
|
||||
H.revive()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
special_role = "Avatar of the Wish Granter"
|
||||
|
||||
/datum/antagonist/wishgranter/give_objectives()
|
||||
add_objective(/datum/objective/hijack)
|
||||
add_antag_objective(/datum/objective/hijack)
|
||||
|
||||
/datum/antagonist/wishgranter/greet()
|
||||
..()
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
var/datum/mind/MM = M.mind
|
||||
if(objectives)
|
||||
for(var/objective in objectives)
|
||||
MM.objectives += new/datum/objective(objective)
|
||||
M.mind.add_mind_objective(new /datum/objective(objective))
|
||||
if(assignedrole)
|
||||
M.mind.assigned_role = assignedrole
|
||||
M.mind.offstation_role = offstation_role
|
||||
|
||||
@@ -58,7 +58,8 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
|
||||
M.ckey = C.ckey // must be before equipOutfit, or that will runtime due to lack of mind
|
||||
M.equipOutfit(/datum/outfit/admin/sol_trader)
|
||||
M.dna.species.after_equip_job(null, M)
|
||||
M.mind.objectives += trader_objectives
|
||||
for(var/datum/objective/O in trader_objectives)
|
||||
M.mind.objective_holder.add_objective(O) // traders dont have a team, so we manually have to add this objective to all of their minds, without setting an owner
|
||||
M.mind.offstation_role = TRUE
|
||||
greet_trader(M)
|
||||
success_spawn = TRUE
|
||||
@@ -71,18 +72,13 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
|
||||
to_chat(M, "<span class='boldnotice'>You are a trader!</span>")
|
||||
to_chat(M, "<span class='notice'>You are currently docked at [get_area(M)].</span>")
|
||||
to_chat(M, "<span class='notice'>You are about to trade with [station_name()].</span>")
|
||||
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(show_objectives), M.mind), 25)
|
||||
addtimer(CALLBACK(M.mind, TYPE_PROC_REF(/datum/mind, announce_objectives)), 2.5 SECONDS)
|
||||
M.create_log(MISC_LOG, "[M] was made into a Sol Trader")
|
||||
|
||||
/datum/event/traders/proc/forge_trader_objectives()
|
||||
var/list/objs = list()
|
||||
|
||||
var/datum/objective/trade/plasma/P = new /datum/objective/trade/plasma
|
||||
P.choose_target()
|
||||
objs += P
|
||||
|
||||
var/datum/objective/trade/credits/C = new /datum/objective/trade/credits
|
||||
C.choose_target()
|
||||
objs += C
|
||||
objs += new /datum/objective/trade/plasma
|
||||
objs += new /datum/objective/trade/credits
|
||||
|
||||
return objs
|
||||
|
||||
@@ -64,9 +64,7 @@
|
||||
message_admins("[key_name_admin(L)] has been marked for death by [key_name_admin(user)].")
|
||||
log_admin("[key_name(L)] has been marked for death by [key_name(user)].")
|
||||
|
||||
var/datum/objective/survive/survive = new
|
||||
survive.owner = L.mind
|
||||
L.mind.objectives += survive
|
||||
L.mind.add_mind_objective(/datum/objective/survive)
|
||||
to_chat(L, "<span class='userdanger'>You've been marked for death! Don't let the demons get you!</span>")
|
||||
L.color = "#FF0000"
|
||||
spawn()
|
||||
|
||||
@@ -21,8 +21,7 @@ GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
|
||||
|
||||
SSjobs.FreeRole(job)
|
||||
|
||||
if(mind.objectives.len)
|
||||
mind.objectives.Cut()
|
||||
if(mind.objective_holder.clear())
|
||||
mind.special_role = null
|
||||
else
|
||||
if(SSticker.mode.name == "AutoTraitor")
|
||||
|
||||
Reference in New Issue
Block a user