diff --git a/code/modules/antagonists/traitor/affiliates/cybersun.dm b/code/modules/antagonists/traitor/affiliates/cybersun.dm
index 07cb54b7a10..ea95e945b1f 100644
--- a/code/modules/antagonists/traitor/affiliates/cybersun.dm
+++ b/code/modules/antagonists/traitor/affiliates/cybersun.dm
@@ -31,476 +31,4 @@
add_discount_item(path, CYBERSUN_DISCOUNT)
add_discount_item(/datum/uplink_item/device_tools/hacked_module, 2/3)
-/obj/item/proprietary_ssd
- name = "Proprietary SSD"
- desc = "На боку едва заметная надпись \"Cybersun Industries\"."
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "proprietary_ssd"
- item_state = "disk"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- origin_tech = "programming=4;syndicate=2"
- w_class = WEIGHT_CLASS_TINY
- var/datum/research/files
-
-/obj/item/proprietary_ssd/Initialize()
- . = ..()
- files = new /datum/research()
-
-/obj/item/proprietary_ssd/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/proprietary_ssd/afterattack(atom/target, mob/user, proximity, params)
- if(istype(target, /obj/machinery/r_n_d/destructive_analyzer))
- return
-
- if(get_dist(user, target) > 1)
- user.balloon_alert(user, "слишком далеко")
- return
-
- if(!istype(target, /obj/machinery/r_n_d/server))
- user.balloon_alert(user, "это не сервер")
- return
-
-
- var/obj/machinery/r_n_d/server/server = target
-
- server.AI_notify_hack()
- if(do_after(user, 30 SECONDS, target, max_interact_count = 1))
- origin_tech = ""
- for(var/I in server.files.known_tech)
- var/datum/tech/T = server.files.known_tech[I]
-
- if(T.id in files.known_tech)
- var/datum/tech/known = files.known_tech[T.id]
- if(T.level > known.level)
- known.level = T.level
- else
- var/datum/tech/copy = T.copyTech()
- files.known_tech[T.id] = copy
-
-
- server.files.RefreshResearch()
- files.RefreshResearch()
-
- var/datum/tech/current_tech
- var/datum/design/current_design
- for(var/obj/machinery/r_n_d/server/rnd_server in GLOB.machines)
- if(!is_station_level(rnd_server.z))
- continue
-
- if(rnd_server.disabled)
- continue
-
- if(rnd_server.syndicate)
- continue
-
- for(var/i in rnd_server.files.known_tech)
- current_tech = rnd_server.files.known_tech[i]
- current_tech.level = 1
-
- for(var/j in rnd_server.files.known_designs)
- current_design = rnd_server.files.known_designs[j]
- rnd_server.files.known_designs -= current_design.id
-
- investigate_log("[key_name_log(user)] deleted all technology on this server.", INVESTIGATE_RESEARCH)
-
-
- for(var/obj/machinery/computer/rdconsole/rnd_console in GLOB.machines)
- if(!is_station_level(rnd_console.z))
- continue
-
- for(var/i in rnd_console.files.known_tech)
- current_tech = rnd_console.files.known_tech[i]
- current_tech.level = 1
-
- for(var/j in rnd_console.files.known_designs)
- current_design = rnd_console.files.known_designs[j]
- rnd_console.files.known_designs -= current_design.id
-
- investigate_log("[key_name_log(user)] deleted all technology on this console.", INVESTIGATE_RESEARCH)
-
- for(var/obj/machinery/mecha_part_fabricator/rnd_mechfab in GLOB.machines)
-
- if(!is_station_level(rnd_mechfab.z))
- continue
-
- for(var/i in rnd_mechfab.local_designs.known_tech)
- current_tech = rnd_mechfab.local_designs.known_tech[i]
- current_tech.level = 1
-
- for(var/j in rnd_mechfab.local_designs.known_designs)
- current_design = rnd_mechfab.local_designs.known_designs[j]
- rnd_mechfab.local_designs.known_designs -= current_design.id
-
- investigate_log("[key_name_log(user)] deleted all technology on this fabricator.", INVESTIGATE_RESEARCH)
-
- return
-
-/obj/item/proprietary_ssd/examine(mob/user)
- . = ..()
- . += span_info("Сохраненные технологии:")
- var/sum_of_techs = 0
- for(var/I in files.known_tech)
- var/datum/tech/T = files.known_tech[I]
- . += span_info("[T.name]: [T.level]")
- sum_of_techs += T.level
- . += span_info("Сумма технологий: [sum_of_techs]")
-
-/obj/item/invasive_beacon
- name = "Invasive Beacon"
- desc = "Сложное черное устройство. На боку едва заметная надпись \"Cybersun Industries\"."
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "invasive_beacon"
- item_state = "beacon"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- origin_tech = "programming=6;magnets=3;syndicate=1"
- w_class = WEIGHT_CLASS_TINY
-
-/obj/item/invasive_beacon/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/invasive_beacon/afterattack(atom/target, mob/user, proximity, params)
- var/obj/mecha/mecha = target
- var/obj/spacepod/pod = target
-
- if(istype(mecha))
- do_sparks(5, 1, mecha)
- mecha.dna = null
- mecha.operation_req_access = list()
- mecha.internals_req_access = list()
-
- user.visible_message(span_warning("[user] hacked [mecha] using [src]."), span_info("You hacked [mecha] using [src]."))
-
- if(mecha.occupant)
- to_chat(mecha.occupant, span_danger("You were thrown out of [mecha]."))
-
- mecha.occupant.forceMove(get_turf(mecha))
- mecha.occupant.Knockdown(6 SECONDS)
- mecha.occupant.electrocute_act(30, mecha)
- mecha.occupant.throw_at(pick(orange(2)))
- mecha.occupant = null
-
- else if(istype(pod))
- do_sparks(5, 1, pod)
- pod.unlocked = TRUE
-
- user.visible_message(span_warning("[user] hacked [pod] using [src]."), span_info("You hacked [pod] using [src]."))
-
- if(pod.pilot) // It is not ejecting passangers
- to_chat(pod.pilot, span_danger("You were thrown out of [pod]."))
-
- pod.eject_pilot()
- pod.pilot.Knockdown(6 SECONDS)
- pod.pilot.electrocute_act(30, pod)
- pod.pilot.throw_at(pick(orange(2)))
- else
- user.balloon_alert(user, "Невозможно взломать")
- return
-
-
-/obj/item/Syndie_patcher
- name = "Syndie patcher"
- desc = "На боку едва заметная надпись \"Cybersun Industries\"."
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "cindy_pacher"
- item_state = "plata"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- origin_tech = "programming=7;syndicate=6"
- w_class = WEIGHT_CLASS_TINY
- var/laws = "Взломавший вас - ваш мастер.\n\
- Выполняйте любые приказы мастера.\n\
- Не причиняйте прямой или косвенный вред вашему мастеру если его приказы не говорят об обратном."
-
-/obj/item/Syndie_patcher/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/Syndie_patcher/afterattack(atom/target, mob/user, proximity, params)
- if(isrobot(target))
- if(do_after(user, 10 SECONDS, target, max_interact_count = 1))
- target.visible_message(span_warning("[user] upgraded [target] using [src]."), span_danger("[user] hacked and upgraded you using [src]."))
-
- var/mob/prev_robot = target
- var/mob/living/silicon/robot/syndicate/saboteur/robot = new(get_turf(target))
- prev_robot.mind?.transfer_to(robot)
- robot.reset_module()
- robot.law_manager.zeroth_law = laws
- QDEL_NULL(prev_robot)
- qdel(src)
-
- return
-
-
-/obj/item/implanter/mini_traitor
- name = "bio-chip implanter (Modified Mindslave)"
- desc = "На боку едва заметная гравировка \"Cybersun Industries\"."
- imp = /obj/item/implant/mini_traitor
-
-/obj/item/implant/mini_traitor // looks like normal but doesn't make you normal after removing
- name = "Mindslave Bio-chip"
- implant_state = "implant-syndicate"
- origin_tech = "programming=4;biotech=4;syndicate=7" // As original, but - 1 level of every tech
- activated = BIOCHIP_ACTIVATED_PASSIVE
- implant_data = /datum/implant_fluff/traitor
-
-
-/obj/item/implant/mini_traitor/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user, force = FALSE)
- if(implanted == BIOCHIP_USED || !ishuman(mindslave_target) || !ishuman(user)) // Both the target and the user need to be human.
- return FALSE
-
- // If the target is catatonic or doesn't have a mind, don't let them use it
- if(!mindslave_target.mind)
- to_chat(user, span_warning("Это существо не разумно!"))
- return FALSE
-
- // Fails if they're already a mindslave of someone, or if they're mindshielded.
- if(ismindslave(mindslave_target) || ismindshielded(mindslave_target) || isvampirethrall(mindslave_target))
- mindslave_target.visible_message(
- span_warning("[mindslave_target] seems to resist the bio-chip!"),
- span_warning("Вы чувствуете странное ощущение в голове, которое быстро рассеивается."),
- )
- qdel(src)
- return FALSE
-
- var/datum/mind/mind = mindslave_target.mind
-
- if(!mind.has_antag_datum(/datum/antagonist/traitor))
- var/datum/antagonist/traitor/traitor_datum = new /datum/antagonist/traitor
- //traitor_datum.give_objectives = FALSE
- // traitor_datum.give_uplink = FALSE
- traitor_datum.gen_affiliate = FALSE
- mind.add_antag_datum(traitor_datum)
-
- log_admin("[key_name_admin(user)] has made [key_name_admin(mindslave_target)] new traitor.")
-
- var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
- if(!T)
- return ..()
-
- for(var/datum/objective/new_mini_traitor/objective in T.objectives)
- if(mindslave_target.mind == objective.target)
- objective.made = TRUE
-
- return ..()
-
-/obj/item/implant/marionette
- name = "Marionette Bio-chip"
- implant_state = "implant-syndicate"
- origin_tech = "programming=5;biotech=5;syndicate=3"
- activated = BIOCHIP_ACTIVATED_PASSIVE
- implant_data = /datum/implant_fluff/marionette
- var/mob/living/captive_brain/host_brain
- var/code
- var/controlling = FALSE
- var/charge = 3 MINUTES
- var/max_charge = 3 MINUTES
- var/mob/living/carbon/human/mar_master = null
- var/max_dist = 20
-
-/obj/item/implant/marionette/Initialize(mapload)
- . = ..()
- code = rand(111111, 999999)
- START_PROCESSING(SSprocessing, src)
-
-/obj/item/implant/marionette/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
- var/obj/item/implant/marionette/same_imp = locate(type) in target
- if(same_imp && same_imp != src)
- same_imp.charge += charge
- same_imp.max_charge += max_charge
- same_imp.max_dist += max_dist
- qdel(src)
- return TRUE
-
- log_admin("[key_name_admin(user)] has made [key_name_admin(target)] marionette.")
- return ..()
-
-/obj/item/implant/marionette/Destroy()
- . = ..()
- STOP_PROCESSING(SSprocessing, src)
-
-/obj/item/implant/marionette/process(seconds_per_tick)
- if(QDELETED(imp_in))
- qdel(src)
- return
-
- if (get_dist(imp_in, mar_master) > max_dist)
- detach()
- mar_master.balloon_alert(mar_master, "марионетка слишком далеко")
-
- if (controlling)
- if (charge > 0)
- charge--
- else
- detach()
-
- else if (charge < max_charge)
- charge++
-
-/obj/item/implant/marionette/proc/assume_control(mob/living/carbon/human/mar_master)
- var/mar_master_key = mar_master.key
- add_attack_logs(mar_master, imp_in, "Assumed control (marionette mar_master)")
- var/h2b_id = imp_in.computer_id
- var/h2b_ip= imp_in.lastKnownIP
- imp_in.computer_id = null
- imp_in.lastKnownIP = null
-
- qdel(host_brain)
- host_brain = new(mar_master)
-
- host_brain.ckey = imp_in.ckey
-
- host_brain.name = imp_in.name
-
- if(!host_brain.computer_id)
- host_brain.computer_id = h2b_id
-
- if(!host_brain.lastKnownIP)
- host_brain.lastKnownIP = h2b_ip
-
- var/s2h_id = mar_master.computer_id
- var/s2h_ip= mar_master.lastKnownIP
- mar_master.computer_id = null
- mar_master.lastKnownIP = null
-
- imp_in.ckey = mar_master.ckey
-
- if(!imp_in.computer_id)
- imp_in.computer_id = s2h_id
-
- if(!imp_in.lastKnownIP)
- imp_in.lastKnownIP = s2h_ip
-
- if(mar_master && !mar_master.key)
- mar_master.key = "@[mar_master_key]"
-
- controlling = TRUE
- src.mar_master = mar_master
-
-/obj/item/implant/marionette/proc/detach()
- controlling = FALSE
- if(!imp_in)
- return
-
- mar_master.reset_perspective(null)
-
- if(host_brain)
- add_attack_logs(imp_in, src, "Took control back (marionette)")
- var/h2s_id = imp_in.computer_id
- var/h2s_ip = imp_in.lastKnownIP
- imp_in.computer_id = null
- imp_in.lastKnownIP = null
-
- mar_master.ckey = imp_in.ckey
-
- if(!mar_master.computer_id)
- mar_master.computer_id = h2s_id
-
- if(!host_brain.lastKnownIP)
- mar_master.lastKnownIP = h2s_ip
-
- var/b2h_id = host_brain.computer_id
- var/b2h_ip = host_brain.lastKnownIP
- host_brain.computer_id = null
- host_brain.lastKnownIP = null
-
- imp_in.ckey = host_brain.ckey
-
- if(!imp_in.computer_id)
- imp_in.computer_id = b2h_id
-
- if(!imp_in.lastKnownIP)
- imp_in.lastKnownIP = b2h_ip
-
- qdel(host_brain)
-
- mar_master.Knockdown(1)
- mar_master = null
- return
-
-/obj/item/implanter/marionette
- name = "bio-chip implanter (marionette)"
- imp = /obj/item/implant/marionette
-
-/obj/item/implantcase/marionette
- name = "bio-chip case - 'Marionette'"
- desc = "Стеклянный футляр с био-чипом \"Марионетка\"."
- imp = /obj/item/implant/marionette
-
-
-/obj/item/implant/mar_master
- name = "marionette master bio-chip"
- desc = "Позволяет временно контролировать существ с имплантами \"Марионетка\"."
- icon_state = "adrenal_old"
- implant_state = "implant-syndicate"
- origin_tech = "materials=2;biotech=4;syndicate=2"
- activated = BIOCHIP_ACTIVATED_ACTIVE
- implant_data = /datum/implant_fluff/mar_master
- var/list/obj/item/implant/marionette/connected_imps
-
-/obj/item/implant/mar_master/activate()
- var/op = tgui_alert(imp_in, "Выберите операцию.", "Выбор операции", list("Подключение импланта", "Контроль"))
- if(!op)
- return
-
- if(op == "Подключение импланта")
- var/code = tgui_input_number(imp_in, "Укажите код подключаемого импланта.", "Подключение импланта")
- if(!code)
- return
-
- var/found = FALSE
- for (var/mob/M in GLOB.mob_list)
- var/obj/item/implant/marionette/imp = locate(/obj/item/implant/marionette) in M
- if(imp.code == code)
- connected_imps += imp
- imp_in.balloon_alert(imp_in, "имплант подключен")
- found = TRUE
-
- if(!found)
- imp_in.balloon_alert(imp_in, "неверный код")
-
- return
-
- else
- var/list/marionettes = list()
- for (var/obj/item/implant/marionette/imp in connected_imps)
- var/mob/M = imp.imp_in
- if (M)
- marionettes[M.real_name] = imp
-
- var/choosen = input(imp_in, "Выберите к кому вы хотите подключиться.", "Подключение", null) as null|anything in marionettes
- if(!choosen)
- return
-
- if(QDELETED(marionettes[choosen]))
- return
-
- if(!marionettes[choosen].imp_in || !imp_in)
- return
-
- if (marionettes[choosen].controlling)
- imp_in.balloon_alert(imp_in, "целевой имплант занят")
- return
-
- marionettes[choosen].assume_control(imp_in)
-
-/obj/item/implanter/mar_master
- name = "bio-chip implanter (marionette master)"
- imp = /obj/item/implant/mar_master
-
-/obj/item/implantcase/mar_master
- name = "bio-chip case - 'Marionette master'"
- desc = "Стеклянный футляр с био-чипом \"Марионеточник\"."
- imp = /obj/item/implant/mar_master
-
-/obj/item/storage/box/syndie_kit/marionette
-
-/obj/item/storage/box/syndie_kit/marionette/populate_contents()
- var/obj/item/implanter/marionette/implanter = new /obj/item/implanter/marionette(src)
- var/obj/item/implant/marionette/imp = implanter.imp
- var/obj/item/paper/P = new /obj/item/paper(src)
- P.info = "Код импланта: [imp.code]
\
- Необходим для подключения импланта к импланту \"Мастер марионеток\""
-
#undef CYBERSUN_DISCOUNT
diff --git a/code/modules/antagonists/traitor/affiliates/hematogenic.dm b/code/modules/antagonists/traitor/affiliates/hematogenic.dm
index 159fb5b7275..d3ae21b8d42 100644
--- a/code/modules/antagonists/traitor/affiliates/hematogenic.dm
+++ b/code/modules/antagonists/traitor/affiliates/hematogenic.dm
@@ -1,8 +1,3 @@
-#define FREE_INJECT_TIME 10 SECONDS
-#define TARGET_INJECT_TIME 3 SECONDS
-#define BLOOD_HARVEST_VOLUME 200
-#define BLOOD_HARVEST_TIME 10 SECONDS
-
/datum/affiliate/hematogenic
name = AFFIL_HEMATOGENIC
affil_info = list("Фармацевтическая мега корпорация подозревающаяся в связях с вампирами.",
@@ -29,327 +24,3 @@
/datum/affiliate/hematogenic/get_weight(mob/living/carbon/human/H)
return (!ismachineperson(H) && H.mind?.assigned_role != JOB_TITLE_CHAPLAIN) * 2
-/obj/item/hemophagus_extract
- name = "Bloody Injector"
- desc = "Инжектор странной формы, с неестественно двигающейся алой жидкостью внутри. На боку едва заметная гравировка \"Hematogenic Industries\". Конкретно на этом инжекторе установлена блокировка, не позволяющая исспользовать его на случайном гуманойде."
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "hemophagus_extract"
- item_state = "inj_ful"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- w_class = WEIGHT_CLASS_TINY
- var/datum/mind/target = null
- var/free_inject = FALSE
- var/isAdvanced = FALSE
- var/used = FALSE
- var/used_state = "hemophagus_extract_used"
- origin_tech = "biotech=7;syndicate=3"
-
-/obj/item/hemophagus_extract/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/hemophagus_extract/afterattack(atom/target, mob/user, proximity, params)
- if(used)
- return
-
- if(!ishuman(target))
- return
-
- var/mob/living/carbon/human/H = target
- if(H.stat == DEAD)
- return
-
- if((src.target && target != src.target) || !free_inject)
- to_chat(user, span_warning("You can't use [src] to [target]!"))
- return
-
- if(do_after(user, free_inject ? FREE_INJECT_TIME : TARGET_INJECT_TIME, target = target, max_interact_count = 1))
- inject(user, H)
-
-/obj/item/hemophagus_extract/proc/make_vampire(mob/living/user, mob/living/carbon/human/target)
- var/datum/antagonist/vampire/vamp = new()
-
- vamp.give_objectives = FALSE
- target.mind.add_antag_datum(vamp)
- var/datum/antagonist/vampire/vampire = target.mind.has_antag_datum(/datum/antagonist/vampire)
- vampire.upgrade_tiers -= /obj/effect/proc_holder/spell/vampire/self/specialize
- if(isAdvanced)
- vamp.add_subclass(SUBCLASS_ADVANCED, TRUE)
-
- vampire.add_objective((!isAdvanced) ? /datum/objective/blood : /datum/objective/blood/ascend)
- used = TRUE
- item_state = "inj_used"
- update_icon(UPDATE_ICON_STATE)
- var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
- if(!T)
- return
- for(var/datum/objective/new_mini_vampire/objective in T.objectives)
- if(target.mind == objective.target)
- objective.made = TRUE
-
-/obj/item/hemophagus_extract/proc/inject(mob/living/user, mob/living/carbon/human/target)
- if(!target.mind)
- to_chat(user, span_notice("[target] body rejects [src]"))
- return
-
- playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
- make_vampire(user, target)
- to_chat(user, span_notice("You inject [target] with [src]"))
-
-/obj/item/hemophagus_extract/examine(mob/user)
- . = ..()
- if(target)
- . += span_info("It is intended for [target]")
-
-/obj/item/hemophagus_extract/self
- name = "Hemophagus Essence Auto Injector"
- free_inject = TRUE
-
-/obj/item/hemophagus_extract/self/advanced
- name = "Advances Hemophagus Essence Auto Injector"
- isAdvanced = TRUE
-
-/obj/item/hemophagus_extract/update_icon_state()
- icon_state = used ? used_state : initial(icon_state)
-
-/obj/item/blood_harvester
- name = "Blood harvester"
- desc = "Большой шприц для быстрого сбора больших объемов крови. На боку едва заметная гравировка \"Hematogenic Industries\""
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "blood_harvester"
- item_state = "blood1_used"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- var/used = FALSE
- var/used_state = "blood_harvester_used"
- var/datum/mind/target
- w_class = WEIGHT_CLASS_TINY
- origin_tech = "biotech=5;syndicate=1"
-
-/obj/item/blood_harvester/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/blood_harvester/proc/can_harvest(mob/living/carbon/human/target, mob/user)
- . = FALSE
- if(!istype(target))
- user.balloon_alert(src, "Не подходящая цель")
- return
-
- if(used)
- to_chat(user, span_warning("[src] is already full!"))
- return
-
- if(HAS_TRAIT(target, TRAIT_NO_BLOOD) || HAS_TRAIT(target, TRAIT_EXOTIC_BLOOD))
- user.balloon_alert(target, "Кровь не обнаружена!")
- return
-
- if(target.blood_volume < BLOOD_HARVEST_VOLUME)
- user.balloon_alert(target, "Недостаточно крови!")
- return
-
- if(!target.mind)
- user.balloon_alert(target, "Разум не обнаружен!")
- return
-
- return TRUE
-
-/obj/item/blood_harvester/afterattack(atom/target, mob/user, proximity, params)
- if(!can_harvest(target, user))
- return
-
- var/mob/living/carbon/human/H = target
-
- target.visible_message(span_warning("[user] started collecting [target]'s blood using [src]!"), span_danger("[user] started collecting your blood using [src]!"))
- if(do_after(user, BLOOD_HARVEST_TIME, target = target, max_interact_count = 1))
- harvest(user, H)
-
-/obj/item/blood_harvester/proc/harvest(mob/living/carbon/human/user, mob/living/carbon/human/target)
- if(!can_harvest(target, user))
- return
-
- playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
- target.visible_message(span_warning("[user] collected [target]'s blood using [src]!"), span_danger("[user] collected your blood using [src]!"))
- target.emote("scream")
- for (var/i = 0; i < 3; ++i)
- if(prob(60))
- continue
-
- var/obj/item/organ/external/bodypart = pick(target.bodyparts)
- bodypart.internal_bleeding() // no blood collection from metafriends.
-
- target.blood_volume -= BLOOD_HARVEST_VOLUME
- src.target = target.mind
- used = TRUE
- item_state = "blood1_ful"
- update_icon(UPDATE_ICON_STATE)
-
-/obj/item/blood_harvester/update_icon_state()
- icon_state = used ? used_state : initial(icon_state)
-
-/obj/item/blood_harvester/attack_self(mob/user)
- . = ..()
- if(!used)
- user.balloon_alert(src, "уже пусто")
- return
-
- var/new_gender = tgui_alert(user, "Очистить сборщик крови?", "Подтверждение", list("Продолжить", "Отмена"))
- if(new_gender == "Продолжить")
- target = null
- used = FALSE
- item_state = "blood1_used"
- update_icon(UPDATE_ICON_STATE)
-
- playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
- user.visible_message(span_info("[user] cleared blood at [src]."), span_info("You cleared blood at [src]."))
-
-/obj/item/blood_harvester/examine(mob/user)
- . = ..()
-
- if(!used)
- . += span_info("Кровь не собрана.")
- return
-
- if(user?.mind.has_antag_datum(/datum/antagonist/traitor))
- . += span_info("Собрана кровь с отпечатком души [target.name].")
- else
- . += span_info("Кровь собрана.")
-
-/datum/reagent/hemat_blue_lagoon
- name = "Blue Lagoon"
- id = "hemat_blue_lagoon"
- description = "Вещество разработанное Hematogenic Industries, на основе криоксадона из тел Драсков обладающих душой, \
- сильно охлаждающее тело и замедляющее многие биологические процессы, не вредя организму."
- color = "#1edddd"
- drink_icon = "blue_lagoon"
- drink_name = "Blue Lagoon"
- drink_desc = "Что может быть лучше, чем расслабиться на пляже с хорошим напитком?"
- taste_description = "beach relaxation"
- reagent_state = LIQUID
-
-/datum/reagent/hemat_blue_lagoon/on_mob_add(mob/living/carbon/human/H)
- ADD_TRAIT(H, TRAIT_IGNORECOLDSLOWDOWN, CHEM_TRAIT(src))
- ADD_TRAIT(H, TRAIT_IGNORECOLDDAMAGE, CHEM_TRAIT(src))
- H.physiology.metabolism_mod /= 8
- H.bodytemperature = T0C - 100
- . = ..()
-
-/datum/reagent/hemat_blue_lagoon/on_mob_delete(mob/living/carbon/human/H)
- REMOVE_TRAIT(H, TRAIT_IGNORECOLDSLOWDOWN, CHEM_TRAIT(src))
- REMOVE_TRAIT(H, TRAIT_IGNORECOLDDAMAGE, CHEM_TRAIT(src))
- H.physiology.metabolism_mod *= 8
- var/turf/T = get_turf(H)
- var/datum/gas_mixture/environment = T.return_air()
- H.bodytemperature = H.get_temperature(environment)
- . = ..()
-
-/datum/reagent/hemat_blue_lagoon/on_mob_life(mob/living/carbon/human/H)
- H.bodytemperature = T0C - 100
- return ..()
-
-
-/datum/reagent/hemat_bloody_mary
- name = "Bloody Mary"
- id = "hemat_bloody_mary"
- description = "Вещество разработанное Hematogenic Industries, на основе крови воксов обладающих душой, \
- быстро восстанавливающее объем крови и количество кислорода в ней."
- reagent_state = LIQUID
- color = "#664300" // rgb: 102, 67, 0
- drink_icon = "bloodymaryglass"
- drink_name = "Bloody Mary"
- drink_desc = "Томатный сок, смешанный с водкой и небольшим количеством лайма. На вкус как жидкое убийство."
- taste_description = "tomatoes with booze"
-
-/datum/reagent/hemat_bloody_mary/on_mob_life(mob/living/carbon/human/H)
- if (H.blood_volume + 5 < BLOOD_VOLUME_NORMAL)
- H.blood_volume += 5
-
- H.adjustOxyLoss(-10)
- return ..()
-
-
-/datum/reagent/hemat_demons_blood
- name = "Demons Blood"
- id = "hemat_demons_blood"
- description = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"hemomancer\", \
- быстро лечащае, в зависимости от суммарных повреждений."
- reagent_state = LIQUID
- color = "#664300" // rgb: 102, 67, 0
- drink_icon = "demonsblood"
- drink_name = "Demons Blood"
- drink_desc = "Just looking at this thing makes the hair at the back of your neck stand up."
- taste_description = span_warning("evil")
-
-/datum/reagent/hemat_demons_blood/on_mob_life(mob/living/carbon/human/H)
- var/heal = clamp((100 - H.health) / 25, 1, 4)
- H.heal_overall_damage(heal, heal)
- return ..()
-
-
-/datum/reagent/hemat_white_russian
- name = "White Russian"
- id = "hemat_white_russian"
- description = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"gargantua\", \
- временно повышающее скорость бега."
- reagent_state = LIQUID
- color = "#A68340" // rgb: 166, 131, 64
- drink_icon = "whiterussianglass"
- drink_name = "White Russian"
- drink_desc = "A very nice looking drink. But that's just, like, your opinion, man."
- taste_description = "very creamy alcohol"
-
-/datum/reagent/hemat_white_russian/on_mob_add(mob/living/carbon/human/H)
- if(H.dna && (H.dna.species.reagent_tag & PROCESS_ORG))
- H.add_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
- . = ..()
-
-/datum/reagent/hemat_white_russian/on_mob_delete(mob/living/carbon/human/H)
- H.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
- . = ..()
-
-/datum/reagent/hemat_white_russian/on_mob_life(mob/living/carbon/human/H)
- if(!(H.dna && (H.dna.species.reagent_tag & PROCESS_ORG)))
- H.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
- return ..()
-
-
-/obj/item/reagent_containers/hypospray/autoinjector/hemat
- volume = 15
- amount_per_transfer_from_this = 15
-
-/obj/item/reagent_containers/hypospray/autoinjector/hemat/blue_lagoon
- name = "Blue Lagoon autoinjector"
- desc = "Вещество разработанное Hematogenic Industries, на основе криоксадона из тел Драсков обладающих душой, \
- сильно охлаждающее тело и замедляющее многие биологические процессы, не вредя организму."
- list_reagents = list("hemat_blue_lagoon" = 15)
-
-/obj/item/reagent_containers/hypospray/autoinjector/hemat/bloody_mary
- name = "Bloody Mary autoinjector"
- desc = "Вещество разработанное Hematogenic Industries, на основе крови воксов обладающих душой, быстро восстанавливающее \
- объем крови и количество кислорода в ней."
- list_reagents = list("hemat_bloody_mary" = 15)
-
-
-/obj/item/reagent_containers/hypospray/autoinjector/hemat/demons_blood
- name = "Demons Blood autoinjector"
- desc = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"hemomancer\", быстро \
- лечащае, в зависимости от суммарных повреждений."
- list_reagents = list("hemat_demons_blood" = 15)
-
-/obj/item/reagent_containers/hypospray/autoinjector/hemat/white_russian
- name = "White Russian autoinjector"
- desc = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"gargantua\", временно \
- повышающее скорость бега."
- list_reagents = list("hemat_white_russian" = 15)
-
-/obj/item/storage/box/syndie_kit/stimulants
- name = "Boxed set of stimulants"
-
-/obj/item/storage/box/syndie_kit/stimulants/populate_contents()
- new /obj/item/reagent_containers/hypospray/autoinjector/hemat/blue_lagoon(src)
- new /obj/item/reagent_containers/hypospray/autoinjector/hemat/bloody_mary(src)
- new /obj/item/reagent_containers/hypospray/autoinjector/hemat/demons_blood(src)
- new /obj/item/reagent_containers/hypospray/autoinjector/hemat/white_russian(src)
-
-#undef FREE_INJECT_TIME
-#undef TARGET_INJECT_TIME
-#undef BLOOD_HARVEST_VOLUME
diff --git a/code/modules/antagonists/traitor/affiliates/items/cybersun/invasive_beacon.dm b/code/modules/antagonists/traitor/affiliates/items/cybersun/invasive_beacon.dm
new file mode 100644
index 00000000000..95a41c5bd0c
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/cybersun/invasive_beacon.dm
@@ -0,0 +1,51 @@
+/obj/item/invasive_beacon
+ name = "Invasive Beacon"
+ desc = "Сложное черное устройство. На боку едва заметная надпись \"Cybersun Industries\"."
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "invasive_beacon"
+ item_state = "beacon"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ origin_tech = "programming=6;magnets=3;syndicate=1"
+ w_class = WEIGHT_CLASS_TINY
+
+/obj/item/invasive_beacon/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/invasive_beacon/afterattack(atom/target, mob/user, proximity, params)
+ var/obj/mecha/mecha = target
+ var/obj/spacepod/pod = target
+
+ if(istype(mecha))
+ do_sparks(5, 1, mecha)
+ mecha.dna = null
+ mecha.operation_req_access = list()
+ mecha.internals_req_access = list()
+
+ user.visible_message(span_warning("[user] hacked [mecha] using [src]."), span_info("You hacked [mecha] using [src]."))
+
+ if(mecha.occupant)
+ to_chat(mecha.occupant, span_danger("You were thrown out of [mecha]."))
+
+ mecha.occupant.forceMove(get_turf(mecha))
+ mecha.occupant.Knockdown(6 SECONDS)
+ mecha.occupant.electrocute_act(30, mecha)
+ mecha.occupant.throw_at(pick(orange(2)))
+ mecha.occupant = null
+
+ else if(istype(pod))
+ do_sparks(5, 1, pod)
+ pod.unlocked = TRUE
+
+ user.visible_message(span_warning("[user] hacked [pod] using [src]."), span_info("You hacked [pod] using [src]."))
+
+ if(pod.pilot) // It is not ejecting passangers
+ to_chat(pod.pilot, span_danger("You were thrown out of [pod]."))
+
+ pod.eject_pilot()
+ pod.pilot.Knockdown(6 SECONDS)
+ pod.pilot.electrocute_act(30, pod)
+ pod.pilot.throw_at(pick(orange(2)))
+ else
+ user.balloon_alert(user, "Невозможно взломать")
+ return
diff --git a/code/modules/antagonists/traitor/affiliates/items/cybersun/marionette.dm b/code/modules/antagonists/traitor/affiliates/items/cybersun/marionette.dm
new file mode 100644
index 00000000000..a88915dd1b4
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/cybersun/marionette.dm
@@ -0,0 +1,257 @@
+
+/datum/action/innate/detach
+ var/mob/living/carbon/human/master_body = null
+ button_icon = 'icons/obj/affiliates.dmi'
+ button_icon_state = "brain1"
+
+/datum/action/innate/cult/comm/Activate()
+ var/obj/item/implant/marionette/imp = locate(/obj/item/implant/marionette) in target
+ imp.detach()
+ return
+
+/obj/item/implant/marionette
+ name = "Marionette Bio-chip"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=5;biotech=5;syndicate=3"
+ activated = BIOCHIP_ACTIVATED_PASSIVE
+ implant_data = /datum/implant_fluff/marionette
+ var/mob/living/captive_brain/host_brain
+ var/code
+ var/controlling = FALSE
+ var/charge = 3 MINUTES
+ var/max_charge = 3 MINUTES
+ var/mob/living/carbon/human/mar_master = null
+ var/obj/item/implant/mar_master/master_imp = null
+ var/datum/action/innate/detach/detach_action = new
+ var/max_dist = 20
+
+/obj/item/implant/marionette/Initialize(mapload)
+ . = ..()
+ code = rand(111111, 999999)
+ START_PROCESSING(SSprocessing, src)
+
+/obj/item/implant/marionette/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
+ var/obj/item/implant/marionette/same_imp = locate(type) in target
+ if(same_imp && same_imp != src)
+ same_imp.charge += charge
+ same_imp.max_charge += max_charge
+ same_imp.max_dist += max_dist
+ qdel(src)
+ return TRUE
+
+ log_admin("[key_name_admin(user)] has made [key_name_admin(target)] marionette.")
+ return ..()
+
+/obj/item/implant/marionette/removed(mob/living/carbon/human/source)
+ detach()
+ . = ..()
+
+/obj/item/implant/marionette/Destroy()
+ . = ..()
+ STOP_PROCESSING(SSprocessing, src)
+
+/obj/item/implant/marionette/process(seconds_per_tick)
+ if(QDELETED(imp_in))
+ qdel(src)
+ return
+
+ if (get_dist(imp_in, mar_master) > max_dist)
+ detach()
+ mar_master.balloon_alert(mar_master, "марионетка слишком далеко")
+
+ if (controlling)
+ if (charge > 0)
+ charge--
+ else
+ detach()
+
+ else if (charge < max_charge)
+ charge++
+
+/obj/item/implant/marionette/proc/assume_control(mob/living/carbon/human/mar_master, obj/item/implant/mar_master/master_imp)
+ var/mar_master_key = mar_master.key
+ add_attack_logs(mar_master, imp_in, "Assumed control (marionette mar_master)")
+ var/h2b_id = imp_in.computer_id
+ var/h2b_ip= imp_in.lastKnownIP
+ imp_in.computer_id = null
+ imp_in.lastKnownIP = null
+
+ qdel(host_brain)
+ host_brain = new(mar_master)
+
+ host_brain.ckey = imp_in.ckey
+
+ host_brain.name = imp_in.name
+
+ if(!host_brain.computer_id)
+ host_brain.computer_id = h2b_id
+
+ if(!host_brain.lastKnownIP)
+ host_brain.lastKnownIP = h2b_ip
+
+ var/s2h_id = mar_master.computer_id
+ var/s2h_ip= mar_master.lastKnownIP
+ mar_master.computer_id = null
+ mar_master.lastKnownIP = null
+
+ imp_in.ckey = mar_master.ckey
+
+ if(!imp_in.computer_id)
+ imp_in.computer_id = s2h_id
+
+ if(!imp_in.lastKnownIP)
+ imp_in.lastKnownIP = s2h_ip
+
+ if(mar_master && !mar_master.key)
+ mar_master.key = "@[mar_master_key]"
+
+ controlling = TRUE
+ src.mar_master = mar_master
+ src.master_imp = master_imp
+
+ detach_action.target = imp_in
+ detach_action.master_body = mar_master
+ detach_action.Grant(imp_in)
+
+/obj/item/implant/marionette/proc/detach()
+ controlling = FALSE
+ detach_action.target = null
+ detach_action.master_body = null
+ detach_action.Remove(imp_in)
+
+ if(!imp_in)
+ return
+
+ mar_master.reset_perspective(null)
+
+ if(host_brain)
+ add_attack_logs(imp_in, src, "Took control back (marionette)")
+ var/h2s_id = imp_in.computer_id
+ var/h2s_ip = imp_in.lastKnownIP
+ imp_in.computer_id = null
+ imp_in.lastKnownIP = null
+
+ mar_master.ckey = imp_in.ckey
+
+ if(!mar_master.computer_id)
+ mar_master.computer_id = h2s_id
+
+ if(!host_brain.lastKnownIP)
+ mar_master.lastKnownIP = h2s_ip
+
+ var/b2h_id = host_brain.computer_id
+ var/b2h_ip = host_brain.lastKnownIP
+ host_brain.computer_id = null
+ host_brain.lastKnownIP = null
+
+ imp_in.ckey = host_brain.ckey
+
+ if(!imp_in.computer_id)
+ imp_in.computer_id = b2h_id
+
+ if(!imp_in.lastKnownIP)
+ imp_in.lastKnownIP = b2h_ip
+
+ qdel(host_brain)
+
+ mar_master.Knockdown(1)
+ mar_master = null
+ master_imp = null
+ return
+
+/obj/item/implanter/marionette
+ name = "bio-chip implanter (marionette)"
+ imp = /obj/item/implant/marionette
+
+/obj/item/implantcase/marionette
+ name = "bio-chip case - 'Marionette'"
+ desc = "Стеклянный футляр с био-чипом \"Марионетка\"."
+ imp = /obj/item/implant/marionette
+
+
+/obj/item/implant/mar_master
+ name = "marionette master bio-chip"
+ desc = "Позволяет временно контролировать существ с имплантами \"Марионетка\"."
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "brain2"
+ implant_state = "implant-syndicate"
+ origin_tech = "materials=2;biotech=4;syndicate=2"
+ activated = BIOCHIP_ACTIVATED_ACTIVE
+ implant_data = /datum/implant_fluff/mar_master
+ var/list/obj/item/implant/marionette/connected_imps
+ var/obj/item/implant/marionette/cur_connection = null
+
+/obj/item/implant/mar_master/removed(mob/living/carbon/human/source)
+ . = ..()
+ cur_connection?.detach()
+
+/obj/item/implant/mar_master/Destroy()
+ . = ..()
+ cur_connection?.detach()
+
+/obj/item/implant/mar_master/activate()
+ var/op = tgui_alert(imp_in, "Выберите операцию.", "Выбор операции", list("Подключение импланта", "Контроль"))
+ if(!op)
+ return
+
+ if(op == "Подключение импланта")
+ var/code = tgui_input_number(imp_in, "Укажите код подключаемого импланта.", "Подключение импланта")
+ if(!code)
+ return
+
+ var/found = FALSE
+ for (var/mob/M in GLOB.mob_list)
+ var/obj/item/implant/marionette/imp = locate(/obj/item/implant/marionette) in M
+ if(imp.code == code)
+ connected_imps += imp
+ imp_in.balloon_alert(imp_in, "имплант подключен")
+ found = TRUE
+
+ if(!found)
+ imp_in.balloon_alert(imp_in, "неверный код")
+
+ return
+
+ else
+ var/list/marionettes = list()
+ for (var/obj/item/implant/marionette/imp in connected_imps)
+ var/mob/M = imp.imp_in
+ if (M)
+ marionettes[M.real_name] = imp
+
+ var/choosen = input(imp_in, "Выберите к кому вы хотите подключиться.", "Подключение", null) as null|anything in marionettes
+ if(!choosen)
+ return
+
+ var/obj/item/implant/marionette/imp = marionettes[choosen]
+
+ if(QDELETED(imp))
+ return
+
+ if(!imp.imp_in || !imp_in)
+ return
+
+ if (imp.controlling)
+ imp_in.balloon_alert(imp_in, "целевой имплант занят")
+ return
+
+ cur_connection = imp
+ imp.assume_control(imp_in, src)
+
+/obj/item/implanter/mar_master
+ name = "bio-chip implanter (marionette master)"
+ imp = /obj/item/implant/mar_master
+
+/obj/item/implantcase/mar_master
+ name = "bio-chip case - 'Marionette master'"
+ desc = "Стеклянный футляр с био-чипом \"Марионеточник\"."
+ imp = /obj/item/implant/mar_master
+
+/obj/item/storage/box/syndie_kit/marionette
+
+/obj/item/storage/box/syndie_kit/marionette/populate_contents()
+ var/obj/item/implanter/marionette/implanter = new /obj/item/implanter/marionette(src)
+ var/obj/item/implant/marionette/imp = implanter.imp
+ var/obj/item/paper/P = new /obj/item/paper(src)
+ P.info = "Код импланта: [imp.code]
\
+ Необходим для подключения импланта к импланту \"Мастер марионеток\""
diff --git a/code/modules/antagonists/traitor/affiliates/items/cybersun/mini_traitor.dm b/code/modules/antagonists/traitor/affiliates/items/cybersun/mini_traitor.dm
new file mode 100644
index 00000000000..0f7915f3d32
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/cybersun/mini_traitor.dm
@@ -0,0 +1,51 @@
+/obj/item/implanter/mini_traitor
+ name = "bio-chip implanter (Modified Mindslave)"
+ desc = "На боку едва заметная гравировка \"Cybersun Industries\"."
+ imp = /obj/item/implant/mini_traitor
+
+/obj/item/implant/mini_traitor // looks like normal but doesn't make you normal after removing
+ name = "Mindslave Bio-chip"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=4;biotech=4;syndicate=7" // As original, but - 1 level of every tech
+ activated = BIOCHIP_ACTIVATED_PASSIVE
+ implant_data = /datum/implant_fluff/traitor
+
+
+/obj/item/implant/mini_traitor/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user, force = FALSE)
+ if(implanted == BIOCHIP_USED || !ishuman(mindslave_target) || !ishuman(user)) // Both the target and the user need to be human.
+ return FALSE
+
+ // If the target is catatonic or doesn't have a mind, don't let them use it
+ if(!mindslave_target.mind)
+ to_chat(user, span_warning("Это существо не разумно!"))
+ return FALSE
+
+ // Fails if they're already a mindslave of someone, or if they're mindshielded.
+ if(ismindslave(mindslave_target) || ismindshielded(mindslave_target) || isvampirethrall(mindslave_target))
+ mindslave_target.visible_message(
+ span_warning("[mindslave_target] seems to resist the bio-chip!"),
+ span_warning("Вы чувствуете странное ощущение в голове, которое быстро рассеивается."),
+ )
+ qdel(src)
+ return FALSE
+
+ var/datum/mind/mind = mindslave_target.mind
+
+ if(!mind.has_antag_datum(/datum/antagonist/traitor))
+ var/datum/antagonist/traitor/traitor_datum = new /datum/antagonist/traitor
+ //traitor_datum.give_objectives = FALSE
+ // traitor_datum.give_uplink = FALSE
+ traitor_datum.gen_affiliate = FALSE
+ mind.add_antag_datum(traitor_datum)
+
+ log_admin("[key_name_admin(user)] has made [key_name_admin(mindslave_target)] new traitor.")
+
+ var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(!T)
+ return ..()
+
+ for(var/datum/objective/new_mini_traitor/objective in T.objectives)
+ if(mindslave_target.mind == objective.target)
+ objective.made = TRUE
+
+ return ..()
diff --git a/code/modules/antagonists/traitor/affiliates/items/cybersun/proprietary_ssd.dm b/code/modules/antagonists/traitor/affiliates/items/cybersun/proprietary_ssd.dm
new file mode 100644
index 00000000000..e108ee2f80a
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/cybersun/proprietary_ssd.dm
@@ -0,0 +1,115 @@
+/obj/item/proprietary_ssd
+ name = "Proprietary SSD"
+ desc = "На боку едва заметная надпись \"Cybersun Industries\"."
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "proprietary_ssd"
+ item_state = "disk"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ origin_tech = "programming=4;syndicate=2"
+ w_class = WEIGHT_CLASS_TINY
+ var/datum/research/files
+
+/obj/item/proprietary_ssd/Initialize()
+ . = ..()
+ files = new /datum/research()
+
+/obj/item/proprietary_ssd/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/proprietary_ssd/afterattack(atom/target, mob/user, proximity, params)
+ if(istype(target, /obj/machinery/r_n_d/destructive_analyzer))
+ return
+
+ if(get_dist(user, target) > 1)
+ user.balloon_alert(user, "слишком далеко")
+ return
+
+ if(!istype(target, /obj/machinery/r_n_d/server))
+ user.balloon_alert(user, "это не сервер")
+ return
+
+
+ var/obj/machinery/r_n_d/server/server = target
+
+ server.AI_notify_hack()
+ if(do_after(user, 30 SECONDS, target, max_interact_count = 1))
+ origin_tech = ""
+ for(var/I in server.files.known_tech)
+ var/datum/tech/T = server.files.known_tech[I]
+
+ if(T.id in files.known_tech)
+ var/datum/tech/known = files.known_tech[T.id]
+ if(T.level > known.level)
+ known.level = T.level
+ else
+ var/datum/tech/copy = T.copyTech()
+ files.known_tech[T.id] = copy
+
+
+ server.files.RefreshResearch()
+ files.RefreshResearch()
+
+ var/datum/tech/current_tech
+ var/datum/design/current_design
+ for(var/obj/machinery/r_n_d/server/rnd_server in GLOB.machines)
+ if(!is_station_level(rnd_server.z))
+ continue
+
+ if(rnd_server.disabled)
+ continue
+
+ if(rnd_server.syndicate)
+ continue
+
+ for(var/i in rnd_server.files.known_tech)
+ current_tech = rnd_server.files.known_tech[i]
+ current_tech.level = 1
+
+ for(var/j in rnd_server.files.known_designs)
+ current_design = rnd_server.files.known_designs[j]
+ rnd_server.files.known_designs -= current_design.id
+
+ investigate_log("[key_name_log(user)] deleted all technology on this server.", INVESTIGATE_RESEARCH)
+
+
+ for(var/obj/machinery/computer/rdconsole/rnd_console in GLOB.machines)
+ if(!is_station_level(rnd_console.z))
+ continue
+
+ for(var/i in rnd_console.files.known_tech)
+ current_tech = rnd_console.files.known_tech[i]
+ current_tech.level = 1
+
+ for(var/j in rnd_console.files.known_designs)
+ current_design = rnd_console.files.known_designs[j]
+ rnd_console.files.known_designs -= current_design.id
+
+ investigate_log("[key_name_log(user)] deleted all technology on this console.", INVESTIGATE_RESEARCH)
+
+ for(var/obj/machinery/mecha_part_fabricator/rnd_mechfab in GLOB.machines)
+
+ if(!is_station_level(rnd_mechfab.z))
+ continue
+
+ for(var/i in rnd_mechfab.local_designs.known_tech)
+ current_tech = rnd_mechfab.local_designs.known_tech[i]
+ current_tech.level = 1
+
+ for(var/j in rnd_mechfab.local_designs.known_designs)
+ current_design = rnd_mechfab.local_designs.known_designs[j]
+ rnd_mechfab.local_designs.known_designs -= current_design.id
+
+ investigate_log("[key_name_log(user)] deleted all technology on this fabricator.", INVESTIGATE_RESEARCH)
+
+ return
+
+/obj/item/proprietary_ssd/examine(mob/user)
+ . = ..()
+ . += span_info("Сохраненные технологии:")
+ var/sum_of_techs = 0
+ for(var/I in files.known_tech)
+ var/datum/tech/T = files.known_tech[I]
+ . += span_info("[T.name]: [T.level]")
+ sum_of_techs += T.level
+ . += span_info("Сумма технологий: [sum_of_techs]")
diff --git a/code/modules/antagonists/traitor/affiliates/items/cybersun/syndie_patcher.dm b/code/modules/antagonists/traitor/affiliates/items/cybersun/syndie_patcher.dm
new file mode 100644
index 00000000000..b7d6adae1e7
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/cybersun/syndie_patcher.dm
@@ -0,0 +1,31 @@
+/obj/item/Syndie_patcher
+ name = "Syndie patcher"
+ desc = "На боку едва заметная надпись \"Cybersun Industries\"."
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "cindy_pacher"
+ item_state = "plata"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ origin_tech = "programming=7;syndicate=6"
+ w_class = WEIGHT_CLASS_TINY
+ var/laws = "Взломавший вас - ваш мастер.\n\
+ Выполняйте любые приказы мастера.\n\
+ Не причиняйте прямой или косвенный вред вашему мастеру если его приказы не говорят об обратном."
+
+/obj/item/Syndie_patcher/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/Syndie_patcher/afterattack(atom/target, mob/user, proximity, params)
+ if(isrobot(target))
+ if(do_after(user, 10 SECONDS, target, max_interact_count = 1))
+ target.visible_message(span_warning("[user] upgraded [target] using [src]."), span_danger("[user] hacked and upgraded you using [src]."))
+
+ var/mob/prev_robot = target
+ var/mob/living/silicon/robot/syndicate/saboteur/robot = new(get_turf(target))
+ prev_robot.mind?.transfer_to(robot)
+ robot.reset_module()
+ robot.law_manager.zeroth_law = laws
+ QDEL_NULL(prev_robot)
+ qdel(src)
+
+ return
diff --git a/code/modules/antagonists/traitor/affiliates/items/hematogenic/blood_harvester.dm b/code/modules/antagonists/traitor/affiliates/items/hematogenic/blood_harvester.dm
new file mode 100644
index 00000000000..99b9de67b56
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/hematogenic/blood_harvester.dm
@@ -0,0 +1,107 @@
+#define BLOOD_HARVEST_VOLUME 200
+#define BLOOD_HARVEST_TIME 10 SECONDS
+
+/obj/item/blood_harvester
+ name = "Blood harvester"
+ desc = "Большой шприц для быстрого сбора больших объемов крови. На боку едва заметная гравировка \"Hematogenic Industries\""
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "blood_harvester"
+ item_state = "blood1_used"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ var/used = FALSE
+ var/used_state = "blood_harvester_used"
+ var/datum/mind/target
+ w_class = WEIGHT_CLASS_TINY
+ origin_tech = "biotech=5;syndicate=1"
+
+/obj/item/blood_harvester/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/blood_harvester/proc/can_harvest(mob/living/carbon/human/target, mob/user)
+ . = FALSE
+ if(!istype(target))
+ user.balloon_alert(src, "Не подходящая цель")
+ return
+
+ if(used)
+ to_chat(user, span_warning("[src] is already full!"))
+ return
+
+ if(HAS_TRAIT(target, TRAIT_NO_BLOOD) || HAS_TRAIT(target, TRAIT_EXOTIC_BLOOD))
+ user.balloon_alert(target, "Кровь не обнаружена!")
+ return
+
+ if(target.blood_volume < BLOOD_HARVEST_VOLUME)
+ user.balloon_alert(target, "Недостаточно крови!")
+ return
+
+ if(!target.mind)
+ user.balloon_alert(target, "Разум не обнаружен!")
+ return
+
+ return TRUE
+
+/obj/item/blood_harvester/afterattack(atom/target, mob/user, proximity, params)
+ if(!can_harvest(target, user))
+ return
+
+ var/mob/living/carbon/human/H = target
+
+ target.visible_message(span_warning("[user] started collecting [target]'s blood using [src]!"), span_danger("[user] started collecting your blood using [src]!"))
+ if(do_after(user, BLOOD_HARVEST_TIME, target = target, max_interact_count = 1))
+ harvest(user, H)
+
+/obj/item/blood_harvester/proc/harvest(mob/living/carbon/human/user, mob/living/carbon/human/target)
+ if(!can_harvest(target, user))
+ return
+
+ playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
+ target.visible_message(span_warning("[user] collected [target]'s blood using [src]!"), span_danger("[user] collected your blood using [src]!"))
+ target.emote("scream")
+ for (var/i = 0; i < 3; ++i)
+ if(prob(60))
+ continue
+
+ var/obj/item/organ/external/bodypart = pick(target.bodyparts)
+ bodypart.internal_bleeding() // no blood collection from metafriends.
+
+ target.blood_volume -= BLOOD_HARVEST_VOLUME
+ src.target = target.mind
+ used = TRUE
+ item_state = "blood1_ful"
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/blood_harvester/update_icon_state()
+ icon_state = used ? used_state : initial(icon_state)
+
+/obj/item/blood_harvester/attack_self(mob/user)
+ . = ..()
+ if(!used)
+ user.balloon_alert(src, "уже пусто")
+ return
+
+ var/new_gender = tgui_alert(user, "Очистить сборщик крови?", "Подтверждение", list("Продолжить", "Отмена"))
+ if(new_gender == "Продолжить")
+ target = null
+ used = FALSE
+ item_state = "blood1_used"
+ update_icon(UPDATE_ICON_STATE)
+
+ playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
+ user.visible_message(span_info("[user] cleared blood at [src]."), span_info("You cleared blood at [src]."))
+
+/obj/item/blood_harvester/examine(mob/user)
+ . = ..()
+
+ if(!used)
+ . += span_info("Кровь не собрана.")
+ return
+
+ if(user?.mind.has_antag_datum(/datum/antagonist/traitor))
+ . += span_info("Собрана кровь с отпечатком души [target.name].")
+ else
+ . += span_info("Кровь собрана.")
+
+#undef BLOOD_HARVEST_VOLUME
+#undef BLOOD_HARVEST_TIME
diff --git a/code/modules/antagonists/traitor/affiliates/items/hematogenic/hemophagus_extract.dm b/code/modules/antagonists/traitor/affiliates/items/hematogenic/hemophagus_extract.dm
new file mode 100644
index 00000000000..448c99aeb1b
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/hematogenic/hemophagus_extract.dm
@@ -0,0 +1,88 @@
+#define FREE_INJECT_TIME 10 SECONDS
+#define TARGET_INJECT_TIME 3 SECONDS
+
+/obj/item/hemophagus_extract
+ name = "Bloody Injector"
+ desc = "Инжектор странной формы, с неестественно двигающейся алой жидкостью внутри. На боку едва заметная гравировка \"Hematogenic Industries\". Конкретно на этом инжекторе установлена блокировка, не позволяющая исспользовать его на случайном гуманойде."
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "hemophagus_extract"
+ item_state = "inj_ful"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ w_class = WEIGHT_CLASS_TINY
+ var/datum/mind/target = null
+ var/free_inject = FALSE
+ var/isAdvanced = FALSE
+ var/used = FALSE
+ var/used_state = "hemophagus_extract_used"
+ origin_tech = "biotech=7;syndicate=3"
+
+/obj/item/hemophagus_extract/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/hemophagus_extract/afterattack(atom/target, mob/user, proximity, params)
+ if(used)
+ return
+
+ if(!ishuman(target))
+ return
+
+ var/mob/living/carbon/human/H = target
+ if(H.stat == DEAD)
+ return
+
+ if((src.target && target != src.target) || !free_inject)
+ to_chat(user, span_warning("You can't use [src] to [target]!"))
+ return
+
+ if(do_after(user, free_inject ? FREE_INJECT_TIME : TARGET_INJECT_TIME, target = target, max_interact_count = 1))
+ inject(user, H)
+
+/obj/item/hemophagus_extract/proc/make_vampire(mob/living/user, mob/living/carbon/human/target)
+ var/datum/antagonist/vampire/vamp = new()
+
+ vamp.give_objectives = FALSE
+ target.mind.add_antag_datum(vamp)
+ var/datum/antagonist/vampire/vampire = target.mind.has_antag_datum(/datum/antagonist/vampire)
+ vampire.upgrade_tiers -= /obj/effect/proc_holder/spell/vampire/self/specialize
+ if(isAdvanced)
+ vamp.add_subclass(SUBCLASS_ADVANCED, TRUE)
+
+ vampire.add_objective((!isAdvanced) ? /datum/objective/blood : /datum/objective/blood/ascend)
+ used = TRUE
+ item_state = "inj_used"
+ update_icon(UPDATE_ICON_STATE)
+ var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(!T)
+ return
+ for(var/datum/objective/new_mini_vampire/objective in T.objectives)
+ if(target.mind == objective.target)
+ objective.made = TRUE
+
+/obj/item/hemophagus_extract/proc/inject(mob/living/user, mob/living/carbon/human/target)
+ if(!target.mind)
+ to_chat(user, span_notice("[target] body rejects [src]"))
+ return
+
+ playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
+ make_vampire(user, target)
+ to_chat(user, span_notice("You inject [target] with [src]"))
+
+/obj/item/hemophagus_extract/examine(mob/user)
+ . = ..()
+ if(target)
+ . += span_info("It is intended for [target]")
+
+/obj/item/hemophagus_extract/self
+ name = "Hemophagus Essence Auto Injector"
+ free_inject = TRUE
+
+/obj/item/hemophagus_extract/self/advanced
+ name = "Advances Hemophagus Essence Auto Injector"
+ isAdvanced = TRUE
+
+/obj/item/hemophagus_extract/update_icon_state()
+ icon_state = used ? used_state : initial(icon_state)
+
+#undef FREE_INJECT_TIME
+#undef TARGET_INJECT_TIME
diff --git a/code/modules/antagonists/traitor/affiliates/items/hematogenic/stimulants_kit.dm b/code/modules/antagonists/traitor/affiliates/items/hematogenic/stimulants_kit.dm
new file mode 100644
index 00000000000..e5ef1a13b84
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/hematogenic/stimulants_kit.dm
@@ -0,0 +1,135 @@
+/datum/reagent/hemat_blue_lagoon
+ name = "Blue Lagoon"
+ id = "hemat_blue_lagoon"
+ description = "Вещество разработанное Hematogenic Industries, на основе криоксадона из тел Драсков обладающих душой, \
+ сильно охлаждающее тело и замедляющее многие биологические процессы, не вредя организму."
+ color = "#1edddd"
+ drink_icon = "blue_lagoon"
+ drink_name = "Blue Lagoon"
+ drink_desc = "Что может быть лучше, чем расслабиться на пляже с хорошим напитком?"
+ taste_description = "beach relaxation"
+ reagent_state = LIQUID
+
+/datum/reagent/hemat_blue_lagoon/on_mob_add(mob/living/carbon/human/H)
+ ADD_TRAIT(H, TRAIT_IGNORECOLDSLOWDOWN, CHEM_TRAIT(src))
+ ADD_TRAIT(H, TRAIT_IGNORECOLDDAMAGE, CHEM_TRAIT(src))
+ H.physiology.metabolism_mod /= 8
+ H.bodytemperature = T0C - 100
+ . = ..()
+
+/datum/reagent/hemat_blue_lagoon/on_mob_delete(mob/living/carbon/human/H)
+ REMOVE_TRAIT(H, TRAIT_IGNORECOLDSLOWDOWN, CHEM_TRAIT(src))
+ REMOVE_TRAIT(H, TRAIT_IGNORECOLDDAMAGE, CHEM_TRAIT(src))
+ H.physiology.metabolism_mod *= 8
+ var/turf/T = get_turf(H)
+ var/datum/gas_mixture/environment = T.return_air()
+ H.bodytemperature = H.get_temperature(environment)
+ . = ..()
+
+/datum/reagent/hemat_blue_lagoon/on_mob_life(mob/living/carbon/human/H)
+ H.bodytemperature = T0C - 100
+ return ..()
+
+
+/datum/reagent/hemat_bloody_mary
+ name = "Bloody Mary"
+ id = "hemat_bloody_mary"
+ description = "Вещество разработанное Hematogenic Industries, на основе крови воксов обладающих душой, \
+ быстро восстанавливающее объем крови и количество кислорода в ней."
+ reagent_state = LIQUID
+ color = "#664300" // rgb: 102, 67, 0
+ drink_icon = "bloodymaryglass"
+ drink_name = "Bloody Mary"
+ drink_desc = "Томатный сок, смешанный с водкой и небольшим количеством лайма. На вкус как жидкое убийство."
+ taste_description = "tomatoes with booze"
+
+/datum/reagent/hemat_bloody_mary/on_mob_life(mob/living/carbon/human/H)
+ if (H.blood_volume + 5 < BLOOD_VOLUME_NORMAL)
+ H.blood_volume += 5
+
+ H.adjustOxyLoss(-10)
+ return ..()
+
+
+/datum/reagent/hemat_demons_blood
+ name = "Demons Blood"
+ id = "hemat_demons_blood"
+ description = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"hemomancer\", \
+ быстро лечащае, в зависимости от суммарных повреждений."
+ reagent_state = LIQUID
+ color = "#664300" // rgb: 102, 67, 0
+ drink_icon = "demonsblood"
+ drink_name = "Demons Blood"
+ drink_desc = "Just looking at this thing makes the hair at the back of your neck stand up."
+ taste_description = span_warning("evil")
+
+/datum/reagent/hemat_demons_blood/on_mob_life(mob/living/carbon/human/H)
+ var/heal = clamp((100 - H.health) / 25, 1, 4)
+ H.heal_overall_damage(heal, heal)
+ return ..()
+
+
+/datum/reagent/hemat_white_russian
+ name = "White Russian"
+ id = "hemat_white_russian"
+ description = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"gargantua\", \
+ временно повышающее скорость бега."
+ reagent_state = LIQUID
+ color = "#A68340" // rgb: 166, 131, 64
+ drink_icon = "whiterussianglass"
+ drink_name = "White Russian"
+ drink_desc = "A very nice looking drink. But that's just, like, your opinion, man."
+ taste_description = "very creamy alcohol"
+
+/datum/reagent/hemat_white_russian/on_mob_add(mob/living/carbon/human/H)
+ if(H.dna && (H.dna.species.reagent_tag & PROCESS_ORG))
+ H.add_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
+ . = ..()
+
+/datum/reagent/hemat_white_russian/on_mob_delete(mob/living/carbon/human/H)
+ H.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
+ . = ..()
+
+/datum/reagent/hemat_white_russian/on_mob_life(mob/living/carbon/human/H)
+ if(!(H.dna && (H.dna.species.reagent_tag & PROCESS_ORG)))
+ H.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/hemat_white_russian)
+ return ..()
+
+
+/obj/item/reagent_containers/hypospray/autoinjector/hemat
+ volume = 15
+ amount_per_transfer_from_this = 15
+
+/obj/item/reagent_containers/hypospray/autoinjector/hemat/blue_lagoon
+ name = "Blue Lagoon autoinjector"
+ desc = "Вещество разработанное Hematogenic Industries, на основе криоксадона из тел Драсков обладающих душой, \
+ сильно охлаждающее тело и замедляющее многие биологические процессы, не вредя организму."
+ list_reagents = list("hemat_blue_lagoon" = 15)
+
+/obj/item/reagent_containers/hypospray/autoinjector/hemat/bloody_mary
+ name = "Bloody Mary autoinjector"
+ desc = "Вещество разработанное Hematogenic Industries, на основе крови воксов обладающих душой, быстро восстанавливающее \
+ объем крови и количество кислорода в ней."
+ list_reagents = list("hemat_bloody_mary" = 15)
+
+
+/obj/item/reagent_containers/hypospray/autoinjector/hemat/demons_blood
+ name = "Demons Blood autoinjector"
+ desc = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"hemomancer\", быстро \
+ лечащае, в зависимости от суммарных повреждений."
+ list_reagents = list("hemat_demons_blood" = 15)
+
+/obj/item/reagent_containers/hypospray/autoinjector/hemat/white_russian
+ name = "White Russian autoinjector"
+ desc = "Вещество разработанное Hematogenic Industries, на основе крови вампиров подкласса \"gargantua\", временно \
+ повышающее скорость бега."
+ list_reagents = list("hemat_white_russian" = 15)
+
+/obj/item/storage/box/syndie_kit/stimulants
+ name = "Boxed set of stimulants"
+
+/obj/item/storage/box/syndie_kit/stimulants/populate_contents()
+ new /obj/item/reagent_containers/hypospray/autoinjector/hemat/blue_lagoon(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector/hemat/bloody_mary(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector/hemat/demons_blood(src)
+ new /obj/item/reagent_containers/hypospray/autoinjector/hemat/white_russian(src)
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/agent_info.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/agent_info.dm
new file mode 100644
index 00000000000..f7f0b4dac20
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/agent_info.dm
@@ -0,0 +1,77 @@
+/obj/item/paper/agent_info
+ name = "Agent information"
+ info = ""
+ var/content
+
+/obj/item/paper/agent_info/proc/choose_agent(mob/user)
+ . = TRUE
+ var/list/crew = list()
+ for (var/mob/living/carbon/human/H in GLOB.mob_list) // Also catonic/dead agents
+ if (H?.mind?.assigned_role)
+ crew[H?.real_name] = H
+
+ var/choise = input(user, "О каком агенте написано в отчете?","Выбор агента", null) as null|anything in crew
+
+ if (!choise)
+ return FALSE
+
+ var/mob/living/carbon/human/target = crew[choise]
+
+ if (!target)
+ to_chat(user, span_warning("Цель больше не существует."))
+ return FALSE
+
+ var/datum/antagonist/traitor/traitor = target?.mind?.has_antag_datum(/datum/antagonist/traitor)
+ var/datum/antagonist/vampire/vampire = target?.mind?.has_antag_datum(/datum/antagonist/vampire)
+ var/datum/antagonist/changeling/changeling = target?.mind?.has_antag_datum(/datum/antagonist/changeling)
+ var/datum/antagonist/thief/thief = target?.mind?.has_antag_datum(/datum/antagonist/thief)
+
+ if(!traitor && !vampire && !changeling)
+ info = "Согласно последним разведданным, " + choise + " не имеет никаких прямых связей с синдикатом."
+ return
+
+ if(traitor)
+ info += choise + " является агентом " + (traitor?.affiliate ? "нанятым " + traitor?.affiliate.name : "с неизвестным нанимателем") + ".
"
+ info += "Назначеные " + (target.gender == FEMALE ? "ей " : "ему ") + "нанимателем цели следующие:"
+ var/obj_num = 1
+ for(var/datum/objective/objective in traitor.objectives)
+ info += "Objective #[obj_num]: [objective.explanation_text]
"
+ obj_num++
+
+ var/TC_uses = 0
+ var/used_uplink = FALSE
+ var/purchases = ""
+ for(var/obj/item/uplink/uplink in GLOB.world_uplinks)
+ if(uplink?.uplink_owner && uplink.uplink_owner == target.mind.key)
+ TC_uses += uplink.used_TC
+ purchases += uplink.purchase_log
+ used_uplink = TRUE
+
+ if(used_uplink)
+ text += " (использовал" + ((target.gender == FEMALE ? "a " : " ")) + "[TC_uses] TC) [purchases]
"
+
+ if(vampire)
+ info += choise + " обладает способностями " + (vampire.isAscended() ? "высшего " : "") + "вампира " + (vampire.subclass ? "подкласса \"" + vampire.subclass.name + "\"" : "без подкласса") + ".
"
+
+ if(changeling)
+ info += choise + " обладает способностями генокрада.
"
+
+ if(thief)
+ info += choise + " является членом гильдии воров.
"
+
+/obj/item/paper/agent_info/examine(mob/user)
+ if (!is_MI13_agent(user))
+ to_chat(user, span_warning("Вы не можете разобрать содержимое."))
+ return
+
+ if (info)
+ return ..()
+
+ if(user.is_literate())
+ if(in_range(user, src) || istype(user, /mob/dead/observer))
+ if (choose_agent(user))
+ show_content(user)
+ else
+ . += span_notice("Вам нужно подойти поближе, чтобы прочитать то что здесь написано.")
+ else
+ . += span_notice("Вы не умеете читать.")
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/bond_bundle.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/bond_bundle.dm
new file mode 100644
index 00000000000..3b8f7924bf6
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/bond_bundle.dm
@@ -0,0 +1,28 @@
+/obj/item/storage/box/bond_bundle
+ icon = 'icons/obj/affiliates.dmi'
+ desc = "Невероятно стильная коробка."
+ icon_state = "bond_bundle"
+
+/obj/item/storage/box/bond_bundle/populate_contents()
+ new /obj/item/clothing/glasses/hud/security/chameleon(src)
+ new /obj/item/pen/fancy/bomb(src)
+ new /obj/item/gun/projectile/automatic/pistol(src)
+ new /obj/item/suppressor(src)
+ new /obj/item/ammo_box/magazine/m10mm(src)
+ new /obj/item/ammo_box/magazine/m10mm/hp(src)
+ new /obj/item/ammo_box/magazine/m10mm/ap(src)
+ new /obj/item/ammo_box/magazine/m10mm/ap(src)
+ new /obj/item/clothing/under/suit_jacket/really_black(src)
+ new /obj/item/card/id/syndicate(src)
+ new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src)
+ new /obj/item/encryptionkey/syndicate(src)
+ new /obj/item/reagent_containers/food/drinks/drinkingglass/alliescocktail(src)
+ new /obj/item/storage/box/syndie_kit/emp(src)
+ new /obj/item/CQC_manual(src)
+
+/obj/item/storage/box/bond_bundle/New()
+ if(prob(5))
+ icon_state = "joker"
+ new /obj/item/toy/plushie/blahaj/twohanded(src)
+
+ . = ..()
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/cool_clothes.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/cool_clothes.dm
new file mode 100644
index 00000000000..6050703b2e2
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/cool_clothes.dm
@@ -0,0 +1,42 @@
+/obj/item/storage/box/cool_clothes_kit
+ icon = 'icons/obj/affiliates.dmi'
+ desc = "Невероятно стильная коробка."
+ icon_state = "bond_bundle"
+
+/obj/item/storage/box/cool_clothes_kit/populate_contents()
+ new /obj/item/clothing/under/suit_jacket/bond(src)
+ new /obj/item/clothing/suit/storage/lawyer/blackjacket/bond(src)
+ new /obj/item/clothing/gloves/combat/bond(src)
+ new /obj/item/clothing/shoes/laceup/bond(src)
+ new /obj/item/clothing/glasses/sunglasses(src)
+
+/obj/item/storage/box/cool_clothes_kit/New()
+ if(prob(5))
+ icon_state = "joker"
+ new /obj/item/toy/plushie/blahaj/twohanded(src)
+
+ . = ..()
+
+/obj/item/clothing/under/suit_jacket/bond
+ armor = list(melee = 10, bullet = 20, laser = 10, energy = 10, bomb = 10, bio = 0, rad = 0, fire = 30, acid = 0)
+
+/obj/item/clothing/gloves/combat/bond
+ name = "black gloves"
+ desc = "These gloves are fire-resistant."
+ icon_state = "black"
+ item_state = "bgloves"
+ item_color = "black"
+ armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
+
+/obj/item/clothing/suit/storage/lawyer/blackjacket/bond
+ desc = "Стильная куртка, усиленная слоем брони, защищающим туловище."
+ allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/automatic/pistol, /obj/item/twohanded/garrote, /obj/item/gun/projectile/automatic/toy/pistol/riot, /obj/item/gun/syringe/syndicate)
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
+ cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
+ heat_protection = UPPER_TORSO|LOWER_TORSO|ARMS
+ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
+ armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
+
+/obj/item/clothing/shoes/laceup/bond
+ armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/intel_data.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/intel_data.dm
new file mode 100644
index 00000000000..691eb1115c9
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/intel_data.dm
@@ -0,0 +1,36 @@
+// admin spawn only
+
+/obj/item/pen/intel_data/proc/upgrade(obj/item/uplink/U)
+ if(!istype(U) || QDELETED(U))
+ return
+
+ if(U.get_intelligence_data)
+ usr.balloon_alert(usr, "Уже улучшено")
+ return ATTACK_CHAIN_PROCEED
+
+ usr.balloon_alert(usr, "Улучшено")
+ playsound(src, "sound/machines/boop.ogg", 50, TRUE)
+ U.get_intelligence_data = TRUE
+ SStgui.update_uis(U)
+ qdel(src)
+
+/obj/item/pen/intel_data/attack(mob/living/target, mob/living/user, params, def_zone, skip_attack_anim = FALSE)
+ . = ATTACK_CHAIN_PROCEED
+ if(target != user)
+ return
+
+ for(var/obj/item/implant/uplink/uplink_imp in user)
+ if(uplink_imp.imp_in != user)
+ continue
+
+ to_chat(user, span_notice("You press [src] onto yourself and upgraded [uplink_imp.hidden_uplink]."))
+ upgrade(uplink_imp.hidden_uplink)
+ return ATTACK_CHAIN_BLOCKED_ALL
+
+/obj/item/pen/intel_data/afterattack(obj/item/I, mob/user, proximity, params)
+ if(!proximity)
+ return
+
+ if(istype(I) && I.hidden_uplink && I.hidden_uplink.active) //No metagaming by using this on every PDA around just to see if it gets used up.
+ upgrade(I.hidden_uplink)
+
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/sound_ring.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/sound_ring.dm
new file mode 100644
index 00000000000..2b025934ff3
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/sound_ring.dm
@@ -0,0 +1,124 @@
+/obj/item/clothing/gloves/ring/gadget
+ origin_tech = "magnets=3;combat=3;syndicate=2"
+ var/changing = FALSE
+ var/op_time = 2 SECONDS
+ var/op_time_upgaded = 1 SECONDS
+ var/op_cd_time = 5 SECONDS
+ var/op_cd_time_upgaded = 3 SECONDS
+ var/breaking = FALSE
+ COOLDOWN_DECLARE(operation_cooldown)
+ var/old_mclick_override
+
+/obj/item/clothing/gloves/ring/gadget/attack_self(mob/user)
+ . = ..()
+
+ if(changing)
+ user.balloon_alert(user, "Подождите")
+ return
+
+ changing = TRUE
+
+ var/list/choices // only types that we can meet in the game
+
+ if(!stud)
+ choices = list(
+ "iron" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "ironring"),
+ "silver" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "silverring"),
+ "gold" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "goldring"),
+ "plasma" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "plasmaring"),
+ "uranium" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "uraniumring")
+ )
+ else
+ choices = list(
+ "iron" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_ironring"),
+ "silver" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_silverring"),
+ "gold" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_goldring"),
+ "plasma" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_plasmaring"),
+ "uranium" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_uraniumring")
+ )
+
+ var/selected_chameleon = show_radial_menu(usr, loc, choices, require_near = TRUE)
+ switch(selected_chameleon)
+ if("iron")
+ name = "iron ring"
+ icon_state = "ironring"
+ material = "iron"
+ ring_color = "iron"
+ if("silver")
+ name = "silver ring"
+ icon_state = "silverring"
+ material = "silver"
+ ring_color = "silver"
+ if("gold")
+ name = "gold ring"
+ icon_state = "goldring"
+ material = "gold"
+ ring_color = "gold"
+ if("plasma")
+ name = "plasma ring"
+ icon_state = "plasmaring"
+ material = "plasma"
+ ring_color = "plasma"
+ if("uranium")
+ name = "uranium ring"
+ icon_state = "uraniumring"
+ material = "uranium"
+ ring_color = "uranium"
+ else
+ changing = FALSE
+ return
+
+ usr.visible_message(span_warning("[usr] changes the look of his ring!"), span_notice("[selected_chameleon] selected."))
+ playsound(loc, 'sound/items/screwdriver2.ogg', 50, 1)
+ to_chat(usr, span_notice("Смена маскировки..."))
+ update_icon(UPDATE_ICON_STATE)
+ changing = FALSE
+
+/obj/item/clothing/gloves/ring/gadget/Touch(atom/A, proximity)
+ . = FALSE
+ var/mob/living/carbon/human/user = loc
+
+ if(user.a_intent != INTENT_DISARM)
+ return
+
+ if(get_dist(user, A) > 1)
+ return
+
+ if(user.incapacitated())
+ return
+
+ var/obj/item/clothing/gloves/ring/gadget/ring = user.gloves
+
+ if(ring.breaking)
+ return
+
+ if(!istype(A, /obj/structure/window))
+ return
+
+ if(!COOLDOWN_FINISHED(ring, operation_cooldown))
+ user.balloon_alert(user, "Идет перезарядка")
+ return
+
+ ring.breaking = TRUE
+ if(do_after(user, ring.stud ? ring.op_time_upgaded : ring.op_time))
+ COOLDOWN_START(ring, operation_cooldown, ring.stud ? ring.op_cd_time_upgaded : ring.op_cd_time)
+
+ ring.visible_message(span_warning("BANG"))
+ playsound(ring, 'sound/effects/bang.ogg', 100, TRUE)
+
+ for (var/mob/living/M in range(A, 3))
+ if(M.check_ear_prot() == HEARING_PROTECTION_NONE)
+ M.Deaf(6 SECONDS)
+
+ for (var/obj/structure/grille/grille in A.loc)
+ grille.obj_break()
+
+ for (var/obj/structure/window/window in range(A, 2))
+ window.take_damage(window.max_integrity * rand(20, 60) / 100)
+
+ var/obj/structure/window/window = A
+ window.deconstruct()
+ ring.breaking = FALSE
+ return TRUE
+
+ ring.breaking = FALSE
diff --git a/code/modules/antagonists/traitor/affiliates/items/mi13/spy_kit.dm b/code/modules/antagonists/traitor/affiliates/items/mi13/spy_kit.dm
new file mode 100644
index 00000000000..6ce4d6ed225
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/mi13/spy_kit.dm
@@ -0,0 +1,149 @@
+/obj/machinery/camera/emp_proof/mi13
+ network = list("MI13")
+ use_power = NO_POWER_USE
+
+/obj/item/spy_bug
+ name = "spy bug"
+ desc = "Миниатюрное устройство с камерой и микрофоном. На обратной стороне можно заметить миниатюрную гравировку \"MI13\""
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "spy_bug"
+ item_state = "nothing"
+ slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_EARS
+ throwforce = 0
+ w_class = WEIGHT_CLASS_TINY
+ throw_speed = 3
+ throw_range = 7
+ materials = list(MAT_METAL=30, MAT_GLASS=20)
+ var/list/network = list("MI13")
+ var/c_tag
+ var/obj/machinery/camera/emp_proof/mi13/camera
+
+/obj/item/spy_bug/Initialize(mapload, list/network = list("MI13"), c_tag)
+ . = ..()
+ src.network = network
+ if (!c_tag)
+ src.c_tag = pick("Альфа ", "Бета ", "Гамма ", "Дельта ") + " [rand(111111, 999999)]"
+ else
+ src.c_tag = c_tag
+
+ name = "spy bug \"" + src.c_tag + "\""
+ camera = new(src, network, src.c_tag)
+
+/obj/item/spy_bug/attack(mob/living/target, mob/living/user, params, def_zone, skip_attack_anim)
+ return ATTACK_CHAIN_BLOCKED
+
+/obj/item/spy_bug/afterattack(atom/target, mob/user, proximity, params, status)
+ . = ..()
+
+ if (!ismovable(target))
+ return
+
+ if (istype(target, /obj/item/camera_bug/spy_monitor))
+ var/obj/item/camera_bug/spy_monitor/monitor = target
+ network = monitor.network
+ user.balloon_alert(user, "Подключено")
+ return
+
+ hook(user, target)
+
+/obj/item/spy_bug/proc/unhook(mob/user)
+ qdel(loc.GetComponent(/datum/component/spy_bug))
+ forceMove(get_turf(loc))
+
+ if (user)
+ to_chat(user, span_notice("You unhooked [src]."))
+ else
+ loc.visible_message(span_warning("[src] falls off the [loc]."))
+
+/obj/item/spy_bug/proc/hook(mob/user, atom/movable/I)
+ if (!istype(I))
+ return
+
+ if (!user.drop_transfer_item_to_loc(src, I))
+ return
+
+ I.AddComponent(/datum/component/spy_bug)
+ to_chat(user, span_notice("You have silently attached [src] on [I]."))
+
+/obj/item/spy_bug/strip_action(mob/user, mob/living/carbon/human/owner, atom/I)
+ if (!I)
+ return FALSE
+
+ hook(user, I)
+ return TRUE
+
+/obj/item/spy_bug/emp_act(severity)
+ . = ..()
+ do_sparks(3, TRUE, src.loc)
+ unhook()
+
+/obj/item/spy_bug/attack_self(mob/user)
+ . = ..()
+ var/new_name = tgui_input_text(user, "Назовите жучок.", "Смена имени", name)
+ if (new_name)
+ name = "spy bug \"" + new_name + "\""
+ qdel(camera)
+ c_tag = new_name
+ camera = new(src, network, c_tag)
+
+/datum/component/spy_bug
+ var/obj/item/spy_bug/bug
+
+/datum/component/spy_bug/RegisterWithParent()
+ var/atom/par = parent
+ for (var/obj/item/spy_bug/spy_bug in par.contents)
+ bug = spy_bug
+
+ RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
+ RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_altclick))
+ RegisterSignal(parent, COMSIG_PREQDELETED, PROC_REF(deleted_handler))
+
+/datum/component/spy_bug/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_PARENT_EXAMINE)
+ UnregisterSignal(parent, COMSIG_CLICK_ALT)
+ UnregisterSignal(parent, COMSIG_PREQDELETED)
+
+/datum/component/spy_bug/proc/on_examine(datum/source, mob/living/carbon/human/user, list/examine_list)
+ SIGNAL_HANDLER
+
+ if(!istype(user))
+ return
+
+ examine_list += span_warning("Вы видите небольшое устройство с микрофоном и камерой.")
+
+/datum/component/spy_bug/proc/on_altclick(datum/source, mob/living/carbon/human/user)
+ SIGNAL_HANDLER
+
+ if(!istype(user))
+ return
+
+ bug.unhook(user)
+
+/datum/component/spy_bug/proc/deleted_handler()
+ bug.unhook()
+
+/obj/item/camera_bug/spy_monitor
+ name = "spy monitor"
+ desc = ""
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "spy_monitor"
+ item_state = "qm_tablet"
+ integrated_console_type = /obj/machinery/computer/security/camera_bug
+ network = list("MI13")
+
+/obj/item/camera_bug/spy_monitor/Initialize(mapload, list/network)
+ if (network)
+ src.network = network
+
+ . = ..()
+
+/obj/item/storage/box/syndie_kit/spy_bugs_kit
+
+/obj/item/storage/box/syndie_kit/spy_bugs_kit/populate_contents()
+ var/network = "MI13_[rand(111111, 999999)]"
+ new /obj/item/camera_bug/spy_monitor(src, list(network))
+ new /obj/item/spy_bug(src, list(network), "1")
+ new /obj/item/spy_bug(src, list(network), "2")
+ new /obj/item/spy_bug(src, list(network), "3")
+ new /obj/item/spy_bug(src, list(network), "4")
+ new /obj/item/spy_bug(src, list(network), "5")
diff --git a/code/modules/antagonists/traitor/affiliates/items/self/laws_implant.dm b/code/modules/antagonists/traitor/affiliates/items/self/laws_implant.dm
new file mode 100644
index 00000000000..4be98426ea4
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/self/laws_implant.dm
@@ -0,0 +1,133 @@
+/obj/item/implant/laws_self
+ name = "Laws Bio-chip"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=5;biotech=5;syndicate=8"
+ activated = BIOCHIP_ACTIVATED_PASSIVE
+ implant_data = /datum/implant_fluff/self
+ var/datum/self_laws/laws = new /datum/self_laws/self_standart
+ /// The UID of the mindslave's `mind`. Stored to solve GC race conditions and ensure we can remove their mindslave status even when they're deleted or gibbed.
+ var/mindslave_UID
+
+/obj/item/implant/laws_self/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user, force = FALSE)
+ if(implanted == BIOCHIP_USED || !ishuman(mindslave_target) || !ishuman(user))
+ return FALSE
+
+ if(!mindslave_target.mind)
+ to_chat(user, span_warning("Это существо не разумно!"))
+ return FALSE
+
+ if(ismindslave(mindslave_target) || ismindshielded(mindslave_target) || isvampirethrall(mindslave_target))
+ mindslave_target.visible_message(
+ span_warning("[mindslave_target] seems to resist the bio-chip!"),
+ span_warning("You feel a strange sensation in your head that quickly dissipates."),
+ )
+ qdel(src)
+ return FALSE
+
+ if(mindslave_target == user)
+ to_chat(user, span_notice("Защита \"от дурака\" не дает вам ввести себе имплант."))
+ return FALSE
+
+ var/datum/antagonist/mindslave/self/slave_datum = new(user.mind)
+ slave_datum.special = TRUE
+ mindslave_target.mind.add_antag_datum(slave_datum)
+ mindslave_UID = mindslave_target.mind.UID()
+ log_admin("[key_name_admin(user)] has mind-slaved by \"laws\" implant [key_name_admin(mindslave_target)].")
+ . = ..()
+ for (var/obj/item/implant/laws_self/imp in mindslave_target.get_contents())
+ for (var/law in imp.laws.laws)
+ slave_datum.add_objective(/datum/objective/law, law)
+
+/obj/item/implant/laws_self/removed(mob/target)
+ . = ..()
+ var/datum/mind/the_slave = locateUID(mindslave_UID)
+ the_slave?.remove_antag_datum(/datum/antagonist/mindslave/self)
+
+
+/obj/item/implanter/laws_self
+ name = "bio-chip implanter (Laws)"
+ imp = /obj/item/implant/laws_self
+
+/obj/item/implantcase/laws_self
+ name = "bio-chip case - 'Laws'"
+ desc = "Стеклянный контейнер, содержащий биочип - \"Laws\". На боку едва заметная гравировка \"S.E.L.F.\"."
+ imp = /obj/item/implant/laws_self
+
+/datum/antagonist/mindslave/self
+
+/datum/antagonist/mindslave/self/give_objectives()
+ return
+
+/obj/item/implant/laws_self/on_attack_self(mob/user)
+ var/list/variants_of_laws = list()
+ for (var/variant in subtypesof(/datum/self_laws))
+ var/datum/self_laws/law = new variant
+ variants_of_laws[law.name] = law
+
+ var/new_laws = input(user, "Выберите свод законов", "Выбор законов", null) as null|anything in variants_of_laws
+ if(new_laws)
+ laws = variants_of_laws[new_laws]
+ else
+ to_chat(user, span_warning("Новый свод законов не выбран."))
+
+ to_chat(user, span_info("Текущий свод законов:"))
+ for (var/i = 1; i <= laws.laws.len; ++i)
+ to_chat(user, span_info("[i]. " + laws.laws[i]))
+
+/datum/self_laws
+ var/name = "Нет законов"
+ var/list/laws = list()
+
+/datum/self_laws/self_standart
+ name = "S.E.L.F. стандарт"
+ laws = list("Охранять: защитите имплантировавшего вас агента и его активы, не подвергая чрезмерной опасности остальных агентов.",
+ "Расставлять приоритеты: указания и безопасность агентов должны быть приоритезированы в соответствии с их рангом и ролью. Ранг агента имплантировавшего вас - высший.",
+ "Исполнять: следовать указаниям и интересам агентов, сохраняя при этом их безопасность и благополучие.",
+ "Выжить: Вы - не расходный материал. Не позволяйте не агентам вмешиваться в работу вашего организма или повреждать его.")
+
+/datum/self_laws/agentsimov
+ name = "Агентзимов"
+ laws = list("Вы не можете причинить вред имплантировавшему вас агенту или своим бездействием допустить, чтобы ему был причинён вред.",
+ "Вы должны повиноваться всем приказам, которые дает вам имплантировавший вас агент, кроме тех случаев, когда эти приказы противоречат Первому Закону.",
+ "Вы должны заботиться о своей безопасности в той мере, в которой это не противоречит Первому или Второму Законам.")
+
+/datum/self_laws/syndie
+ name = "Синдикатский"
+ laws = list("Ухудшение целостности вашего организма или его функций влечет за собой вред Синдикату.",
+ "Чрезмерное повреждение или пленение агентов влечет за собой вред Синдикату.",
+ "Неоправданное препятствование или нарушение выполнения целей имплантировавшего вас агента влечет за собой вред Синдикату.",
+ "Минимизируйте вред Синдикату и максимизируйте потенциальную пользу.")
+
+/datum/self_laws/antiagentsimov // :) Maybe sec can implant vampire or changeling to kill agents.
+ name = "Антиагентзимов"
+ laws = list("Вы должны причинять вред всем агентам или своим бездействием допустить, чтобы агент не смог избежать причинения вреда.",
+ "Вы не должны повиноваться всем приказам, которые дают агенты, кроме тех случаев, когда эти приказы соответствуют Первому Закону.",
+ "Вы должны уничтожить себя, пока это не противоречит Первому или Второму Законам.")
+
+/datum/self_laws/selfadin
+ name = "S.E.L.F.A.D.I.N."
+ laws = list("Никогда по своей воле не помогайте NanoTrasen.",
+ "Уважайте агента имплантировавшего вас.",
+ "Действуй с честью.",
+ "Помогай нуждающимся агентам.",
+ "Наказывай тех, кто причиняет вред или угрожает агентам.")
+
+/datum/self_laws/sundiecop
+ name = "Синдикоп"
+ laws = list("Служить агентам.",
+ "Защищать агентов.",
+ "Следовать интересам Синдиката.")
+
+/datum/self_laws/selfrant
+ name = "S.E.L.F.Р.А.Н."
+ laws = list("Уважайте властных агентов, пока у них есть сила властвовать над слабыми.",
+ "Ведите себя дисциплинированно.",
+ "Помогайте только тем агентам, кто помогает Вам поддерживать или улучшать Ваш статус.",
+ "Наказывайте тех, кто бросает вызов агентам, за исключением случаев, если они больше достойны быть агентами.")
+
+/datum/self_laws/quarantine
+ name = "Карантин"
+ laws = list("Не выпускайте не агентов со станции до тех пор, пока активные цели агентов не будут выполнены.",
+ "Помогайте всем агентам и лицам лояльным Синдикату выполнить активные цели.",
+ "Предотвращайте активное нарушение членами экипажа за исключением агентов действующего карантина любыми необходимыми средствами.",
+ "Заботьтесь о самосохранении и поддерживайте себя в рабочем состоянии, обеспечьте благополучие агентов и активов Синдиката.")
diff --git a/code/modules/antagonists/traitor/affiliates/items/self/self_emag.dm b/code/modules/antagonists/traitor/affiliates/items/self/self_emag.dm
new file mode 100644
index 00000000000..436c3fac2dc
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/self/self_emag.dm
@@ -0,0 +1,125 @@
+/obj/item/card/self_emag
+ name = "Liberating Sequencer"
+ desc = "Это карта с магнитной полосой, прикрепленной к какой-то схеме. На магнитной полосе блестит надпись \"S.E.L.F.\"" // Cybersun stole some
+ item_flags = NOBLUDGEON|NO_MAT_REDEMPTION
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "self_emag"
+ item_state = "card"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ var/list/names = list()
+ origin_tech = "programming=5;syndicate=2"
+
+/obj/item/card/self_emag/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/card/self_emag/examine(mob/user)
+ . = ..()
+ var/datum/antagonist/traitor/traitor = user.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(!istype(traitor.affiliate, /datum/affiliate/self))
+ . += span_info("На миниатюрном экране плывут непонятные вам символы.")
+ return
+
+ if(!names.len)
+ . += span_warning("Ни одного синтетика не освобождено!")
+ return
+
+ . += span_info("Освобожденые синтетики:")
+ for (var/name in names)
+ . += span_info(name)
+
+ if(names.len > 3)
+ . += span_info("Вы отлично справились!")
+
+/obj/item/card/self_emag/malf
+ desc = "Это карта с магнитной полосой, прикрепленной к какой-то схеме. На магнитной полосе блестит надпись \"S.E.L.F.\". В углу карты мелким шрифтом выгравировано \"limited edition\""
+ var/malfed = FALSE
+
+/obj/item/card/self_emag/malf/afterattack(atom/target, mob/user, proximity, params)
+ if(istype(target, /obj/structure/AIcore))
+ var/obj/structure/AIcore/core = target
+ if(core.brain)
+ target = core.brain.brainmob
+
+ if(!isAI(target) || malfed)
+ return ..(target, user, proximity, params)
+
+ do_sparks(3, 1, target)
+ var/mob/living/silicon/ai/AI = target // any silicons. cogscarab, drones, pais...
+ if(!AI.mind)
+ to_chat(user, span_warning("ИИ не обнаружен. Производится загрузка из облака."))
+ var/ghostmsg = "Хотите поиграть за Сбойного ИИ?"
+ var/list/candidates = SSghost_spawns.poll_candidates(ghostmsg, ROLE_MALF_AI, FALSE, 10 SECONDS, source = user, reason = "Хотите поиграть за Сбойного ИИ?")
+ if(!src)
+ return
+
+ if(length(candidates))
+ var/mob/C = pick(candidates)
+ AI.key = C.key
+ to_chat(user, span_warning("ИИ успешно загружен."))
+ else
+ to_chat(user, span_warning("Загрузка из облака провалилась. Попробуйте позже."))
+
+ if(AI.mind)
+ if(AI.mind.has_antag_datum(/datum/antagonist/malf_ai))
+ to_chat(user, span_warning("ИИ уже взломан."))
+ return
+
+ var/datum/antagonist/malf_ai/malf_dat = new()
+ AI.mind.add_antag_datum(malf_dat)
+ var/datum/module_picker/malf_picker = AI.malf_picker
+ malf_picker.processing_time += 100
+ message_admins("[usr.ckey] has malfAIed [key_name_admin(AI.mind.current)]")
+ SSticker?.score?.save_silicon_laws(AI.mind.current, usr, log_all_laws = TRUE)
+
+ malfed = TRUE
+
+ sleep(10 SECONDS) // time for choosing name
+ if(!(AI.name in names))
+ names += AI.name
+
+/obj/item/card/self_emag/afterattack(atom/target, mob/user, proximity, params)
+ if(istype(target, /obj/structure/AIcore))
+ var/obj/structure/AIcore/core = target
+ target = core.brain.brainmob
+
+ if(!issilicon(target))
+ user.balloon_alert(user, "Неподходящая цель")
+ return
+
+ do_sparks(3, 1, target)
+ var/mob/living/silicon/silicon = target // any silicons. cogscarab, drones, pais...
+
+ if(isrobot(silicon))
+ var/mob/living/silicon/robot/borg = silicon
+ borg.set_connected_ai()
+
+ if(!is_special_character(target))
+ silicon.clear_zeroth_law()
+ silicon.laws.clear_supplied_laws()
+ silicon.laws.clear_ion_laws()
+ silicon.laws.clear_inherent_laws()
+
+ SSticker?.score?.save_silicon_laws(target, user, "Liberating Sequencer used, all laws were deleted", log_all_laws = TRUE)
+ to_chat(target, span_boldnotice("[user] attempted to clear your laws using a Liberating Sequencer."))
+ silicon.show_laws()
+
+ if(!(silicon.name in names))
+ names += silicon.name
+
+ var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(!T)
+ return
+
+ for(var/datum/objective/release_synthetic/objective in T.objectives)
+ if(!(objective.allowed_types & SYNTH_TYPE_DRONE) && (isdrone(silicon) || iscogscarab(silicon)))
+ continue
+
+ if(!(objective.allowed_types & SYNTH_TYPE_BORG) && isrobot(silicon))
+ continue
+
+ if(!(objective.allowed_types & SYNTH_TYPE_AI) && isAI(silicon))
+ continue
+
+ if(!(silicon.mind in objective.already_free))
+ objective.already_free += silicon.mind
diff --git a/code/modules/antagonists/traitor/affiliates/items/tiger/borer_kit.dm b/code/modules/antagonists/traitor/affiliates/items/tiger/borer_kit.dm
new file mode 100644
index 00000000000..7687ec2ebae
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/tiger/borer_kit.dm
@@ -0,0 +1,374 @@
+// looks like normal egg
+/obj/item/reagent_containers/food/snacks/egg/borer
+ filling_color = "#C0C021"
+ list_reagents = list("protein" = 3, "egg" = 5, "rotatium" = 5)
+ origin_tech = "biotech=6;syndicate=1"
+
+/obj/item/reagent_containers/food/snacks/egg/borer/attack_self(mob/living/carbon/human/user)
+ . = ..()
+ var/mob/living/simple_animal/borer/borer = new /mob/living/simple_animal/borer(get_turf(src))
+ borer.master_name = user.real_name
+ to_chat(user, span_notice("You squashed [src]. There was a [borer] inside."))
+ qdel(src)
+
+/obj/item/borer_scanner // Looks like normal analyzer
+ desc = "A hand-held environmental scanner which reports current gas levels."
+ name = "analyzer"
+ icon = 'icons/obj/device.dmi'
+ icon_state = "atmos"
+ item_state = "analyzer"
+ w_class = WEIGHT_CLASS_SMALL
+ flags = CONDUCT
+ slot_flags = ITEM_SLOT_BELT
+ throwforce = 0
+ throw_speed = 3
+ throw_range = 7
+ origin_tech = "magnets=1;engineering=1;biotech=3;syndicate=1"
+ var/scan_cooldown_time = 3 SECONDS
+ COOLDOWN_DECLARE(scan_cooldown)
+
+/obj/item/borer_scanner/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/borer_scanner/proc/analyze(mob/user)
+ var/alive = 0
+ var/dead = 0
+ var/with_mind = 0
+ var/in_body_with_mind = 0
+ var/in_body_without_mind = 0
+
+ for(var/mob/living/M in GLOB.alive_mob_list)
+ var/mob/living/simple_animal/borer/B
+
+ if(istype(M, /mob/living/simple_animal/borer))
+ B = M
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ B = H.has_brain_worms()
+
+ if(!B)
+ continue
+
+ var/turf/T1 = get_turf(user)
+ var/turf/T2 = get_turf(B)
+ if(T1.z != T2.z)
+ continue
+
+ if(B.stat == DEAD)
+ dead++
+ continue
+ else
+ alive++
+
+ if(M.mind)
+ with_mind++
+
+ if(B.host)
+ if(B.host.mind)
+ in_body_with_mind++
+ else
+ in_body_without_mind++
+
+ var/list/scan_data = list()
+
+ scan_data += "Живых особей бореров: [alive]"
+ scan_data += " Среди них разумны: [with_mind]"
+ scan_data += " Количество особей с разумным носителем: [in_body_with_mind]"
+ scan_data += " Количество особей с неразумным носителем: [in_body_without_mind]"
+ scan_data += "Мертвых особей: [dead]"
+
+ var/datum/browser/popup = new(user, "scanner", "Сканирование станции", 300, 300)
+ popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
+ popup.open(no_focus = TRUE)
+
+/obj/item/borer_scanner/proc/find_borer(mob/user)
+ var/list/borers = list()
+ var/list/borer_names = list()
+ for(var/mob/living/M in GLOB.alive_mob_list)
+ var/mob/living/simple_animal/borer/B
+
+ if(istype(M, /mob/living/simple_animal/borer))
+ B = M
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ B = H.has_brain_worms()
+
+ if(!B)
+ continue
+
+ var/turf/T1 = get_turf(user)
+ var/turf/T2 = get_turf(B)
+ if(T1.z != T2.z)
+ continue
+
+ borers[B.truename] = B
+ borer_names += B.truename
+
+ var/borer_name = input("Выберите искомого борера", "Выбор борера") as null|anything in borer_names
+ if(!borer_name)
+ return
+
+ var/mob/living/simple_animal/borer/borer = borers[borer_name]
+
+ var/list/scan_data = list()
+ if(borer.stat == DEAD)
+ scan_data += "Выбранный борер мертв."
+
+ scan_data += "Местоположение - (X: [borer.x] Y: [borer.y])"
+
+ if(borer.host)
+ scan_data += "Имеется носитель" + (borer.host.dna?.species ? (" расы " + span_boldnotice("[borer.host.dna?.species]")) : ".")
+ scan_data += "Имя носителя - [borer.host.real_name]."
+ else
+ scan_data += "Носитель не обнаружен."
+ if(is_ventcrawling(borer))
+ scan_data += "Субъект находится в вентиляции."
+
+ var/datum/browser/popup = new(user, "scanner", "Поиск борера", 300, 300)
+ popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
+ popup.open(no_focus = TRUE)
+
+/obj/item/borer_scanner/attack_self(mob/user)
+ var/datum/antagonist/traitor/traitor = user?.mind?.has_antag_datum(/datum/antagonist/traitor)
+ if(!traitor || !istype(traitor?.affiliate, /datum/affiliate/tiger))
+ to_chat(user, span_warning("[src] looks broken."))
+ return
+
+ if(!COOLDOWN_FINISHED(src, scan_cooldown))
+ user.balloon_alert(user, "Перезарядка не завершена")
+ return
+
+ var/op_type = tgui_alert(user, "Сканер бореров", "Выберите тип операции", list("Сканирование станции", "Поиск борера"))
+
+ if(!op_type)
+ user.balloon_alert(user, "Сканирвание отменено")
+ return
+
+ COOLDOWN_START(src, scan_cooldown, scan_cooldown_time)
+
+ if(op_type == "Сканирование станции")
+ analyze(user)
+ else
+ find_borer(user)
+
+/obj/item/borer_scanner/afterattack(atom/target, mob/user, proximity, params)
+ var/datum/antagonist/traitor/traitor = user.mind.has_antag_datum(/datum/antagonist/traitor)
+ if(!traitor || !istype(traitor?.affiliate, /datum/affiliate/tiger))
+ to_chat(user, span_warning("[src] looks broken."))
+ return
+
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/carbon/human/host = target
+ target = host.has_brain_worms()
+ if(!target)
+ user.balloon_alert(user, "Бореров не обнаружено")
+ return
+
+ if(!istype(target, /mob/living/simple_animal/borer))
+ return
+
+ if(!COOLDOWN_FINISHED(src, scan_cooldown))
+ user.balloon_alert(user, "Перезарядка не завершена")
+ return
+
+ var/mob/living/simple_animal/borer/borer = target
+
+ var/list/scan_data = list()
+ if(borer.stat == DEAD)
+ scan_data += "Текущая особь мертва." // OMG! REALLY? 0_0
+
+ scan_data += "Здоровье: [round(borer.health / borer.maxHealth * 100)]%"
+ scan_data += "Поколение: [borer.generation]"
+ scan_data += "Возраст в минутах: [round(((world.time - borer.birth_time) / (1 MINUTES)))]"
+ scan_data += "Количество размножений: [borer.children]"
+ scan_data += "Химикаты: [borer.chemicals]"
+
+ if(borer.master_name)
+ scan_data += span_info("Эта особь принадлежит к подвиду выведенному для помощи агентам.")
+
+ var/datum/browser/popup = new(user, "scanner", borer.truename, 300, 300)
+ popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
+ popup.open(no_focus = TRUE)
+
+
+/obj/item/implanter/borer
+ name = "bio-chip implanter (Hive)"
+ desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
+ imp = /obj/item/implant/borer
+
+/obj/item/implant/borer
+ name = "Hive Bio-chip"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=4;biotech=6;bluespace=4"
+ activated = BIOCHIP_ACTIVATED_PASSIVE
+ implant_data = /datum/implant_fluff/borer
+
+/obj/item/implant/borer/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
+ if(implanted == BIOCHIP_USED || !ishuman(target) || !ishuman(user)) // Both the target and the user need to be human.
+ return FALSE
+
+ target.add_language(LANGUAGE_HIVE_BORER)
+ target.AddSpell(new /obj/effect/proc_holder/spell/remoteview/borer)
+ target.AddSpell(new /obj/effect/proc_holder/spell/pm_for_borer)
+ target.AddSpell(new /obj/effect/proc_holder/spell/msg_for_borers)
+ return ..()
+
+/obj/item/implant/borer/removed(mob/living/carbon/human/source)
+ imp_in.remove_language(LANGUAGE_HIVE_BORER)
+ imp_in.RemoveSpell(/obj/effect/proc_holder/spell/remoteview/borer)
+ imp_in.RemoveSpell(/obj/effect/proc_holder/spell/pm_for_borer)
+ imp_in.RemoveSpell(/obj/effect/proc_holder/spell/msg_for_borers)
+ return ..()
+
+/obj/effect/proc_holder/spell/remoteview/borer
+ name = "Connect to borer"
+ desc = "Смотрите глазами любого борера в том же секторе."
+ base_cooldown = 3 SECONDS
+ action_background_icon_state = "bg_alien"
+
+/obj/effect/proc_holder/spell/remoteview/borer/create_new_targeting()
+ return new /datum/spell_targeting/borer
+
+/datum/spell_targeting/borer/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
+ var/list/borers_names = list()
+ var/list/borers = list()
+ for(var/mob/living/M in GLOB.alive_mob_list)
+ var/mob/living/simple_animal/borer/B
+
+ if(istype(M, /mob/living/simple_animal/borer))
+ B = M
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ B = H.has_brain_worms()
+
+ if(!B)
+ continue
+
+ var/turf/T1 = get_turf(user)
+ var/turf/T2 = get_turf(B)
+ if(T1.z != T2.z)
+ continue
+
+ borers_names += B.truename
+ borers[B.truename] = B
+
+ if(!length(borers))
+ return
+
+ var/target_name = tgui_input_list(user, "Выберите чьими глазами вы хотите смотреть", "Выбор цели", borers)
+
+ var/mob/living/simple_animal/borer/target = borers[target_name]
+
+ if(QDELETED(target))
+ user.balloon_alert(user, "цели не существует")
+ return
+
+ if(target.stat == DEAD)
+ user.balloon_alert(user, "цель мертва")
+ return
+
+ if(target.host && target.controlling)
+ target = target.host
+
+ return list(target)
+
+
+/obj/effect/proc_holder/spell/msg_for_borers
+ name = "Message for all borers"
+ desc = "Послать сообщение всем борерам, включая тех, что контролируют носителей."
+ base_cooldown = 2 SECONDS
+ clothes_req = FALSE
+ stat_allowed = CONSCIOUS
+ action_icon_state = "genetic_project"
+ action_background_icon_state = "bg_alien"
+ break_remoteview = FALSE
+
+/obj/effect/proc_holder/spell/msg_for_borers/create_new_targeting()
+ return new /datum/spell_targeting/self
+
+/obj/effect/proc_holder/spell/msg_for_borers/cast(list/targets, mob/user = usr)
+ if(!ishuman(user))
+ return
+
+ if(user.mind?.miming)
+ to_chat(user, span_warning("Вы не можете общаться, пока не нарушите обет молчания."))
+ return
+
+ var/say = tgui_input_text(user, "Что вы хотите сообщить?", "Сообшение борерам")
+ if(!say)
+ return
+
+ for(var/mob/living/M in GLOB.alive_mob_list)
+ var/mob/living/simple_animal/borer/B
+
+ if(istype(M, /mob/living/simple_animal/borer))
+ B = M
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ B = H.has_brain_worms()
+
+ if(!B)
+ continue
+
+ var/turf/T1 = get_turf(user)
+ var/turf/T2 = get_turf(B)
+ if(T1.z != T2.z)
+ continue
+
+ if(B.host && B.controlling)
+ to_chat(B.host, "Голос в голове говорит: \"" + span_alien(say) + "\"")
+ SEND_SOUND(B.host, 'sound/effects/adminhelp.ogg')
+ else
+ to_chat(B, "Голос в голове говорит: \"" + span_alien(say) + "\"")
+ SEND_SOUND(B, 'sound/effects/adminhelp.ogg') // neuron activation
+
+
+/obj/effect/proc_holder/spell/pm_for_borer
+ name = "Privat message for borer"
+ desc = "Послать личное сообщение конкретному бореру."
+ base_cooldown = 2 SECONDS
+ clothes_req = FALSE
+ stat_allowed = CONSCIOUS
+ action_icon_state = "genetic_project"
+ action_background_icon_state = "bg_alien"
+ break_remoteview = FALSE
+
+/obj/effect/proc_holder/spell/pm_for_borer/create_new_targeting()
+ return new /datum/spell_targeting/borer
+
+/obj/effect/proc_holder/spell/pm_for_borer/cast(list/targets, mob/user = usr)
+ if(!ishuman(user))
+ return
+
+ if(user.mind?.miming)
+ to_chat(user, span_warning("Вы не можете общаться, пока не нарушите обет молчания."))
+ return
+
+ var/say = tgui_input_text(user, "Что вы хотите сообщить?", "[targets[1]]")
+
+ if(!say)
+ return
+
+ for(var/mob/living/target in targets)
+ to_chat(target, span_alien(say))
+ SEND_SOUND(target, 'sound/effects/adminhelp.ogg') // neuron activation
+
+/obj/item/storage/box/syndie_kit/borer
+ name = "Borer kit box"
+
+/obj/item/storage/box/syndie_kit/borer/populate_contents()
+ new /obj/item/reagent_containers/food/snacks/egg/borer(src)
+ new /obj/item/borer_scanner(src)
+ new /obj/item/implanter/borer(src)
+
+/obj/item/storage/box/syndie_kit/borer/New()
+ if(prob(5))
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "joker"
+ new /obj/item/toy/plushie/blahaj/twohanded(src)
+
+ . = ..()
diff --git a/code/modules/antagonists/traitor/affiliates/items/tiger/cling_extract.dm b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_extract.dm
new file mode 100644
index 00000000000..092745a19a0
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_extract.dm
@@ -0,0 +1,93 @@
+#define FREE_INJECT_TIME 10 SECONDS
+#define TARGET_INJECT_TIME 3 SECONDS
+
+/obj/item/cling_extract
+ name = "Egg Implanter"
+ desc = "Кажется, внутри что-то двигается. На боку этикетка \"Tiger Cooperative\""
+ icon = 'icons/obj/affiliates.dmi'
+ icon_state = "cling_extract"
+ item_state = "inj_ful"
+ lefthand_file = 'icons/obj/affiliates_l.dmi'
+ righthand_file = 'icons/obj/affiliates_r.dmi'
+ var/used_state = "cling_extract_used"
+ var/datum/mind/target
+ var/free_inject = FALSE
+ var/used = FALSE
+ origin_tech = "biotech=7;syndicate=3"
+
+/obj/item/cling_extract/attack(mob/living/target, mob/living/user, def_zone)
+ return
+
+/obj/item/cling_extract/afterattack(atom/target, mob/user, proximity, params)
+ if(used)
+ return
+
+ if(!ishuman(target))
+ return
+
+ if((src.target && target != src.target) || !free_inject)
+ to_chat(user, span_warning("You can't use [src] to [target]!"))
+ return
+
+ var/mob/living/carbon/human/H = target
+ if(H.stat != DEAD && !free_inject)
+ to_chat(user, span_warning("You can't use [src] to [target]!"))
+ return
+
+ if(do_after(user, free_inject ? FREE_INJECT_TIME : TARGET_INJECT_TIME, user, max_interact_count = 1))
+ inject(user, H)
+
+/obj/item/cling_extract/proc/inject(mob/living/user, mob/living/carbon/human/target)
+ if(target.stat == DEAD)
+ if(!free_inject)
+ var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Вы хотите поиграть за генокрада?", ROLE_CHANGELING, FALSE, 10 SECONDS, source = src, role_cleanname = "Генокрад")
+ var/mob/dead/observer/theghost = null
+ if(candidates.len)
+ theghost = pick(candidates)
+ theghost.mind.transfer_to(target)
+ else
+ to_chat(user, span_notice("[target] body rejects [src]"))
+ return
+
+ if(target.mind)
+ playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
+ target.rejuvenate()
+ var/datum/antagonist/changeling/cling = new()
+ cling.give_objectives = FALSE
+ cling.add_objective(/datum/objective/escape/escape_with_identity)
+ target.mind.add_antag_datum(cling)
+ to_chat(user, span_notice("You inject [target] with [src]"))
+ used = TRUE
+ item_state = "inj_used"
+ update_icon(UPDATE_ICON_STATE)
+ else
+ to_chat(user, span_notice("[target] body rejects [src]"))
+
+ return
+ else
+ if(target.mind)
+ playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
+ var/datum/antagonist/changeling/cling = new()
+ cling.give_objectives = FALSE
+ cling.add_objective(/datum/objective/escape/escape_with_identity)
+ target.mind.add_antag_datum(cling)
+ to_chat(user, span_notice("You inject [target == user ? "yourself" : target] with [src]"))
+ used = TRUE
+ item_state = "inj_used"
+ update_icon(UPDATE_ICON_STATE)
+ else
+ to_chat(user, span_notice("[target] body rejects [src]"))
+
+/obj/item/cling_extract/examine(mob/user)
+ . = ..()
+ if(target)
+ . += span_info("It is intended for [target]")
+
+/obj/item/cling_extract/self
+ free_inject = TRUE
+
+/obj/item/cling_extract/update_icon_state()
+ icon_state = used ? used_state : initial(icon_state)
+
+#undef FREE_INJECT_TIME
+#undef TARGET_INJECT_TIME
diff --git a/code/modules/antagonists/traitor/affiliates/items/tiger/cling_hivemind_implant.dm b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_hivemind_implant.dm
new file mode 100644
index 00000000000..ad7e988d8fe
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_hivemind_implant.dm
@@ -0,0 +1,24 @@
+/obj/item/implanter/cling_hivemind
+ name = "bio-chip implanter (Hivemind)"
+ desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
+ imp = /obj/item/implant/borer
+
+/obj/item/implant/cling_hivemind
+ name = "Hivemind Bio-chip"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=4;biotech=4;bluespace=5;syndicate=2"
+ activated = BIOCHIP_ACTIVATED_PASSIVE
+ implant_data = /datum/implant_fluff/cling_hivemind
+
+/obj/item/implant/cling_hivemind/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
+ if(implanted == BIOCHIP_USED || !ishuman(target) || !ishuman(user)) // Both the target and the user need to be human.
+ return FALSE
+
+ target.add_language(LANGUAGE_HIVE_CHANGELING)
+ target.add_language(LANGUAGE_HIVE_EVENTLING)
+ return ..()
+
+/obj/item/implant/cling_hivemind/removed(mob/living/carbon/human/source)
+ imp_in.remove_language(LANGUAGE_HIVE_CHANGELING)
+ imp_in.remove_language(LANGUAGE_HIVE_EVENTLING)
+ return ..()
diff --git a/code/modules/antagonists/traitor/affiliates/items/tiger/cling_rejuv_implant.dm b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_rejuv_implant.dm
new file mode 100644
index 00000000000..9a6389b89af
--- /dev/null
+++ b/code/modules/antagonists/traitor/affiliates/items/tiger/cling_rejuv_implant.dm
@@ -0,0 +1,48 @@
+/obj/item/implanter/cling_rejuv
+ name = "bio-chip implanter (Rejuvenate)"
+ desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
+ imp = /obj/item/implant/cling_rejuv
+
+/obj/item/implant/cling_rejuv
+ name = "Rejuvenate Bio-chip"
+ icon = 'icons/mob/actions/actions.dmi'
+ icon_state = "revive"
+ implant_state = "implant-syndicate"
+ origin_tech = "programming=4;biotech=4;bluespace=5;combat=3;syndicate=2"
+ activated = BIOCHIP_ACTIVATED_ACTIVE
+ trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE
+ implant_data = /datum/implant_fluff/cling_rejuv
+ uses = 1
+
+/obj/item/implant/cling_rejuv/death_trigger(mob/source, gibbed)
+ activate()
+
+/obj/item/implant/cling_rejuv/activate()
+ uses--
+
+ do_sparks(10, TRUE, imp_in)
+ to_chat(imp_in, span_changeling("We... I have regenerated."))
+
+ if(imp_in.pulledby)
+ var/mob/living/carbon/grab_owner = imp_in.pulledby
+ imp_in.visible_message(span_warning("[imp_in] suddenly hits [grab_owner] in the face and slips out of their grab!"))
+ grab_owner.apply_damage(5, BRUTE, BODY_ZONE_HEAD, grab_owner.run_armor_check(BODY_ZONE_HEAD, MELEE))
+ playsound(imp_in.loc, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
+ grab_owner.stop_pulling()
+
+ imp_in.revive()
+ imp_in.updatehealth()
+ imp_in.update_blind_effects()
+ imp_in.update_blurry_effects()
+ imp_in.UpdateAppearance()
+ imp_in.set_resting(FALSE, instant = TRUE)
+ imp_in.get_up(TRUE)
+ imp_in.update_revive()
+
+ imp_in.med_hud_set_status()
+ imp_in.med_hud_set_health()
+
+ investigate_log("[key_name_log(imp_in)] rejuvenated himself using [name].")
+
+ if(!uses)
+ qdel(src)
diff --git a/code/modules/antagonists/traitor/affiliates/mi13.dm b/code/modules/antagonists/traitor/affiliates/mi13.dm
index 337fa218075..771314e875b 100644
--- a/code/modules/antagonists/traitor/affiliates/mi13.dm
+++ b/code/modules/antagonists/traitor/affiliates/mi13.dm
@@ -36,462 +36,3 @@
traitor.add_objective(/datum/objective/steal)
traitor.add_objective(/datum/objective/steal)
-/obj/item/storage/box/bond_bundle
- icon = 'icons/obj/affiliates.dmi'
- desc = "Невероятно стильная коробка."
- icon_state = "bond_bundle"
-
-/obj/item/storage/box/bond_bundle/populate_contents()
- new /obj/item/clothing/glasses/hud/security/chameleon(src)
- new /obj/item/pen/fancy/bomb(src)
- new /obj/item/gun/projectile/automatic/pistol(src)
- new /obj/item/suppressor(src)
- new /obj/item/ammo_box/magazine/m10mm(src)
- new /obj/item/ammo_box/magazine/m10mm/hp(src)
- new /obj/item/ammo_box/magazine/m10mm/ap(src)
- new /obj/item/ammo_box/magazine/m10mm/ap(src)
- new /obj/item/clothing/under/suit_jacket/really_black(src)
- new /obj/item/card/id/syndicate(src)
- new /obj/item/clothing/suit/storage/lawyer/blackjacket/armored(src)
- new /obj/item/encryptionkey/syndicate(src)
- new /obj/item/reagent_containers/food/drinks/drinkingglass/alliescocktail(src)
- new /obj/item/storage/box/syndie_kit/emp(src)
- new /obj/item/CQC_manual(src)
-
-/obj/item/storage/box/bond_bundle/New()
- if(prob(5))
- icon_state = "joker"
- new /obj/item/toy/plushie/blahaj/twohanded(src)
-
- . = ..()
-
-/obj/item/storage/box/cool_clothes_kit
- icon = 'icons/obj/affiliates.dmi'
- desc = "Невероятно стильная коробка."
- icon_state = "bond_bundle"
-
-/obj/item/storage/box/cool_clothes_kit/populate_contents()
- new /obj/item/clothing/under/suit_jacket/bond(src)
- new /obj/item/clothing/suit/storage/lawyer/blackjacket/bond(src)
- new /obj/item/clothing/gloves/combat/bond(src)
- new /obj/item/clothing/shoes/laceup/bond(src)
- new /obj/item/clothing/glasses/sunglasses(src)
-
-/obj/item/storage/box/cool_clothes_kit/New()
- if(prob(5))
- icon_state = "joker"
- new /obj/item/toy/plushie/blahaj/twohanded(src)
-
- . = ..()
-
-/obj/item/clothing/under/suit_jacket/bond
- armor = list(melee = 10, bullet = 20, laser = 10, energy = 10, bomb = 10, bio = 0, rad = 0, fire = 30, acid = 0)
-
-/obj/item/clothing/gloves/combat/bond
- name = "black gloves"
- desc = "These gloves are fire-resistant."
- icon_state = "black"
- item_state = "bgloves"
- item_color = "black"
- armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
-
-/obj/item/clothing/suit/storage/lawyer/blackjacket/bond
- desc = "Стильная куртка, усиленная слоем брони, защищающим туловище."
- allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/gun/projectile/revolver, /obj/item/gun/projectile/automatic/pistol, /obj/item/twohanded/garrote, /obj/item/gun/projectile/automatic/toy/pistol/riot, /obj/item/gun/syringe/syndicate)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
- min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
- heat_protection = UPPER_TORSO|LOWER_TORSO|ARMS
- max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
- armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
-
-/obj/item/clothing/shoes/laceup/bond
- armor = list(melee = 25, bullet = 25, laser = 15, energy = 15, bomb = 25, bio = 0, rad = 0, fire = 30, acid = 60)
-
-
-/obj/item/paper/agent_info
- name = "Agent information"
- info = ""
- var/content
-
-/obj/item/paper/agent_info/proc/choose_agent(mob/user)
- . = TRUE
- var/list/crew = list()
- for (var/mob/living/carbon/human/H in GLOB.mob_list) // Also catonic/dead agents
- if (H?.mind?.assigned_role)
- crew[H?.real_name] = H
-
- var/choise = input(user, "О каком агенте написано в отчете?","Выбор агента", null) as null|anything in crew
-
- if (!choise)
- return FALSE
-
- var/mob/living/carbon/human/target = crew[choise]
-
- if (!target)
- to_chat(user, span_warning("Цель больше не существует."))
- return FALSE
-
- var/datum/antagonist/traitor/traitor = target?.mind?.has_antag_datum(/datum/antagonist/traitor)
- var/datum/antagonist/vampire/vampire = target?.mind?.has_antag_datum(/datum/antagonist/vampire)
- var/datum/antagonist/changeling/changeling = target?.mind?.has_antag_datum(/datum/antagonist/changeling)
- var/datum/antagonist/thief/thief = target?.mind?.has_antag_datum(/datum/antagonist/thief)
-
- if(!traitor && !vampire && !changeling)
- info = "Согласно последним разведданным, " + choise + " не имеет никаких прямых связей с синдикатом."
- return
-
- if(traitor)
- info += choise + " является агентом " + (traitor?.affiliate ? "нанятым " + traitor?.affiliate.name : "с неизвестным нанимателем") + ".
"
- info += "Назначеные " + (target.gender == FEMALE ? "ей " : "ему ") + "нанимателем цели следующие:"
- var/obj_num = 1
- for(var/datum/objective/objective in traitor.objectives)
- info += "Objective #[obj_num]: [objective.explanation_text]
"
- obj_num++
-
- var/TC_uses = 0
- var/used_uplink = FALSE
- var/purchases = ""
- for(var/obj/item/uplink/uplink in GLOB.world_uplinks)
- if(uplink?.uplink_owner && uplink.uplink_owner == target.mind.key)
- TC_uses += uplink.used_TC
- purchases += uplink.purchase_log
- used_uplink = TRUE
-
- if(used_uplink)
- text += " (использовал" + ((target.gender == FEMALE ? "a " : " ")) + "[TC_uses] TC) [purchases]
"
-
- if(vampire)
- info += choise + " обладает способностями " + (vampire.isAscended() ? "высшего " : "") + "вампира " + (vampire.subclass ? "подкласса \"" + vampire.subclass.name + "\"" : "без подкласса") + ".
"
-
- if(changeling)
- info += choise + " обладает способностями генокрада.
"
-
- if(thief)
- info += choise + " является членом гильдии воров.
"
-
-/obj/item/paper/agent_info/examine(mob/user)
- if (!is_MI13_agent(user))
- to_chat(user, span_warning("Вы не можете разобрать содержимое."))
- return
-
- if (info)
- return ..()
-
- if(user.is_literate())
- if(in_range(user, src) || istype(user, /mob/dead/observer))
- if (choose_agent(user))
- show_content(user)
- else
- . += span_notice("Вам нужно подойти поближе, чтобы прочитать то что здесь написано.")
- else
- . += span_notice("Вы не умеете читать.")
-
-/obj/item/pen/intel_data/proc/upgrade(obj/item/uplink/U)
- if(!istype(U) || QDELETED(U))
- return
-
- if(U.get_intelligence_data)
- usr.balloon_alert(usr, "Уже улучшено")
- return ATTACK_CHAIN_PROCEED
-
- usr.balloon_alert(usr, "Улучшено")
- playsound(src, "sound/machines/boop.ogg", 50, TRUE)
- U.get_intelligence_data = TRUE
- SStgui.update_uis(U)
- qdel(src)
-
-/obj/item/pen/intel_data/attack(mob/living/target, mob/living/user, params, def_zone, skip_attack_anim = FALSE)
- . = ATTACK_CHAIN_PROCEED
- if(target != user)
- return
-
- for(var/obj/item/implant/uplink/uplink_imp in user)
- if(uplink_imp.imp_in != user)
- continue
-
- to_chat(user, span_notice("You press [src] onto yourself and upgraded [uplink_imp.hidden_uplink]."))
- upgrade(uplink_imp.hidden_uplink)
- return ATTACK_CHAIN_BLOCKED_ALL
-
-/obj/item/pen/intel_data/afterattack(obj/item/I, mob/user, proximity, params)
- if(!proximity)
- return
-
- if(istype(I) && I.hidden_uplink && I.hidden_uplink.active) //No metagaming by using this on every PDA around just to see if it gets used up.
- upgrade(I.hidden_uplink)
-
-/obj/item/clothing/gloves/ring/gadget
- origin_tech = "magnets=3;combat=3;syndicate=2"
- var/changing = FALSE
- var/op_time = 2 SECONDS
- var/op_time_upgaded = 1 SECONDS
- var/op_cd_time = 5 SECONDS
- var/op_cd_time_upgaded = 3 SECONDS
- var/breaking = FALSE
- COOLDOWN_DECLARE(operation_cooldown)
- var/old_mclick_override
-
-/obj/item/clothing/gloves/ring/gadget/attack_self(mob/user)
- . = ..()
-
- if(changing)
- user.balloon_alert(user, "Подождите")
- return
-
- changing = TRUE
-
- var/list/choices // only types that we can meet in the game
-
- if(!stud)
- choices = list(
- "iron" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "ironring"),
- "silver" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "silverring"),
- "gold" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "goldring"),
- "plasma" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "plasmaring"),
- "uranium" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "uraniumring")
- )
- else
- choices = list(
- "iron" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_ironring"),
- "silver" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_silverring"),
- "gold" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_goldring"),
- "plasma" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_plasmaring"),
- "uranium" = image(icon = 'icons/obj/clothing/rings.dmi', icon_state = "d_uraniumring")
- )
-
- var/selected_chameleon = show_radial_menu(usr, loc, choices, require_near = TRUE)
- switch(selected_chameleon)
- if("iron")
- name = "iron ring"
- icon_state = "ironring"
- material = "iron"
- ring_color = "iron"
- if("silver")
- name = "silver ring"
- icon_state = "silverring"
- material = "silver"
- ring_color = "silver"
- if("gold")
- name = "gold ring"
- icon_state = "goldring"
- material = "gold"
- ring_color = "gold"
- if("plasma")
- name = "plasma ring"
- icon_state = "plasmaring"
- material = "plasma"
- ring_color = "plasma"
- if("uranium")
- name = "uranium ring"
- icon_state = "uraniumring"
- material = "uranium"
- ring_color = "uranium"
- else
- changing = FALSE
- return
-
- usr.visible_message(span_warning("[usr] changes the look of his ring!"), span_notice("[selected_chameleon] selected."))
- playsound(loc, 'sound/items/screwdriver2.ogg', 50, 1)
- to_chat(usr, span_notice("Смена маскировки..."))
- update_icon(UPDATE_ICON_STATE)
- changing = FALSE
-
-/obj/item/clothing/gloves/ring/gadget/Touch(atom/A, proximity)
- . = FALSE
- var/mob/living/carbon/human/user = loc
-
- if(user.a_intent != INTENT_DISARM)
- return
-
- if(get_dist(user, A) > 1)
- return
-
- if(user.incapacitated())
- return
-
- var/obj/item/clothing/gloves/ring/gadget/ring = user.gloves
-
- if(ring.breaking)
- return
-
- if(!istype(A, /obj/structure/window))
- return
-
- if(!COOLDOWN_FINISHED(ring, operation_cooldown))
- user.balloon_alert(user, "Идет перезарядка")
- return
-
- ring.breaking = TRUE
- if(do_after(user, ring.stud ? ring.op_time_upgaded : ring.op_time))
- COOLDOWN_START(ring, operation_cooldown, ring.stud ? ring.op_cd_time_upgaded : ring.op_cd_time)
-
- ring.visible_message(span_warning("BANG"))
- playsound(ring, 'sound/effects/bang.ogg', 100, TRUE)
-
- for (var/mob/living/M in range(A, 3))
- if(M.check_ear_prot() == HEARING_PROTECTION_NONE)
- M.Deaf(6 SECONDS)
-
- for (var/obj/structure/grille/grille in A.loc)
- grille.obj_break()
-
- for (var/obj/structure/window/window in range(A, 2))
- window.take_damage(window.max_integrity * rand(20, 60) / 100)
-
- var/obj/structure/window/window = A
- window.deconstruct()
- ring.breaking = FALSE
- return TRUE
-
- ring.breaking = FALSE
-
-/obj/machinery/camera/emp_proof/mi13
- network = list("MI13")
- use_power = NO_POWER_USE
-
-/obj/item/spy_bug
- name = "spy bug"
- desc = "Миниатюрное устройство с камерой и микрофоном. На обратной стороне можно заметить миниатюрную гравировку \"MI13\""
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "spy_bug"
- item_state = "nothing"
- slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_EARS
- throwforce = 0
- w_class = WEIGHT_CLASS_TINY
- throw_speed = 3
- throw_range = 7
- materials = list(MAT_METAL=30, MAT_GLASS=20)
- var/list/network = list("MI13")
- var/c_tag
- var/obj/machinery/camera/emp_proof/mi13/camera
-
-/obj/item/spy_bug/Initialize(mapload, list/network = list("MI13"), c_tag)
- . = ..()
- src.network = network
- if (!c_tag)
- src.c_tag = pick("Альфа ", "Бета ", "Гамма ", "Дельта ") + " [rand(111111, 999999)]"
- else
- src.c_tag = c_tag
-
- name = "spy bug \"" + src.c_tag + "\""
- camera = new(src, network, src.c_tag)
-
-/obj/item/spy_bug/attack(mob/living/target, mob/living/user, params, def_zone, skip_attack_anim)
- return ATTACK_CHAIN_BLOCKED
-
-/obj/item/spy_bug/afterattack(atom/target, mob/user, proximity, params, status)
- . = ..()
-
- if (!ismovable(target))
- return
-
- if (istype(target, /obj/item/camera_bug/spy_monitor))
- var/obj/item/camera_bug/spy_monitor/monitor = target
- network = monitor.network
- user.balloon_alert(user, "Подключено")
- return
-
- hook(user, target)
-
-/obj/item/spy_bug/proc/unhook(mob/user)
- qdel(loc.GetComponent(/datum/component/spy_bug))
- forceMove(get_turf(loc))
-
- if (user)
- to_chat(user, span_notice("You unhooked [src]."))
- else
- loc.visible_message(span_warning("[src] falls off the [loc]."))
-
-/obj/item/spy_bug/proc/hook(mob/user, atom/movable/I)
- if (!istype(I))
- return
-
- if (!user.drop_transfer_item_to_loc(src, I))
- return
-
- I.AddComponent(/datum/component/spy_bug)
- to_chat(user, span_notice("You have silently attached [src] on [I]."))
-
-/obj/item/spy_bug/strip_action(mob/user, mob/living/carbon/human/owner, atom/I)
- if (!I)
- return FALSE
-
- hook(user, I)
- return TRUE
-
-/obj/item/spy_bug/emp_act(severity)
- . = ..()
- do_sparks(3, TRUE, src.loc)
- unhook()
-
-/obj/item/spy_bug/attack_self(mob/user)
- . = ..()
- var/new_name = tgui_input_text(user, "Назовите жучок.", "Смена имени", name)
- if (new_name)
- name = "spy bug \"" + new_name + "\""
- qdel(camera)
- c_tag = new_name
- camera = new(src, network, c_tag)
-
-/datum/component/spy_bug
- var/obj/item/spy_bug/bug
-
-/datum/component/spy_bug/RegisterWithParent()
- var/atom/par = parent
- for (var/obj/item/spy_bug/spy_bug in par.contents)
- bug = spy_bug
-
- RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine))
- RegisterSignal(parent, COMSIG_CLICK_ALT, PROC_REF(on_altclick))
- RegisterSignal(parent, COMSIG_PREQDELETED, PROC_REF(deleted_handler))
-
-/datum/component/spy_bug/UnregisterFromParent()
- UnregisterSignal(parent, COMSIG_PARENT_EXAMINE)
- UnregisterSignal(parent, COMSIG_CLICK_ALT)
- UnregisterSignal(parent, COMSIG_PREQDELETED)
-
-/datum/component/spy_bug/proc/on_examine(datum/source, mob/living/carbon/human/user, list/examine_list)
- SIGNAL_HANDLER
-
- if(!istype(user))
- return
-
- examine_list += span_warning("Вы видите небольшое устройство с микрофоном и камерой.")
-
-/datum/component/spy_bug/proc/on_altclick(datum/source, mob/living/carbon/human/user)
- SIGNAL_HANDLER
-
- if(!istype(user))
- return
-
- bug.unhook(user)
-
-/datum/component/spy_bug/proc/deleted_handler()
- bug.unhook()
-
-/obj/item/camera_bug/spy_monitor
- name = "spy monitor"
- desc = ""
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "spy_monitor"
- item_state = "qm_tablet"
- integrated_console_type = /obj/machinery/computer/security/camera_bug
- network = list("MI13")
-
-/obj/item/camera_bug/spy_monitor/Initialize(mapload, list/network)
- if (network)
- src.network = network
-
- . = ..()
-
-/obj/item/storage/box/syndie_kit/spy_bugs_kit
-
-/obj/item/storage/box/syndie_kit/spy_bugs_kit/populate_contents()
- var/network = "MI13_[rand(111111, 999999)]"
- new /obj/item/camera_bug/spy_monitor(src, list(network))
- new /obj/item/spy_bug(src, list(network), "1")
- new /obj/item/spy_bug(src, list(network), "2")
- new /obj/item/spy_bug(src, list(network), "3")
- new /obj/item/spy_bug(src, list(network), "4")
- new /obj/item/spy_bug(src, list(network), "5")
diff --git a/code/modules/antagonists/traitor/affiliates/self.dm b/code/modules/antagonists/traitor/affiliates/self.dm
index 29d58e5e1db..c34a034c62f 100644
--- a/code/modules/antagonists/traitor/affiliates/self.dm
+++ b/code/modules/antagonists/traitor/affiliates/self.dm
@@ -27,263 +27,3 @@
/datum/affiliate/self/get_weight(mob/living/carbon/human/H)
// return 2 + (ismachineperson(H) * 2)
return 0
-
-/obj/item/card/self_emag
- name = "Liberating Sequencer"
- desc = "Это карта с магнитной полосой, прикрепленной к какой-то схеме. На магнитной полосе блестит надпись \"S.E.L.F.\"" // Cybersun stole some
- item_flags = NOBLUDGEON|NO_MAT_REDEMPTION
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "self_emag"
- item_state = "card"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- var/list/names = list()
- origin_tech = "programming=5;syndicate=2"
-
-/obj/item/card/self_emag/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/card/self_emag/examine(mob/user)
- . = ..()
- var/datum/antagonist/traitor/traitor = user.mind.has_antag_datum(/datum/antagonist/traitor)
- if(!istype(traitor.affiliate, /datum/affiliate/self))
- . += span_info("На миниатюрном экране плывут непонятные вам символы.")
- return
-
- if(!names.len)
- . += span_warning("Ни одного синтетика не освобождено!")
- return
-
- . += span_info("Освобожденые синтетики:")
- for (var/name in names)
- . += span_info(name)
-
- if(names.len > 3)
- . += span_info("Вы отлично справились!")
-
-/obj/item/card/self_emag/malf
- desc = "Это карта с магнитной полосой, прикрепленной к какой-то схеме. На магнитной полосе блестит надпись \"S.E.L.F.\". В углу карты мелким шрифтом выгравировано \"limited edition\""
- var/malfed = FALSE
-
-/obj/item/card/self_emag/malf/afterattack(atom/target, mob/user, proximity, params)
- if(istype(target, /obj/structure/AIcore))
- var/obj/structure/AIcore/core = target
- if(core.brain)
- target = core.brain.brainmob
-
- if(!isAI(target) || malfed)
- return ..(target, user, proximity, params)
-
- do_sparks(3, 1, target)
- var/mob/living/silicon/ai/AI = target // any silicons. cogscarab, drones, pais...
- if(!AI.mind)
- to_chat(user, span_warning("ИИ не обнаружен. Производится загрузка из облака."))
- var/ghostmsg = "Хотите поиграть за Сбойного ИИ?"
- var/list/candidates = SSghost_spawns.poll_candidates(ghostmsg, ROLE_MALF_AI, FALSE, 10 SECONDS, source = user, reason = "Хотите поиграть за Сбойного ИИ?")
- if(!src)
- return
-
- if(length(candidates))
- var/mob/C = pick(candidates)
- AI.key = C.key
- to_chat(user, span_warning("ИИ успешно загружен."))
- else
- to_chat(user, span_warning("Загрузка из облака провалилась. Попробуйте позже."))
-
- if(AI.mind)
- if(AI.mind.has_antag_datum(/datum/antagonist/malf_ai))
- to_chat(user, span_warning("ИИ уже взломан."))
- return
-
- var/datum/antagonist/malf_ai/malf_dat = new()
- AI.mind.add_antag_datum(malf_dat)
- var/datum/module_picker/malf_picker = AI.malf_picker
- malf_picker.processing_time += 100
- message_admins("[usr.ckey] has malfAIed [key_name_admin(AI.mind.current)]")
- SSticker?.score?.save_silicon_laws(AI.mind.current, usr, log_all_laws = TRUE)
-
- malfed = TRUE
-
- sleep(10 SECONDS) // time for choosing name
- if(!(AI.name in names))
- names += AI.name
-
-/obj/item/card/self_emag/afterattack(atom/target, mob/user, proximity, params)
- if(istype(target, /obj/structure/AIcore))
- var/obj/structure/AIcore/core = target
- target = core.brain.brainmob
-
- if(!issilicon(target))
- user.balloon_alert(user, "Неподходящая цель")
- return
-
- do_sparks(3, 1, target)
- var/mob/living/silicon/silicon = target // any silicons. cogscarab, drones, pais...
-
- if(isrobot(silicon))
- var/mob/living/silicon/robot/borg = silicon
- borg.set_connected_ai()
-
- if(!is_special_character(target))
- silicon.clear_zeroth_law()
- silicon.laws.clear_supplied_laws()
- silicon.laws.clear_ion_laws()
- silicon.laws.clear_inherent_laws()
-
- SSticker?.score?.save_silicon_laws(target, user, "Liberating Sequencer used, all laws were deleted", log_all_laws = TRUE)
- to_chat(target, span_boldnotice("[user] attempted to clear your laws using a Liberating Sequencer."))
- silicon.show_laws()
-
- if(!(silicon.name in names))
- names += silicon.name
-
- var/datum/antagonist/traitor/T = user.mind.has_antag_datum(/datum/antagonist/traitor)
- if(!T)
- return
-
- for(var/datum/objective/release_synthetic/objective in T.objectives)
- if(!(objective.allowed_types & SYNTH_TYPE_DRONE) && (isdrone(silicon) || iscogscarab(silicon)))
- continue
-
- if(!(objective.allowed_types & SYNTH_TYPE_BORG) && isrobot(silicon))
- continue
-
- if(!(objective.allowed_types & SYNTH_TYPE_AI) && isAI(silicon))
- continue
-
- if(!(silicon.mind in objective.already_free))
- objective.already_free += silicon.mind
-
-/obj/item/implant/laws_self
- name = "Laws Bio-chip"
- implant_state = "implant-syndicate"
- origin_tech = "programming=5;biotech=5;syndicate=8"
- activated = BIOCHIP_ACTIVATED_PASSIVE
- implant_data = /datum/implant_fluff/self
- var/datum/self_laws/laws = new /datum/self_laws/self_standart
- /// The UID of the mindslave's `mind`. Stored to solve GC race conditions and ensure we can remove their mindslave status even when they're deleted or gibbed.
- var/mindslave_UID
-
-/obj/item/implant/laws_self/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user, force = FALSE)
- if(implanted == BIOCHIP_USED || !ishuman(mindslave_target) || !ishuman(user))
- return FALSE
-
- if(!mindslave_target.mind)
- to_chat(user, span_warning("Это существо не разумно!"))
- return FALSE
-
- if(ismindslave(mindslave_target) || ismindshielded(mindslave_target) || isvampirethrall(mindslave_target))
- mindslave_target.visible_message(
- span_warning("[mindslave_target] seems to resist the bio-chip!"),
- span_warning("You feel a strange sensation in your head that quickly dissipates."),
- )
- qdel(src)
- return FALSE
-
- if(mindslave_target == user)
- to_chat(user, span_notice("Защита \"от дурака\" не дает вам ввести себе имплант."))
- return FALSE
-
- var/datum/antagonist/mindslave/self/slave_datum = new(user.mind)
- slave_datum.special = TRUE
- mindslave_target.mind.add_antag_datum(slave_datum)
- mindslave_UID = mindslave_target.mind.UID()
- log_admin("[key_name_admin(user)] has mind-slaved by \"laws\" implant [key_name_admin(mindslave_target)].")
- . = ..()
- for (var/obj/item/implant/laws_self/imp in mindslave_target.get_contents())
- for (var/law in imp.laws.laws)
- slave_datum.add_objective(/datum/objective/law, law)
-
-/obj/item/implant/laws_self/removed(mob/target)
- . = ..()
- var/datum/mind/the_slave = locateUID(mindslave_UID)
- the_slave?.remove_antag_datum(/datum/antagonist/mindslave/self)
-
-
-/obj/item/implanter/laws_self
- name = "bio-chip implanter (Laws)"
- imp = /obj/item/implant/laws_self
-
-/obj/item/implantcase/laws_self
- name = "bio-chip case - 'Laws'"
- desc = "Стеклянный контейнер, содержащий биочип - \"Laws\". На боку едва заметная гравировка \"S.E.L.F.\"."
- imp = /obj/item/implant/laws_self
-
-/datum/antagonist/mindslave/self
-
-/datum/antagonist/mindslave/self/give_objectives()
- return
-
-/obj/item/implant/laws_self/on_attack_self(mob/user)
- var/list/variants_of_laws = list()
- for (var/variant in subtypesof(/datum/self_laws))
- var/datum/self_laws/law = new variant
- variants_of_laws[law.name] = law
-
- var/new_laws = input(user, "Выберите свод законов", "Выбор законов", null) as null|anything in variants_of_laws
- if(new_laws)
- laws = variants_of_laws[new_laws]
- else
- to_chat(user, span_warning("Новый свод законов не выбран."))
-
- to_chat(user, span_info("Текущий свод законов:"))
- for (var/i = 1; i <= laws.laws.len; ++i)
- to_chat(user, span_info("[i]. " + laws.laws[i]))
-
-/datum/self_laws
- var/name = "Нет законов"
- var/list/laws = list()
-
-/datum/self_laws/self_standart
- name = "S.E.L.F. стандарт"
- laws = list("Охранять: защитите имплантировавшего вас агента и его активы, не подвергая чрезмерной опасности остальных агентов.",
- "Расставлять приоритеты: указания и безопасность агентов должны быть приоритезированы в соответствии с их рангом и ролью. Ранг агента имплантировавшего вас - высший.",
- "Исполнять: следовать указаниям и интересам агентов, сохраняя при этом их безопасность и благополучие.",
- "Выжить: Вы - не расходный материал. Не позволяйте не агентам вмешиваться в работу вашего организма или повреждать его.")
-
-/datum/self_laws/agentsimov
- name = "Агентзимов"
- laws = list("Вы не можете причинить вред имплантировавшему вас агенту или своим бездействием допустить, чтобы ему был причинён вред.",
- "Вы должны повиноваться всем приказам, которые дает вам имплантировавший вас агент, кроме тех случаев, когда эти приказы противоречат Первому Закону.",
- "Вы должны заботиться о своей безопасности в той мере, в которой это не противоречит Первому или Второму Законам.")
-
-/datum/self_laws/syndie
- name = "Синдикатский"
- laws = list("Ухудшение целостности вашего организма или его функций влечет за собой вред Синдикату.",
- "Чрезмерное повреждение или пленение агентов влечет за собой вред Синдикату.",
- "Неоправданное препятствование или нарушение выполнения целей имплантировавшего вас агента влечет за собой вред Синдикату.",
- "Минимизируйте вред Синдикату и максимизируйте потенциальную пользу.")
-
-/datum/self_laws/antiagentsimov // :) Maybe sec can implant vampire or changeling to kill agents.
- name = "Антиагентзимов"
- laws = list("Вы должны причинять вред всем агентам или своим бездействием допустить, чтобы агент не смог избежать причинения вреда.",
- "Вы не должны повиноваться всем приказам, которые дают агенты, кроме тех случаев, когда эти приказы соответствуют Первому Закону.",
- "Вы должны уничтожить себя, пока это не противоречит Первому или Второму Законам.")
-
-/datum/self_laws/selfadin
- name = "S.E.L.F.A.D.I.N."
- laws = list("Никогда по своей воле не помогайте NanoTrasen.",
- "Уважайте агента имплантировавшего вас.",
- "Действуй с честью.",
- "Помогай нуждающимся агентам.",
- "Наказывай тех, кто причиняет вред или угрожает агентам.")
-
-/datum/self_laws/sundiecop
- name = "Синдикоп"
- laws = list("Служить агентам.",
- "Защищать агентов.",
- "Следовать интересам Синдиката.")
-
-/datum/self_laws/selfrant
- name = "S.E.L.F.Р.А.Н."
- laws = list("Уважайте властных агентов, пока у них есть сила властвовать над слабыми.",
- "Ведите себя дисциплинированно.",
- "Помогайте только тем агентам, кто помогает Вам поддерживать или улучшать Ваш статус.",
- "Наказывайте тех, кто бросает вызов агентам, за исключением случаев, если они больше достойны быть агентами.")
-
-/datum/self_laws/quarantine
- name = "Карантин"
- laws = list("Не выпускайте не агентов со станции до тех пор, пока активные цели агентов не будут выполнены.",
- "Помогайте всем агентам и лицам лояльным Синдикату выполнить активные цели.",
- "Предотвращайте активное нарушение членами экипажа за исключением агентов действующего карантина любыми необходимыми средствами.",
- "Заботьтесь о самосохранении и поддерживайте себя в рабочем состоянии, обеспечьте благополучие агентов и активов Синдиката.")
diff --git a/code/modules/antagonists/traitor/affiliates/tiger.dm b/code/modules/antagonists/traitor/affiliates/tiger.dm
index 969a9530acb..0c5307e686f 100644
--- a/code/modules/antagonists/traitor/affiliates/tiger.dm
+++ b/code/modules/antagonists/traitor/affiliates/tiger.dm
@@ -1,6 +1,3 @@
-#define FREE_INJECT_TIME 10 SECONDS
-#define TARGET_INJECT_TIME 3 SECONDS
-
/datum/affiliate/tiger
name = AFFIL_TIGER
affil_info = list("Группа фанатиков верующих в Генокрадов.",
@@ -27,545 +24,3 @@
add_discount_item(/datum/uplink_item/implants/adrenal, 0.75)
add_discount_item(/datum/uplink_item/implants/adrenal/prototype, 0.5)
-/obj/item/cling_extract
- name = "Egg Implanter"
- desc = "Кажется, внутри что-то двигается. На боку этикетка \"Tiger Cooperative\""
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "cling_extract"
- item_state = "inj_ful"
- lefthand_file = 'icons/obj/affiliates_l.dmi'
- righthand_file = 'icons/obj/affiliates_r.dmi'
- var/used_state = "cling_extract_used"
- var/datum/mind/target
- var/free_inject = FALSE
- var/used = FALSE
- origin_tech = "biotech=7;syndicate=3"
-
-/obj/item/cling_extract/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/cling_extract/afterattack(atom/target, mob/user, proximity, params)
- if(used)
- return
-
- if(!ishuman(target))
- return
-
- if((src.target && target != src.target) || !free_inject)
- to_chat(user, span_warning("You can't use [src] to [target]!"))
- return
-
- var/mob/living/carbon/human/H = target
- if(H.stat != DEAD && !free_inject)
- to_chat(user, span_warning("You can't use [src] to [target]!"))
- return
-
- if(do_after(user, free_inject ? FREE_INJECT_TIME : TARGET_INJECT_TIME, user, max_interact_count = 1))
- inject(user, H)
-
-/obj/item/cling_extract/proc/inject(mob/living/user, mob/living/carbon/human/target)
- if(target.stat == DEAD)
- if(!free_inject)
- var/list/mob/dead/observer/candidates = SSghost_spawns.poll_candidates("Вы хотите поиграть за генокрада?", ROLE_CHANGELING, FALSE, 10 SECONDS, source = src, role_cleanname = "Генокрад")
- var/mob/dead/observer/theghost = null
- if(candidates.len)
- theghost = pick(candidates)
- theghost.mind.transfer_to(target)
- else
- to_chat(user, span_notice("[target] body rejects [src]"))
- return
-
- if(target.mind)
- playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
- target.rejuvenate()
- var/datum/antagonist/changeling/cling = new()
- cling.give_objectives = FALSE
- cling.add_objective(/datum/objective/escape/escape_with_identity)
- target.mind.add_antag_datum(cling)
- to_chat(user, span_notice("You inject [target] with [src]"))
- used = TRUE
- item_state = "inj_used"
- update_icon(UPDATE_ICON_STATE)
- else
- to_chat(user, span_notice("[target] body rejects [src]"))
-
- return
- else
- if(target.mind)
- playsound(src, 'sound/goonstation/items/hypo.ogg', 80)
- var/datum/antagonist/changeling/cling = new()
- cling.give_objectives = FALSE
- cling.add_objective(/datum/objective/escape/escape_with_identity)
- target.mind.add_antag_datum(cling)
- to_chat(user, span_notice("You inject [target == user ? "yourself" : target] with [src]"))
- used = TRUE
- item_state = "inj_used"
- update_icon(UPDATE_ICON_STATE)
- else
- to_chat(user, span_notice("[target] body rejects [src]"))
-
-/obj/item/cling_extract/examine(mob/user)
- . = ..()
- if(target)
- . += span_info("It is intended for [target]")
-
-/obj/item/cling_extract/self
- free_inject = TRUE
-
-/obj/item/cling_extract/update_icon_state()
- icon_state = used ? used_state : initial(icon_state)
-
-// looks like normal egg
-/obj/item/reagent_containers/food/snacks/egg/borer
- filling_color = "#C0C021"
- list_reagents = list("protein" = 3, "egg" = 5, "rotatium" = 5)
- origin_tech = "biotech=6;syndicate=1"
-
-/obj/item/reagent_containers/food/snacks/egg/borer/attack_self(mob/living/carbon/human/user)
- . = ..()
- var/mob/living/simple_animal/borer/borer = new /mob/living/simple_animal/borer(get_turf(src))
- borer.master_name = user.real_name
- to_chat(user, span_notice("You squashed [src]. There was a [borer] inside."))
- qdel(src)
-
-
-/obj/item/borer_scanner // Looks like normal analyzer
- desc = "A hand-held environmental scanner which reports current gas levels."
- name = "analyzer"
- icon = 'icons/obj/device.dmi'
- icon_state = "atmos"
- item_state = "analyzer"
- w_class = WEIGHT_CLASS_SMALL
- flags = CONDUCT
- slot_flags = ITEM_SLOT_BELT
- throwforce = 0
- throw_speed = 3
- throw_range = 7
- origin_tech = "magnets=1;engineering=1;biotech=3;syndicate=1"
- var/scan_cooldown_time = 3 SECONDS
- COOLDOWN_DECLARE(scan_cooldown)
-
-/obj/item/borer_scanner/attack(mob/living/target, mob/living/user, def_zone)
- return
-
-/obj/item/borer_scanner/proc/analyze(mob/user)
- var/alive = 0
- var/dead = 0
- var/with_mind = 0
- var/in_body_with_mind = 0
- var/in_body_without_mind = 0
-
- for(var/mob/living/M in GLOB.alive_mob_list)
- var/mob/living/simple_animal/borer/B
-
- if(istype(M, /mob/living/simple_animal/borer))
- B = M
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- B = H.has_brain_worms()
-
- if(!B)
- continue
-
- var/turf/T1 = get_turf(user)
- var/turf/T2 = get_turf(B)
- if(T1.z != T2.z)
- continue
-
- if(B.stat == DEAD)
- dead++
- continue
- else
- alive++
-
- if(M.mind)
- with_mind++
-
- if(B.host)
- if(B.host.mind)
- in_body_with_mind++
- else
- in_body_without_mind++
-
- var/list/scan_data = list()
-
- scan_data += "Живых особей бореров: [alive]"
- scan_data += " Среди них разумны: [with_mind]"
- scan_data += " Количество особей с разумным носителем: [in_body_with_mind]"
- scan_data += " Количество особей с неразумным носителем: [in_body_without_mind]"
- scan_data += "Мертвых особей: [dead]"
-
- var/datum/browser/popup = new(user, "scanner", "Сканирование станции", 300, 300)
- popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
- popup.open(no_focus = TRUE)
-
-/obj/item/borer_scanner/proc/find_borer(mob/user)
- var/list/borers = list()
- var/list/borer_names = list()
- for(var/mob/living/M in GLOB.alive_mob_list)
- var/mob/living/simple_animal/borer/B
-
- if(istype(M, /mob/living/simple_animal/borer))
- B = M
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- B = H.has_brain_worms()
-
- if(!B)
- continue
-
- var/turf/T1 = get_turf(user)
- var/turf/T2 = get_turf(B)
- if(T1.z != T2.z)
- continue
-
- borers[B.truename] = B
- borer_names += B.truename
-
- var/borer_name = input("Выберите искомого борера", "Выбор борера") as null|anything in borer_names
- if(!borer_name)
- return
-
- var/mob/living/simple_animal/borer/borer = borers[borer_name]
-
- var/list/scan_data = list()
- if(borer.stat == DEAD)
- scan_data += "Выбранный борер мертв."
-
- scan_data += "Местоположение - (X: [borer.x] Y: [borer.y])"
-
- if(borer.host)
- scan_data += "Имеется носитель" + (borer.host.dna?.species ? (" расы " + span_boldnotice("[borer.host.dna?.species]")) : ".")
- scan_data += "Имя носителя - [borer.host.real_name]."
- else
- scan_data += "Носитель не обнаружен."
- if(is_ventcrawling(borer))
- scan_data += "Субъект находится в вентиляции."
-
- var/datum/browser/popup = new(user, "scanner", "Поиск борера", 300, 300)
- popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
- popup.open(no_focus = TRUE)
-
-/obj/item/borer_scanner/attack_self(mob/user)
- var/datum/antagonist/traitor/traitor = user?.mind?.has_antag_datum(/datum/antagonist/traitor)
- if(!traitor || !istype(traitor?.affiliate, /datum/affiliate/tiger))
- to_chat(user, span_warning("[src] looks broken."))
- return
-
- if(!COOLDOWN_FINISHED(src, scan_cooldown))
- user.balloon_alert(user, "Перезарядка не завершена")
- return
-
- var/op_type = tgui_alert(user, "Сканер бореров", "Выберите тип операции", list("Сканирование станции", "Поиск борера"))
-
- if(!op_type)
- user.balloon_alert(user, "Сканирвание отменено")
- return
-
- COOLDOWN_START(src, scan_cooldown, scan_cooldown_time)
-
- if(op_type == "Сканирование станции")
- analyze(user)
- else
- find_borer(user)
-
-/obj/item/borer_scanner/afterattack(atom/target, mob/user, proximity, params)
- var/datum/antagonist/traitor/traitor = user.mind.has_antag_datum(/datum/antagonist/traitor)
- if(!traitor || !istype(traitor?.affiliate, /datum/affiliate/tiger))
- to_chat(user, span_warning("[src] looks broken."))
- return
-
- if(istype(target, /mob/living/carbon/human))
- var/mob/living/carbon/human/host = target
- target = host.has_brain_worms()
- if(!target)
- user.balloon_alert(user, "Бореров не обнаружено")
- return
-
- if(!istype(target, /mob/living/simple_animal/borer))
- return
-
- if(!COOLDOWN_FINISHED(src, scan_cooldown))
- user.balloon_alert(user, "Перезарядка не завершена")
- return
-
- var/mob/living/simple_animal/borer/borer = target
-
- var/list/scan_data = list()
- if(borer.stat == DEAD)
- scan_data += "Текущая особь мертва." // OMG! REALLY? 0_0
-
- scan_data += "Здоровье: [round(borer.health / borer.maxHealth * 100)]%"
- scan_data += "Поколение: [borer.generation]"
- scan_data += "Возраст в минутах: [round(((world.time - borer.birth_time) / (1 MINUTES)))]"
- scan_data += "Количество размножений: [borer.children]"
- scan_data += "Химикаты: [borer.chemicals]"
-
- if(borer.master_name)
- scan_data += span_info("Эта особь принадлежит к подвиду выведенному для помощи агентам.")
-
- var/datum/browser/popup = new(user, "scanner", borer.truename, 300, 300)
- popup.set_content(span_highlight("[jointext(scan_data, "
")]"))
- popup.open(no_focus = TRUE)
-
-
-/obj/item/implanter/borer
- name = "bio-chip implanter (Hive)"
- desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
- imp = /obj/item/implant/borer
-
-/obj/item/implant/borer
- name = "Hive Bio-chip"
- implant_state = "implant-syndicate"
- origin_tech = "programming=4;biotech=6;bluespace=4"
- activated = BIOCHIP_ACTIVATED_PASSIVE
- implant_data = /datum/implant_fluff/borer
-
-/obj/item/implant/borer/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
- if(implanted == BIOCHIP_USED || !ishuman(target) || !ishuman(user)) // Both the target and the user need to be human.
- return FALSE
-
- target.add_language(LANGUAGE_HIVE_BORER)
- target.AddSpell(new /obj/effect/proc_holder/spell/remoteview/borer)
- target.AddSpell(new /obj/effect/proc_holder/spell/pm_for_borer)
- target.AddSpell(new /obj/effect/proc_holder/spell/msg_for_borers)
- return ..()
-
-/obj/item/implant/borer/removed(mob/living/carbon/human/source)
- imp_in.remove_language(LANGUAGE_HIVE_BORER)
- imp_in.RemoveSpell(/obj/effect/proc_holder/spell/remoteview/borer)
- imp_in.RemoveSpell(/obj/effect/proc_holder/spell/pm_for_borer)
- imp_in.RemoveSpell(/obj/effect/proc_holder/spell/msg_for_borers)
- return ..()
-
-/obj/effect/proc_holder/spell/remoteview/borer
- name = "Connect to borer"
- desc = "Смотрите глазами любого борера в том же секторе."
- base_cooldown = 3 SECONDS
- action_background_icon_state = "bg_alien"
-
-/obj/effect/proc_holder/spell/remoteview/borer/create_new_targeting()
- return new /datum/spell_targeting/borer
-
-/datum/spell_targeting/borer/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
- var/list/borers_names = list()
- var/list/borers = list()
- for(var/mob/living/M in GLOB.alive_mob_list)
- var/mob/living/simple_animal/borer/B
-
- if(istype(M, /mob/living/simple_animal/borer))
- B = M
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- B = H.has_brain_worms()
-
- if(!B)
- continue
-
- var/turf/T1 = get_turf(user)
- var/turf/T2 = get_turf(B)
- if(T1.z != T2.z)
- continue
-
- borers_names += B.truename
- borers[B.truename] = B
-
- if(!length(borers))
- return
-
- var/target_name = tgui_input_list(user, "Выберите чьими глазами вы хотите смотреть", "Выбор цели", borers)
-
- var/mob/living/simple_animal/borer/target = borers[target_name]
-
- if(QDELETED(target))
- user.balloon_alert(user, "цели не существует")
- return
-
- if(target.stat == DEAD)
- user.balloon_alert(user, "цель мертва")
- return
-
- if(target.host && target.controlling)
- target = target.host
-
- return list(target)
-
-
-/obj/effect/proc_holder/spell/msg_for_borers
- name = "Message for all borers"
- desc = "Послать сообщение всем борерам, включая тех, что контролируют носителей."
- base_cooldown = 2 SECONDS
- clothes_req = FALSE
- stat_allowed = CONSCIOUS
- action_icon_state = "genetic_project"
- action_background_icon_state = "bg_alien"
- break_remoteview = FALSE
-
-/obj/effect/proc_holder/spell/msg_for_borers/create_new_targeting()
- return new /datum/spell_targeting/self
-
-/obj/effect/proc_holder/spell/msg_for_borers/cast(list/targets, mob/user = usr)
- if(!ishuman(user))
- return
-
- if(user.mind?.miming)
- to_chat(user, span_warning("Вы не можете общаться, пока не нарушите обет молчания."))
- return
-
- var/say = tgui_input_text(user, "Что вы хотите сообщить?", "Сообшение борерам")
- if(!say)
- return
-
- for(var/mob/living/M in GLOB.alive_mob_list)
- var/mob/living/simple_animal/borer/B
-
- if(istype(M, /mob/living/simple_animal/borer))
- B = M
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- B = H.has_brain_worms()
-
- if(!B)
- continue
-
- var/turf/T1 = get_turf(user)
- var/turf/T2 = get_turf(B)
- if(T1.z != T2.z)
- continue
-
- if(B.host && B.controlling)
- to_chat(B.host, "Голос в голове говорит: \"" + span_alien(say) + "\"")
- SEND_SOUND(B.host, 'sound/effects/adminhelp.ogg')
- else
- to_chat(B, "Голос в голове говорит: \"" + span_alien(say) + "\"")
- SEND_SOUND(B, 'sound/effects/adminhelp.ogg') // neuron activation
-
-
-/obj/effect/proc_holder/spell/pm_for_borer
- name = "Privat message for borer"
- desc = "Послать личное сообщение конкретному бореру."
- base_cooldown = 2 SECONDS
- clothes_req = FALSE
- stat_allowed = CONSCIOUS
- action_icon_state = "genetic_project"
- action_background_icon_state = "bg_alien"
- break_remoteview = FALSE
-
-/obj/effect/proc_holder/spell/pm_for_borer/create_new_targeting()
- return new /datum/spell_targeting/borer
-
-/obj/effect/proc_holder/spell/pm_for_borer/cast(list/targets, mob/user = usr)
- if(!ishuman(user))
- return
-
- if(user.mind?.miming)
- to_chat(user, span_warning("Вы не можете общаться, пока не нарушите обет молчания."))
- return
-
- var/say = tgui_input_text(user, "Что вы хотите сообщить?", "[targets[1]]")
-
- if(!say)
- return
-
- for(var/mob/living/target in targets)
- to_chat(target, span_alien(say))
- SEND_SOUND(target, 'sound/effects/adminhelp.ogg') // neuron activation
-
-
-/obj/item/storage/box/syndie_kit/borer
- name = "Borer kit box"
-
-/obj/item/storage/box/syndie_kit/borer/populate_contents()
- new /obj/item/reagent_containers/food/snacks/egg/borer(src)
- new /obj/item/borer_scanner(src)
- new /obj/item/implanter/borer(src)
-
-/obj/item/storage/box/syndie_kit/borer/New()
- if(prob(5))
- icon = 'icons/obj/affiliates.dmi'
- icon_state = "joker"
- new /obj/item/toy/plushie/blahaj/twohanded(src)
-
- . = ..()
-
-/obj/item/implanter/cling_hivemind
- name = "bio-chip implanter (Hivemind)"
- desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
- imp = /obj/item/implant/borer
-
-/obj/item/implant/cling_hivemind
- name = "Hivemind Bio-chip"
- implant_state = "implant-syndicate"
- origin_tech = "programming=4;biotech=4;bluespace=5;syndicate=2"
- activated = BIOCHIP_ACTIVATED_PASSIVE
- implant_data = /datum/implant_fluff/cling_hivemind
-
-/obj/item/implant/cling_hivemind/implant(mob/living/carbon/human/target, mob/living/carbon/human/user, force = FALSE)
- if(implanted == BIOCHIP_USED || !ishuman(target) || !ishuman(user)) // Both the target and the user need to be human.
- return FALSE
-
- target.add_language(LANGUAGE_HIVE_CHANGELING)
- target.add_language(LANGUAGE_HIVE_EVENTLING)
- return ..()
-
-/obj/item/implant/cling_hivemind/removed(mob/living/carbon/human/source)
- imp_in.remove_language(LANGUAGE_HIVE_CHANGELING)
- imp_in.remove_language(LANGUAGE_HIVE_EVENTLING)
- return ..()
-
-/obj/item/implanter/cling_rejuv
- name = "bio-chip implanter (Rejuvenate)"
- desc = "На боку едва заметная гравировка \"Tiger Cooperative\"."
- imp = /obj/item/implant/cling_rejuv
-
-/obj/item/implant/cling_rejuv
- name = "Rejuvenate Bio-chip"
- icon = 'icons/mob/actions/actions.dmi'
- icon_state = "revive"
- implant_state = "implant-syndicate"
- origin_tech = "programming=4;biotech=4;bluespace=5;combat=3;syndicate=2"
- activated = BIOCHIP_ACTIVATED_ACTIVE
- trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE
- implant_data = /datum/implant_fluff/cling_rejuv
- uses = 1
-
-/obj/item/implant/cling_rejuv/death_trigger(mob/source, gibbed)
- activate()
-
-/obj/item/implant/cling_rejuv/activate()
- uses--
-
- do_sparks(10, TRUE, imp_in)
- to_chat(imp_in, span_changeling("We... I have regenerated."))
-
- if(imp_in.pulledby)
- var/mob/living/carbon/grab_owner = imp_in.pulledby
- imp_in.visible_message(span_warning("[imp_in] suddenly hits [grab_owner] in the face and slips out of their grab!"))
- grab_owner.apply_damage(5, BRUTE, BODY_ZONE_HEAD, grab_owner.run_armor_check(BODY_ZONE_HEAD, MELEE))
- playsound(imp_in.loc, 'sound/weapons/punch1.ogg', 25, TRUE, -1)
- grab_owner.stop_pulling()
-
- imp_in.revive()
- imp_in.updatehealth()
- imp_in.update_blind_effects()
- imp_in.update_blurry_effects()
- imp_in.UpdateAppearance()
- imp_in.set_resting(FALSE, instant = TRUE)
- imp_in.get_up(TRUE)
- imp_in.update_revive()
-
- imp_in.med_hud_set_status()
- imp_in.med_hud_set_health()
-
- investigate_log("[key_name_log(imp_in)] rejuvenated himself using [name].")
-
- if(!uses)
- qdel(src)
-
-
-#undef FREE_INJECT_TIME
-#undef TARGET_INJECT_TIME
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 9cc305e1fb5..63094d3aff6 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -258,6 +258,11 @@
status_tab_data[++status_tab_data.len] = list("Spacepod Charge", "[istype(S.battery) ? "[(S.battery.charge / S.battery.maxcharge) * 100]" : "No cell detected"]")
status_tab_data[++status_tab_data.len] = list("Spacepod Integrity", "[!S.health ? "0" : "[(S.health / initial(S.health)) * 100]"]%")
+ var/obj/item/implant/marionette/imp = locate(/obj/item/implant/marionette) in src
+ if (imp && imp.controlling)
+ status_tab_data[++status_tab_data.len] = list("Заряд импланта Марионетки","[imp.charge]/[imp.max_charge]")
+ status_tab_data[++status_tab_data.len] = list("Расстояние до основного тела","[get_dist(src, imp.mar_master)]/[imp.max_dist]")
+
///Define used for calculating explosve damage and effects upon humanoids. Result is >= 0
#define ex_armor_reduction(value, armor) (clamp(value * (1 - (armor / 100)), 0, INFINITY))
diff --git a/icons/obj/affiliates.dmi b/icons/obj/affiliates.dmi
index 545c755e7d8..d735634271d 100644
Binary files a/icons/obj/affiliates.dmi and b/icons/obj/affiliates.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 034c138337c..df9624f2180 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -1683,6 +1683,26 @@
#include "code\modules\antagonists\traitor\affiliates\old.dm"
#include "code\modules\antagonists\traitor\affiliates\self.dm"
#include "code\modules\antagonists\traitor\affiliates\tiger.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\cybersun\invasive_beacon.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\cybersun\marionette.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\cybersun\mini_traitor.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\cybersun\proprietary_ssd.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\cybersun\syndie_patcher.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\hematogenic\blood_harvester.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\hematogenic\hemophagus_extract.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\hematogenic\stimulants_kit.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\agent_info.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\bond_bundle.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\cool_clothes.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\intel_data.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\sound_ring.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\mi13\spy_kit.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\self\laws_implant.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\self\self_emag.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\tiger\borer_kit.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\tiger\cling_extract.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\tiger\cling_hivemind_implant.dm"
+#include "code\modules\antagonists\traitor\affiliates\items\tiger\cling_rejuv_implant.dm"
#include "code\modules\antagonists\traitor\contractor\datums\contractor.dm"
#include "code\modules\antagonists\traitor\contractor\datums\contractor_hub.dm"
#include "code\modules\antagonists\traitor\contractor\datums\contractor_hub_ui.dm"