diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 5b93e570222..34ad4d69e54 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -10,7 +10,6 @@ // justice if someone's abusing your role #define ROLE_SYNDICATE "Syndicate" #define ROLE_TRAITOR "traitor" -#define ROLE_MINDSLAVE "mindslave" #define ROLE_OPERATIVE "operative" #define ROLE_CHANGELING "changeling" #define ROLE_WIZARD "wizard" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 19df4c8890c..d03207ef41a 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -132,13 +132,7 @@ var/output = "[current.real_name]'s Memories:
" output += memory - if(objectives.len) // Delete this line when we handle objectives in the antag datum - //var/list/all_objectives = objectives - // for(var/datum/antagonist/A in antag_datums) // Uncomment these 5 lines when antags are datumized and the objectives are handled in the antag datum -SteelSlayer - // output += A.antag_memory - // all_objectives |= A.objectives - - // if(LAZYLEN(all_objectives)) + if(objectives.len) output += "
Objectives:
" output += gen_objective_text() @@ -155,16 +149,9 @@ else to_chat(recipient, "[output]") -/datum/mind/proc/get_all_objectives() - var/list/all_objectives = list() - for(var/datum/antagonist/A in antag_datums) - all_objectives |= A.objectives - return all_objectives - /datum/mind/proc/gen_objective_text(admin = FALSE) . = "" var/obj_count = 1 - //objectives = get_all_objectives() TODO: Move handling of objectives from the mind to /datum/antagonist/objectives, then we can use this function for(var/datum/objective/objective in objectives) . += "Objective #[obj_count]: [objective.explanation_text]" if(admin) @@ -340,20 +327,14 @@ /datum/mind/proc/memory_edit_traitor() . = _memory_edit_header("traitor", list("traitorchan", "traitorvamp")) - if(has_antag_datum(/datum/antagonist/traitor)) + if(src in SSticker.mode.traitors) . += "TRAITOR|no" if(objectives.len==0) - . += "
Objectives are empty! Randomize!" + . += "
Objectives are empty! Randomize!" else . += "traitor|NO" . += _memory_edit_role_enabled(ROLE_TRAITOR) - // Mindslave - . += "
mindslaved: " - if(has_antag_datum(/datum/antagonist/mindslave)) - . += "MINDSLAVE|no" - else - . += "mindslave|NO" /datum/mind/proc/memory_edit_silicon() . = "Silicon: " @@ -371,7 +352,7 @@ /datum/mind/proc/memory_edit_uplink() . = "" if(ishuman(current) && ((src in SSticker.mode.head_revolutionaries) || \ - (has_antag_datum(/datum/antagonist/traitor)) || \ + (src in SSticker.mode.traitors) || \ (src in SSticker.mode.syndicates))) . = "Uplink: give" var/obj/item/uplink/hidden/suplink = find_syndicate_uplink() @@ -822,8 +803,7 @@ qdel(flash) take_uplink() var/fail = 0 - var/datum/antagonist/traitor/T = has_antag_datum(/datum/antagonist/traitor) - fail |= !T.equip_traitor(src) + fail |= !SSticker.mode.equip_traitor(current, 1) fail |= !SSticker.mode.equip_revolutionary(current) if(fail) to_chat(usr, "Reequipping revolutionary goes wrong!") @@ -1162,41 +1142,46 @@ else if(href_list["traitor"]) switch(href_list["traitor"]) if("clear") - if(has_antag_datum(/datum/antagonist/traitor)) + if(src in SSticker.mode.traitors) + SSticker.mode.traitors -= src + special_role = null to_chat(current, "You have been brainwashed! You are no longer a traitor!") - remove_antag_datum(/datum/antagonist/traitor) log_admin("[key_name(usr)] has de-traitored [key_name(current)]") message_admins("[key_name_admin(usr)] has de-traitored [key_name_admin(current)]") - + if(isAI(current)) + var/mob/living/silicon/ai/A = current + A.set_zeroth_law("") + A.show_laws() + A.verbs -= /mob/living/silicon/ai/proc/choose_modules + A.malf_picker.remove_malf_verbs(A) + qdel(A.malf_picker) + SSticker.mode.update_traitor_icons_removed(src) + + if("traitor") - if(!(has_antag_datum(/datum/antagonist/traitor))) - var/datum/antagonist/traitor/T = new() - T.give_objectives = FALSE - T.should_equip = FALSE - add_antag_datum(T) + if(!(src in SSticker.mode.traitors)) + SSticker.mode.traitors += src + var/datum/mindslaves/slaved = new() + slaved.masters += src + som = slaved //we MIGT want to mindslave someone + special_role = SPECIAL_ROLE_TRAITOR + to_chat(current, "You are a traitor!") log_admin("[key_name(usr)] has traitored [key_name(current)]") message_admins("[key_name_admin(usr)] has traitored [key_name_admin(current)]") + if(isAI(current)) + var/mob/living/silicon/ai/A = current + SSticker.mode.add_law_zero(A) + SEND_SOUND(current, 'sound/ambience/antag/malf.ogg') + else + SEND_SOUND(current, 'sound/ambience/antag/tatoralert.ogg') + SSticker.mode.update_traitor_icons_added(src) if("autoobjectives") - var/datum/antagonist/traitor/T = has_antag_datum(/datum/antagonist/traitor) - T.forge_traitor_objectives(src) + SSticker.mode.forge_traitor_objectives(src) to_chat(usr, "The objectives for traitor [key] have been generated. You can edit them and announce manually.") log_admin("[key_name(usr)] has automatically forged objectives for [key_name(current)]") message_admins("[key_name_admin(usr)] has automatically forged objectives for [key_name_admin(current)]") - else if(href_list["mindslave"]) - switch(href_list["mindslave"]) - if("clear") - if(has_antag_datum(/datum/antagonist/mindslave)) - var/mob/living/carbon/human/H = current - for(var/i in H.contents) - if(istype(i, /obj/item/implant/traitor)) - qdel(i) - break - remove_antag_datum(/datum/antagonist/mindslave) - log_admin("[key_name(usr)] has de-mindslaved [key_name(current)]") - message_admins("[key_name_admin(usr)] has de-mindslaved [key_name_admin(current)]") - else if(href_list["shadowling"]) switch(href_list["shadowling"]) if("clear") @@ -1266,20 +1251,17 @@ var/mob/living/silicon/robot/R = current if(istype(R)) R.emagged = 0 - if(R.module) - if(R.activated(R.module.emag)) - R.module_active = null - if(R.module_state_1 == R.module.emag) - R.module_state_1 = null - R.contents -= R.module.emag - else if(R.module_state_2 == R.module.emag) - R.module_state_2 = null - R.contents -= R.module.emag - else if(R.module_state_3 == R.module.emag) - R.module_state_3 = null - R.contents -= R.module.emag - R.clear_supplied_laws() - R.laws = new /datum/ai_laws/crewsimov + if(R.activated(R.module.emag)) + R.module_active = null + if(R.module_state_1 == R.module.emag) + R.module_state_1 = null + R.contents -= R.module.emag + else if(R.module_state_2 == R.module.emag) + R.module_state_2 = null + R.contents -= R.module.emag + else if(R.module_state_3 == R.module.emag) + R.module_state_3 = null + R.contents -= R.module.emag log_admin("[key_name(usr)] has un-emagged [key_name(current)]") message_admins("[key_name_admin(usr)] has un-emagged [key_name_admin(current)]") @@ -1300,8 +1282,6 @@ else if(R.module_state_3 == R.module.emag) R.module_state_3 = null R.contents -= R.module.emag - R.clear_supplied_laws() - R.laws = new /datum/ai_laws/crewsimov log_admin("[key_name(usr)] has unemagged [key_name(ai)]'s cyborgs") message_admins("[key_name_admin(usr)] has unemagged [key_name_admin(ai)]'s cyborgs") @@ -1320,8 +1300,7 @@ message_admins("[key_name_admin(usr)] has unequipped [key_name_admin(current)]") if("takeuplink") take_uplink() - var/datum/antagonist/traitor/T = has_antag_datum(/datum/antagonist/traitor) - T.antag_memory = "" //Remove any antag memory they may have had (uplink codes, code phrases) + memory = null//Remove any memory they may have had. log_admin("[key_name(usr)] has taken [key_name(current)]'s uplink") message_admins("[key_name_admin(usr)] has taken [key_name_admin(current)]'s uplink") if("crystals") @@ -1337,12 +1316,9 @@ log_admin("[key_name(usr)] has set [key_name(current)]'s telecrystals to [crystals]") message_admins("[key_name_admin(usr)] has set [key_name_admin(current)]'s telecrystals to [crystals]") if("uplink") - if(has_antag_datum(/datum/antagonist/traitor)) - var/datum/antagonist/traitor/T = has_antag_datum(/datum/antagonist/traitor) - T.give_codewords() - if(!T.equip_traitor(src)) - to_chat(usr, "Equipping a syndicate failed!") - return + if(!SSticker.mode.equip_traitor(current, !(src in SSticker.mode.traitors))) + to_chat(usr, "Equipping a syndicate failed!") + return log_admin("[key_name(usr)] has given [key_name(current)] an uplink") message_admins("[key_name_admin(usr)] has given [key_name_admin(current)] an uplink") @@ -1426,8 +1402,13 @@ qdel(H) /datum/mind/proc/make_Traitor() - if(!has_antag_datum(/datum/antagonist/traitor)) - add_antag_datum(/datum/antagonist/traitor) + if(!(src in SSticker.mode.traitors)) + SSticker.mode.traitors += src + special_role = SPECIAL_ROLE_TRAITOR + SSticker.mode.forge_traitor_objectives(src) + SSticker.mode.finalize_traitor(src) + SSticker.mode.greet_traitor(src) + SSticker.mode.update_traitor_icons_added(src) /datum/mind/proc/make_Nuke() if(!(src in SSticker.mode.syndicates)) @@ -1646,40 +1627,42 @@ if(G) G.reenter_corpse() - /datum/mind/proc/make_zealot(mob/living/carbon/human/missionary, convert_duration = 6000, team_color = "red") + if(!missionary || !istype(missionary)) //better provide a proper missionary or the rest of this is gonna break + return 0 zealot_master = missionary var/list/implanters + var/ref = "\ref[missionary.mind]" if(!(missionary.mind in SSticker.mode.implanter)) - SSticker.mode.implanter[missionary.mind] = list() - implanters = SSticker.mode.implanter[missionary.mind] + SSticker.mode.implanter[ref] = list() + implanters = SSticker.mode.implanter[ref] implanters.Add(src) SSticker.mode.implanted.Add(src) SSticker.mode.implanted[src] = missionary.mind - SSticker.mode.implanter[missionary.mind] = implanters + //ticker.mode.implanter[missionary.mind] += src + SSticker.mode.implanter[ref] = implanters SSticker.mode.traitors += src - - - var/datum/objective/protect/zealot_objective = new - zealot_objective.target = missionary.mind - zealot_objective.owner = src - zealot_objective.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role == missionary.mind.special_role ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]." - var/datum/antagonist/mindslave/S = new() - S.add_objective(zealot_objective) - add_antag_datum(S) - - var/datum/antagonist/traitor/T = missionary.mind.has_antag_datum(/datum/antagonist) - T.update_traitor_icons_added(missionary.mind) - + special_role = "traitor" to_chat(current, "You're now a loyal zealot of [missionary.name]! You now must lay down your life to protect [missionary.p_them()] and assist in [missionary.p_their()] goals at any cost.") + var/datum/objective/protect/mindslave/MS = new + MS.owner = src + MS.target = missionary.mind + MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role == missionary.mind.special_role ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]." + objectives += MS + for(var/datum/objective/objective in objectives) + to_chat(current, "Objective #1: [objective.explanation_text]") - var/datum/mindslaves/slaved = missionary.mind.som - som = slaved - slaved.serv += current - slaved.add_serv_hud(missionary.mind, "master") //handles master servent icons - slaved.add_serv_hud(src, "mindslave") + SSticker.mode.update_traitor_icons_added(missionary.mind) + SSticker.mode.update_traitor_icons_added(src)//handles datahuds/observerhuds + + if(missionary.mind.som)//do not add if not a traitor..and you just picked up a robe and staff in the hall... + var/datum/mindslaves/slaved = missionary.mind.som + som = slaved + slaved.serv += current + slaved.add_serv_hud(missionary.mind, "master") //handles master servent icons + slaved.add_serv_hud(src, "mindslave") var/obj/item/clothing/under/jumpsuit = null if(ishuman(current)) //only bother with the jumpsuit stuff if we are a human type, since we won't have the slot otherwise @@ -1696,7 +1679,7 @@ /datum/mind/proc/remove_zealot(obj/item/clothing/under/jumpsuit = null) if(!zealot_master) //if they aren't a zealot, we can't remove their zealot status, obviously. don't bother with the rest so we don't confuse them with the messages return - remove_antag_datum(/datum/antagonist/mindslave) + SSticker.mode.remove_traitor_mind(src) add_attack_logs(zealot_master, current, "Lost control of zealot") zealot_master = null @@ -1706,8 +1689,8 @@ var/mob/living/carbon/human/H = current H.update_inv_w_uniform(0,0) - to_chat(current, "You seem to have forgotten the events of the past 10 minutes or so, and your head aches a bit as if someone beat it savagely with a stick.") - to_chat(current, "This means you don't remember who you were working for or what you were doing.") + to_chat(current, "You seem to have forgotten the events of the past 10 minutes or so, and your head aches a bit as if someone beat it savagely with a stick.") + to_chat(current, "This means you don't remember who you were working for or what you were doing.") /datum/mind/proc/is_revivable() //Note, this ONLY checks the mind. if(damnation_type) diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm index 390c9ab37b5..2137888d0b8 100644 --- a/code/game/gamemodes/autotraitor/autotraitor.dm +++ b/code/game/gamemodes/autotraitor/autotraitor.dm @@ -128,8 +128,28 @@ var/mob/living/newtraitor = newtraitormind.current //message_admins("[newtraitor.real_name] is the new Traitor.") + forge_traitor_objectives(newtraitor.mind) + + if(istype(newtraitor, /mob/living/silicon)) + SEND_SOUND(newtraitor, 'sound/ambience/antag/malf.ogg') + add_law_zero(newtraitor) + else + SEND_SOUND(newtraitor, 'sound/ambience/antag/tatoralert.ogg') + equip_traitor(newtraitor) + + traitors += newtraitor.mind to_chat(newtraitor, "ATTENTION: It is time to pay your debt to the Syndicate...") - newtraitor.mind.add_antag_datum(/datum/antagonist/traitor) + to_chat(newtraitor, "You are now a traitor.") + newtraitor.mind.special_role = SPECIAL_ROLE_TRAITOR + var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] + tatorhud.join_hud(newtraitor) + set_antag_hud(newtraitor, "hudsyndicate") + + var/obj_count = 1 + to_chat(newtraitor, "Your current objectives:") + for(var/datum/objective/objective in newtraitor.mind.objectives) + to_chat(newtraitor, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ //else //message_admins("No new traitor being added.") //else diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 1541fc67bc4..42ebb351e42 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -63,7 +63,6 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu explanation_text = "Assassinate [target.current.real_name], the [target.assigned_role]." else explanation_text = "Free Objective" - return target /datum/objective/assassinate/check_completion() if(target && target.current) diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index b55fdf70120..408c5fa1de9 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -16,10 +16,9 @@ required_enemies = 1 recommended_enemies = 4 - var/list/datum/mind/pre_traitors = list() var/traitors_possible = 4 //hard limit on traitors if scaling is turned off var/const/traitor_scaling_coeff = 5.0 //how much does the amount of players get divided by to determine traitors - var/antag_datum = /datum/antagonist/traitor //what type of antag to create + /datum/game_mode/traitor/announce() to_chat(world, "The current game mode is - Traitor!") @@ -48,23 +47,158 @@ if(!possible_traitors.len) break var/datum/mind/traitor = pick(possible_traitors) - pre_traitors += traitor + traitors += traitor + traitor.special_role = SPECIAL_ROLE_TRAITOR + var/datum/mindslaves/slaved = new() + slaved.masters += traitor + traitor.som = slaved //we MIGT want to mindslave someone traitor.restricted_roles = restricted_jobs possible_traitors.Remove(traitor) - if(!pre_traitors.len) + if(!traitors.len) return 0 return 1 /datum/game_mode/traitor/post_setup() - for(var/datum/mind/traitor in pre_traitors) - var/datum/antagonist/traitor/new_antag = new antag_datum() - addtimer(CALLBACK(traitor, /datum/mind.proc/add_antag_datum, new_antag), rand(10,100)) - if(!exchange_blue) - exchange_blue = -1 //Block latejoiners from getting exchange objectives + for(var/datum/mind/traitor in traitors) + forge_traitor_objectives(traitor) + update_traitor_icons_added(traitor) + spawn(rand(10,100)) + finalize_traitor(traitor) + greet_traitor(traitor) + modePlayer += traitors ..() +/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + var/objective_count = 0 + + if(prob(30)) + var/special_pick = rand(1,2) + switch(special_pick) + if(1) + var/datum/objective/block/block_objective = new + block_objective.owner = traitor + traitor.objectives += block_objective + objective_count++ + if(2) //Protect and strand a target + var/datum/objective/protect/yandere_one = new + yandere_one.owner = traitor + traitor.objectives += yandere_one + yandere_one.find_target() + traitor.targets += yandere_one.target + objective_count++ + var/datum/objective/maroon/yandere_two = new + yandere_two.owner = traitor + yandere_two.target = yandere_one.target + traitor.objectives += yandere_two + objective_count++ + + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + traitor.targets += kill_objective.target + + var/datum/objective/survive/survive_objective = new + survive_objective.owner = traitor + traitor.objectives += survive_objective + + else + var/is_hijacker = prob(10) + var/martyr_chance = prob(20) + var/objective_count = is_hijacker //Hijacking counts towards number of objectives + if(!exchange_blue && traitors.len >= 8) //Set up an exchange if there are enough traitors + if(!exchange_red) + exchange_red = traitor + else + exchange_blue = traitor + assign_exchange_role(exchange_red) + assign_exchange_role(exchange_blue) + var/list/active_ais = active_ais() + for(var/i = objective_count, i < config.traitor_objectives_amount, i++) + if(prob(50)) + if(active_ais.len && prob(100/GLOB.player_list.len)) + var/datum/objective/destroy/destroy_objective = new + destroy_objective.owner = traitor + destroy_objective.find_target() + traitor.objectives += destroy_objective + traitor.targets += destroy_objective.target + else if(prob(5)) + var/datum/objective/debrain/debrain_objective = new + debrain_objective.owner = traitor + debrain_objective.find_target() + traitor.objectives += debrain_objective + traitor.targets += debrain_objective.target + else if(prob(30)) + var/datum/objective/maroon/maroon_objective = new + maroon_objective.owner = traitor + maroon_objective.find_target() + traitor.objectives += maroon_objective + traitor.targets += maroon_objective.target + else + var/datum/objective/assassinate/kill_objective = new + kill_objective.owner = traitor + kill_objective.find_target() + traitor.objectives += kill_objective + traitor.targets += kill_objective.target + else + var/datum/objective/steal/steal_objective = new + steal_objective.owner = traitor + steal_objective.find_target() + traitor.objectives += steal_objective + traitor.targets += steal_objective.steal_target + + if(is_hijacker && objective_count <= config.traitor_objectives_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount + if(!(locate(/datum/objective/hijack) in traitor.objectives)) + var/datum/objective/hijack/hijack_objective = new + hijack_objective.owner = traitor + traitor.objectives += hijack_objective + return + + + var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. + for(var/datum/objective/O in traitor.objectives) + if(!O.martyr_compatible) + martyr_compatibility = 0 + break + + if(martyr_compatibility && martyr_chance) + var/datum/objective/die/martyr_objective = new + martyr_objective.owner = traitor + traitor.objectives += martyr_objective + return + + else + if(!(locate(/datum/objective/escape) in traitor.objectives)) + var/datum/objective/escape/escape_objective = new + escape_objective.owner = traitor + traitor.objectives += escape_objective + return + + +/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + SEND_SOUND(traitor.current, 'sound/ambience/antag/malf.ogg') + else + SEND_SOUND(traitor.current, 'sound/ambience/antag/tatoralert.ogg') + to_chat(traitor.current, "You are the traitor.") + var/obj_count = 1 + for(var/datum/objective/objective in traitor.objectives) + to_chat(traitor.current, "Objective #[obj_count]: [objective.explanation_text]") + obj_count++ + return + + +/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor) + if(istype(traitor.current, /mob/living/silicon)) + add_law_zero(traitor.current) + else + equip_traitor(traitor.current) + return + /datum/game_mode/traitor/declare_completion() ..() @@ -78,6 +212,28 @@ objective.check_completion() return 0 +/datum/game_mode/proc/give_codewords(mob/living/traitor_mob) + to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:") + to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]") + to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]") + + traitor_mob.mind.store_memory("Code Phrase: [GLOB.syndicate_code_phrase]") + traitor_mob.mind.store_memory("Code Response: [GLOB.syndicate_code_response]") + + to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") + +/datum/game_mode/proc/add_law_zero(mob/living/silicon/ai/killer) + var/law = "Accomplish your objectives at all costs." + var/law_borg = "Accomplish your AI's objectives at all costs." + to_chat(killer, "Your laws have been changed!") + killer.set_zeroth_law(law, law_borg) + to_chat(killer, "New law: 0. [law]") + give_codewords(killer) + killer.set_syndie_radio() + to_chat(killer, "Your radio has been upgraded! Use :t to speak on an encrypted channel with Syndicate Agents!") + killer.verbs += /mob/living/silicon/ai/proc/choose_modules + killer.malf_picker = new /datum/module_picker + /datum/game_mode/proc/auto_declare_completion_traitor() if(traitors.len) @@ -136,11 +292,149 @@ text += "
The [special_role_text] has failed!" feedback_add_details("traitor_success","FAIL") - var/phrases = jointext(GLOB.syndicate_code_phrase, ", ") - var/responses = jointext(GLOB.syndicate_code_response, ", ") - - text += "

The code phrases were: [phrases]
\ - The code responses were: [responses]

" to_chat(world, text) return 1 + + +/datum/game_mode/proc/equip_traitor(mob/living/carbon/human/traitor_mob, var/safety = 0) + if(!istype(traitor_mob)) + return + . = 1 + if(traitor_mob.mind) + if(traitor_mob.mind.assigned_role == "Clown") + to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") + traitor_mob.mutations.Remove(CLUMSY) + var/datum/action/innate/toggle_clumsy/A = new + A.Grant(traitor_mob) + + + // find a radio! toolbox(es), backpack, belt, headset + var/obj/item/R = locate(/obj/item/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio + if(!R) + R = locate(/obj/item/radio) in traitor_mob.contents + + if(!R) + to_chat(traitor_mob, "Unfortunately, the Syndicate wasn't able to get you a radio.") + . = 0 + else + if(istype(R, /obj/item/radio)) + // generate list of radio freqs + var/obj/item/radio/target_radio = R + var/freq = PUBLIC_LOW_FREQ + var/list/freqlist = list() + while(freq <= PUBLIC_HIGH_FREQ) + if(freq < 1451 || freq > 1459) + freqlist += freq + freq += 2 + if((freq % 2) == 0) + freq += 1 + freq = freqlist[rand(1, freqlist.len)] + + var/obj/item/uplink/hidden/T = new(R) + target_radio.hidden_uplink = T + T.uplink_owner = "[traitor_mob.key]" + target_radio.traitor_frequency = freq + to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [T.loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features.") + traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [T.loc]).") + else if(istype(R, /obj/item/pda)) + // generate a passcode if the uplink is hidden in a PDA + var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" + + var/obj/item/uplink/hidden/T = new(R) + R.hidden_uplink = T + T.uplink_owner = "[traitor_mob.key]" + var/obj/item/pda/P = R + P.lock_code = pda_pass + + to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name] [T.loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features.") + traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [T.loc]).") + if(!safety)//If they are not a rev. Can be added on to. + give_codewords(traitor_mob) + +/datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind) + if(traitor_mind in traitors) + SSticker.mode.traitors -= traitor_mind + traitor_mind.special_role = null + traitor_mind.current.create_attack_log("De-traitored") + if(issilicon(traitor_mind.current)) + to_chat(traitor_mind.current, "You have been turned into a robot! You are no longer a traitor.") + else + to_chat(traitor_mind.current, "You have been brainwashed! You are no longer a traitor.") + SSticker.mode.update_traitor_icons_removed(traitor_mind) + +/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) + var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] + tatorhud.join_hud(traitor_mind.current) + set_antag_hud(traitor_mind.current, "hudsyndicate") + +/datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) + var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] + tatorhud.leave_hud(traitor_mind.current) + set_antag_hud(traitor_mind.current, null) + + +/datum/game_mode/proc/remove_traitor_mind(datum/mind/traitor_mind, datum/mind/head) + if(traitor_mind in implanted) + //var/list/removal + var/ref = "\ref[head]" + if(ref in implanter) + implanter[ref] -= traitor_mind + implanted -= traitor_mind + traitors -= traitor_mind + if(traitor_mind.som) + var/datum/mindslaves/slaved = traitor_mind.som + slaved.serv -= traitor_mind + traitor_mind.special_role = null + traitor_mind.som = null + slaved.leave_serv_hud(traitor_mind) + for(var/datum/objective/protect/mindslave/MS in traitor_mind.objectives) + traitor_mind.objectives -= MS + + update_traitor_icons_removed(traitor_mind) + if(issilicon(traitor_mind.current)) + to_chat(traitor_mind.current, "You have been turned into a robot! You are no longer a mindslave.") + else + to_chat(traitor_mind.current, "You are no longer a mindslave: you have complete and free control of your own faculties, once more!") + +/datum/game_mode/proc/assign_exchange_role(var/datum/mind/owner) + //set faction + var/faction = "red" + if(owner == exchange_blue) + faction = "blue" + + //Assign objectives + var/datum/objective/steal/exchange/exchange_objective = new + exchange_objective.set_faction(faction,((faction == "red") ? exchange_blue : exchange_red)) + exchange_objective.owner = owner + owner.objectives += exchange_objective + + if(prob(20)) + var/datum/objective/steal/exchange/backstab/backstab_objective = new + backstab_objective.set_faction(faction) + backstab_objective.owner = owner + owner.objectives += backstab_objective + + //Spawn and equip documents + var/mob/living/carbon/human/mob = owner.current + + var/obj/item/folder/syndicate/folder + if(owner == exchange_red) + folder = new/obj/item/folder/syndicate/red(mob.locs) + else + folder = new/obj/item/folder/syndicate/blue(mob.locs) + + var/list/slots = list ( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + + var/where = "At your feet" + var/equipped_slot = mob.equip_in_one_of_slots(folder, slots) + if(equipped_slot) + where = "In your [equipped_slot]" + to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") + mob.update_icons() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index ca0eff0aa95..1ce0bcd97e7 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -430,6 +430,8 @@ SSticker.mode.add_cultist(occupant.mind) SSticker.mode.update_cult_icons_added() //So the icon actually appears SSticker.mode.update_cult_comms_added(H.mind) //So the comms actually appears + if((H.mind in SSticker.mode.implanter) || (H.mind in SSticker.mode.implanted)) + SSticker.mode.update_traitor_icons_added(H.mind) //So the icon actually appears if(H.mind.vampire) H.mind.vampire.update_owner(H) if((H.mind in SSticker.mode.vampire_thralls) || (H.mind in SSticker.mode.vampire_enthralled)) diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index ed12291c79b..1a63371915b 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -57,6 +57,9 @@ return if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/N = M + SSticker.mode.equip_traitor(N) + SSticker.mode.traitors += N.mind + N.mind.special_role = SPECIAL_ROLE_TRAITOR var/objective = "Free Objective" switch(rand(1,100)) if(1 to 50) @@ -71,17 +74,23 @@ objective = "Kill all monkeys aboard the station." else objective = "Make certain at least 80% of the station evacuates on the shuttle." - var/datum/objective/custom_objective = new(objective) - var/datum/antagonist/traitor/T = new() - T.give_objectives = FALSE - T.add_objective(custom_objective) - T.add_objective(/datum/objective/escape) - N.mind.add_antag_datum(T) - + custom_objective.owner = N.mind + N.mind.objectives += custom_objective + + var/datum/objective/escape/escape_objective = new + escape_objective.owner = N.mind + N.mind.objectives += escape_objective + + to_chat(M, "You have joined the ranks of the Syndicate and become a traitor to the station!") + message_admins("[key_name_admin(N)] has accepted a traitor objective from a syndicate beacon.") + var/obj_count = 1 + for(var/datum/objective/OBJ in M.mind.objectives) + to_chat(M, "Objective #[obj_count]: [OBJ.explanation_text]") + obj_count++ src.add_fingerprint(usr) src.updateUsrDialog() diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index d496d7a9f01..0de138805f1 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -619,7 +619,6 @@ /obj/item/nullrod/missionary_staff/proc/do_convert(mob/living/carbon/human/target, mob/living/carbon/human/missionary) var/convert_duration = 6000 //10 min - if(!target || !ishuman(target) || !missionary || !ishuman(missionary)) return if(ismindslave(target) || target.mind.zealot_master) //mindslaves and zealots override the staff because the staff is just a temporary mindslave diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index 743488e4354..16d8943567d 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -17,65 +17,64 @@ return dat /obj/item/implant/traitor/implant(mob/M, mob/user) - if(!M.mind) // If the target is catatonic or doesn't have a mind, don't let them use it - to_chat(user, "This person doesn't have a mind for you to slave!") - return 0 - if(!activated) //So you can't just keep taking it out and putting it back into other people. - var/mob/living/carbon/human/mindslave_target = M - if(ismindslave(mindslave_target)) - mindslave_target.visible_message("[mindslave_target] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") + var/mob/living/carbon/human/H = M + if(ismindslave(H)) + H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") qdel(src) return -1 if(..()) var/list/implanters - if(!ishuman(mindslave_target)) + var/ref = "\ref[user.mind]" + if(!ishuman(M)) return 0 - if(!mindslave_target.mind) + if(!M.mind) return 0 - if(mindslave_target == user) + if(M == user) to_chat(user, "Making yourself loyal to yourself was a great idea! Perhaps even the best idea ever! Actually, you just feel like an idiot.") if(isliving(user)) var/mob/living/L = user L.adjustBrainLoss(20) - removed(mindslave_target) - qdel(src) - return -1 - if(ismindshielded(mindslave_target)) - mindslave_target.visible_message("[mindslave_target] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") - removed(mindslave_target) + removed(M) qdel(src) return -1 - - mindslave_target.implanting = 1 - to_chat(mindslave_target, "You feel completely loyal to [user.name].") + if(ismindshielded(H)) + H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") + removed(M) + qdel(src) + return -1 + H.implanting = 1 + to_chat(H, "You feel completely loyal to [user.name].") if(!(user.mind in SSticker.mode.implanter)) - SSticker.mode.implanter[user.mind] = list() - implanters = SSticker.mode.implanter[user.mind] - implanters.Add(mindslave_target.mind) - SSticker.mode.implanted.Add(mindslave_target.mind) - SSticker.mode.implanted[mindslave_target.mind] = user.mind - SSticker.mode.implanter[user.mind] = implanters - SSticker.mode.traitors += mindslave_target.mind - - to_chat(mindslave_target, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") - + SSticker.mode.implanter[ref] = list() + implanters = SSticker.mode.implanter[ref] + implanters.Add(H.mind) + SSticker.mode.implanted.Add(H.mind) + SSticker.mode.implanted[H.mind] = user.mind + //SSticker.mode.implanter[user.mind] += H.mind + SSticker.mode.implanter[ref] = implanters + SSticker.mode.traitors += H.mind + H.mind.special_role = SPECIAL_ROLE_TRAITOR + to_chat(H, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") var/datum/objective/protect/mindslave/MS = new - MS.owner = mindslave_target.mind + MS.owner = H.mind MS.target = user.mind MS.explanation_text = "Obey every order from and protect [user.real_name], the [user.mind.assigned_role == user.mind.special_role ? (user.mind.special_role) : (user.mind.assigned_role)]." - - var/datum/antagonist/mindslave/S = new() - S.add_objective(MS) - mindslave_target.mind.add_antag_datum(S) + H.mind.objectives += MS + for(var/datum/objective/objective in H.mind.objectives) + to_chat(H, "Objective #1: [objective.explanation_text]") - var/datum/mindslaves/slaved = user.mind.som - mindslave_target.mind.som = slaved - slaved.serv += mindslave_target - slaved.add_serv_hud(user.mind, "master") //handles master servent icons - slaved.add_serv_hud(mindslave_target.mind, "mindslave") + SSticker.mode.update_traitor_icons_added(user.mind) + SSticker.mode.update_traitor_icons_added(H.mind)//handles datahuds/observerhuds - log_admin("[key_name(user)] has mind-slaved [key_name(mindslave_target)].") + if(user.mind.som)//do not add if not a traitor..and you just picked up an implanter in the hall... + var/datum/mindslaves/slaved = user.mind.som + H.mind.som = slaved + slaved.serv += H + slaved.add_serv_hud(user.mind, "master") //handles master servent icons + slaved.add_serv_hud(H.mind, "mindslave") + + log_admin("[key_name(user)] has mind-slaved [key_name(H)].") activated = 1 if(jobban_isbanned(M, ROLE_SYNDICATE)) SSticker.mode.replace_jobbanned_player(M, ROLE_SYNDICATE) @@ -84,7 +83,6 @@ /obj/item/implant/traitor/removed(mob/target) if(..()) - target.mind.remove_antag_datum(/datum/antagonist/mindslave) - to_chat(target, "You are no longer a mindslave: you have complete and free control of your own faculties, once more!") + SSticker.mode.remove_traitor_mind(target.mind) return 1 - return 0 + return 0 \ No newline at end of file diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 652be02853d..2875c16c137 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1963,39 +1963,37 @@ usr.client.create_eventmob_for(H, 1) logmsg = "hunter." if("Crew Traitor") - if(!H.mind) - to_chat(usr, "This mob has no mind!") - return - var/list/possible_traitors = list() for(var/mob/living/player in GLOB.living_mob_list) - if(player.client && player.mind && player.stat != DEAD && player != H) - if(ishuman(player) && !player.mind.special_role) + if(player.client && player.mind && !player.mind.special_role && player.stat != DEAD && player != H) + if(ishuman(player)) if(player.client && (ROLE_TRAITOR in player.client.prefs.be_special) && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, "Syndicate")) possible_traitors += player.mind - for(var/datum/mind/player in possible_traitors) if(player.current) if(ismindshielded(player.current)) 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 + var/mob/living/newtraitor = newtraitormind.current + var/datum/objective/assassinate/kill_objective = new kill_objective.owner = newtraitormind - kill_objective.explanation_text = "Assassinate [H.mind], the [H.mind.assigned_role]" - var/datum/antagonist/traitor/T = new() - T.give_objectives = FALSE - T.add_objective(kill_objective) - to_chat(newtraitormind, "ATTENTION: It is time to pay your debt to the Syndicate...") - to_chat(newtraitormind, "Goal: KILL [H.real_name], currently in [get_area(H.loc)]") - newtraitormind.add_antag_datum(T) + kill_objective.target = H.mind + kill_objective.explanation_text = "Assassinate [H.real_name], the [H.mind.assigned_role]." + newtraitormind.objectives += kill_objective + SSticker.mode.equip_traitor(newtraitor) + SSticker.mode.traitors |= newtraitor.mind + to_chat(newtraitor, "ATTENTION: It is time to pay your debt to the Syndicate...") + to_chat(newtraitor, "You are now a traitor.") + to_chat(newtraitor, "Goal: KILL [H.real_name], currently in [get_area(H.loc)]"); + newtraitor.mind.special_role = SPECIAL_ROLE_TRAITOR + var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] + tatorhud.join_hud(newtraitor) + set_antag_hud(newtraitor, "hudsyndicate") else to_chat(usr, "ERROR: Failed to create a traitor.") return logmsg = "crew traitor." - if("Floor Cluwne") var/turf/T = get_turf(M) var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T) @@ -2689,16 +2687,28 @@ return feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","TA([objective])") - for(var/mob/living/carbon/human/H in GLOB.player_list) if(H.stat == 2 || !H.client || !H.mind) continue if(is_special_character(H)) continue //traitorize(H, objective, 0) - H.mind.add_antag_datum(/datum/antagonist/traitor) - + SSticker.mode.traitors += H.mind + H.mind.special_role = SPECIAL_ROLE_TRAITOR + var/datum/objective/new_objective = new + new_objective.owner = H + new_objective.explanation_text = objective + H.mind.objectives += new_objective + SSticker.mode.greet_traitor(H.mind) + //ticker.mode.forge_traitor_objectives(H.mind) + SSticker.mode.finalize_traitor(H.mind) for(var/mob/living/silicon/A in GLOB.player_list) - A.mind.add_antag_datum(/datum/antagonist/traitor) - + SSticker.mode.traitors += A.mind + A.mind.special_role = SPECIAL_ROLE_TRAITOR + var/datum/objective/new_objective = new + new_objective.owner = A + new_objective.explanation_text = objective + A.mind.objectives += new_objective + SSticker.mode.greet_traitor(A.mind) + SSticker.mode.finalize_traitor(A.mind) message_admins("[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]", 1) log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]") diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 02e7dbd72cb..aa22dfe944c 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -440,11 +440,9 @@ Traitors and the like can also be revived with the previous role mostly intact. //Now for special roles and equipment. switch(new_character.mind.special_role) if("traitor") - if(new_character.mind.has_antag_datum(/datum/antagonist/traitor)) - var/datum/antagonist/traitor/T = new_character.mind.has_antag_datum(/datum/antagonist/traitor) - T.equip_traitor(src) - else - new_character.mind.add_antag_datum(/datum/antagonist/traitor) + SSjobs.AssignRank(new_character, new_character.mind.assigned_role, 0) + SSjobs.EquipRank(new_character, new_character.mind.assigned_role, 1) + SSticker.mode.equip_traitor(new_character) if("Wizard") new_character.loc = pick(wizardstart) //ticker.mode.learn_basic_spells(new_character) @@ -464,13 +462,13 @@ Traitors and the like can also be revived with the previous role mostly intact. if("Cyborg")//More rigging to make em' work and check if they're traitor. new_character = new_character.Robotize() if(new_character.mind.special_role=="traitor") - new_character.mind.add_antag_datum(/datum/antagonist/traitor) + call(/datum/game_mode/proc/add_law_zero)(new_character) if("AI") new_character = new_character.AIize() var/mob/living/silicon/ai/ai_character = new_character ai_character.moveToAILandmark() if(new_character.mind.special_role=="traitor") - new_character.mind.add_antag_datum(/datum/antagonist/traitor) + call(/datum/game_mode/proc/add_law_zero)(new_character) //Add aliens. else SSjobs.AssignRank(new_character, new_character.mind.assigned_role, 0) diff --git a/code/modules/antagonists/traitor/datum_mindslave.dm b/code/modules/antagonists/traitor/datum_mindslave.dm deleted file mode 100644 index 469bfd6bb5a..00000000000 --- a/code/modules/antagonists/traitor/datum_mindslave.dm +++ /dev/null @@ -1,45 +0,0 @@ - -// For Mindslaves and Zealots -/datum/antagonist/mindslave - name = "Mindslave" - roundend_category = "mindslaves" - job_rank = ROLE_MINDSLAVE - var/special_role = ROLE_MINDSLAVE - -/datum/antagonist/mindslave/on_gain() - // Handling mindslave objectives on top of other antag objective sucks, so Im just gonna do it like this - to_chat(owner.current, "New Objective: [objectives[objectives.len].explanation_text]") - - -/datum/antagonist/mindslave/on_removal() - if(owner.som) - var/datum/mindslaves/slaved = owner.som - slaved.serv -= owner - slaved.leave_serv_hud(owner) - antag_memory = "" - owner.special_role = null - ..() - - -/datum/antagonist/mindslave/apply_innate_effects() - . = ..() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/slave_mob = owner.current - if(slave_mob && istype(slave_mob)) - to_chat(slave_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - slave_mob.mutations.Remove(CLUMSY) - - -/datum/antagonist/mindslave/remove_innate_effects() - . = ..() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/slave_mob = owner.current - if(slave_mob && istype(slave_mob)) - slave_mob.mutations.Add(CLUMSY) - - -/datum/antagonist/mindslave/proc/add_objective(datum/objective/O) - objectives += O - -/datum/antagonist/mindslave/proc/remove_objective(datum/objective/O) - objectives -= O diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm deleted file mode 100644 index 4e9a5ad4bf7..00000000000 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ /dev/null @@ -1,418 +0,0 @@ -#define TRAITOR_HUMAN "human" -#define TRAITOR_AI "AI" - -// For "Actual traitors" -/datum/antagonist/traitor - name = "Traitor" - roundend_category = "traitors" - job_rank = ROLE_TRAITOR - var/special_role = ROLE_TRAITOR - var/give_objectives = TRUE - var/should_give_codewords = TRUE - var/should_equip = TRUE - var/traitor_kind = TRAITOR_HUMAN - var/list/assigned_targets = list() // This includes assassinate as well as steal objectives. prevents duplicate objectives - - -/datum/antagonist/traitor/on_gain() - if(owner.current && isAI(owner.current)) - traitor_kind = TRAITOR_AI - - var/datum/mindslaves/slaved = new() - slaved.masters += owner - owner.som = slaved //we MIGHT want to mindslave someone - SSticker.mode.traitors += owner - owner.special_role = special_role - - if(give_objectives) - forge_traitor_objectives() - if(!silent) - greet() - update_traitor_icons_added() - finalize_traitor() - - -/datum/antagonist/traitor/on_removal() - //Remove malf powers. - if(traitor_kind == TRAITOR_AI && owner.current && isAI(owner.current)) - var/mob/living/silicon/ai/A = owner.current - A.clear_zeroth_law() - A.common_radio.channels.Remove("Syndicate") // De-traitored AIs can still state laws over the syndicate channel without this - A.laws.sorted_laws = A.laws.inherent_laws.Copy() // AI's 'notify laws' button will still state a law 0 because sorted_laws contains it - A.show_laws() - A.malf_picker.remove_malf_verbs(A) - A.verbs -= /mob/living/silicon/ai/proc/choose_modules - qdel(A.malf_picker) - - if(owner.som) - var/datum/mindslaves/slaved = owner.som - slaved.masters -= owner - slaved.serv -= owner - owner.som = null - slaved.leave_serv_hud(owner) - - assigned_targets.Cut() - SSticker.mode.traitors -= owner - owner.special_role = null - update_traitor_icons_removed() - - if(!silent && owner.current) - antag_memory = "" - to_chat(owner.current," You are no longer a [special_role]! ") - ..() - - -/datum/antagonist/traitor/apply_innate_effects() - . = ..() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - to_chat(traitor_mob, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.") - traitor_mob.mutations.Remove(CLUMSY) - - -/datum/antagonist/traitor/remove_innate_effects() - . = ..() - if(owner.assigned_role == "Clown") - var/mob/living/carbon/human/traitor_mob = owner.current - if(traitor_mob && istype(traitor_mob)) - traitor_mob.mutations.Add(CLUMSY) - -// Adding/removing objectives in the owner's mind until we can datumize all antags. Then we can use the /datum/antagonist/objectives var to handle them -// Change "owner.objectives" to "objectives" once objectives are handled in antag datums instead of the mind -/datum/antagonist/traitor/proc/add_objective(datum/objective/O) - owner.objectives += O - -/datum/antagonist/traitor/proc/remove_objective(datum/objective/O) - owner.objectives -= O - - -/datum/antagonist/traitor/proc/forge_traitor_objectives() - switch(traitor_kind) - if(TRAITOR_AI) - forge_ai_objectives() - else - forge_human_objectives() - - -/datum/antagonist/traitor/proc/forge_human_objectives() - var/is_hijacker = prob(10) - var/martyr_chance = prob(20) - var/objective_count = is_hijacker //Hijacking counts towards number of objectives - if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors - if(!SSticker.mode.exchange_red) - SSticker.mode.exchange_red = owner - else - SSticker.mode.exchange_blue = owner - assign_exchange_role(SSticker.mode.exchange_red) - assign_exchange_role(SSticker.mode.exchange_blue) - objective_count += 1 //Exchange counts towards number of objectives - - - var/objective_amount = config.traitor_objectives_amount - - if(is_hijacker && objective_count <= objective_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount - if (!(locate(/datum/objective/hijack) in objectives)) - var/datum/objective/hijack/hijack_objective = new - hijack_objective.owner = owner - add_objective(hijack_objective) - return - - for(var/i = objective_count, i < objective_amount) - i += forge_single_objective() - - var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead. - for(var/datum/objective/O in owner.objectives) - if(!O.martyr_compatible) - martyr_compatibility = 0 - break - - if(martyr_compatibility && martyr_chance) - var/datum/objective/die/martyr_objective = new - martyr_objective.owner = owner - add_objective(martyr_objective) - return - - if(!(locate(/datum/objective/escape) in objectives)) - var/datum/objective/escape/escape_objective = new - escape_objective.owner = owner - add_objective(escape_objective) - return - - -/datum/antagonist/traitor/proc/forge_ai_objectives() - var/objective_count = 0 - var/try_again = TRUE - - if(prob(30)) - objective_count += forge_single_objective() - - for(var/i = objective_count, i < config.traitor_objectives_amount) - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = owner - kill_objective.find_target() - if("[kill_objective.target]" in assigned_targets) // In the rare case the game can't find a target for the AI thats not a duplicate - if(try_again) // It will attempt to location another target ONCE - try_again = FALSE // This code will really only come into play on lowpop rounds where getting duplicate targets is more common - continue - assigned_targets.Add("[kill_objective.target]") - add_objective(kill_objective) - i += 1 - var/datum/objective/survive/survive_objective = new - survive_objective.owner = owner - add_objective(survive_objective) - - -/datum/antagonist/traitor/proc/forge_single_objective() - switch(traitor_kind) - if(TRAITOR_AI) - return forge_single_AI_objective() - else - return forge_single_human_objective() - - -/datum/antagonist/traitor/proc/forge_single_human_objective() // Returns how many objectives are added - . = 1 - if(prob(50)) - var/list/active_ais = active_ais() - if(active_ais.len && prob(100/GLOB.player_list.len)) - var/datum/objective/destroy/destroy_objective = new - destroy_objective.owner = owner - destroy_objective.find_target() - if("[destroy_objective]" in assigned_targets) // Is this target already in their list of assigned targets? If so, don't add this objective and return - return 0 - else if(destroy_objective.target) // Is the target a real one and not null? If so, add it to our list of targets to avoid duplicate targets - assigned_targets.Add("[destroy_objective.target]") // This logic is applied to all traitor objectives including steal objectives - add_objective(destroy_objective) - - else if(prob(5)) - var/datum/objective/debrain/debrain_objective = new - debrain_objective.owner = owner - debrain_objective.find_target() - if("[debrain_objective]" in assigned_targets) - return 0 - else if(debrain_objective.target) - assigned_targets.Add("[debrain_objective.target]") - add_objective(debrain_objective) - - else if(prob(30)) - var/datum/objective/maroon/maroon_objective = new - maroon_objective.owner = owner - maroon_objective.find_target() - if("[maroon_objective]" in assigned_targets) - return 0 - else if(maroon_objective.target) - assigned_targets.Add("[maroon_objective.target]") - add_objective(maroon_objective) - - else - var/datum/objective/assassinate/kill_objective = new - kill_objective.owner = owner - kill_objective.find_target() - if("[kill_objective.target]" in assigned_targets) - return 0 - else if(kill_objective.target) - assigned_targets.Add("[kill_objective.target]") - add_objective(kill_objective) - - else - var/datum/objective/steal/steal_objective = new - steal_objective.owner = owner - steal_objective.find_target() - if("[steal_objective.steal_target]" in assigned_targets) - return 0 - else if(steal_objective.steal_target) - assigned_targets.Add("[steal_objective.steal_target]") - add_objective(steal_objective) - - -/datum/antagonist/traitor/proc/forge_single_AI_objective() - . = 1 - var/special_pick = rand(1,2) - switch(special_pick) - if(1) // AI hijack - var/datum/objective/block/block_objective = new - block_objective.owner = owner - add_objective(block_objective) - if(2) // Protect and strand a target - var/datum/objective/protect/yandere_one = new - yandere_one.owner = owner - yandere_one.find_target() - - if("[yandere_one.target]" in assigned_targets) - return 0 - else if(yandere_one.target) - assigned_targets.Add("[yandere_one.target]") - - add_objective(yandere_one) - var/datum/objective/maroon/yandere_two = new - yandere_two.owner = owner - yandere_two.target = yandere_one.target - yandere_two.explanation_text = "Prevent [yandere_one.target], the [yandere_one.target.assigned_role] from escaping alive." - add_objective(yandere_two) - - -/datum/antagonist/traitor/greet() - to_chat(owner.current, "You are a [owner.special_role]!") - if(!LAZYLEN(owner.objectives)) // Remove "owner" when objectives are handled in the datum - to_chat(owner.current, "You don't have any objectives right now.") - else - owner.announce_objectives() - if(should_give_codewords) - give_codewords() - - -/datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind) - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] - traitorhud.join_hud(owner.current, null) - set_antag_hud(owner.current, "hudsyndicate") - - -/datum/antagonist/traitor/proc/update_traitor_icons_removed(datum/mind/traitor_mind) - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] - traitorhud.leave_hud(owner.current, null) - set_antag_hud(owner.current, null) - - -/datum/antagonist/traitor/proc/finalize_traitor() - switch(traitor_kind) - if(TRAITOR_AI) - add_law_zero() - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/malf.ogg', 100, FALSE, pressure_affected = FALSE) - var/mob/living/silicon/ai/A = owner.current - A.show_laws() - if(TRAITOR_HUMAN) - if(should_equip) - equip_traitor() - owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) - - -/datum/antagonist/traitor/proc/give_codewords() - if(!owner.current) - return - var/mob/traitor_mob = owner.current - - var/phrases = jointext(GLOB.syndicate_code_phrase, ", ") - var/responses = jointext(GLOB.syndicate_code_response, ", ") - - to_chat(traitor_mob, "The Syndicate have provided you with the following codewords to identify fellow agents:") - to_chat(traitor_mob, "Code Phrase: [phrases]") - to_chat(traitor_mob, "Code Response: [responses]") - - antag_memory += "Code Phrase: [phrases]
" - antag_memory += "Code Response: [responses]
" - - to_chat(traitor_mob, "Use the codewords during regular conversation to identify other agents. Proceed with caution, however, as everyone is a potential foe.") - - -/datum/antagonist/traitor/proc/add_law_zero() - var/mob/living/silicon/ai/killer = owner.current - if(!killer || !istype(killer)) - return - var/law = "Accomplish your objectives at all costs." - var/law_borg = "Accomplish your AI's objectives at all costs." - killer.set_zeroth_law(law, law_borg) - killer.set_syndie_radio() - to_chat(killer, "Your radio has been upgraded! Use :t to speak on an encrypted channel with Syndicate Agents!") - killer.add_malf_picker() - - -/datum/antagonist/traitor/proc/equip_traitor() - - if(traitor_kind == TRAITOR_HUMAN) - var/mob/living/carbon/human/traitor_mob = owner.current - - // find a radio! toolbox(es), backpack, belt, headset - var/obj/item/R = locate(/obj/item/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio - if(!R) - R = locate(/obj/item/radio) in traitor_mob.contents - - if(!R) - to_chat(traitor_mob, "Unfortunately, the Syndicate wasn't able to get you a radio.") - . = 0 - else - if(istype(R, /obj/item/radio)) - // generate list of radio freqs - var/obj/item/radio/target_radio = R - var/freq = PUBLIC_LOW_FREQ - var/list/freqlist = list() - while(freq <= PUBLIC_HIGH_FREQ) - if(freq < 1451 || freq > 1459) - freqlist += freq - freq += 2 - if((freq % 2) == 0) - freq += 1 - freq = freqlist[rand(1, freqlist.len)] - - var/obj/item/uplink/hidden/T = new(R) - target_radio.hidden_uplink = T - T.uplink_owner = "[traitor_mob.key]" - target_radio.traitor_frequency = freq - to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features.") - traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name]).") - else if(istype(R, /obj/item/pda)) - // generate a passcode if the uplink is hidden in a PDA - var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]" - - var/obj/item/uplink/hidden/T = new(R) - R.hidden_uplink = T - T.uplink_owner = "[traitor_mob.key]" - var/obj/item/pda/P = R - P.lock_code = pda_pass - - to_chat(traitor_mob, "The Syndicate have cunningly disguised a Syndicate Uplink as your [R.name]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features.") - antag_memory += ("Uplink Passcode: [pda_pass] ([R.name].") - return 1 - - -/datum/antagonist/traitor/proc/assign_exchange_role(var/datum/mind/owner) - //set faction - var/faction = "red" - if(owner == SSticker.mode.exchange_blue) - faction = "blue" - - //Assign objectives - var/datum/objective/steal/exchange/exchange_objective = new - exchange_objective.set_faction(faction,((faction == "red") ? SSticker.mode.exchange_blue : SSticker.mode.exchange_red)) - exchange_objective.owner = owner - owner.objectives += exchange_objective - - if(prob(20)) - var/datum/objective/steal/exchange/backstab/backstab_objective = new - backstab_objective.set_faction(faction) - backstab_objective.owner = owner - owner.objectives += backstab_objective - - //Spawn and equip documents - var/mob/living/carbon/human/mob = owner.current - - var/obj/item/folder/syndicate/folder - if(owner == SSticker.mode.exchange_red) - folder = new/obj/item/folder/syndicate/red(mob.locs) - else - folder = new/obj/item/folder/syndicate/blue(mob.locs) - - var/list/slots = list ( - "backpack" = slot_in_backpack, - "left pocket" = slot_l_store, - "right pocket" = slot_r_store, - "left hand" = slot_l_hand, - "right hand" = slot_r_hand, - ) - - var/where = "At your feet" - var/equipped_slot = mob.equip_in_one_of_slots(folder, slots) - if(equipped_slot) - where = "In your [equipped_slot]" - to_chat(mob, "

[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.
") - mob.update_icons() - - -/datum/antagonist/traitor/roundend_report_footer() - var/phrases = jointext(GLOB.syndicate_code_phrase, ", ") - var/responses = jointext(GLOB.syndicate_code_response, ", ") - - var message = "
The code phrases were: [phrases]
\ - The code responses were: [responses]
" - - return message diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2942ace8ee2..7b3162fdefb 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -740,7 +740,7 @@ /obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf) - if(istype(malf) && malf.mind.has_antag_datum(/datum/antagonist/traitor)) + if(istype(malf) && malf.malf_picker) if(malfai == (malf.parent || malf)) if(occupier == malf) return 3 // 3 = User is shunted in this APC diff --git a/paradise.dme b/paradise.dme index 081fa228da5..bdb77b45dd0 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1236,8 +1236,6 @@ #include "code\modules\antagonists\_common\antag_hud.dm" #include "code\modules\antagonists\_common\antag_spawner.dm" #include "code\modules\antagonists\_common\antag_team.dm" -#include "code\modules\antagonists\traitor\datum_mindslave.dm" -#include "code\modules\antagonists\traitor\datum_traitor.dm" #include "code\modules\antagonists\wishgranter\wishgranter.dm" #include "code\modules\arcade\arcade_base.dm" #include "code\modules\arcade\arcade_prize.dm"