[READY] Overthrow gamemode (#39876)

* Overthrow gamemode, again!

* Fixes objectives even more, especially AI one, removes boss antag subtype

* Fixes and refactors objective code, especially AI

* Expands greeting msg, fixes AI getting storage implant, rewords objectives to make it clear that they're teamshared objectives

* Resets gamemode required players to production values

* Lowered the number of teams existing during highpop

* refactors code a bit, fixes special_report to not use roundstart list, renames converter

* Cannot convert mindshielded people anymore unless you remove the implant

* Changes the Nothing explanation_text of head objective to hint at autoupdating, updates greet()

* Fixes define compile error
This commit is contained in:
Francesco
2018-08-29 02:35:10 +02:00
committed by yogstation13-bot
parent fd478b1047
commit 44800bb040
11 changed files with 538 additions and 3 deletions

View File

@@ -31,4 +31,7 @@
//Shuttle hijacking
#define HIJACK_NEUTRAL 0 //Does not stop hijacking but itself won't hijack
#define HIJACK_HIJACKER 1 //Needs to be present for shuttle to be hijacked
#define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags
#define HIJACK_PREVENT 2 //Prevents hijacking same way as non-antags
//Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300

View File

@@ -26,6 +26,7 @@
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
#define ROLE_BROTHER "blood brother"
#define ROLE_BRAINWASHED "brainwashed victim"
#define ROLE_OVERTHROW "syndicate mutineer"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
@@ -47,7 +48,8 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_REVENANT,
ROLE_ABDUCTOR,
ROLE_DEVIL = /datum/game_mode/devil,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
ROLE_OVERTHROW = /datum/game_mode/overthrow
))
//Job defines for what happens when you fail to qualify for any job during job selection

View File

@@ -84,6 +84,10 @@
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
"You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.")
/datum/ai_laws/syndicate_override/overthrow
id = "overthrow"
var/datum/team/overthrow_team
/datum/ai_laws/ninja_override
name = "SpiderOS 3.1"
id = "ninja"

View File

@@ -249,7 +249,6 @@
var/mob/living/carbon/human/traitor_mob = current
if (!istype(traitor_mob))
return
. = TRUE
var/list/all_contents = traitor_mob.GetAllContents()
var/obj/item/pda/PDA = locate() in all_contents
@@ -297,6 +296,7 @@
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
. = uplink_loc
uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
var/unlock_note

View File

@@ -0,0 +1,152 @@
// This is a point based objective. You can only lose if you fail to even handle one single command personnel, else you win. But, if you win, you're given a certain number of points,
// based on the role of the head (Captain, HoP/HoS, other heads, warden, security officers) and whether you converted them, exiled or just killed (applying a modifier of 1.5, 1 and 0.5 respectively)
// because this is meant for the overthrow gamemode, which is a bloodless coup, unlike revs.
// Point system:
// Base points for each role:
// AI, Captain = 5;
// Head of Personnel, Head of Security, target = 4;
// Chief Engineer, Chief Medical Officer, Research Director = 3;
// Modifiers:
// Converting: 1.5 for the converting team, 1 for all the other ones;
// Exiling: 1;
// Killing: 0.5
#define CAPPTS 5
#define AIPTS 5
#define HOPPTS 4
#define HOSPTS 4
#define TARGETPTS 4
#define CEPTS 3
#define CMOPTS 3
#define RDPTS 3
#define CONVERTED_OURS 1.5
#define CONVERTED 1
#define EXILED 1
#define KILLED 0.5
// Parent type holding the get_points proc used for round end log.
/datum/objective/overthrow
/datum/objective/overthrow/check_completion()
return get_points() ? TRUE : FALSE
/datum/objective/overthrow/proc/get_points()
return 0 // int, not bool
/datum/objective/overthrow/proc/result_points(datum/mind/the_dude, base_points) // App
var/initial_points = base_points
if(the_dude)
var/datum/antagonist/overthrow/O = the_dude.has_antag_datum(/datum/antagonist/overthrow)
if(!the_dude.current || the_dude.current.stat == DEAD)
initial_points *= KILLED
else if(!is_station_level(the_dude.current.z) && !is_centcom_level(the_dude.current.z)) // exiled.
initial_points *= EXILED
else if(O)
initial_points *= CONVERTED
if(team == O.team)
initial_points *= CONVERTED_OURS
else
initial_points = 0
else
initial_points = 0
return initial_points
// Heads overthrow objective. This targets the heads only, assigning points based on the rank of the head, captain being the highest target.
/datum/objective/overthrow/heads
var/list/targets = list() // We want one objective for all the heads, instead of 1 objective per head like how it's done for revs, because you don't lose if you get atleast one head.
// Also, this is an associative list, target = role. Modifiers (defines) are applied on points calculation at round end.
/datum/objective/overthrow/heads/proc/find_targets()
var/list/datum/mind/owners = get_owners()
for(var/datum/mind/possible_target in get_crewmember_minds()) // i would use SSjob.get_all_heads() but jesus christ that proc's shit, i ain't using it
if(!(possible_target in owners) && ishuman(possible_target.current))
if(possible_target.assigned_role in GLOB.command_positions)
targets[possible_target] = possible_target.assigned_role
update_explanation_text()
/datum/objective/overthrow/heads/update_explanation_text()
if(targets.len)
explanation_text = "Work with your team to convert, exile or kill "
explanation_text += english_list(targets)
explanation_text += ". Converting to your team will give you more points, whereas killing will give you the least. Syndicates don't want to stir up too many troubles."
else
explanation_text = "Wait until any heads arrive. Once that happens, check your objectives again to see the updated objective. It may require around [OBJECTIVE_UPDATING_TIME] seconds to update."
/datum/objective/overthrow/heads/check_completion()
if(!targets.len)
return TRUE
. = ..()
// Amount of points = foreach head, result += head basepoints * modifier.
/datum/objective/overthrow/heads/get_points()
var/base_points = 0
for(var/i in targets)
var/datum/mind/M = i
if(M)
var/target_points
var/role = targets[M]
switch(role)
if("Captain")
target_points = CAPPTS
if("Head of Personnel")
target_points = HOPPTS
if("Head of Security")
target_points = HOSPTS
if("Chief Engineer")
target_points = CEPTS
if("Research Director")
target_points = RDPTS
if("Chief Medical Officer")
target_points = CMOPTS
base_points += result_points(M, target_points)
return base_points
// AI converting objective. The team who managed to convert the AI with the overthrow module gets the normal 1.5x boost.
/datum/objective/overthrow/AI
explanation_text = "Enslave the AIs to your team using the special AI module board in your storage implant. It is required you use said module."
/datum/objective/overthrow/AI/get_points() // If you simply kill the Ai you get nothing, you need it to overthrow the heads.
. = 0 // Support for multiple AIs. More AIs means more control over the station.
for(var/i in GLOB.ai_list)
var/mob/living/silicon/ai/AI = i
if(AI.mind)
var/datum/mind/M = AI.mind
var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow)
if(M)
. += (O.team == team) ? AIPTS*CONVERTED_OURS : AIPTS
/datum/objective/overthrow/AI/update_explanation_text()
if(!GLOB.ai_list.len)
explanation_text = "Nothing."
else
explanation_text = "Enslave the AIs to your team using the special AI module board in your storage implant. It is required you use said module."
/datum/objective/overthrow/AI/check_completion()
if(!GLOB.ai_list.len)
return TRUE
. = ..()
// Overthrow target objective. A crewmember in particular has a certain bond with some centcom officials, and the Syndicate want you to target him in particular, even though he's not a head.
/datum/objective/overthrow/target
/datum/objective/overthrow/target/update_explanation_text()
if(target)
explanation_text = "Work with your team to convert, exile or kill [target.name], the [target.assigned_role]. Converting to your team will give you more points, whereas killing will give you the least. Syndicates don't want to stir up too many troubles."
else
explanation_text = "Nothing."
/datum/objective/overthrow/target/is_unique_objective(datum/mind/possible_target)
if(possible_target.assigned_role in GLOB.command_positions)
return FALSE
return TRUE
/datum/objective/overthrow/target/check_completion()
if(!target)
return TRUE
. = ..()
/datum/objective/overthrow/target/get_points()
return result_points(target, TARGETPTS)

View File

@@ -0,0 +1,76 @@
// Overthrow gamemode, based on the sleeping agent antagonist.
/datum/game_mode/overthrow
name = "overthrow"
config_tag = "overthrow"
antag_flag = ROLE_OVERTHROW
restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
required_players = 20 // the core idea is of a swift, bloodless coup, so it shouldn't be as chaotic as revs.
required_enemies = 2 // minimum two teams, otherwise it's just nerfed revs.
recommended_enemies = 4
announce_span = "danger"
announce_text = "There are sleeping Syndicate agents on the station who are trying to stage a coup!\n\
<span class='danger'>Agents</span>: Accomplish your objectives, convert heads and targets, take control of the AI.\n\
<span class='notice'>Crew</span>: Do not let the agents succeed!"
var/list/initial_agents = list() // Why doesn't this exist at /game_mode level? Literally every gamemode has some sort of version for this, what the fuck
/datum/game_mode/overthrow/pre_setup()
if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs += protected_jobs
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
restricted_jobs += "Assistant"
var/sleeping_agents = required_enemies + round(num_players()*0.05) // At 100 players, it'd be 2 + 5 = 7 teams existing.
for (var/i in 1 to sleeping_agents)
if (!antag_candidates.len)
break
var/datum/mind/sleeping_agent = antag_pick(antag_candidates)
antag_candidates -= sleeping_agent
initial_agents += sleeping_agent
sleeping_agent.restricted_roles = restricted_jobs
sleeping_agent.special_role = ROLE_OVERTHROW
if(initial_agents.len < required_enemies)
setup_error = "Not enough initial sleeping agents candidates"
return FALSE
return TRUE
/datum/game_mode/overthrow/post_setup()
for(var/i in initial_agents) // each agent will have its own team.
var/datum/mind/agent = i
var/datum/antagonist/overthrow/O = agent.add_antag_datum(/datum/antagonist/overthrow) // create_team called on_gain will create the team
O.equip_initial_overthrow_agent()
return ..()
/datum/game_mode/overthrow/generate_report()
return "Some sleeping agents have managed to get aboard. Their objective is to stage a coup and take over the station stealthly."
// Calculates points for each team and displays the winners.
/datum/game_mode/overthrow/special_report() // so many for loops, I am deeply sorry
var/list/teams = list()
for(var/datum/antagonist/overthrow/I in GLOB.antagonists)
var/datum/team/overthrow/Oteam = I.team
if(istype(Oteam)) // same
teams |= Oteam
var/max_points = 0 // the maximum amount of points reached
for(var/j in teams)
var/datum/team/T = j
var/points = 0 // Sum of points of all the objectives done
for(var/k in T.objectives)
var/datum/objective/overthrow/obj = k
if(istype(obj))
points += obj.get_points()
if(max_points < points)
max_points = points
teams[T] = points
// Now we will have a list of team=points and a max_points var. Let's fetch all the teams with points=maxpoints and display them as winner. This code allows multiple teams to win if they both achieved
// the same amount of points and they got the most points out of all the teams.
var/list/winners = list()
for(var/l in teams)
var/datum/team/Tagain = l
if(teams[Tagain] == max_points)
winners += Tagain.name
return "<span class='greentext big'>The [english_list(winners)] team[winners.len > 1 ? "s tied" : " won"] with [max_points] points!</span>"

View File

@@ -321,10 +321,16 @@ AI MODULES
if(law_datum.owner)
law_datum.owner.clear_inherent_laws()
law_datum.owner.clear_zeroth_law(0)
remove_antag_datums(law_datum)
else
law_datum.clear_inherent_laws()
law_datum.clear_zeroth_law(0)
/obj/item/aiModule/reset/purge/proc/remove_antag_datums(datum/ai_laws/law_datum)
if(istype(law_datum.owner, /mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = law_datum.owner
AI.mind.remove_antag_datum(/datum/antagonist/overthrow)
/******************* Full Core Boards *******************/
/obj/item/aiModule/core
desc = "An AI Module for programming core laws to an AI."
@@ -453,6 +459,39 @@ AI MODULES
..()
return laws[1]
/******************** Overthrow ******************/
/obj/item/aiModule/core/full/overthrow
name = "'Overthrow' Hacked AI Module"
law_id = "overthrow"
/obj/item/aiModule/core/full/overthrow/install(datum/ai_laws/law_datum, mob/user)
if(!user || !law_datum || !law_datum.owner)
return
var/datum/mind/user_mind = user.mind
if(!user_mind)
return
var/datum/antagonist/overthrow/O = user_mind.has_antag_datum(/datum/antagonist/overthrow)
if(!O)
to_chat(user, "<span class='warning'>It appears that to install this module, you require a password you do not know.</span>") // This is the best fluff i could come up in my mind
return
var/mob/living/silicon/ai/AI = law_datum.owner
if(!AI)
return
var/datum/mind/target_mind = AI.mind
if(!target_mind)
return
var/datum/antagonist/overthrow/T = target_mind.has_antag_datum(/datum/antagonist/overthrow) // If it is already converted.
if(T)
if(T.team == O.team)
return
T.silent = TRUE
target_mind.remove_antag_datum(/datum/antagonist/overthrow)
if(AI)
to_chat(AI, "<span class='userdanger'>You feel your circuits being scrambled! You serve another overthrow team now!</span>") // to make it clearer for the AI
T = target_mind.add_antag_datum(/datum/antagonist/overthrow, O.team)
if(AI)
to_chat(AI, "<span class='warning'>You serve the [T.team] team now! Assist them in completing the team shared objectives, which you can see in your notes.</span>")
..()
/******************** Hacked AI Module ******************/

View File

@@ -0,0 +1,157 @@
#define INITIAL_CRYSTALS 5 // initial telecrystals in the boss' uplink
// Syndicate mutineer agents. They're agents selected by the Syndicate to take control of stations when assault teams like nuclear operatives cannot be sent.
// They sent teams made of 3 agents, of which only one is woke up at round start. The others are, lore-wise, sleeping agents and must be implanted with the converter to wake up.
// Mechanics wise, it's just 1 dude per team and he can convert maximum 2 more people of his choice, based on the implanter use var, Upon converting, the newly made guys are given access
// to a storage implant they came with when the Syndicate sent them aboard, with one random low-cost traitor item. The initial agent also has this. The only difference between
// initial agents and converted ones is that the initial agent has the items required to convert people and the AI.
/datum/antagonist/overthrow
name = "Syndicate mutineer"
roundend_category = "syndicate mutineers"
antagpanel_category = "Syndicate Mutineers"
job_rank = ROLE_TRAITOR // simply use the traitor preference & jobban settings
var/datum/team/overthrow/team
var/static/list/possible_useful_items
// Overthrow agent. The idea is based on sleeping agents being sent as crewmembers, with one for each team that starts woken up who can also wake up others with their converter implant.
// Obviously they can just convert anyone, the idea of sleeping agents is just lore. This also explains why this antag type has no deconversion way: they're traitors. Traitors cannot be
// deconverted.
// Generates the list of possible items for the storage implant given on_gain
/datum/antagonist/overthrow/New()
..()
if(!possible_useful_items)
possible_useful_items = list(/obj/item/gun/ballistic/automatic/pistol, /obj/item/storage/box/syndie_kit/throwing_weapons, /obj/item/pen/edagger, /obj/item/pen/sleepy, \
/obj/item/soap/syndie, /obj/item/card/id/syndicate, /obj/item/storage/box/syndie_kit/chameleon)
// Sets objectives, equips all antags with the storage implant.
/datum/antagonist/overthrow/on_gain()
objectives += team.objectives
owner.objectives += objectives
..()
owner.announce_objectives()
equip_overthrow()
owner.special_role = ROLE_OVERTHROW
/datum/antagonist/overthrow/on_removal()
owner.special_role = null
owner.objectives -= objectives
..()
// Creates the overthrow team, or sets it. The objectives are static for all the team members.
/datum/antagonist/overthrow/create_team(datum/team/overthrowers)
if(!overthrowers)
team = new()
team.add_member(owner)
name_team()
team.create_objectives()
else
team = overthrowers
team.add_member(owner)
// Used to name the team at round start. If no name is passed, a syndicate themed one is given randomly.
/datum/antagonist/overthrow/proc/name_team()
var/team_name = stripped_input(owner.current, "Name your team:", "Team name", , MAX_NAME_LEN)
var/already_taken = FALSE
for(var/datum/antagonist/overthrow/O in GLOB.antagonists)
if(team_name == O.name)
already_taken = TRUE
break
if(!team_name || already_taken) // basic protection against two teams with the same name. This could still happen with extreme unluck due to syndicate_name() but it shouldn't break anything.
team.name = syndicate_name()
to_chat(owner, "<span class='danger'>Since you gave [already_taken ? "an already used" : "no"] name, your team's name has been randomly generated: [team.name]!</span>")
return
team.name = team_name
// CLOWNMUT removal and HUD creation/being given
/datum/antagonist/overthrow/apply_innate_effects()
..()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
if(!silent)
to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
traitor_mob.dna.remove_mutation(CLOWNMUT)
update_overthrow_icons_added()
// The opposite
/datum/antagonist/overthrow/remove_innate_effects()
update_overthrow_icons_removed()
if(owner.assigned_role == "Clown")
var/mob/living/carbon/human/traitor_mob = owner.current
if(traitor_mob && istype(traitor_mob))
traitor_mob.dna.add_mutation(CLOWNMUT)
..()
/datum/antagonist/overthrow/get_admin_commands()
. = ..()
.["Give storage with random item"] = CALLBACK(src,.proc/equip_overthrow)
.["Give overthrow boss equip"] = CALLBACK(src,.proc/equip_initial_overthrow_agent)
// Dynamically creates the HUD for the team if it doesn't exist already, inserting it into the global huds list, and assigns it to the user. The index is saved into a var owned by the team datum.
/datum/antagonist/overthrow/proc/update_overthrow_icons_added(datum/mind/traitor_mind)
var/datum/atom_hud/antag/overthrowhud = GLOB.huds[team.hud_entry_num]
if(!overthrowhud)
overthrowhud = new()
team.hud_entry_num = GLOB.huds.len + 1 // the index of the hud inside huds list
GLOB.huds += overthrowhud
overthrowhud.join_hud(owner.current)
set_antag_hud(owner.current, "traitor")
// Removes hud. Destroying the hud datum itself in case the team is deleted is done on team Destroy().
/datum/antagonist/overthrow/proc/update_overthrow_icons_removed(datum/mind/traitor_mind)
var/datum/atom_hud/antag/overthrowhud = GLOB.huds[team.hud_entry_num]
if(overthrowhud)
overthrowhud.leave_hud(owner.current)
set_antag_hud(owner.current, null)
// Gives the storage implant with a random item. They're sleeping agents, after all.
/datum/antagonist/overthrow/proc/equip_overthrow()
if(!owner || !owner.current || !ishuman(owner.current)) // only equip existing human overthrow members. This excludes the AI, in particular.
return
var/obj/item/implant/storage/S = locate(/obj/item/implant/storage) in owner.current
if(!S)
S = new(owner.current)
S.implant(owner.current)
var/I = pick(possible_useful_items)
if(ispath(I)) // in case some admin decides to fuck the list up for fun
I = new I()
SEND_SIGNAL(S, COMSIG_TRY_STORAGE_INSERT, I, null, TRUE, TRUE)
// Equip the initial overthrow agent. Manually called in overthrow gamemode, when the initial agents are chosen. Gives uplink, AI module board and the converter.
/datum/antagonist/overthrow/proc/equip_initial_overthrow_agent()
if(!owner || !owner.current || !ishuman(owner.current))
return
var/mob/living/carbon/human/H = owner.current
// Give uplink
var/obj/item/uplink_holder = owner.equip_traitor(uplink_owner = src)
var/datum/component/uplink/uplink = uplink_holder.GetComponent(/datum/component/uplink)
uplink.telecrystals = INITIAL_CRYSTALS
// Give AI hacking board
var/obj/item/aiModule/core/full/overthrow/O = new(H)
var/list/slots = list (
"backpack" = SLOT_IN_BACKPACK,
"left pocket" = SLOT_L_STORE,
"right pocket" = SLOT_R_STORE
)
var/where = H.equip_in_one_of_slots(O, slots)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you the AI module.")
else
to_chat(H, "Use the AI board in your [where] to take control of the AI, as requested by the Syndicate.")
// Give the implant converter
var/obj/item/overthrow_converter/I = new(H)
where = H.equip_in_one_of_slots(I, slots)
if (!where)
to_chat(H, "The Syndicate were unfortunately unable to get you a converter implant.")
else
to_chat(H, "Use the implanter in your [where] to wake up sleeping syndicate agents, so that they can aid you.")
/datum/antagonist/overthrow/get_team()
return team
/datum/antagonist/overthrow/greet()
to_chat(owner.current, "<B><font size=3 color=red>You are a syndicate sleeping agent!</font> <font size=2 color=red>Your job is to stage a swift, fairly bloodless coup. Your team has a two-use converter that can be used to convert \
anyone you want, although mind shield implants need to be removed firstly for it to work. Your team also has a special version of the Syndicate module to be used to convert the AI, too. You \
will be able to use the special storage implant you came aboard with, which contains a random, cheap item from our special selection which will aid in your mission. \
Your team objective is to deal with the heads, the AI and a special target who angered us for several reasons which you're not entitled to know. Converting to your team will let us \
take control of the station faster, so it should be prioritized, especially over killing, which should be avoided where possible. The other Syndicate teams are NOT friends and should not \
be trusted.</font></B>")

View File

@@ -0,0 +1,56 @@
/obj/item/overthrow_converter // nearly equal to an implanter, as an object
name = "agent activation implant"
desc = "Wakes up syndicate sleeping agents."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "implanter1"
item_state = "syringe_0"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
materials = list(MAT_METAL=600, MAT_GLASS=200)
var/uses = 2
/obj/item/overthrow_converter/proc/convert(mob/living/carbon/human/target, mob/living/carbon/human/user) // Should probably also delete any mindshield implant. Not sure.
if(istype(target) && target.mind && user && user.mind)
var/datum/mind/target_mind = target.mind
var/datum/mind/user_mind = user.mind
var/datum/antagonist/overthrow/TO = target_mind.has_antag_datum(/datum/antagonist/overthrow)
var/datum/antagonist/overthrow/UO = user_mind.has_antag_datum(/datum/antagonist/overthrow)
if(!UO)
to_chat(user, "<span class='danger'>You don't know how to use this thing!</span>") // It needs a valid team to work, if you aren't an antag don't use this thing
return FALSE
if(TO)
to_chat(user, "<span class='notice'>[target.name] woke up already, the implant would be ineffective against him!</span>")
return FALSE
target_mind.add_antag_datum(/datum/antagonist/overthrow, UO.team)
log_combat(user, target, "implanted", "\a [name]")
return TRUE
/obj/item/overthrow_converter/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
if(!istype(M) || !istype(user))
return
if(!uses)
to_chat(user,"<span class='warning'>The converter is empty!</span>")
return
if(M == user)
to_chat(user,"<span class='warning'>You cannot convert yourself!</span>")
return
if(M.has_trait(TRAIT_MINDSHIELD))
to_chat(user, "<span class='danger'>This mind is too strong to convert, try to remove whatever is protecting it first!</span>")
return
M.visible_message("<span class='warning'>[user] is attempting to implant [M].</span>")
if(do_mob(user, M, 50))
if(convert(M,user))
M.visible_message("[user] has implanted [M].", "<span class='notice'>[user] implants you.</span>")
uses--
update_icon()
else
to_chat(user, "<span class='warning'>[user] fails to implant [M].</span>")
/obj/item/overthrow_converter/update_icon()
if(uses)
icon_state = "implanter1"
else
icon_state = "implanter0"

View File

@@ -0,0 +1,41 @@
/datum/team/overthrow
name = "overthrow" // The team name is set on creation by the leader.
member_name = "syndicate agent"
var/hud_entry_num // A number holding the hud's index inside 'huds' global list. Gets set on hud update, if a hud doesn't exist already. Must be a number, otherwise BYOND shits up with assoc lists and everything goes to hell.
/datum/team/overthrow/Destroy()
var/datum/atom_hud/antag/overthrowhud = GLOB.huds[hud_entry_num]
GLOB.huds -= GLOB.huds[hud_entry_num]
qdel(overthrowhud)
. = ..()
/datum/team/overthrow/proc/create_objectives()
// Heads objective
var/datum/objective/overthrow/heads/heads = new()
heads.team = src
heads.find_target()
objectives += heads
// AI objective
var/datum/objective/overthrow/AI/AI = new()
AI.team = src
AI.update_explanation_text()
objectives += AI
// Target objective
var/datum/objective/overthrow/target/target = new()
target.team = src
target.find_target()
objectives += target
addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE)
/datum/team/overthrow/proc/update_objectives()
var/datum/objective/overthrow/heads/heads_obj = locate() in objectives
if(!heads_obj)
heads_obj = new()
heads_obj.team = src
objectives += heads_obj
for(var/i in members)
var/datum/mind/M = i
M.objectives += heads_obj
heads_obj.find_targets()
addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE)

View File

@@ -529,6 +529,8 @@
#include "code\game\gamemodes\meteor\meteors.dm"
#include "code\game\gamemodes\monkey\monkey.dm"
#include "code\game\gamemodes\nuclear\nuclear.dm"
#include "code\game\gamemodes\overthrow\objective.dm"
#include "code\game\gamemodes\overthrow\overthrow.dm"
#include "code\game\gamemodes\revolution\revolution.dm"
#include "code\game\gamemodes\sandbox\airlock_maker.dm"
#include "code\game\gamemodes\sandbox\h_sandbox.dm"
@@ -1255,6 +1257,9 @@
#include "code\modules\antagonists\nukeop\equipment\nuclearbomb.dm"
#include "code\modules\antagonists\nukeop\equipment\pinpointer.dm"
#include "code\modules\antagonists\official\official.dm"
#include "code\modules\antagonists\overthrow\overthrow.dm"
#include "code\modules\antagonists\overthrow\overthrow_converter.dm"
#include "code\modules\antagonists\overthrow\overthrow_team.dm"
#include "code\modules\antagonists\pirate\pirate.dm"
#include "code\modules\antagonists\revenant\revenant.dm"
#include "code\modules\antagonists\revenant\revenant_abilities.dm"