Renames all typepaths + names of implants to biochips (#23172)

* The fix

* Contraaaaaa

* Fixes CI

* Fixes the pads + cases

* Uplink datums

* Update code/datums/mind.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/__HELPERS/unsorted.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Update code/modules/research/designs/medical_designs.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Update code/modules/research/designs/medical_designs.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Update code/modules/research/designs/medical_designs.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Update code/modules/research/designs/medical_designs.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Update code/modules/surgery/implant_removal.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Outfits now use a proper variable name

* Fixes surgery (oops)

* More .dme changes

* Renames the folder

* Fixes bad merge

* Contra review

* Update code/game/objects/items/weapons/dice.dm

Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>

* Fixes CI fail

---------

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com>
Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com>
This commit is contained in:
DGamerL
2024-01-06 23:15:55 +00:00
committed by GitHub
co-authored by Burzah Contrabang S34N
parent fad6509b5e
commit 382a71df0d
94 changed files with 674 additions and 675 deletions
@@ -0,0 +1,244 @@
/// If used, an implant will trigger when an emote is intentionally used.
#define BIOCHIP_EMOTE_TRIGGER_INTENTIONAL (1<<0)
/// If used, an implant will trigger when an emote is forced/unintentionally used.
#define BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL (1<<1)
/// If used, an implant will always trigger when the user makes an emote.
#define BIOCHIP_EMOTE_TRIGGER_ALWAYS (BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL | BIOCHIP_EMOTE_TRIGGER_INTENTIONAL)
/// If used, an implant will trigger on the user's first death.
#define BIOCHIP_TRIGGER_DEATH_ONCE (1<<2)
/// If used, an implant will trigger any time a user dies.
#define BIOCHIP_TRIGGER_DEATH_ANY (1<<3)
/// If used, an implant will NOT trigger on death when a user is gibbed.
#define BIOCHIP_TRIGGER_NOT_WHEN_GIBBED (1<<4)
// Defines related to the way that the implant is activated. This is the value for implant.activated
/// The implant is passively active (like a mindshield)
#define BIOCHIP_ACTIVATED_PASSIVE 0
/// The implant is activated manually by a trigger
#define BIOCHIP_ACTIVATED_ACTIVE 1
/**
* # Implants
*
* Code for implants that can be inserted into a person and have some sort of passive or triggered action.
*
*/
/obj/item/bio_chip
name = "bio-chip"
icon = 'icons/obj/bio_chips.dmi'
icon_state = "generic" //Shows up as a auto surgeon, used as a placeholder when a implant doesn't have a sprite
origin_tech = "materials=2;biotech=3;programming=2"
actions_types = list(/datum/action/item_action/hands_free/activate)
item_color = "black"
flags = DROPDEL // By default, don't let implants be harvestable.
///which implant overlay should be used for implant cases. This should point to a state in bio_chips.dmi
var/implant_state = "implant-default"
/// How the implant is activated.
var/activated = BIOCHIP_ACTIVATED_ACTIVE
/// Whether the implant is implanted. Null if it's never been inserted, TRUE if it's currently inside someone, or FALSE if it's been removed.
var/implanted
/// Who the implant is inside of.
var/mob/living/imp_in
/// Whether multiple implants of this same type can be inserted into someone.
var/allow_multiple = FALSE
/// Amount of times that the implant can be triggered by the user. If the implant can't be used, it can't be inserted.
var/uses = -1
/// List of emote keys that activate this implant when used.
var/list/trigger_emotes
/// What type of action will trigger this emote. Bitfield of IMPLANT_EMOTE_* defines.
var/trigger_causes
/// Whether this implant has already triggered on death or not, to prevent it firing multiple times.
var/has_triggered_on_death = FALSE
///the implant_fluff datum attached to this implant, purely cosmetic "lore" information
var/datum/implant_fluff/implant_data = /datum/implant_fluff
/obj/item/bio_chip/Initialize(mapload)
. = ..()
if(ispath(implant_data))
implant_data = new implant_data
/obj/item/bio_chip/Destroy()
if(imp_in)
removed(imp_in)
QDEL_NULL(implant_data)
return ..()
/obj/item/bio_chip/proc/unregister_emotes()
if(imp_in && LAZYLEN(trigger_emotes))
for(var/emote in trigger_emotes)
UnregisterSignal(imp_in, COMSIG_MOB_EMOTED(emote))
/**
* Set the emote that will trigger the implant.
* * user - User who is trying to associate the implant to themselves.
* * emote_key - Key of the emote that should trigger the implant.
* * on_implant - Whether this proc is being called during the implantation of the implant.
* * silent - If true, the user won't get any to_chat messages if an implantation fails.
*/
/obj/item/bio_chip/proc/set_trigger(mob/user, emote_key, on_implant = FALSE, silent = TRUE)
if(imp_in != user)
return FALSE
if(!emote_key)
return FALSE
if(LAZYIN(trigger_emotes, emote_key) && !on_implant)
if(!silent)
to_chat(user, "<span class='warning'> You've already registered [emote_key]!")
return FALSE
if(emote_key == "me" || emote_key == "custom")
if(!silent)
to_chat(user, "<span class='warning'> You can't trigger [src] with a custom emote.")
return FALSE
if(!(emote_key in user.usable_emote_keys(trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL)))
if(!silent)
to_chat(user, "<span class='warning'> You can't trigger [src] with that emote! Try *help to see emotes you can use.</span>")
return FALSE
if(!(emote_key in user.usable_emote_keys(trigger_causes & BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL)))
CRASH("User was given an bio-chip for an unintentional emote that they can't use.")
LAZYADD(trigger_emotes, emote_key)
RegisterSignal(user, COMSIG_MOB_EMOTED(emote_key), PROC_REF(on_emote))
/obj/item/bio_chip/proc/on_emote(mob/living/user, datum/emote/fired_emote, key, emote_type, message, intentional)
SIGNAL_HANDLER
if(!implanted || !imp_in)
return
if(!(intentional && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL)) && !(!intentional && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL)))
return
add_attack_logs(user, user, "[intentional ? "intentionally" : "unintentionally"] [src] was [intentional ? "intentionally" : "unintentionally"] triggered with the emote [fired_emote].")
emote_trigger(key, user, intentional)
/obj/item/bio_chip/proc/on_death(mob/source, gibbed)
SIGNAL_HANDLER
if(!implanted || !imp_in)
return
if(gibbed && (trigger_causes & BIOCHIP_TRIGGER_NOT_WHEN_GIBBED))
return
// This should help avoid infinite recursion for things like dust that call death()
if(has_triggered_on_death && (trigger_causes & BIOCHIP_TRIGGER_DEATH_ONCE))
return
has_triggered_on_death = TRUE
add_attack_logs(source, source, "had their [src] bio-chip triggered on [gibbed ? "gib" : "death"].")
death_trigger(source, gibbed)
/obj/item/bio_chip/proc/emote_trigger(emote, mob/source, force)
return
/obj/item/bio_chip/proc/death_trigger(mob/source, gibbed)
return
/obj/item/bio_chip/proc/activate(cause)
return
/obj/item/bio_chip/ui_action_click()
activate("action_button")
/**
* Try to implant ourselves into a mob.
*
* * source - The person the implant is being administered to.
* * user - The person who is doing the implanting.
*
* Returns
* 1 if the implant injects successfully
* -1 if the implant fails to inject
* 0 if there's no room for the implant.
*/
/obj/item/bio_chip/proc/implant(mob/source, mob/user, force)
if(!force && !can_implant(source, user))
return
var/obj/item/bio_chip/imp_e = locate(type) in source
if(!allow_multiple && imp_e && imp_e != src)
if(imp_e.uses < initial(imp_e.uses)*2)
if(uses == -1)
imp_e.uses = -1
else
imp_e.uses = min(imp_e.uses + uses, initial(imp_e.uses)*2)
qdel(src)
return 1
else
return 0
loc = source
imp_in = source
implanted = TRUE
if(trigger_emotes)
if(!(trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL | BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL))
CRASH("Bio-chip [src] has trigger emotes defined but no trigger cause with which to use them!")
if(!activated && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL))
CRASH("Bio-chip [src] has intentional emote triggers on a passive bio-chip")
// If you can't activate the implant manually, you shouldn't be able to deliberately activate it with an emote
for(var/emote in trigger_emotes)
set_trigger(source, emote, TRUE, TRUE)
if(activated)
for(var/X in actions)
var/datum/action/A = X
A.Grant(source)
if(trigger_causes & (BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_DEATH_ANY))
RegisterSignal(source, COMSIG_MOB_DEATH, PROC_REF(on_death))
if(ishuman(source))
var/mob/living/carbon/human/H = source
H.sec_hud_set_implants()
if(user)
add_attack_logs(user, source, "Chipped with [src]")
return 1
/**
* Check that we can actually implant this before implanting it
* * source - The person being implanted
* * user - The person doing the implanting
*
* Returns
* TRUE - I could care less, implant it, maybe don't. I don't care.
* FALSE - Don't implant!
*/
/obj/item/bio_chip/proc/can_implant(mob/source, mob/user)
return TRUE
/**
* Clean up when an implant is removed.
* * source - the user who the implant was removed from.
*/
/obj/item/bio_chip/proc/removed(mob/source)
loc = null
imp_in = null
implanted = FALSE
for(var/X in actions)
var/datum/action/A = X
A.Remove(source)
if(ishuman(source))
var/mob/living/carbon/human/H = source
H.sec_hud_set_implants()
if(trigger_causes & (BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_DEATH_ANY))
UnregisterSignal(source, COMSIG_MOB_DEATH)
unregister_emotes()
return TRUE
/obj/item/bio_chip/dropped(mob/user)
. = TRUE
..()
@@ -0,0 +1,59 @@
/obj/item/bio_chip/abductor
name = "recall bio-chip"
desc = "Returns you to the mothership."
icon = 'icons/obj/abductor.dmi'
icon_state = "implant"
activated = BIOCHIP_ACTIVATED_ACTIVE
origin_tech = "materials=2;biotech=7;magnets=4;bluespace=4;abductor=5"
implant_data = /datum/implant_fluff/abductor
implant_state = "implant-alien"
var/obj/machinery/abductor/pad/home
var/cooldown = 30
var/total_cooldown = 30
/obj/item/bio_chip/abductor/activate()
if(cooldown == total_cooldown)
home.Retrieve(imp_in, 1)
cooldown = 0
START_PROCESSING(SSobj, src)
else
to_chat(imp_in, "<span class='warning'>You must wait [(total_cooldown - cooldown) * 2] seconds to use [src] again!</span>")
/obj/item/bio_chip/abductor/process()
if(cooldown < total_cooldown)
cooldown++
if(cooldown == total_cooldown)
STOP_PROCESSING(SSobj, src)
/obj/item/bio_chip/abductor/implant(mob/source, mob/user)
if(..())
var/obj/machinery/abductor/console/console
if(ishuman(source))
var/mob/living/carbon/human/H = source
if(isabductor(H))
var/datum/species/abductor/S = H.dna.species
console = get_team_console(S.team)
home = console.pad
if(!home)
console = get_team_console(pick(1, 2, 3, 4))
home = console.pad
return TRUE
/obj/item/bio_chip/abductor/proc/get_team_console(team)
var/obj/machinery/abductor/console/console
for(var/obj/machinery/abductor/console/c in GLOB.abductor_equipment)
if(c.team == team)
console = c
break
return console
/obj/item/bio_chip_implanter/abductor
name = "bio-chip implanter (abductor)"
implant_type = /obj/item/bio_chip/abductor
/obj/item/bio_chip_case/abductor
name = "bio-chip case - 'abductor'"
desc = "A glass case containing an abductor bio-chip."
implant_type = /obj/item/bio_chip/abductor
@@ -0,0 +1,34 @@
/obj/item/bio_chip/adrenalin
name = "adrenal bio-chip"
desc = "Removes all stuns and knockdowns."
icon_state = "adrenal"
origin_tech = "materials=2;biotech=4;combat=3;syndicate=4"
uses = 3
implant_data = /datum/implant_fluff/adrenaline
implant_state = "implant-syndicate"
/obj/item/bio_chip/adrenalin/activate()
uses--
to_chat(imp_in, "<span class='notice'>You feel a sudden surge of energy!</span>")
imp_in.SetStunned(0)
imp_in.SetWeakened(0)
imp_in.SetKnockDown(0)
imp_in.SetParalysis(0)
imp_in.adjustStaminaLoss(-75)
imp_in.stand_up(TRUE)
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
imp_in.reagents.add_reagent("synaptizine", 10)
imp_in.reagents.add_reagent("omnizine", 10)
imp_in.reagents.add_reagent("stimulative_agent", 10)
if(!uses)
qdel(src)
/obj/item/bio_chip_implanter/adrenalin
name = "bio-chip implanter (adrenalin)"
implant_type = /obj/item/bio_chip/adrenalin
/obj/item/bio_chip_case/adrenaline
name = "bio-chip case - 'Adrenaline'"
desc = "A glass case containing an adrenaline bio-chip."
implant_type = /obj/item/bio_chip/adrenalin
@@ -0,0 +1,69 @@
/obj/item/bio_chip_case
name = "bio-chip case"
desc = "A glass case containing a bio-chip."
icon = 'icons/obj/bio_chips.dmi'
icon_state = "implantcase"
item_state = "implantcase"
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_TINY
origin_tech = "materials=1;biotech=2"
container_type = OPENCONTAINER | INJECTABLE | DRAWABLE
materials = list(MAT_GLASS = 500)
var/obj/item/bio_chip/imp
var/obj/item/bio_chip/implant_type
/obj/item/bio_chip_case/Initialize(mapload)
. = ..()
if(!implant_type)
return
imp = new implant_type(src)
update_state()
/obj/item/bio_chip_case/Destroy()
if(imp)
QDEL_NULL(imp)
return ..()
/obj/item/bio_chip_case/proc/update_state()
if(imp)
origin_tech = imp.origin_tech
flags = imp.flags & ~DROPDEL
reagents = imp.reagents
else
origin_tech = initial(origin_tech)
flags = initial(flags)
reagents = null
update_icon(UPDATE_OVERLAYS)
/obj/item/bio_chip_case/update_overlays()
. = ..()
if(imp)
var/image/implant_overlay = image('icons/obj/bio_chips.dmi', imp.implant_state)
. += implant_overlay
/obj/item/bio_chip_case/attackby(obj/item/W, mob/user)
..()
if(is_pen(W))
rename_interactive(user, W)
else if(istype(W, /obj/item/bio_chip_implanter))
var/obj/item/bio_chip_implanter/I = W
if(I.imp)
if(imp || I.imp.implanted)
return
I.imp.forceMove(src)
imp = I.imp
I.imp = null
update_state()
I.update_icon(UPDATE_ICON_STATE)
else
if(imp)
if(I.imp)
return
imp.loc = I
I.imp = imp
imp = null
update_state()
I.update_icon(UPDATE_ICON_STATE)
@@ -0,0 +1,52 @@
/obj/item/bio_chip/chem
name = "chem bio-chip"
desc = "Injects things."
icon_state = "reagents"
origin_tech = "materials=3;biotech=4"
container_type = OPENCONTAINER
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
implant_data = /datum/implant_fluff/chem
implant_state = "implant-nanotrasen"
/obj/item/bio_chip/chem/Initialize(mapload)
. = ..()
create_reagents(50)
GLOB.tracked_implants += src
/obj/item/bio_chip/chem/Destroy()
GLOB.tracked_implants -= src
return ..()
/obj/item/bio_chip/chem/death_trigger(mob/victim, gibbed)
activate(reagents.total_volume)
/obj/item/bio_chip/chem/activate(cause)
if(!cause || !imp_in)
return FALSE
var/mob/living/carbon/R = imp_in
var/injectamount
var/list/implant_chems = list()
for(var/datum/reagent/chems in reagents.reagent_list)
implant_chems += chems.name
var/contained_chemicals = english_list(implant_chems)
if(cause == "action_button")
injectamount = reagents.total_volume
else
injectamount = cause
reagents.trans_to(R, injectamount)
add_attack_logs(usr, R, "Chem bio-chip activated injecting [injectamount]u of [contained_chemicals]")
to_chat(R, "<span class='italics'>You hear a faint beep.</span>")
if(!reagents.total_volume)
to_chat(R, "<span class='italics'>You hear a faint click from your chest.</span>")
qdel(src)
/obj/item/bio_chip_implanter/chem
name = "bio-chip implanter (chem)"
implant_type = /obj/item/bio_chip/chem
/obj/item/bio_chip_case/chem
name = "bio-chip case - 'Remote Chemical'"
desc = "A glass case containing a remote chemical bio-chip."
implant_type = /obj/item/bio_chip/chem
@@ -0,0 +1,63 @@
/obj/item/bio_chip/death_alarm
name = "death alarm bio-chip"
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
activated = BIOCHIP_ACTIVATED_PASSIVE
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
implant_data = /datum/implant_fluff/death_alarm
implant_state = "implant-nanotrasen"
var/mobname = "Unknown"
var/static/list/stealth_areas = typecacheof(list(/area/syndicate_mothership, /area/shuttle/syndicate_elite))
/obj/item/bio_chip/death_alarm/implant(mob/target)
. = ..()
if(.)
mobname = target.real_name
/obj/item/bio_chip/death_alarm/activate(cause) // Death signal sends name followed by the gibbed / not gibbed check
var/mob/M = imp_in
var/area/t = get_area(M)
var/obj/item/radio/headset/a = new /obj/item/radio/headset(src)
a.follow_target = M
switch(cause)
if("gib")
a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
qdel(src)
if("emp")
var/name = prob(50) ? t.name : pick(SSmapping.teleportlocs)
a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm")
else
if(is_type_in_typecache(t, stealth_areas))
//give the syndies a bit of stealth
a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm")
else
a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm")
qdel(src)
qdel(a)
/obj/item/bio_chip/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this
activate("emp") //let's shout that this dude is dead
/obj/item/bio_chip/death_alarm/death_trigger(mob/source, gibbed)
if(gibbed)
activate("gib")
else
activate("death")
/obj/item/bio_chip/death_alarm/removed(mob/target)
if(..())
UnregisterSignal(target, COMSIG_MOB_DEATH)
return TRUE
return FALSE
/obj/item/bio_chip_implanter/death_alarm
name = "bio-chip implanter (Death Alarm)"
implant_type = /obj/item/bio_chip/death_alarm
/obj/item/bio_chip_case/death_alarm
name = "bio-chip Case - 'Death Alarm'"
desc = "A case containing a death alarm bio-chip."
implant_type = /obj/item/bio_chip/death_alarm
@@ -0,0 +1,35 @@
// Dust implant, for CC officers. Prevents gear theft if they die.
/obj/item/bio_chip/dust
name = "duster bio-chip"
desc = "A remote controlled bio-chip that will dust the user upon activation (or death of user)."
icon = 'icons/obj/bio_chips.dmi'
icon_state = "dust"
actions_types = list(/datum/action/item_action/hands_free/activate/always)
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_NOT_WHEN_GIBBED
implant_data = /datum/implant_fluff/dust
implant_state = "implant-nanotrasen"
/obj/item/bio_chip/dust/death_trigger(mob/source, force)
activate("death")
/obj/item/bio_chip/dust/activate(cause)
if(!cause || !imp_in || cause == "emp")
return FALSE
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your dusting bio-chip? This will turn you to ash!", "Dusting Confirmation", "Yes", "No") != "Yes")
return FALSE
to_chat(imp_in, "<span class='notice'>Your dusting bio-chip activates!</span>")
imp_in.visible_message("<span class = 'warning'>[imp_in] burns up in a flash!</span>")
imp_in.dust()
/obj/item/bio_chip/dust/emp_act(severity)
return
/obj/item/bio_chip_implanter/dust
name = "bio-chip implanter (Dust-on-death)"
implant_type = /obj/item/bio_chip/dust
/obj/item/bio_chip_case/dust
name = "bio-chip case - 'Dust'"
desc = "A glass case containing a dust bio-chip."
implant_type = /obj/item/bio_chip/dust
@@ -0,0 +1,23 @@
/obj/item/bio_chip/emp
name = "emp bio-chip"
desc = "Triggers an EMP."
icon_state = "emp"
origin_tech = "biotech=3;magnets=4;syndicate=1"
uses = 2
implant_data = /datum/implant_fluff/emp
implant_state = "implant-syndicate"
/obj/item/bio_chip/emp/activate()
uses--
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(empulse), get_turf(imp_in), 3, 5, 1)
if(!uses)
qdel(src)
/obj/item/bio_chip_implanter/emp
name = "bio-chip implanter (EMP)"
implant_type = /obj/item/bio_chip/emp
/obj/item/bio_chip_case/emp
name = "bio-chip case - 'EMP'"
desc = "A glass case containing an EMP bio-chip."
implant_type = /obj/item/bio_chip/emp
@@ -0,0 +1,148 @@
/obj/item/bio_chip/explosive
name = "microbomb bio-chip"
desc = "And boom goes the weasel."
icon_state = "explosive"
origin_tech = "materials=2;combat=3;biotech=4;syndicate=4"
actions_types = list(/datum/action/item_action/hands_free/activate/always)
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE // Not surviving that
implant_data = /datum/implant_fluff/explosive
implant_state = "implant-syndicate"
var/detonating = FALSE
var/weak = 2
var/medium = 0.8
var/heavy = 0.4
var/delay = 7
/obj/item/bio_chip/explosive/death_trigger(mob/source, gibbed)
activate("death")
/obj/item/bio_chip/explosive/activate(cause)
if(!cause || !imp_in)
return FALSE
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your microbomb bio-chip? This will cause you to explode!", "Microbomb Bio-chip Confirmation", "Yes", "No") != "Yes")
return FALSE
if(detonating)
return FALSE
heavy = round(heavy)
medium = round(medium)
weak = round(weak)
detonating = TRUE
to_chat(imp_in, "<span class='danger'>You activate your microbomb bio-chip.</span>")
//If the delay is short, just blow up already jeez
if(delay <= 7)
self_destruct()
return
timed_explosion()
/// Gib the implantee and delete their destructible contents.
/obj/item/bio_chip/explosive/proc/self_destruct()
if(!imp_in)
return
explosion(src, heavy, medium, weak, weak, flame_range = weak)
// In case something happens to the implantee between now and the
// self-destruct
var/current_location = get_turf(imp_in)
var/list/destructed_items = list()
// Iterate over the implantee's contents and take out indestructible
// things to avoid having to worry about containers and recursion
for(var/obj/item/I in imp_in.get_contents())
if(I == src) // Don't delete ourselves prematurely
continue
// Drop indestructible items on the ground first, to avoid them
// getting deleted when destroying the rest of the items, which we
// track in a list to qdel afterwards
if(I.resistance_flags & INDESTRUCTIBLE)
I.forceMove(current_location)
else
destructed_items += I
QDEL_LIST_CONTENTS(destructed_items)
imp_in.gib()
qdel(src)
/obj/item/bio_chip/explosive/implant(mob/source)
var/obj/item/bio_chip/explosive/imp_e = locate(type) in source
if(imp_e && imp_e != src)
imp_e.heavy += heavy
imp_e.medium += medium
imp_e.weak += weak
imp_e.delay += delay
qdel(src)
return TRUE
return ..()
/obj/item/bio_chip/explosive/proc/timed_explosion()
imp_in.visible_message("<span class = 'warning'>[imp_in] starts beeping ominously!</span>")
playsound(loc, 'sound/items/timer.ogg', 30, 0)
var/wait_delay = delay / 4
sleep(wait_delay)
if(imp_in && imp_in.stat)
imp_in.visible_message("<span class = 'warning'>[imp_in] doubles over in pain!</span>")
imp_in.Weaken(14 SECONDS)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(wait_delay)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(wait_delay)
playsound(loc, 'sound/items/timer.ogg', 30, 0)
sleep(wait_delay)
self_destruct()
/obj/item/bio_chip/explosive/macro
name = "macrobomb bio-chip"
desc = "And boom goes the weasel. And everything else nearby."
icon_state = "explosive"
origin_tech = "materials=3;combat=5;biotech=4;syndicate=5"
weak = 16
medium = 8
heavy = 4
delay = 3 SECONDS
implant_data = new /datum/implant_fluff/explosive_macro
/obj/item/bio_chip/explosive/macro/activate(cause)
if(!cause || !imp_in)
return FALSE
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your macrobomb bio-chip? This will cause you to explode and gib!", "Macrobomb Bio-chip Confirmation", "Yes", "No") != "Yes")
return FALSE
to_chat(imp_in, "<span class='notice'>You activate your macrobomb bio-chip.</span>")
timed_explosion()
/obj/item/bio_chip/explosive/macro/implant(mob/source)
var/obj/item/bio_chip/explosive/imp_e = locate(type) in source
if(imp_e && imp_e != src)
return FALSE
imp_e = locate(/obj/item/bio_chip/explosive) in source
if(imp_e && imp_e != src)
heavy += imp_e.heavy
medium += imp_e.medium
weak += imp_e.weak
delay += imp_e.delay
qdel(imp_e)
return ..()
/obj/item/bio_chip_implanter/explosive
name = "bio-chip implanter (explosive)"
implant_type = /obj/item/bio_chip/explosive
/obj/item/bio_chip_case/explosive
name = "bio-chip case - 'Micro Explosive'"
desc = "A glass case containing a micro explosive bio-chip."
implant_type = /obj/item/bio_chip/explosive
/obj/item/bio_chip_implanter/explosive_macro
name = "bio-chip implanter (macro-explosive)"
implant_type = /obj/item/bio_chip/explosive/macro
/obj/item/bio_chip_case/explosive_macro
name = "bio-chip case - 'Macro Explosive'"
desc = "A glass case containing a macro explosive bio-chip."
implant_type = /obj/item/bio_chip/explosive/macro
@@ -0,0 +1,136 @@
/**
* # Bio-chip Fluff Datum
*
* Bio-chip fluff is just lore about the bio-chip that is accessed through the implantpad, you must attach
* one of these datums to the implant_data var on a bio-chip for it to show it up.
*/
/datum/implant_fluff
var/name = "Unknown bio-chip"
var/life = "Not Specified."
var/notes = "No Notes."
var/function = "An electronic insert that supplements biological functions."
/datum/implant_fluff/abductor
name = "GC$X9%D#G"
life = "Unknown."
notes = "Appears to contain highly advanced bluespace technology."
/datum/implant_fluff/adrenaline
name = "Cybersun Industries RX-2 Adrenaline Bio-chip"
life = "Five days."
notes = "One of Cybersun Industries oldest and simplest implants, even in its simplicity it is rumoured to be one of Cybersun Industries best-selling products."
function = "Subjects injected with this bio-chip can activate an injection of medical cocktails that removes stuns, increases speed, and has mild healing effects."
/datum/implant_fluff/supercharge
name = "Cybersun Industries RX-4 Synthetic Supercharge Bio-chip"
life = "Known to last for up to a year."
notes = "One of Cybersun Industries simplest implants, it's rumored that synthetic rights groups maintain stockpiles of these."
function = "Synthetic subjects injected with this bio-chip can activate an injection of lubricants, coolants, and positronic patching fluid."
/datum/implant_fluff/chem
name = "BioTech Solutions MJ-420 Prisoner Management Bio-chip" //ah yes, MJ-420, old coders are FUNNY
life = "Deactivates upon death but remains within the body."
notes = "Can be loaded with any sort of chemical agent via the common syringe and can hold 50 units. Can only be loaded while still in its original case."
function = "Contains a small capsule that can contain various chemicals. Upon receiving a specially encoded signal the bio-chip releases the chemicals directly into the blood stream."
/datum/implant_fluff/death_alarm
name = "BioTech Solutions MJ-102 Death Alarm Bio-chip"
notes = "Alerts crew to crewmember death."
function = "Contains a compact radio signaler that triggers when the host's lifesigns cease."
/datum/implant_fluff/dust
name = "Nanotrasen Employee Dust Bio-chip"
life = "Unknown, attempts to retrieve a sample of the bio-chip have often led to the destruction of the bio-chip... and user."
notes = "Activates upon death or from manual activation by the user."
function = "Contains a compact, electrically activated heat source that turns its host to ash upon activation, or their death."
/datum/implant_fluff/emp
name = "Cybersun Industries RX-22 Electromagnetic Pulse Emitter Bio-chip"
life = "Destroyed upon final activation."
notes = "An minituarized nuclear squib fit snuggly into a bio-chip."
function = "Upon detonization the bio-chip will release an EMP affecting the immediate area around the user."
/datum/implant_fluff/explosive
name = "Cybersun Industries RX-78 Employee Management Bio-chip"
life = "Destroyed upon activation."
notes = "Appears to contain a small, dense explosive device wired to a signaller chip, the serial number on the side is scratched out."
function = "Contains a compact, electrically detonated explosive that detonates upon receiving a specially encoded signal or upon host death."
/datum/implant_fluff/explosive_macro
name = "Cybersun Industries RX-79 Employee Management Bio-chip"
life = "Destroyed upon activation."
notes = "Compared to its predecessor, the RX-79 contains a much larger explosive; sometimes you just need a bigger boom. Due to its bulkiness, it has been known to press into the user's frontal lobe, impairing judgement."
function = "Contains a bulky, electrically triggered explosive that detonates upon receiving a specially encoded signal or upon host death."
/datum/implant_fluff/freedom
name = "Cybersun Industries RX-92 Quick Escape Bio-chip"
life = "Destroyed after 4 uses."
notes = "A bio-chip that is illegal in many systems. It is notoriously known for allowing users to grotesquely fracture bones and over-exert joints in order to slip out of the tightest of restraints."
function = "Uses a mixture of cybernetic nanobots, bone regrowth chemicals, and radio signals to quickly break the user out of restraints."
/datum/implant_fluff/protofreedom
name = "Cybersun Industries X-92 Quick Escape Bio-chip"
life = "Destroyed after 1 use."
notes = "A bio-chip that is illegal in many systems. This is the early prototype version of the RX-92. It's significantly cheaper than it's newer version."
function = "Uses a mixture of cheap cybernetic nanobots, bone regrowth chemicals, and radio signals to quickly break the user out of restraints."
/datum/implant_fluff/health
name = "Nanotrasen Health Bio-chip"
/datum/implant_fluff/krav_maga
name = "Prospero Foreign Industries Krav Maga Neurotrainer"
life = "Will cease functioning 4 hours after death of host."
notes = "As a consequence of using a neurotrainer, using this bio-chip will overwrite other martial arts knowledge in the users brain."
function = "Teaches even the clumsiest host the arts of Krav Maga."
/datum/implant_fluff/mindshield
name = "Nanotrasen Type 3 Mindshield Bio-chip"
life = "Studies have shown the bio-chip to last up to 10 years."
notes = "This is the third iteration of a bio-chip that has garnered attention from many galactic humanoid rights groups over concerns of self autonomy. Allegedly, it used to force the user to be completely loyal to Nanotrasen."
function = "Personnel injected with this device can better resist mental compulsions such as brainwashing and mindslaving."
/datum/implant_fluff/storage
name = "Cybersun Industries RX-16 Collapsible Body Cavity Bio-chip"
notes = "Prolonged usage of this bio-chip often results in the users bones being fractured and occassionaly complete organ failure."
function = "Allows the user to store two small objects within a cybernetic body cavity."
/datum/implant_fluff/tracking
name = "Nanotrasen RFID Tracking Bio-chip"
life = "Unknown, known to last up to a few years."
notes = "Tracking bio-chips are Neuro-safe! Makes use of a specialized shell that will melt and disintegrate into bio-safe elements in the event of a malfunction. "
function = "Continuously transmits a low power signal. Can be used for tracking and teleporting to the user."
/datum/implant_fluff/traitor
name = "Syndicate Type E Mindslave Bio-chip"
life = "Unknown, no collected sample has been active long enough to determine lifespan."
notes = "Any humanoid injected with this bio-chip will become loyal to the injector, unless of course the host is already loyal to someone else. It's Diplomacy made easy. The Syndicate is known to use this for political and diplomatic leverage."
function = " Contains a small pod of nanobots that manipulate the host's mental functions and slave the host to the implanter."
/datum/implant_fluff/uplink
name = "Syndicate Agent Uplink Bio-chip"
life = "Unknown, no collected sample has been active long enough to determine lifespan."
notes = "An intricate piece of machinery that interfaces directly with the users brain and which inner workings are a closely guarded syndicate secret."
function = "Allows the user to access a syndicate uplink connected contained within their body, invisible from the outside but provides the same functionality as a regular uplink."
/datum/implant_fluff/sad_trombone
name = "BioTech Solutions Comedy Bio-chip"
function = "Plays a sad trombone noise upon death of the implantee, allows clowns to entertain the crew even post-mortem."
/datum/implant_fluff/pathfinder
name = "Paizo Productions 5-E Pathfinder Implant"
life = "Lasts 2-12 months. Known to fail at the worst possible time, space radation may be a factor."
notes = "By use of an internal private GPS signal, allows the pathfinder module to have the MODsuit find the user. Also wirelessly transfers ID information to the suit, to allow doors to open."
function = "Allows for the recall of a Modular Outerwear Device by the implant owner at any time."
/datum/implant_fluff/gorilla_rampage
name = "Magillitis Serum Bio-chip"
life = "Unknown, no collected sample has been active long enough to determine lifespan."
notes = "An experimental serum which causes rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
function = "Allows the user to transform into an angry fast and robust gorilla. Very deadly in close quarters."
/datum/implant_fluff/stealth
name = "Syndicate S3 \"Stealth\" Bio-chip"
life = "Unknown. No collected sample has been active long enough to determine lifespan."
notes = "Manually activated by the user."
function = "Allows the user to summon a box from a bluespace pocket located inside the implant. The exterior of this box is lined with experimental cloaking panels which render the box invisible to the naked eye."
@@ -0,0 +1,56 @@
/obj/item/bio_chip/freedom
name = "freedom bio-chip"
desc = "Use this to escape from those evil Red Shirts."
icon_state = "freedom"
item_color = "r"
origin_tech = "combat=5;magnets=3;biotech=4;syndicate=2"
uses = 4
implant_data = /datum/implant_fluff/freedom
implant_state = "implant-syndicate"
/obj/item/bio_chip/freedom/activate()
uses--
to_chat(imp_in, "You feel a faint click.")
if(iscarbon(imp_in))
var/mob/living/carbon/C_imp_in = imp_in
C_imp_in.uncuff()
for(var/obj/item/grab/G in C_imp_in.grabbed_by)
var/mob/living/carbon/M = G.assailant
C_imp_in.visible_message("<span class='warning'>[C_imp_in] suddenly shocks [M] from their wrists and slips out of their grab!</span>")
M.Stun(2 SECONDS) //Drops the grab
M.apply_damage(2, BURN, "r_hand", M.run_armor_check("r_hand", "energy"))
M.apply_damage(2, BURN, "l_hand", M.run_armor_check("l_hand", "energy"))
C_imp_in.SetStunned(0) //This only triggers if they are grabbed, to have them break out of the grab, without the large stun time.
C_imp_in.SetWeakened(0)
playsound(C_imp_in.loc, "sound/weapons/egloves.ogg", 75, 1)
if(!uses)
qdel(src)
/obj/item/bio_chip_implanter/freedom
name = "bio-chip implanter (freedom)"
implant_type = /obj/item/bio_chip/freedom
/obj/item/bio_chip_case/freedom
name = "bio-chip case - 'Freedom'"
desc = "A glass case containing a freedom bio-chip."
implant_type = /obj/item/bio_chip/freedom
/obj/item/bio_chip/freedom/prototype
name = "prototype freedom bio-chip"
desc = "Use this to escape from those evil Red Shirts. Works only once!"
icon_state = "freedom"
item_color = "r"
origin_tech = "combat=5;magnets=3;biotech=3;syndicate=1"
uses = 1
implant_data = /datum/implant_fluff/protofreedom
implant_state = "implant-syndicate"
/obj/item/bio_chip_implanter/freedom/prototype
name = "bio-chip implanter (proto-freedom)"
implant_type = /obj/item/bio_chip/freedom/prototype
/obj/item/bio_chip_case/freedom/prototype
name = "bio-chip case - 'Proto-Freedom'"
desc = "A glass case containing a prototype freedom bio-chip."
implant_type = /obj/item/bio_chip/freedom/prototype
@@ -0,0 +1,25 @@
/obj/item/bio_chip/gorilla_rampage //Dumb path but easier to search for admins
name = "magillitis serum bio-chip"
desc = "An experimental biochip which causes irreversable rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
icon_state = "gorilla_rampage"
origin_tech = "combat=5;biotech=5;syndicate=2"
uses = 1
implant_data = /datum/implant_fluff/gorilla_rampage
implant_state = "implant-syndicate"
/obj/item/bio_chip/gorilla_rampage/activate()
if(!iscarbon(imp_in))
return
var/mob/living/carbon/target = imp_in
target.visible_message("<span class='userdanger'>[target] swells and their hair grows rapidly. Uh oh!.</span>","<span class='userdanger'>You feel your muscles swell and your hair grow as you return to monke.</span>", "<span class='userdanger'>You hear angry gorilla noises.</span>")
target.gorillize(TRUE)
/obj/item/bio_chip_implanter/gorilla_rampage
name = "bio-chip implanter (magillitis serum)"
implant_type = /obj/item/bio_chip/gorilla_rampage
/obj/item/bio_chip_case/gorilla_rampage
name = "bio-chip case - 'magillitis serum'"
desc = "A glass case containing a magillitis bio-chip."
implant_type = /obj/item/bio_chip/gorilla_rampage
@@ -0,0 +1,23 @@
/obj/item/bio_chip/health
name = "health bio-chip"
activated = FALSE
implant_data = /datum/implant_fluff/health
implant_state = "implant-default"
var/healthstring = ""
/obj/item/bio_chip/health/proc/sensehealth()
if(!imp_in)
return "ERROR"
else
healthstring = "[round(imp_in.getOxyLoss())] - [round(imp_in.getFireLoss())] - [round(imp_in.getToxLoss())] - [round(imp_in.getBruteLoss())]"
return healthstring
/obj/item/bio_chip_implanter/health
name = "implanter (health)"
implant_type = /obj/item/bio_chip/health
/obj/item/bio_chip_case/health
name = "implant case - 'Health'"
desc = "A glass case containing a health implant."
implant_type = /obj/item/bio_chip/health
@@ -0,0 +1,29 @@
/obj/item/bio_chip/krav_maga
name = "krav maga bio-chip"
desc = "Teaches you the arts of Krav Maga in 5 short instructional videos beamed directly into your eyeballs."
icon = 'icons/obj/wizard.dmi'
icon_state ="scroll2"
activated = BIOCHIP_ACTIVATED_ACTIVE
origin_tech = "materials=2;biotech=4;combat=5;syndicate=4"
implant_data = /datum/implant_fluff/krav_maga
implant_state = "implant-default"
var/datum/martial_art/krav_maga/style = new
/obj/item/bio_chip/krav_maga/activate()
var/mob/living/carbon/human/H = imp_in
if(!ishuman(H) || !H.mind)
return
if(istype(H.mind.martial_art, /datum/martial_art/krav_maga))
style.remove(H)
else
style.teach(H, TRUE)
/obj/item/bio_chip_implanter/krav_maga
name = "bio-chip implanter (krav maga)"
implant_type = /obj/item/bio_chip/krav_maga
/obj/item/bio_chip_case/krav_maga
name = "bio-chip case - 'Krav Maga'"
desc = "A glass case containing a bio-chip that can teach the user the art of Krav Maga."
implant_type = /obj/item/bio_chip/krav_maga
@@ -0,0 +1,43 @@
/obj/item/bio_chip/mindshield
name = "mindshield bio-chip"
desc = "Stops people messing with your mind."
origin_tech = "materials=2;biotech=4;programming=4"
activated = BIOCHIP_ACTIVATED_PASSIVE
implant_data = /datum/implant_fluff/mindshield
implant_state = "implant-nanotrasen"
/obj/item/bio_chip/mindshield/can_implant(mob/source, mob/user)
if(source.mind?.has_antag_datum(/datum/antagonist/rev/head))
source.visible_message("<span class='biggerdanger'>[source] seems to resist [src]!</span>",
"<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
return FALSE
return ..()
/obj/item/bio_chip/mindshield/implant(mob/target)
if(!..())
return FALSE
if(target.mind)
if(target.mind.has_antag_datum(/datum/antagonist/rev))
SSticker.mode.remove_revolutionary(target.mind)
if(target.mind in SSticker.mode.cult)
to_chat(target, "<span class='warning'>You feel the corporate tendrils of Nanotrasen try to invade your mind!</span>")
return TRUE
to_chat(target, "<span class='notice'>Your mind feels hardened - more resistant to brainwashing.</span>")
return TRUE
/obj/item/bio_chip/mindshield/removed(mob/target, silent = 0)
if(..())
if(target.stat != DEAD && !silent)
to_chat(target, "<span class='boldnotice'>Your mind softens. You feel susceptible to the effects of brainwashing once more.</span>")
return TRUE
return FALSE
/obj/item/bio_chip_implanter/mindshield
name = "bio-chip implanter (mindshield)"
implant_type = /obj/item/bio_chip/mindshield
/obj/item/bio_chip_case/mindshield
name = "bio-chip case - 'mindshield'"
desc = "A glass case containing a mindshield bio-chip."
implant_type = /obj/item/bio_chip/mindshield
@@ -0,0 +1,95 @@
/obj/item/bio_chip_pad
name = "bio-chip pad"
desc = "Used to modify bio-chips."
icon = 'icons/obj/bio_chips.dmi'
icon_state = "implantpad-off"
item_state = "electronic"
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
var/obj/item/bio_chip_case/case
/obj/item/bio_chip_pad/Destroy()
if(case)
eject_case()
return ..()
/obj/item/bio_chip_pad/examine(mob/user)
. = ..()
. += "<span class='notice'>You can <b>Alt-Click</b> [src] to remove it's stored implant.</span>"
/obj/item/bio_chip_pad/update_icon_state()
if(case)
icon_state = "implantpad-on"
else
icon_state = "implantpad-off"
/obj/item/bio_chip_pad/attack_self(mob/user)
ui_interact(user)
/obj/item/bio_chip_pad/attackby(obj/item/bio_chip_case/C, mob/user)
if(istype(C))
addcase(user, C)
else
return ..()
/obj/item/bio_chip_pad/proc/addcase(mob/user, obj/item/bio_chip_case/C)
if(!user || !C)
return
if(case)
to_chat(user, "<span class='warning'>There's already a bio-chip in the pad!</span>")
return
user.unEquip(C)
C.forceMove(src)
case = C
update_icon(UPDATE_ICON_STATE)
/obj/item/bio_chip_pad/proc/eject_case(mob/user)
if(!case)
return
if(user)
if(user.put_in_hands(case))
add_fingerprint(user)
case.add_fingerprint(user)
case = null
update_icon(UPDATE_ICON_STATE)
return
case.forceMove(get_turf(src))
case = null
update_icon(UPDATE_ICON_STATE)
/obj/item/bio_chip_pad/AltClick(mob/user)
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
return
eject_case(user)
/obj/item/bio_chip_pad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "ImplantPad", name, 410, 400, master_ui, state)
ui.open()
/obj/item/bio_chip_pad/ui_data(mob/user)
var/list/data = list()
data["contains_case"] = case ? TRUE : FALSE
if(case && case.imp)
var/datum/implant_fluff/implant_data = case.imp.implant_data
data["implant"] = list(
"name" = implant_data.name,
"life" = implant_data.life,
"notes" = implant_data.notes,
"function" = implant_data.function,
"image" = "[icon2base64(icon(initial(case.imp.icon), initial(case.imp.icon_state), SOUTH, 1))]",
)
return data
/obj/item/bio_chip_pad/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
switch(action)
if("eject_case")
eject_case(ui.user)
@@ -0,0 +1,48 @@
/obj/item/bio_chip/grey_autocloner
name = "technocracy cloning bio-chip"
desc = "Allows for advanced instantanious cloning!"
icon_state = "generic"
origin_tech = "materials=3;combat=5;syndicate=2"
activated = FALSE
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
implant_state = "implant-alien"
var/obj/machinery/grey_autocloner/linked
var/datum/dna2/record/our_record
/obj/item/bio_chip/grey_autocloner/Destroy()
linked = null
our_record = null
return ..()
/obj/item/bio_chip/grey_autocloner/death_trigger(mob/source, gibbed)
imp_in.ghostize(TRUE)
if(linked)
linked.growclone(our_record)
/obj/item/bio_chip/grey_autocloner/implant(mob/source, mob/user, force)
if(!linked)
to_chat(user, "<span class='warning'>Please link the implanter with a Technocracy cloning pod!</span>")
return FALSE
. = ..()
if(!. || !ishuman(imp_in))
return FALSE
our_record = new /datum/dna2/record()
our_record.ckey = imp_in.ckey
var/obj/item/organ/B = imp_in.get_int_organ(/obj/item/organ/internal/brain)
B.dna.check_integrity()
our_record.dna = B.dna.Clone()
our_record.id = copytext(md5(B.dna.real_name), 2, 6)
our_record.name = B.dna.real_name
our_record.types = DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
our_record.languages = imp_in.languages
if(imp_in.mind) //Save that mind so traitors can continue traitoring after cloning.
our_record.mind = imp_in.mind.UID()
/obj/item/bio_chip_implanter/grey_autocloner
name = "bio-chip implanter (Technocracy cloning)"
implant_type = /obj/item/bio_chip/grey_autocloner
/obj/item/bio_chip_case/grey_autocloner
name = "bio-chip case - 'Technocracy cloning'"
desc = "A glass case containing an Technocracy bio-chip."
implant_type = /obj/item/bio_chip/grey_autocloner
@@ -0,0 +1,27 @@
/obj/item/bio_chip/sad_trombone
name = "sad trombone bio-chip"
activated = FALSE
trigger_emotes = list("deathgasp")
// If something forces the clown to fake death, it's pretty funny to still see the sad trombone played
trigger_causes = BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL | BIOCHIP_TRIGGER_DEATH_ANY
implant_data = /datum/implant_fluff/sad_trombone
implant_state = "implant-honk"
/obj/item/bio_chip/sad_trombone/emote_trigger(emote, mob/source, force)
activate(emote)
/obj/item/bio_chip/sad_trombone/death_trigger(mob/user, gibbed)
activate(gibbed)
/obj/item/bio_chip/sad_trombone/activate()
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, FALSE)
/obj/item/bio_chip_implanter/sad_trombone
name = "bio-chip implanter (sad trombone)"
implant_type = /obj/item/bio_chip/sad_trombone
/obj/item/bio_chip_case/sad_trombone
name = "bio-chip case - 'Sad Trombone'"
desc = "A glass case containing a sad trombone bio-chip."
implant_type = /obj/item/bio_chip/sad_trombone
@@ -0,0 +1,177 @@
/**
* # Stealth Implant
*
* Implant which allows you to summon an MGS-style cardboard box that turns you invisble after a short delay.
*/
/obj/item/bio_chip/stealth
name = "S3 bio-chip"
desc = "Allows you to be hidden in plain sight."
implant_state = "implant-syndicate"
implant_data = /datum/implant_fluff/stealth
actions_types = list(/datum/action/item_action/agent_box)
/obj/item/bio_chip_implanter/stealth
name = "bio-chip implanter (stealth)"
implant_type = /obj/item/bio_chip/stealth
/datum/action/item_action/agent_box
name = "Deploy Box"
desc = "Find inner peace, here, in the box."
check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_STUNNED
background_icon_state = "bg_agent"
button_icon_state = "deploy_box"
use_itemicon = FALSE
/// If TRUE, the box can't be deployed
var/on_cooldown = FALSE
/datum/action/item_action/agent_box/Trigger(trigger_flags, left_click)
. = ..()
if(!.)
return FALSE
if(istype(owner.loc, /obj/structure/closet/cardboard/agent))
var/obj/structure/closet/cardboard/agent/box = owner.loc
if(box.open())
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
recall_box_animation()
return
// Box closing from here on out.
if(!isturf(owner.loc)) //Don't let the player use this to escape mechs/welded closets.
to_chat(owner, "<span class='warning'>You need more space to activate this implant!</span>")
return
owner.playsound_local(owner, 'sound/misc/box_deploy.ogg', 50, TRUE)
spawn_box()
/datum/action/item_action/agent_box/proc/spawn_box()
// Do the box's fade in spawn animation with an image so it follows the owner.
var/image/fake_box = image('icons/obj/cardboard_boxes.dmi', owner, "agentbox", ABOVE_MOB_LAYER)
flick_overlay_view(fake_box, owner, 0.4 SECONDS)
fake_box.alpha = 0
fake_box.pixel_z = 30
animate(fake_box, pixel_z = fake_box.pixel_z - 30, alpha = fake_box.alpha + 255, time = 3, loop = 1)
sleep(3)
// Spawn the actual box
var/obj/structure/closet/cardboard/agent/box = new(get_turf(owner), owner)
box.implant_user_UID = owner.UID()
// Slightly shorter time since we needed 0.3s to to do the spawn animation.
INVOKE_ASYNC(box, TYPE_PROC_REF(/obj/structure/closet/cardboard/agent, go_invisible), 1.7 SECONDS)
box.create_fake_box()
owner.forceMove(box)
RegisterSignal(box, COMSIG_PARENT_QDELETING, PROC_REF(start_cooldown))
/datum/action/item_action/agent_box/proc/start_cooldown(datum/source)
SIGNAL_HANDLER
on_cooldown = TRUE
addtimer(CALLBACK(src, PROC_REF(end_cooldown)), 10 SECONDS)
UpdateButtonIcon()
/datum/action/item_action/agent_box/proc/end_cooldown()
on_cooldown = FALSE
UpdateButtonIcon()
/datum/action/item_action/agent_box/IsAvailable()
if(..() && !on_cooldown)
return TRUE
return FALSE
/datum/action/item_action/agent_box/proc/recall_box_animation()
var/image/fake_box = image('icons/obj/cardboard_boxes.dmi', owner, "agentbox", ABOVE_MOB_LAYER)
flick_overlay_view(fake_box, owner, 0.4 SECONDS)
animate(fake_box, pixel_z = fake_box.pixel_z + 30, alpha = fake_box.alpha - 255, time = 3, loop = 1)
/datum/action/item_action/agent_box/Grant(mob/grant_to)
. = ..()
if(owner)
RegisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT, PROC_REF(suicide_act))
/datum/action/item_action/agent_box/Remove(mob/M)
if(owner)
UnregisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT)
return ..()
/datum/action/item_action/agent_box/proc/suicide_act(datum/source)
SIGNAL_HANDLER
if(!istype(owner.loc, /obj/structure/closet/cardboard/agent))
return
var/obj/structure/closet/cardboard/agent/box = owner.loc
owner.visible_message("<span class='suicide'>[owner] falls out of [box]! It looks like [owner.p_they()] committed suicide!</span>")
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
INVOKE_ASYNC(box, TYPE_PROC_REF(/obj/structure/closet/cardboard/agent, open))
INVOKE_ASYNC(owner, TYPE_PROC_REF(/atom/movable, throw_at), get_turf(owner))
return OXYLOSS
// Stealth implant box
/obj/structure/closet/cardboard/agent
name = "inconspicious box"
desc = "It's so normal that you didn't notice it before."
icon_state = "agentbox"
max_integrity = 1
move_speed_multiplier = 0.5 // You can move at run speed while in this box.
material_drop = null
/// UID of the person who summoned this box with an implant.
var/implant_user_UID
// This has to be a separate object and not just an image because the image will inherit the box's 0 alpha while it is stealthed.
/// A holder effect which follows the src box so we can display an image to the person inside the box.
var/obj/effect/fake_box
/// The box image attached to the `fake_box` object.
var/image/box_img
/obj/structure/closet/cardboard/agent/Destroy()
var/mob/living/implant_user = locateUID(implant_user_UID)
implant_user?.client?.images -= box_img
QDEL_NULL(fake_box)
QDEL_NULL(box_img)
return ..()
/obj/structure/closet/cardboard/agent/open()
. = ..()
if(!.)
return FALSE
qdel(src)
// When the box is opened, it's deleted, so we never need to update this.
/obj/structure/closet/cardboard/agent/update_icon_state()
return
/obj/structure/closet/cardboard/agent/proc/create_fake_box()
if(fake_box)
return
fake_box = new(get_turf(src))
fake_box.mouse_opacity = MOUSE_OPACITY_TRANSPARENT // This object should be completely invisible.
box_img = image(icon, fake_box, icon_state, ABOVE_MOB_LAYER)
box_img.alpha = 128
RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(move_fake_box))
var/mob/living/implant_user = locateUID(implant_user_UID)
implant_user.client?.images += box_img
/obj/structure/closet/cardboard/agent/proc/move_fake_box(datum/source, oldloc, move_dir)
SIGNAL_HANDLER
// For non-standard movement such as teleports.
if(!move_dir)
fake_box.loc = get_turf(src)
return
// For basic 8-directional movement.
fake_box.loc = get_step(fake_box, move_dir)
/obj/structure/closet/cardboard/agent/proc/go_invisible(invis_time = 2 SECONDS)
animate(src, alpha = 0, time = invis_time)
sleep(invis_time)
// This is so people can't locate the box by spamming right click everywhere.
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/structure/closet/cardboard/agent/proc/reveal()
alpha = 255
mouse_opacity = MOUSE_OPACITY_OPAQUE
addtimer(CALLBACK(src, PROC_REF(go_invisible)), 1 SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE)
/obj/structure/closet/cardboard/agent/Bump(atom/A)
. = ..()
if(isliving(A))
reveal()
/obj/structure/closet/cardboard/agent/Bumped(atom/movable/A)
. = ..()
if(isliving(A))
reveal()
@@ -0,0 +1,74 @@
/obj/item/storage/hidden/implant
name = "bluespace pocket"
storage_slots = 2
max_w_class = WEIGHT_CLASS_NORMAL
max_combined_w_class = WEIGHT_CLASS_GIGANTIC
w_class = WEIGHT_CLASS_BULKY
cant_hold = list(/obj/item/disk/nuclear)
w_class_override = list(/obj/item/storage/belt)
silent = TRUE
/obj/item/bio_chip/storage
name = "storage bio-chip"
desc = "Stores up to two big items in a bluespace pocket."
icon_state = "storage"
origin_tech = "materials=2;magnets=4;bluespace=5;syndicate=4"
item_color = "r"
implant_data = /datum/implant_fluff/storage
implant_state = "implant-syndicate"
var/obj/item/storage/hidden/implant/storage
/obj/item/bio_chip/storage/Initialize(mapload)
. = ..()
storage = new /obj/item/storage/hidden/implant(src)
/obj/item/bio_chip/storage/emp_act(severity)
..()
storage.emp_act(severity)
/obj/item/bio_chip/storage/activate()
if(!length(storage.mobs_viewing))
storage.MouseDrop(imp_in)
else
for(var/mob/to_close in storage.mobs_viewing)
storage.close(to_close)
/obj/item/bio_chip/storage/removed(source)
if(..())
for(var/mob/M in range(1))
if(M.s_active == storage)
storage.close(M)
for(var/obj/item/I in storage)
storage.remove_from_storage(I, get_turf(source))
return TRUE
/obj/item/bio_chip/storage/implant(mob/source)
var/obj/item/bio_chip/storage/imp_e = locate(type) in source
if(imp_e)
imp_e.storage.storage_slots += storage.storage_slots
imp_e.storage.max_combined_w_class += storage.max_combined_w_class
imp_e.storage.contents += storage.contents
for(var/mob/M in range(1))
if(M.s_active == storage)
storage.close(M)
storage.show_to(source)
qdel(src)
return TRUE
return ..()
/obj/item/bio_chip/storage/proc/get_contents() //Used for swiftly returning a list of the implant's contents i.e. for checking a theft objective's completion.
if(storage && storage.contents)
return storage.contents
/obj/item/bio_chip_implanter/storage
name = "bio-chip implanter (storage)"
implant_type = /obj/item/bio_chip/storage
/obj/item/bio_chip_case/storage
name = "bio-chip case - 'Storage'"
desc = "A glass case containing a storage bio-chip."
implant_type = /obj/item/bio_chip/storage
@@ -0,0 +1,34 @@
/obj/item/bio_chip/supercharge
name = "supercharge bio-chip"
desc = "Removes all stuns and knockdowns."
icon_state = "adrenal"
origin_tech = "materials=3;combat=5;syndicate=4"
uses = 3
implant_data = /datum/implant_fluff/adrenaline
implant_state = "implant-syndicate"
/obj/item/bio_chip/supercharge/activate()
uses--
to_chat(imp_in, "<span class='notice'>You feel an electric sensation as your components enter overdrive!</span>")
imp_in.SetStunned(0)
imp_in.SetWeakened(0)
imp_in.SetKnockDown(0)
imp_in.SetParalysis(0)
imp_in.adjustStaminaLoss(-75)
imp_in.stand_up(TRUE)
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
imp_in.reagents.add_reagent("surge_plus", 10)
imp_in.reagents.add_reagent("liquid_solder", 10)
imp_in.reagents.add_reagent("combatlube", 10)
if(!uses)
qdel(src)
/obj/item/bio_chip_implanter/supercharge
name = "bio-chip implanter (supercharge)"
implant_type = /obj/item/bio_chip/supercharge
/obj/item/bio_chip_case/supercharge
name = "bio-chip case - 'supercharge'"
desc = "A glass case containing an supercharge bio-chip."
implant_type = /obj/item/bio_chip/supercharge
@@ -0,0 +1,43 @@
/obj/item/bio_chip/tracking
name = "tracking bio-chip"
desc = "Track with this."
activated = BIOCHIP_ACTIVATED_PASSIVE
origin_tech = "materials=2;magnets=2;programming=2;biotech=2"
implant_data = /datum/implant_fluff/tracking
implant_state = "implant-nanotrasen"
var/warn_cooldown = 0
var/obj/item/gps/internal_gps
var/internal_gps_path = /obj/item/gps/internal/tracking_implant
/obj/item/bio_chip/tracking/Initialize(mapload)
. = ..()
GLOB.tracked_implants += src
/obj/item/bio_chip/tracking/Destroy()
QDEL_NULL(internal_gps)
GLOB.tracked_implants -= src
return ..()
/obj/item/bio_chip/tracking/implant(mob/target)
. = ..()
if(!.)
return
internal_gps = new internal_gps_path(src)
/obj/item/bio_chip/tracking/removed(mob/target)
. = ..()
if(.)
QDEL_NULL(internal_gps)
/obj/item/gps/internal/tracking_implant
gpstag = "TRACK0"
local = FALSE
/obj/item/bio_chip_implanter/tracking
name = "bio-chip implanter (tracking)"
implant_type = /obj/item/bio_chip/tracking
/obj/item/bio_chip_case/tracking
name = "bio-chip case - 'Tracking'"
desc = "A glass case containing a tracking bio-chip."
implant_type = /obj/item/bio_chip/tracking
@@ -0,0 +1,55 @@
/obj/item/bio_chip/traitor
name = "Mindslave Bio-chip"
desc = "Divide and Conquer"
origin_tech = "programming=5;biotech=5;syndicate=8"
activated = FALSE
implant_data = /datum/implant_fluff/traitor
implant_state = "implant-syndicate"
/// 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/bio_chip/traitor/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user)
// Check `activated` here so you can't just keep taking it out and putting it back into other people.
if(activated || !istype(mindslave_target) || !istype(user)) // Both the target and the user need to be human.
return FALSE
// If the target is catatonic or doesn't have a mind, return.
if(!mindslave_target.mind)
to_chat(user, "<span class='warning'><i>This person doesn't have a mind for you to slave!</i></span>")
return FALSE
// Fails if they're already a mindslave of someone, or if they're mindshielded.
if(ismindslave(mindslave_target) || ismindshielded(mindslave_target))
mindslave_target.visible_message(
"<span class='warning'>[mindslave_target] seems to resist the bio-chip!</span>", \
"<span class='warning'>You feel a strange sensation in your head that quickly dissipates.</span>")
qdel(src)
return FALSE
// Mindslaving yourself.
if(mindslave_target == user)
to_chat(user, "<span class='notice'>Making yourself loyal to yourself was a great idea! Perhaps even the best idea ever! Actually, you just feel like an idiot.</span>")
user.adjustBrainLoss(20)
qdel(src)
return FALSE
// Create a new mindslave datum for the target with the user as their master.
mindslave_target.mind.add_antag_datum(new /datum/antagonist/mindslave(user.mind))
mindslave_UID = mindslave_target.mind.UID()
log_admin("[key_name_admin(user)] has mind-slaved [key_name_admin(mindslave_target)].")
return ..()
/obj/item/bio_chip/traitor/removed(mob/target)
. = ..()
var/datum/mind/M = locateUID(mindslave_UID)
M.remove_antag_datum(/datum/antagonist/mindslave)
/obj/item/bio_chip_implanter/traitor
name = "bio-chip implanter (Mindslave)"
implant_type = /obj/item/bio_chip/traitor
/obj/item/bio_chip_case/traitor
name = "bio-chip case - 'Mindslave'"
desc = "A glass case containing a mindslave bio-chip."
implant_type = /obj/item/bio_chip/traitor
@@ -0,0 +1,62 @@
/obj/item/bio_chip/uplink
name = "uplink bio-chip"
desc = "Summon things."
icon = 'icons/obj/radio.dmi'
icon_state = "radio"
origin_tech = "materials=4;magnets=4;programming=4;biotech=4;syndicate=5;bluespace=5"
implant_data = /datum/implant_fluff/uplink
implant_state = "implant-syndicate"
/obj/item/bio_chip/uplink/Initialize(mapload)
. = ..()
hidden_uplink = new(src)
hidden_uplink.uses = 50
/obj/item/bio_chip/uplink/nuclear/Initialize(mapload)
. = ..()
if(hidden_uplink)
hidden_uplink.update_uplink_type(UPLINK_TYPE_NUCLEAR)
/obj/item/bio_chip/uplink/sit/Initialize(mapload)
. = ..()
if(hidden_uplink)
hidden_uplink.update_uplink_type(UPLINK_TYPE_SIT)
/obj/item/bio_chip/uplink/admin/Initialize(mapload)
. = ..()
if(hidden_uplink)
hidden_uplink.update_uplink_type(UPLINK_TYPE_ADMIN)
/obj/item/bio_chip/uplink/implant(mob/source)
var/obj/item/bio_chip/imp_e = locate(type) in source
if(imp_e && imp_e != src)
imp_e.hidden_uplink.uses += hidden_uplink.uses
qdel(src)
return TRUE
if(..())
hidden_uplink.uplink_owner="[source.key]"
return TRUE
return FALSE
/obj/item/bio_chip/uplink/activate()
if(hidden_uplink)
hidden_uplink.check_trigger(imp_in)
/obj/item/bio_chip_implanter/uplink
name = "bio-chip implanter (uplink)"
implant_type = /obj/item/bio_chip/uplink
/obj/item/bio_chip_case/uplink
name = "bio-chip case - 'Syndicate Uplink'"
desc = "A glass case containing an uplink bio-chip."
implant_type = /obj/item/bio_chip/uplink
/obj/item/bio_chip_implanter/nuclear
name = "bio-chip implanter (Nuclear Agent Uplink)"
implant_type = /obj/item/bio_chip/uplink/nuclear
/obj/item/bio_chip_case/nuclear
name = "bio-chip case - 'Nuclear Agent Uplink'"
implant_type = /obj/item/bio_chip/uplink/nuclear
@@ -0,0 +1,56 @@
/obj/item/bio_chip_implanter
name = "bio-chip implanter"
desc = "A sterile automatic bio-chip injector."
icon = 'icons/obj/bio_chips.dmi'
icon_state = "implanter0"
item_state = "syringe_0"
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
origin_tech = "materials=2;biotech=3"
materials = list(MAT_METAL = 600, MAT_GLASS = 200)
toolspeed = 1
var/obj/item/bio_chip/imp
var/obj/item/bio_chip/implant_type
/obj/item/bio_chip_implanter/update_icon_state()
if(imp)
icon_state = "implanter1"
origin_tech = imp.origin_tech
else
icon_state = "implanter0"
origin_tech = initial(origin_tech)
/obj/item/bio_chip_implanter/attack(mob/living/carbon/M, mob/user)
if(!iscarbon(M))
return
if(user && imp)
if(M != user)
M.visible_message("<span class='warning'>[user] is attempting to bio-chip [M].</span>")
var/turf/T = get_turf(M)
if(T && (M == user || do_after(user, 50 * toolspeed, target = M)))
if(user && M && (get_turf(M) == T) && src && imp)
if(imp.implant(M, user))
if(M == user)
to_chat(user, "<span class='notice'>You bio-chip yourself.</span>")
else
M.visible_message("[user] has implanted [M].", "<span class='notice'>[user] bio-chips you.</span>")
imp = null
update_icon(UPDATE_ICON_STATE)
/obj/item/bio_chip_implanter/attackby(obj/item/W, mob/user, params)
..()
if(is_pen(W))
rename_interactive(user, W)
/obj/item/bio_chip_implanter/Initialize(mapload)
. = ..()
if(!implant_type)
return
imp = new implant_type()
update_icon(UPDATE_ICON_STATE)
/obj/item/bio_chip_implanter/Destroy()
QDEL_NULL(imp)
. = ..()