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:
Contrabang
2023-10-01 14:14:10 +01:00
committed by GitHub
parent 4ce0b08f9c
commit 7e0aa47311
42 changed files with 630 additions and 477 deletions
+15 -6
View File
@@ -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>");
+4 -14
View File
@@ -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)
+41 -64
View File
@@ -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)
+98 -29
View File
@@ -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()
..()
+1 -1
View File
@@ -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
+5 -9
View File
@@ -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")