diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index de82f0b8c34..1a1ed2b4c5e 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -201,4 +201,37 @@ icon_state = "memorizer" item_state = "nullrod" +/obj/item/device/flash/armimplant + name = "photon projector" + desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocals fix the flashbulb if it ever burns out." + var/flashcd = 20 + var/overheat = 0 + var/obj/item/organ/internal/cyberimp/arm/flash/I = null + +/obj/item/device/flash/armimplant/Destroy() + I = null + return ..() + +/obj/item/device/flash/armimplant/burn_out() + if(I && I.owner) + to_chat(I.owner, "Your photon projector implant overheats and deactivates!") + I.Retract() + overheat = FALSE + addtimer(src, "cooldown", flashcd * 2) + +/obj/item/device/flash/armimplant/try_use_flash(mob/user = null) + if(overheat) + if(I && I.owner) + to_chat(I.owner, "Your photon projector is running too hot to be used again so quickly!") + return FALSE + overheat = TRUE + addtimer(src, "cooldown", flashcd) + playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1) + update_icon(1) + return TRUE + +/obj/item/device/flash/armimplant/proc/cooldown() + overheat = FALSE + + /obj/item/device/flash/synthetic //just a regular flash now diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index 13bc85999e0..c642226a8d6 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -151,6 +151,13 @@ origin_tech = "materials=3;combat=4" attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut") +/obj/item/weapon/kitchen/knife/combat/cyborg + name = "cyborg knife" + icon = 'icons/obj/items_cyborg.dmi' + icon_state = "knife" + desc = "A cyborg-mounted plasteel knife. Extremely sharp and durable." + origin_tech = null + /obj/item/weapon/kitchen/knife/carrotshiv name = "carrot shiv" icon_state = "carrotshiv" diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 1c1dbbd8363..2bb2924837d 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -200,26 +200,29 @@ name = "energy blade" desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." icon_state = "blade" - force = 30 - sharp = 1 - edge = 1 + force = 30 //Normal attacks deal esword damage + hitsound = 'sound/weapons/blade1.ogg' + active = 1 throwforce = 1//Throwing or dropping the item deletes it. throw_speed = 3 throw_range = 1 w_class = WEIGHT_CLASS_BULKY //So you can't hide it in your pocket or some such. - armour_penetration = 50 - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") var/datum/effect/system/spark_spread/spark_system + sharp = 1 + edge = 1 //Most of the other special functions are handled in their own files. aka special snowflake code so kewl /obj/item/weapon/melee/energy/blade/New() + ..() spark_system = new /datum/effect/system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) -/obj/item/weapon/melee/energy/blade/dropped() - ..() - qdel(src) - /obj/item/weapon/melee/energy/blade/attack_self(mob/user) return + +/obj/item/weapon/melee/energy/blade/hardlight + name = "hardlight blade" + desc = "An extremely sharp blade made out of hard light. Packs quite a punch." + icon_state = "lightblade" + item_state = "lightblade" \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index 150f2d647bc..52c66369fe9 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -922,7 +922,7 @@ "brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain, "cell" = /obj/item/organ/internal/cell, "optics" = /obj/item/organ/internal/eyes/optical_sensor, //Default darksight of 2. - "charger" = /obj/item/organ/internal/cyberimp/chest/arm_mod/power_cord + "charger" = /obj/item/organ/internal/cyberimp/arm/power_cord ) vision_organ = /obj/item/organ/internal/eyes/optical_sensor diff --git a/code/modules/projectiles/guns/mounted.dm b/code/modules/projectiles/guns/mounted.dm index 8fec6cd8b8e..a767c94cc9c 100644 --- a/code/modules/projectiles/guns/mounted.dm +++ b/code/modules/projectiles/guns/mounted.dm @@ -1,30 +1,20 @@ /obj/item/weapon/gun/energy/gun/advtaser/mounted name = "mounted taser" desc = "An arm mounted dual-mode weapon that fires electrodes and disabler shots." - icon_state = "armcannon" + icon = 'icons/obj/items_cyborg.dmi' + icon_state = "taser" + item_state = "armcannonstun4" force = 5 - flags = NODROP - w_class = WEIGHT_CLASS_HUGE - can_flashlight = 0 selfcharge = 1 + can_flashlight = 0 trigger_guard = TRIGGER_GUARD_ALLOW_ALL // Has no trigger at all, uses neural signals instead -/obj/item/weapon/gun/energy/gun/advtaser/mounted/dropped()//if somebody manages to drop this somehow... - ..() - loc = null//send it to nullspace to get retrieved by the implant later on. gotta cover those edge cases. - /obj/item/weapon/gun/energy/laser/mounted name = "mounted laser" - desc = "An arm mounted cannon that fires lethal lasers. Doesn't come with a charge beam." - icon_state = "armcannon" + desc = "An arm mounted cannon that fires lethal lasers." + icon = 'icons/obj/items_cyborg.dmi' + icon_state = "laser" item_state = "armcannonlase" force = 5 - flags = NODROP - w_class = WEIGHT_CLASS_HUGE - materials = null selfcharge = 1 - trigger_guard = TRIGGER_GUARD_ALLOW_ALL - -/obj/item/weapon/gun/energy/laser/mounted/dropped() - ..() - loc = null + trigger_guard = TRIGGER_GUARD_ALLOW_ALL \ No newline at end of file diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 601ad98346a..52a5b9e027c 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -271,6 +271,17 @@ build_path = /obj/item/organ/internal/cyberimp/mouth/breathing_tube category = list("Misc", "Medical Designs") +/datum/design/cyberimp_toolset + name = "Toolset Arm Implant" + desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm." + id = "ci-toolset" + req_tech = list("materials" = 3, "engineering" = 4, "biotech" = 4, "powerstorage" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list (MAT_METAL = 2500, MAT_GLASS = 1500, MAT_SILVER = 1500) + construction_time = 200 + build_path = /obj/item/organ/internal/cyberimp/arm/toolset + category = list("Misc", "Medical Designs") + /datum/design/cyberimp_medical_hud name = "Medical HUD implant" desc = "These cybernetic eyes will display a medical HUD over everything you see. Wiggle eyes to control." diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm new file mode 100644 index 00000000000..a3c1b2bb474 --- /dev/null +++ b/code/modules/surgery/organs/augments_arms.dm @@ -0,0 +1,315 @@ +/obj/item/organ/internal/cyberimp/arm + name = "arm-mounted implant" + desc = "You shouldn't see this! Adminhelp and report this as an issue on github!" + parent_organ = "r_arm" + slot = "r_arm_device" + icon_state = "implant-toolkit" + w_class = WEIGHT_CLASS_NORMAL + actions_types = list(/datum/action/item_action/organ_action/toggle) + + var/list/items_list = list() + // Used to store a list of all items inside, for multi-item implants. + // I would use contents, but they shuffle on every activation/deactivation leading to interface inconsistencies. + + var/obj/item/holder = null + // You can use this var for item path, it would be converted into an item on New() + +/obj/item/organ/internal/cyberimp/arm/New() + ..() + if(ispath(holder)) + holder = new holder(src) + + update_icon() + slot = parent_organ + "_device" + items_list = contents.Copy() + +/obj/item/organ/internal/cyberimp/arm/update_icon() + if(parent_organ == "r_arm") + transform = null + else // Mirroring the icon + transform = matrix(-1, 0, 0, 0, 1, 0) + +/obj/item/organ/internal/cyberimp/arm/examine(mob/user) + ..() + to_chat(user, "[src] is assembled in the [parent_organ == "r_arm" ? "right" : "left"] arm configuration. You can use a screwdriver to reassemble it.") + +/obj/item/organ/internal/cyberimp/arm/attackby(obj/item/weapon/W, mob/user, params) + ..() + if(isscrewdriver(W)) + if(parent_organ == "r_arm") + parent_organ = "l_arm" + else + parent_organ = "r_arm" + slot = parent_organ + "_device" + to_chat(user, "You modify [src] to be installed on the [parent_organ == "r_arm" ? "right" : "left"] arm.") + update_icon() + else if(istype(W, /obj/item/weapon/card/emag)) + emag_act() + +/obj/item/organ/internal/cyberimp/arm/remove(mob/living/carbon/M, special = 0) + Retract() + . = ..() + +/obj/item/organ/internal/cyberimp/arm/emag_act() + return 0 + +/obj/item/organ/internal/cyberimp/arm/gun/emp_act(severity) + if(prob(15/severity) && owner) + to_chat(owner, "[src] is hit by EMP!") + // give the owner an idea about why his implant is glitching + Retract() + ..() + +/obj/item/organ/internal/cyberimp/arm/proc/Retract() + if(!holder || (holder in src)) + return + + owner.visible_message("[owner] retracts [holder] back into \his [parent_organ == "r_arm" ? "right" : "left"] arm.", + "[holder] snaps back into your [parent_organ == "r_arm" ? "right" : "left"] arm.", + "You hear a short mechanical noise.") + + if(istype(holder, /obj/item/device/flash/armimplant)) + var/obj/item/device/flash/F = holder + F.set_light(0) + + owner.unEquip(holder, 1) + holder.forceMove(src) + holder = null + playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + +/obj/item/organ/internal/cyberimp/arm/proc/Extend(var/obj/item/item) + if(!(item in src)) + return + + + holder = item + + holder.flags |= NODROP + holder.unacidable = 1 + holder.slot_flags = null + holder.w_class = WEIGHT_CLASS_HUGE + holder.materials = null + + if(istype(holder, /obj/item/device/flash/armimplant)) + var/obj/item/device/flash/F = holder + F.set_light(7) + + var/arm_slot = (parent_organ == "r_arm" ? slot_r_hand : slot_l_hand) + var/obj/item/arm_item = owner.get_item_by_slot(arm_slot) + + if(arm_item) + if(!owner.unEquip(arm_item)) + owner << "Your [arm_item] interferes with [src]!" + return + else + owner << "You drop [arm_item] to activate [src]!" + + if(parent_organ == "r_arm" ? !owner.put_in_r_hand(holder) : !owner.put_in_l_hand(holder)) + owner << "Your [src] fails to activate!" + return + + // Activate the hand that now holds our item. + if(parent_organ == "r_arm" ? owner.hand : !owner.hand) + owner.swap_hand() + + owner.visible_message("[owner] extends [holder] from \his [parent_organ == "r_arm" ? "right" : "left"] arm.", + "You extend [holder] from your [parent_organ == "r_arm" ? "right" : "left"] arm.", + "You hear a short mechanical noise.") + playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + +/obj/item/organ/internal/cyberimp/arm/ui_action_click() + if(crit_fail || (!holder && !contents.len)) + to_chat(owner, "The implant doesn't respond. It seems to be broken...") + return + + // You can emag the arm-mounted implant by activating it while holding emag in it's hand. + var/arm_slot = (parent_organ == "r_arm" ? slot_r_hand : slot_l_hand) + if(istype(owner.get_item_by_slot(arm_slot), /obj/item/weapon/card/emag) && emag_act()) + return + + if(!holder || (holder in src)) + holder = null + if(contents.len == 1) + Extend(contents[1]) + else // TODO: make it similar to borg's storage-like module selection + var/obj/item/choise = input("Activate which item?", "Arm Implant", null, null) as null|anything in items_list + if(owner && owner == usr && owner.stat != DEAD && (src in owner.internal_organs) && !holder && istype(choise) && (choise in contents)) + // This monster sanity check is a nice example of how bad input() is. + Extend(choise) + else + Retract() + + +/obj/item/organ/internal/cyberimp/arm/gun/emp_act(severity) + if(prob(30/severity) && owner && !crit_fail) + Retract() + owner.visible_message("A loud bang comes from [owner]\'s [parent_organ == "r_arm" ? "right" : "left"] arm!") + playsound(get_turf(owner), 'sound/weapons/flashbang.ogg', 100, 1) + to_chat(owner, "You feel an explosion erupt inside your [parent_organ == "r_arm" ? "right" : "left"] arm as your implant breaks!") + owner.adjust_fire_stacks(20) + owner.IgniteMob() + owner.adjustFireLoss(25) + crit_fail = 1 + else // The gun will still discharge anyway. + ..() + + +/obj/item/organ/internal/cyberimp/arm/gun/laser + name = "arm-mounted laser implant" + desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arm and remains inside when not in use." + icon_state = "arm_laser" + origin_tech = "materials=4;combat=4;biotech=4;powerstorage=4;syndicate=3" + contents = newlist(/obj/item/weapon/gun/energy/laser/mounted) + +/obj/item/organ/internal/cyberimp/arm/gun/laser/l + parent_organ = "l_arm" + + +/obj/item/organ/internal/cyberimp/arm/gun/taser + name = "arm-mounted taser implant" + desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arm and remains inside when not in use." + icon_state = "arm_taser" + origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4" + contents = newlist(/obj/item/weapon/gun/energy/gun/advtaser/mounted) + +/obj/item/organ/internal/cyberimp/arm/gun/taser/l + parent_organ = "l_arm" + + +/obj/item/organ/internal/cyberimp/arm/toolset + name = "integrated toolset implant" + desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm. Contains all neccessary tools." + origin_tech = "materials=3;engineering=4;biotech=3;powerstorage=4" + contents = newlist(/obj/item/weapon/screwdriver/cyborg, /obj/item/weapon/wrench/cyborg, /obj/item/weapon/weldingtool/largetank/cyborg, + /obj/item/weapon/crowbar/cyborg, /obj/item/weapon/wirecutters/cyborg, /obj/item/device/multitool/cyborg) + +/obj/item/organ/internal/cyberimp/arm/toolset/l + parent_organ = "l_arm" + +/obj/item/organ/internal/cyberimp/arm/toolset/emag_act() + if(!(locate(/obj/item/weapon/kitchen/knife/combat/cyborg) in items_list)) + to_chat(usr, "You unlock [src]'s integrated knife!") + items_list += new /obj/item/weapon/kitchen/knife/combat/cyborg(src) + return 1 + return 0 + +/obj/item/organ/internal/cyberimp/arm/esword + name = "arm-mounted energy blade" + desc = "An illegal, and highly dangerous cybernetic implant that can project a deadly blade of concentrated enregy." + contents = newlist(/obj/item/weapon/melee/energy/blade/hardlight) + origin_tech = "materials=4;combat=5;biotech=3;powerstorage=2;syndicate=5" + +/obj/item/organ/internal/cyberimp/arm/medibeam + name = "integrated medical beamgun" + desc = "A cybernetic implant that allows the user to project a healing beam from their hand." + contents = newlist(/obj/item/weapon/gun/medbeam) + origin_tech = "materials=5;combat=2;biotech=5;powerstorage=4;syndicate=1" + +/obj/item/organ/internal/cyberimp/arm/flash + name = "integrated high-intensity photon projector" //Why not + desc = "An integrated projector mounted onto a user's arm, that is able to be used as a powerful flash." + contents = newlist(/obj/item/device/flash/armimplant) + origin_tech = "materials=4;combat=3;biotech=4;magnets=4;powerstorage=3" + +/obj/item/organ/internal/cyberimp/arm/flash/New() + ..() + if(locate(/obj/item/device/flash/armimplant) in items_list) + var/obj/item/device/flash/armimplant/F = locate(/obj/item/device/flash/armimplant) in items_list + F.I = src + +/obj/item/organ/internal/cyberimp/arm/baton + name = "arm electrification implant" + desc = "An illegal combat implant that allows the user to administer disabling shocks from their arm." + contents = newlist(/obj/item/borg/stun) + origin_tech = "materials=3;combat=5;biotech=4;powerstorage=4;syndicate=3" + +/obj/item/organ/internal/cyberimp/arm/combat + name = "combat cybernetics implant" + desc = "A powerful cybernetic implant that contains combat modules built into the user's arm" + contents = newlist(/obj/item/weapon/melee/energy/blade/hardlight, /obj/item/weapon/gun/medbeam, /obj/item/borg/stun, /obj/item/device/flash/armimplant) + origin_tech = "materials=5;combat=7;biotech=5;powerstorage=5;syndicate=6;programming=5" + +/obj/item/organ/internal/cyberimp/arm/combat/New() + ..() + if(locate(/obj/item/device/flash/armimplant) in items_list) + var/obj/item/device/flash/armimplant/F = locate(/obj/item/device/flash/armimplant) in items_list + F.I = src + +/obj/item/organ/internal/cyberimp/arm/surgery + name = "surgical toolset implant" + desc = "A set of surgical tools hidden behind a concealed panel on the user's arm" + contents = newlist(/obj/item/weapon/retractor, /obj/item/weapon/hemostat, /obj/item/weapon/cautery, /obj/item/weapon/surgicaldrill, /obj/item/weapon/scalpel, /obj/item/weapon/circular_saw, /obj/item/weapon/bonegel, /obj/item/weapon/FixOVein, /obj/item/weapon/bonesetter) + origin_tech = "materials=3;engineering=3;biotech=3;programming=2;magnets=3" + +// lets make IPCs even *more* vulnerable to EMPs! +/obj/item/organ/internal/cyberimp/arm/power_cord + name = "APC-compatible power adapter implant" + desc = "An implant commonly installed inside IPCs in order to allow them to easily collect energy from their environment" + origin_tech = "materials=3;biotech=2;powerstorage=3" + contents = newlist(/obj/item/apc_powercord) + +/obj/item/organ/internal/cyberimp/arm/power_cord/emp_act(severity) + // To allow repair via nanopaste/screwdriver + // also so IPCs don't also catch on fire and fall even more apart upon EMP + damage = 1 + crit_fail = TRUE + +/obj/item/organ/internal/cyberimp/arm/power_cord/surgeryize() + if(crit_fail && owner) + to_chat(owner, "Your [src] feels functional again.") + crit_fail = FALSE + + +/obj/item/apc_powercord + name = "power cable" + desc = "Insert into a nearby APC to draw power from it." + icon = 'icons/obj/power.dmi' + icon_state = "wire1" + flags = NOBLUDGEON + +/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag) + return ..() + user.changeNext_move(CLICK_CD_MELEE) + var/obj/machinery/power/apc/A = target + var/mob/living/carbon/human/H = user + if(H.get_int_organ(/obj/item/organ/internal/cell)) + if(A.emagged || A.stat & BROKEN) + var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread + s.set_up(3, 1, A) + s.start() + to_chat(H, "The APC power currents surge erratically, damaging your chassis!") + H.adjustFireLoss(10,0) + else if(A.cell && A.cell.charge > 0) + if(H.nutrition >= NUTRITION_LEVEL_WELL_FED) + to_chat(user, "You are already fully charged!") + else + addtimer(src, "powerdraw_loop", 0, TRUE, A, H) + else + to_chat(user, "There is no charge to draw from that APC.") + else + to_chat(user, "You lack a cell in which to store charge!") + +/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/A, mob/living/carbon/human/H) + H.visible_message("[H] inserts a power connector into \the [A].", "You begin to draw power from \the [A].") + while(do_after(H, 10, target = A)) + if(loc != H) + to_chat(H, "You must keep your connector out while charging!") + break + if(A.cell.charge == 0) + to_chat(H, "\The [A] has no more charge.") + break + A.charging = 1 + if(A.cell.charge >= 500) + H.nutrition += 50 + A.cell.charge -= 500 + to_chat(H, "You siphon off some of the stored charge for your own use.") + else + H.nutrition += A.cell.charge/10 + A.cell.charge = 0 + to_chat(H, "You siphon off the last of \the [A]'s charge.") + break + if(H.nutrition > NUTRITION_LEVEL_WELL_FED) + to_chat(H, "You are now fully charged.") + break + H.visible_message("[H] unplugs from \the [A].", "You unplug from \the [A].") \ No newline at end of file diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index 13061db2c4d..0a99a9b9e5a 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -273,175 +273,6 @@ if(H.stat == CONSCIOUS) to_chat(H, "You feel your heart beating again!") -//ARM...THAT GO IN THE CHEST -/obj/item/organ/internal/cyberimp/chest/arm_mod//dummy parent item for making arm-mod implants. works best with nodrop items that are sent to nullspace upon being dropped. - name = "Arm-mounted item implant" - desc = "You shouldn't see this! Adminhelp and report this as an issue on github!" - icon_state = "chest_implant" - implant_color = "#007ACC" - slot = "shoulders" - origin_tech = "materials=5;biotech=4;powerstorage=4" - actions_types = list(/datum/action/item_action/organ_action/toggle) - var/obj/holder//is defined as the retractable item itself. ensure this is defined somewhere! - var/out = 0//determines if the item is in the owner's hand or not - var/overloaded = 0//is set to 1 when owner gets EMPed. if set to 1, implant doesn't work. - var/lasthand = null - -/obj/item/organ/internal/cyberimp/chest/arm_mod/ui_action_click() - toggle_item() - -/obj/item/organ/internal/cyberimp/chest/arm_mod/proc/toggle_item() - if(overloaded)//ensure the implant isn't broken - to_chat(owner, "The implant doesn't respond. It seems to be broken...") - return - owner.changeNext_move(CLICK_CD_MELEE) - if(owner.next_move < world.time) - return // No spam - if(out)//check if the owner has the item out already - owner.unEquip(holder, 1)//if he does, take it away. then, - holder.loc = null//stash it in nullspace - out = 0//and set this to clarify the item isn't out. - owner.visible_message("[owner] retracts [holder].","You retract [holder].") - playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) - else//if he doesn't have the item out - if(owner.put_in_hands(holder))//put it in his hands. - lasthand = owner.get_active_hand() - out = 1 - owner.visible_message("[owner] extends [holder]!","You extend [holder]!") - playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) - else//if this fails to put the item in his hands, - holder.loc = null//keep it in nullspace - to_chat(owner, "You can't extend [holder] if you can't use your hands!") - -/obj/item/organ/internal/cyberimp/chest/arm_mod/emp_act(severity)//if the implant gets EMPed... - if(!owner || overloaded)//ensure that it's in an owner and that it's not already EMPed, then... - return - if(out)//check if he has the item out... - owner.unEquip(holder, 1)//if he does, take it away. - holder.loc = null - out = 0 - owner.visible_message("[holder] forcibly retracts into [owner]'s arm.") - overload() // Make sure this doesn't happen again - -/obj/item/organ/internal/cyberimp/chest/arm_mod/proc/overload() - owner.visible_message("A loud bang comes from [owner]...") - playsound(get_turf(owner), 'sound/effects/bang.ogg', 100, 1) - to_chat(owner, "You feel an explosion erupt inside you as your chest implant breaks. Is it hot in here?") - owner.adjust_fire_stacks(20) - owner.IgniteMob()//ignite the owner, as well as - owner.say("AUUUUUUUUUUUUUUUUUUGH!!") - if(prob(50)) - if(lasthand == "r_hand") - var/obj/item/organ/external/limb = owner.get_organ("r_arm") - limb.droplimb(0, DROPLIMB_EDGE) - else if(lasthand == "l_hand") - var/obj/item/organ/external/limb = owner.get_organ("l_arm") - limb.droplimb(0, DROPLIMB_EDGE) - owner.say("I HAVE BEEN DISARMED!!!") - owner.adjustFireLoss(25)//severely injure him! - overloaded = TRUE - -/obj/item/organ/internal/cyberimp/chest/arm_mod/tase//mounted, self-charging taser! - name = "Arm-cannon taser implant" - desc = "A variant of the arm cannon implant that fires electrodes and disabler shots. The cannon emerges from the subject's arms and remains in the shoulders when not in use." - icon_state = "armcannon_tase_implant" - origin_tech = "materials=5;combat=5;biotech=4;powerstorage=4" - actions_types = list(/datum/action/item_action/organ_action/toggle) - -/obj/item/organ/internal/cyberimp/chest/arm_mod/tase/New()//when the implant is created... - ..() - holder = new /obj/item/weapon/gun/energy/gun/advtaser/mounted(src)//assign a brand new item to it. (in this case, a gun) - -/obj/item/organ/internal/cyberimp/chest/arm_mod/lase//mounted, self-charging laser! - name = "Arm-cannon laser implant" - desc = "A variant of the arm cannon implant that fires lethal laser beams. The cannon emerges from the subject's arms and remains in the shoulders when not in use." - icon_state = "armcannon_lase_implant" - origin_tech = "materials=4;combat=4;biotech=4;powerstorage=4;syndicate=3" - actions_types = list(/datum/action/item_action/organ_action/toggle) - -/obj/item/organ/internal/cyberimp/chest/arm_mod/lase/New() - ..() - holder = new /obj/item/weapon/gun/energy/laser/mounted(src) - -// lets make IPCs even *more* vulnerable to EMPs! -/obj/item/organ/internal/cyberimp/chest/arm_mod/power_cord - name = "APC-compatible power adapter implant" - desc = "An implant commonly installed inside IPCs in order to allow them to easily collect energy from their environment" - origin_tech = "materials=3;biotech=2;powerstorage=3" - slot = "shoulders2" - actions_types = list(/datum/action/item_action/organ_action/toggle) - - -/obj/item/organ/internal/cyberimp/chest/arm_mod/power_cord/New() - ..() - holder = new /obj/item/apc_powercord(src) - -/obj/item/organ/internal/cyberimp/chest/arm_mod/power_cord/overload() - // To allow repair via nanopaste/screwdriver - // also so IPCs don't also catch on fire and fall even more apart upon EMP - damage = 1 - overloaded = TRUE - -/obj/item/organ/internal/cyberimp/chest/arm_mod/power_cord/surgeryize() - if(overloaded && owner) - to_chat(owner, "Your [src] feels functional again.") - overloaded = FALSE - - -/obj/item/apc_powercord - name = "power cable" - desc = "Insert into a nearby APC to draw power from it." - icon = 'icons/obj/power.dmi' - icon_state = "wire1" - flags = NODROP | NOBLUDGEON - -/obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) - if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag) - return ..() - user.changeNext_move(CLICK_CD_MELEE) - var/obj/machinery/power/apc/A = target - var/mob/living/carbon/human/H = user - if(H.get_int_organ(/obj/item/organ/internal/cell)) - if(A.emagged || A.stat & BROKEN) - var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread - s.set_up(3, 1, A) - s.start() - to_chat(H, "The APC power currents surge erratically, damaging your chassis!") - H.adjustFireLoss(10,0) - else if(A.cell && A.cell.charge > 0) - if(H.nutrition >= NUTRITION_LEVEL_WELL_FED) - to_chat(user, "You are already fully charged!") - else - addtimer(src, "powerdraw_loop", 0, TRUE, A, H) - else - to_chat(user, "There is no charge to draw from that APC.") - else - to_chat(user, "You lack a cell in which to store charge!") - -/obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/A, mob/living/carbon/human/H) - H.visible_message("[H] inserts a power connector into \the [A].", "You begin to draw power from \the [A].") - while(do_after(H, 10, target = A)) - if(loc != H) - to_chat(H, "You must keep your connector out while charging!") - break - if(A.cell.charge == 0) - to_chat(H, "\The [A] has no more charge.") - break - A.charging = 1 - if(A.cell.charge >= 500) - H.nutrition += 50 - A.cell.charge -= 500 - to_chat(H, "You siphon off some of the stored charge for your own use.") - else - H.nutrition += A.cell.charge/10 - A.cell.charge = 0 - to_chat(H, "You siphon off the last of \the [A]'s charge.") - break - if(H.nutrition > NUTRITION_LEVEL_WELL_FED) - to_chat(H, "You are now fully charged.") - break - H.visible_message("[H] unplugs from \the [A].", "You unplug from \the [A].") - //BOX O' IMPLANTS /obj/item/weapon/storage/box/cyber_implants diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 47535c044eb..602a6e295d5 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -5,7 +5,6 @@ force = 1 w_class = WEIGHT_CLASS_SMALL throwforce = 0 - var/zone = "chest" var/slot // DO NOT add slots with matching names to different zones - it will break internal_organs_slot list! vital = 0 diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index e44f20046db..d3f3c2c933b 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -38,7 +38,6 @@ var/static/regex/multispin_words = regex("like a record baby") /obj/item/organ/internal/vocal_cords //organs that are activated through speech with the :x channel name = "vocal cords" icon_state = "appendix" - zone = "mouth" slot = "vocal_cords" parent_organ = "mouth" var/spans = null diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index 420d56de43d..5dcb5954da5 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -14,7 +14,7 @@ /datum/surgery/organ_manipulation_boneless name = "Organ Manipulation" - possible_locs = list("chest","head","groin", "eyes", "mouth") + possible_locs = list("chest","head","groin", "eyes", "mouth", "l_arm", "r_arm") steps = list(/datum/surgery_step/generic/cut_open,/datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/internal/manipulate_organs,/datum/surgery_step/generic/cauterize) requires_organic_bodypart = 1 diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index e1dc252412d..5d8a81f4bc6 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -12,7 +12,7 @@ /datum/surgery/cybernetic_repair/internal name = "Internal Component Manipulation" steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/robotics/manipulate_robotic_organs) - possible_locs = list("eyes", "chest","head","groin") + possible_locs = list("eyes", "chest","head","groin","l_arm","r_arm") requires_organic_bodypart = 0 /datum/surgery/cybernetic_amputation diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 1461df9bbbe..ae7ba3e5f1a 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index c66e67820a3..9317819aa92 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi index 9b38b205075..03b8eba0f8c 100644 Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ diff --git a/icons/obj/items_cyborg.dmi b/icons/obj/items_cyborg.dmi new file mode 100644 index 00000000000..cddb57303d2 Binary files /dev/null and b/icons/obj/items_cyborg.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 2d1bb9ac749..cccdb4d16fb 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index e4569806d57..2b49b438b85 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/paradise.dme b/paradise.dme index 0775e9b2577..6cee9859062 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2148,6 +2148,7 @@ #include "code\modules\surgery\slime.dm" #include "code\modules\surgery\surgery.dm" #include "code\modules\surgery\tools.dm" +#include "code\modules\surgery\organs\augments_arms.dm" #include "code\modules\surgery\organs\augments_eyes.dm" #include "code\modules\surgery\organs\augments_internal.dm" #include "code\modules\surgery\organs\autoimplanter.dm" diff --git a/sound/weapons/flashbang.ogg b/sound/weapons/flashbang.ogg new file mode 100644 index 00000000000..389aad77bc2 Binary files /dev/null and b/sound/weapons/flashbang.ogg differ