mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-28 22:47:59 +01:00
Move all the non-weapons out of code/game/objects/weapons (#29820)
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
/**
|
||||
* # 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)
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_ACTIVATED, cause, imp_in)
|
||||
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]")
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_IMPLANTED, source, user, force)
|
||||
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()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_REMOVED, source)
|
||||
return TRUE
|
||||
|
||||
/obj/item/bio_chip/dropped(mob/user)
|
||||
. = TRUE
|
||||
..()
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/obj/item/bio_chip/abductor
|
||||
name = "recall bio-chip"
|
||||
desc = "Returns you to the mothership."
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "implant"
|
||||
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)
|
||||
if(imp_in.has_status_effect(STATUS_EFFECT_ABDUCTOR_COOLDOWN))
|
||||
to_chat(imp_in, "<span class='warning'>The teleporter will not activate yet to prevent potential damage!</span>")
|
||||
return
|
||||
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,101 @@
|
||||
/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_no_addiction", 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
|
||||
|
||||
/obj/item/bio_chip/basic_adrenalin
|
||||
name = "basic adrenal bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=2;biotech=4;combat=3;syndicate=3"
|
||||
uses = 1
|
||||
implant_data = /datum/implant_fluff/basic_adrenalin
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/basic_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", 7.5)
|
||||
imp_in.reagents.add_reagent("weak_omnizine", 7.5)
|
||||
imp_in.reagents.add_reagent("stimulative_agent", 7.5)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/basic_adrenalin
|
||||
name = "bio-chip implanter (basic adrenalin)"
|
||||
implant_type = /obj/item/bio_chip/basic_adrenalin
|
||||
|
||||
/obj/item/bio_chip_case/basic_adrenalin
|
||||
name = "bio-chip case - 'Basic Adrenaline'"
|
||||
desc = "A glass case containing an smaller than normal adrenaline bio-chip."
|
||||
implant_type = /obj/item/bio_chip/basic_adrenalin
|
||||
|
||||
/obj/item/bio_chip/proto_adrenalin
|
||||
name = "proto-adrenal bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=2;biotech=4;combat=3;syndicate=2"
|
||||
uses = 1
|
||||
implant_data = /datum/implant_fluff/proto_adrenaline
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/proto_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.setStaminaLoss(0) //Since it doesn't have a good followup like adrenals, and getting batoned the moment after triggering it will stamina crit you, will set to zero over - 75
|
||||
imp_in.stand_up(TRUE)
|
||||
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
|
||||
imp_in.reagents.add_reagent("stimulative_cling", 1)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/proto_adrenalin
|
||||
name = "bio-chip implanter (proto-adrenalin)"
|
||||
implant_type = /obj/item/bio_chip/proto_adrenalin
|
||||
|
||||
/obj/item/bio_chip_case/proto_adrenalin
|
||||
name = "bio-chip case - 'proto-adrenalin'"
|
||||
desc = "A glass case containing an proto-adrenalin bio-chip."
|
||||
implant_type = /obj/item/bio_chip/proto_adrenalin
|
||||
@@ -0,0 +1,68 @@
|
||||
/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_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__legacy__attackchain(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,68 @@
|
||||
/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))
|
||||
/// Tracking to prevent multiple EMPs in the same tick from flooding radio.
|
||||
COOLDOWN_DECLARE(emp_spam_lock)
|
||||
|
||||
/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")
|
||||
if(!COOLDOWN_FINISHED(src, emp_spam_lock))
|
||||
return
|
||||
var/name = prob(50) ? t.name : pick(SSmapping.teleportlocs)
|
||||
a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm")
|
||||
COOLDOWN_START(src, emp_spam_lock, 0.1 SECONDS)
|
||||
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,76 @@
|
||||
/datum/deathrattle_group
|
||||
var/name
|
||||
var/list/implants = list()
|
||||
|
||||
/datum/deathrattle_group/New(name)
|
||||
if(name)
|
||||
src.name = name
|
||||
else
|
||||
// Give the group a unique name for debugging, and possible future
|
||||
// use for making custom linked groups.
|
||||
src.name = "[rand(100, 999)] [pick(GLOB.phonetic_alphabet)]"
|
||||
|
||||
/*
|
||||
* Proc called by new implant being added to the group. Listens for the
|
||||
* implant being implanted, removed and destroyed.
|
||||
*
|
||||
* If implant is already implanted in a person, then trigger the implantation
|
||||
* code.
|
||||
*/
|
||||
/datum/deathrattle_group/proc/register(obj/item/bio_chip/deathrattle/implant)
|
||||
if(implant in implants)
|
||||
return
|
||||
RegisterSignal(implant, COMSIG_PARENT_QDELETING, PROC_REF(on_implant_destruction))
|
||||
RegisterSignal(implant, COMSIG_IMPLANT_ACTIVATED, PROC_REF(on_user_death))
|
||||
|
||||
implants += implant
|
||||
|
||||
|
||||
/datum/deathrattle_group/proc/on_implant_destruction(obj/item/bio_chip/implant)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
implants -= implant
|
||||
|
||||
/datum/deathrattle_group/proc/on_user_death(obj/item/bio_chip/implant, source, mob/owner)
|
||||
SIGNAL_HANDLER
|
||||
var/victim_name = owner.mind ? owner.mind.name : owner.real_name
|
||||
// All "hearers" hear the same sound.
|
||||
var/sound = pick(
|
||||
'sound/items/knell1.ogg',
|
||||
'sound/items/knell2.ogg',
|
||||
'sound/items/knell3.ogg',
|
||||
'sound/items/knell4.ogg',
|
||||
)
|
||||
|
||||
|
||||
for(var/obj/item/bio_chip/deathrattle/other_implant as anything in implants)
|
||||
|
||||
// Skip the unfortunate soul, and any unimplanted implants
|
||||
if(implant == other_implant || !implant.imp_in)
|
||||
continue
|
||||
|
||||
var/mob/living/recipient = other_implant.imp_in
|
||||
to_chat(recipient, "<i>You hear a strange, robotic voice in your head...</i> <span class='robot'>\"<b>[victim_name]</b> has died...\"</span>")
|
||||
recipient.playsound_local(get_turf(recipient), sound, vol = 75, vary = FALSE, pressure_affected = FALSE, use_reverb = FALSE)
|
||||
qdel(implant)
|
||||
|
||||
/obj/item/bio_chip/deathrattle
|
||||
name = "deathrattle implant"
|
||||
desc = "Hope no one else dies, prepare for when they do."
|
||||
activated = BIOCHIP_ACTIVATED_PASSIVE
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE
|
||||
implant_data = /datum/implant_fluff/deathrattle
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
actions_types = null
|
||||
|
||||
/obj/item/bio_chip/deathrattle/emp_act(severity)
|
||||
activate("emp")
|
||||
|
||||
/obj/item/bio_chip/deathrattle/death_trigger(mob/source, gibbed)
|
||||
activate("death")
|
||||
|
||||
/obj/item/bio_chip_case/deathrattle
|
||||
name = "implant case - 'Deathrattle'"
|
||||
desc = "A glass case containing a deathrattle implant."
|
||||
implant_type = /obj/item/bio_chip/deathrattle
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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_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,147 @@
|
||||
/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, cause = name)
|
||||
|
||||
// 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."
|
||||
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,26 @@
|
||||
/// Dumb path but easier to search for admins
|
||||
/obj/item/bio_chip/gorilla_rampage
|
||||
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,27 @@
|
||||
/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"
|
||||
origin_tech = "materials=2;biotech=4;combat=5;syndicate=4"
|
||||
implant_data = /datum/implant_fluff/krav_maga
|
||||
|
||||
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(IS_CULTIST(target))
|
||||
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,120 @@
|
||||
/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
|
||||
var/static/list/cached_base64_icons = list()
|
||||
|
||||
/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__legacy__attackchain(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/bio_chip_pad/attackby__legacy__attackchain(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)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/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)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/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_state(mob/user)
|
||||
return GLOB.default_state
|
||||
|
||||
/obj/item/bio_chip_pad/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "BioChipPad", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
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
|
||||
var/icon/base64icon = cached_base64_icons["[initial(case.imp.icon)][initial(case.imp.icon_state)]"]
|
||||
if(!base64icon)
|
||||
base64icon = "[icon2base64(icon(initial(case.imp.icon), initial(case.imp.icon_state), SOUTH, 1))]"
|
||||
cached_base64_icons["[initial(case.imp.icon)][initial(case.imp.icon_state)]"] = base64icon
|
||||
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))]",
|
||||
)
|
||||
if(istype(case.imp, /obj/item/bio_chip/tracking))
|
||||
var/obj/item/bio_chip/tracking/T = case.imp
|
||||
data["gps"] = T
|
||||
data["tag"] = T.gpstag
|
||||
else
|
||||
data["gps"] = null
|
||||
data["tag"] = null
|
||||
else
|
||||
// Sanity check in the case that a pad is used for multiple types of implants.
|
||||
data["gps"] = null
|
||||
data["tag"] = null
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/bio_chip_pad/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("eject_case")
|
||||
eject_case(ui.user)
|
||||
if("tag")
|
||||
var/obj/item/bio_chip/tracking/T = case.imp
|
||||
var/newtag = params["newtag"] || ""
|
||||
newtag = uppertext(paranoid_sanitize(copytext_char(newtag, 1, 5)))
|
||||
if(!length(newtag) || T.gpstag == newtag)
|
||||
return
|
||||
T.gpstag = newtag
|
||||
@@ -0,0 +1,47 @@
|
||||
/obj/item/bio_chip/grey_autocloner
|
||||
name = "technocracy cloning bio-chip"
|
||||
desc = "Allows for advanced instantanious cloning!"
|
||||
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,46 @@
|
||||
/obj/item/bio_chip/shock
|
||||
name = "power bio-chip"
|
||||
desc = "A shockingly effective bio-chip for stunning or killing all those in your way. Do it."
|
||||
icon_state = "lighting_bolt"
|
||||
item_color = "r"
|
||||
origin_tech = "combat=5;magnets=3;biotech=4;syndicate=2"
|
||||
implant_data = /datum/implant_fluff/shock
|
||||
implant_state = "implant-syndicate"
|
||||
var/enabled = FALSE
|
||||
var/old_mclick_override
|
||||
var/datum/middle_click_override/shock_implant/mclick_override = new /datum/middle_click_override/shock_implant
|
||||
COOLDOWN_DECLARE(last_shocked)
|
||||
var/shock_delay = 3 SECONDS
|
||||
var/unlimited_power = FALSE // Does this really need explanation?
|
||||
var/shock_range = 7
|
||||
|
||||
/obj/item/bio_chip/shock/activate()
|
||||
enabled = !enabled
|
||||
to_chat(imp_in, "<span class='notice'>You toggle the implant [enabled? "on" : "off"].</span>")
|
||||
if(enabled)
|
||||
if(imp_in.middleClickOverride)
|
||||
old_mclick_override = imp_in.middleClickOverride
|
||||
imp_in.middleClickOverride = mclick_override
|
||||
else
|
||||
if(old_mclick_override)
|
||||
imp_in.middleClickOverride = old_mclick_override
|
||||
old_mclick_override = null
|
||||
else
|
||||
imp_in.middleClickOverride = null
|
||||
|
||||
/obj/item/bio_chip/shock/removed()
|
||||
if(old_mclick_override)
|
||||
imp_in.middleClickOverride = old_mclick_override
|
||||
old_mclick_override = null
|
||||
else
|
||||
imp_in.middleClickOverride = null
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip_implanter/shock
|
||||
name = "bio-chip implanter (power)"
|
||||
implant_type = /obj/item/bio_chip/shock
|
||||
|
||||
/obj/item/bio_chip_case/shock
|
||||
name = "bio-chip case - 'power'"
|
||||
desc = "A glass case containing a power bio-chip."
|
||||
implant_type = /obj/item/bio_chip/shock
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* # 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"
|
||||
/// 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)
|
||||
// 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)
|
||||
owner.forceMove(box)
|
||||
owner.overlay_fullscreen("agent_box", /atom/movable/screen/fullscreen/center/agent_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)
|
||||
owner.clear_fullscreen("agent_box")
|
||||
build_all_button_icons()
|
||||
|
||||
/datum/action/item_action/agent_box/proc/end_cooldown()
|
||||
on_cooldown = FALSE
|
||||
build_all_button_icons()
|
||||
|
||||
/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
|
||||
|
||||
/obj/structure/closet/cardboard/agent/attackby__legacy__attackchain(obj/item/I, mob/living/user)
|
||||
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/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("recal", 10)
|
||||
imp_in.reagents.add_reagent("surge_plus", 10)
|
||||
imp_in.reagents.add_reagent("synthetic_omnizine_no_addiction", 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 a supercharge bio-chip."
|
||||
implant_type = /obj/item/bio_chip/supercharge
|
||||
@@ -0,0 +1,52 @@
|
||||
/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/gpstag = "TRACK0"
|
||||
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(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/obj/item/organ/internal/cyberimp/chest/bluespace_anchor/anchor = H.get_int_organ(/obj/item/organ/internal/cyberimp/chest/bluespace_anchor)
|
||||
if(anchor)
|
||||
target.visible_message("<span class='danger'>[src] sparks out, disrupted by [anchor] inside [H]!</span>")
|
||||
qdel(src)
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
internal_gps = new internal_gps_path(src)
|
||||
if(gpstag)
|
||||
internal_gps.gpstag = gpstag
|
||||
|
||||
/obj/item/bio_chip/tracking/removed(mob/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
QDEL_NULL(internal_gps)
|
||||
|
||||
/obj/item/gps/internal/tracking_implant
|
||||
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(IS_MINDSLAVE(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/implant(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/implant)
|
||||
|
||||
/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,55 @@
|
||||
/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)
|
||||
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__legacy__attackchain(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__legacy__attackchain(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)
|
||||
. = ..()
|
||||
Reference in New Issue
Block a user