diff --git a/aurorastation.dme b/aurorastation.dme index e264c1c9b45..39d019a09fb 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -817,6 +817,7 @@ #include "code\game\objects\items\toys.dm" #include "code\game\objects\items\trash.dm" #include "code\game\objects\items\devices\aicard.dm" +#include "code\game\objects\items\devices\augment_implanter.dm" #include "code\game\objects\items\devices\binoculars.dm" #include "code\game\objects\items\devices\chameleonproj.dm" #include "code\game\objects\items\devices\debugger.dm" @@ -1336,6 +1337,7 @@ #include "code\modules\client\preference_setup\loadout\gear_tweaks.dm" #include "code\modules\client\preference_setup\loadout\loadout.dm" #include "code\modules\client\preference_setup\loadout\loadout_accessories.dm" +#include "code\modules\client\preference_setup\loadout\loadout_augments.dm" #include "code\modules\client\preference_setup\loadout\loadout_computer.dm" #include "code\modules\client\preference_setup\loadout\loadout_cosmetics.dm" #include "code\modules\client\preference_setup\loadout\loadout_ears.dm" @@ -2177,6 +2179,7 @@ #include "code\modules\organs\internal\lungs.dm" #include "code\modules\organs\internal\stomach.dm" #include "code\modules\organs\internal\species\diona.dm" +#include "code\modules\organs\subtypes\augment.dm" #include "code\modules\organs\subtypes\autakh.dm" #include "code\modules\organs\subtypes\diona.dm" #include "code\modules\organs\subtypes\industrial.dm" diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 96e6457edb3..0f10a926b85 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -111,6 +111,22 @@ #define BP_OPTICS "optics" #define BP_IPCTAG "ipc tag" +//Augment organs +#define BP_AUG_TIMEPIECE "integrated timepiece" +#define BP_AUG_PDA "integrated pda" +#define BP_AUG_TOOL "retractable combitool" +#define BP_AUG_PEN "retractable combipen" +#define BP_AUG_LIGHTER "retractable lighter" +#define BP_AUG_HEALTHSCAN "integrated health scanner" +#define BP_AUG_TESLA "tesla spine" +#define BP_AUG_EYE_SENSORS "integrated eyes sensors" +#define BP_AUG_HAIR "synthetic hair extensions" +#define BP_AUG_SUSPENSION "calf suspension" +#define BP_AUG_TASTE_BOOSTER "taste booster" +#define BP_AUG_RADIO "integrated radio" +#define BP_AUG_FUEL_CELL "integrated fuel cell" +#define BP_AUG_AIR_ANALYZER "integrated air analyzer" + //Organ defines #define PROCESS_ACCURACY 10 #define DEFAULT_BLOOD_AMOUNT 560 //Default blood amount in units @@ -304,6 +320,7 @@ #define PROSTHETIC_XMG "Xion Manufacturing Group" #define PROSTHETIC_DIONA "Unknown Model" #define PROSTHETIC_AUTAKH "Aut'akh Manufactured" +#define PROSTHETIC_TESLA "Tesla Powered Prosthetics" //Brain Damage defines #define BRAIN_DAMAGE_MILD 10 diff --git a/code/controllers/subsystems/garbage-debug.dm b/code/controllers/subsystems/garbage-debug.dm index e31fa720ed2..e0031ccb557 100644 --- a/code/controllers/subsystems/garbage-debug.dm +++ b/code/controllers/subsystems/garbage-debug.dm @@ -790,6 +790,7 @@ SearchVar(ntnrc_uid) SearchVar(all_robolimbs) SearchVar(chargen_robolimbs) + SearchVar(fabricator_robolimbs) SearchVar(basic_robolimb) SearchVar(moving_levels) SearchVar(cached_space) diff --git a/code/controllers/subsystems/icon_cache.dm b/code/controllers/subsystems/icon_cache.dm index dbb2108c6e0..98fa0225a25 100644 --- a/code/controllers/subsystems/icon_cache.dm +++ b/code/controllers/subsystems/icon_cache.dm @@ -44,6 +44,7 @@ var/list/markings_cache = list() // [icon]-[icon_state]-[limb_name]-[color] var/list/human_eye_cache = list() var/list/human_lip_cache = list() + var/list/internal_organ_cache = list() // Cached composited human hair (beard & hair). // Key: // hair+beard: [beard_style][r_facial][g_facial][b_facial]_[hair_style][r_hair][g_hair][b_hair] diff --git a/code/controllers/subsystems/job.dm b/code/controllers/subsystems/job.dm index 8ccb00d09a9..98f261dfef1 100644 --- a/code/controllers/subsystems/job.dm +++ b/code/controllers/subsystems/job.dm @@ -727,6 +727,10 @@ for(var/thing in prefs.gear) var/datum/gear/G = gear_datums[thing] if(G) + + if(G.augment) //augments are handled somewhere else + continue + var/permitted if(G.allowed_roles) for(var/job_name in G.allowed_roles) @@ -860,4 +864,51 @@ deferred_preference_sanitizations.Cut() + +/datum/controller/subsystem/jobs/proc/EquipAugments(mob/living/carbon/human/H, datum/preferences/prefs) + Debug("EA/([H]): Entry.") + if(!istype(H)) + Debug("EA/([H]): Abort: invalid arguments.") + return FALSE + + var/datum/job/rank = GetJob(H.mind.assigned_role) + + switch (rank.title) + if ("AI", "Cyborg") + Debug("EA/([H]): Abort: synthetic.") + return FALSE + + for(var/thing in prefs.gear) + var/datum/gear/G = gear_datums[thing] + if(G) + if(!G.augment) + continue + + var/permitted = FALSE + if(G.allowed_roles) + for(var/job_name in G.allowed_roles) + if(rank.title == job_name) + permitted = TRUE + break + else + permitted = TRUE + + if(G.whitelisted && (!(H.species.name in G.whitelisted))) + permitted = FALSE + + if(G.faction && G.faction != H.employer_faction) + permitted = FALSE + + if(!permitted) + to_chat(H, SPAN_WARNING("Your current job or whitelist status does not permit you to spawn with [thing]!")) + continue + + var/obj/item/organ/A = new G.path(H) + var/obj/item/organ/external/affected = H.get_organ(A.parent_organ) + A.replaced(H, affected) + H.update_body() + + Debug("EA/([H]): Complete.") + return TRUE + #undef Debug diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm index 1d7438017ce..d07cc90122a 100644 --- a/code/controllers/subsystems/ticker.dm +++ b/code/controllers/subsystems/ticker.dm @@ -619,6 +619,7 @@ var/datum/controller/subsystem/ticker/SSticker if(player.mind.assigned_role == "Captain") captainless = FALSE if(!player_is_antag(player.mind, only_offstation_roles = 1)) + SSjobs.EquipAugments(player, player.client.prefs) SSjobs.EquipRank(player, player.mind.assigned_role, 0) equip_custom_items(player) diff --git a/code/game/machinery/mecha_fabricator.dm b/code/game/machinery/mecha_fabricator.dm index a6d6b83143d..a94354d0563 100644 --- a/code/game/machinery/mecha_fabricator.dm +++ b/code/game/machinery/mecha_fabricator.dm @@ -99,10 +99,10 @@ data["buildable"] = get_build_options() data["category"] = category data["categories"] = categories - if(chargen_robolimbs ) + if(fabricator_robolimbs ) var/list/T = list() - for(var/A in chargen_robolimbs ) - var/datum/robolimb/R = chargen_robolimbs [A] + for(var/A in fabricator_robolimbs ) + var/datum/robolimb/R = fabricator_robolimbs [A] T += list(list("id" = A, "company" = R.company)) data["manufacturers"] = T data["manufacturer"] = manufacturer @@ -134,7 +134,7 @@ category = href_list["category"] if(href_list["manufacturer"]) - if(href_list["manufacturer"] in chargen_robolimbs ) + if(href_list["manufacturer"] in fabricator_robolimbs ) manufacturer = href_list["manufacturer"] if(href_list["eject"]) diff --git a/code/game/objects/items/devices/augment_implanter.dm b/code/game/objects/items/devices/augment_implanter.dm new file mode 100644 index 00000000000..274fdc3687a --- /dev/null +++ b/code/game/objects/items/devices/augment_implanter.dm @@ -0,0 +1,59 @@ +/obj/item/device/augment_implanter + name = "augment implanter" + desc = "A complex single use injector that is used to implant augments without the need for surgery." + w_class = ITEMSIZE_NORMAL + origin_tech = list(TECH_BIO = 5, TECH_MATERIAL = 2) + icon = 'icons/obj/guns/decloner.dmi' + icon_state = "decloner" + item_state = "decloner" + contained_sprite = TRUE + var/obj/item/organ/augment_type + +/obj/item/device/augment_implanter/Initialize() + . = ..() + if(!augment_type) + augment_type = new augment_type(src) + +/obj/item/device/augment_implanter/examine(mob/user) + ..(user) + if(augment_type) + to_chat(user, FONT_SMALL(SPAN_NOTICE("\The [augment_type] can be seen floating inside \the [src]'s biogel."))) + +/obj/item/device/augment_implanter/afterattack(mob/living/L, mob/user, proximity) + if(!proximity) + return + + if(!augment_type) + to_chat(user, SPAN_WARNING("\The [src] is empty!")) + return + + if(!ishuman(L)) + to_chat(user, SPAN_WARNING("\The [src] has no effect on \the [L].")) + return + + var/mob/living/carbon/human/H = L + + if(!(H.species.name in augment_type.species_restricted)) + to_chat(user, SPAN_WARNING("\The [augment_type] is not compatible with \the [H]'s body.")) + return + + if(H.internal_organs_by_name[augment_type.organ_tag]) + to_chat(user, SPAN_WARNING("\The [H] already has a [augment_type].")) + return + + if(!do_mob(user, H, 4 SECONDS)) + return + + augment_type.replaced(H, augment_type.parent_organ) + H.update_body() + H.updatehealth() + H.UpdateDamageIcon() + augment_type = null + + user.visible_message(SPAN_WARNING("\The [user] thrusts \the [src] deep into \the [H], injecting something!")) + +/obj/item/device/augment_implanter/advanced_tesla + augment_type = /obj/item/organ/internal/augment/tesla/advanced + +/obj/item/device/augment_implanter/advanced_suspension + augment_type = /obj/item/organ/internal/augment/suspension/advanced diff --git a/code/modules/cargo/random_stock/t2_uncommon.dm b/code/modules/cargo/random_stock/t2_uncommon.dm index e0dda968b4e..3c54cb5666a 100644 --- a/code/modules/cargo/random_stock/t2_uncommon.dm +++ b/code/modules/cargo/random_stock/t2_uncommon.dm @@ -91,7 +91,7 @@ STOCK_ITEM_UNCOMMON(chempack, 5) STOCK_ITEM_UNCOMMON(robolimbs, 3) for (var/i in 1 to rand(2, 5)) - var/manuf = pick(chargen_robolimbs) + var/manuf = pick(fabricator_robolimbs) var/type = pick( \ /obj/item/robot_parts/l_arm, \ /obj/item/robot_parts/r_arm, \ diff --git a/code/modules/client/preference_setup/loadout/loadout.dm b/code/modules/client/preference_setup/loadout/loadout.dm index 42771c8c054..b0158157132 100644 --- a/code/modules/client/preference_setup/loadout/loadout.dm +++ b/code/modules/client/preference_setup/loadout/loadout.dm @@ -237,6 +237,7 @@ var/list/gear_datums = list() var/sort_category = "General" var/list/gear_tweaks = list() //List of datums which will alter the item after it has been spawned. var/flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION + var/augment = FALSE /datum/gear/New() ..() diff --git a/code/modules/client/preference_setup/loadout/loadout_augments.dm b/code/modules/client/preference_setup/loadout/loadout_augments.dm new file mode 100644 index 00000000000..d26aa052700 --- /dev/null +++ b/code/modules/client/preference_setup/loadout/loadout_augments.dm @@ -0,0 +1,67 @@ +/datum/gear/augment + display_name = "integrated timepiece" + description = "An augment that allows the user to consult the time anywhere." + path = /obj/item/organ/internal/augment/timepiece + cost = 1 + augment = TRUE + sort_category = "Augments" + whitelisted = list("Human", "Off-Worlder Human", "Tajara", "Zhan-Khazan Tajara", "M'sai Tajara", "Aut'akh Unathi", "Skrell", "Baseline Frame", "Hephaestus G1 Industrial Frame", "Hephaestus G2 Industrial Frame", "Xion Industrial Frame", "Zeng-Hu Mobility Frame", "Bishop Accessory Frame") + flags = GEAR_NO_SELECTION + +/datum/gear/augment/eye_sensors + display_name = "integrated eye sensors" + description = "An eye augment that allows the user to deploy medical or security sensors." + path = /obj/item/organ/internal/augment/eye_sensors + cost = 4 + whitelisted = list("Human", "Off-Worlder Human", "Tajara", "Zhan-Khazan Tajara", "M'sai Tajara", "Aut'akh Unathi", "Skrell", "Baseline Frame", "Hephaestus G1 Industrial Frame", "Hephaestus G2 Industrial Frame", "Xion Industrial Frame", "Zeng-Hu Mobility Frame", "Bishop Accessory Frame", "Vaurca Worker", "Vaurca Warrior") + + +/datum/gear/augment/cyber_hair + display_name = "synthetic hair extensions" + description = "A hair augment that allows the user to change the shape and color of their hair." + path = /obj/item/organ/internal/augment/cyber_hair + cost = 2 + +/datum/gear/augment/combitool + display_name = "retractable combitool" + description = "An augment that allows the user to deploy a robotic combitool." + path = /obj/item/organ/internal/augment/tool/combitool + cost = 5 + +/datum/gear/augment/combitool/New() + ..() + var/augs = list() + augs["retractable combitool, right hand"] = /obj/item/organ/internal/augment/tool/combitool + augs["retractable combitool, left hand"] = /obj/item/organ/internal/augment/tool/combitool/left + gear_tweaks += new /datum/gear_tweak/path(augs) + +/datum/gear/augment/health_scanner + display_name = "integrated health scanner" + description = "An augment that allows the user scan their own health condition." + path = /obj/item/organ/internal/augment/health_scanner + cost = 3 + +/datum/gear/augment/suspension + display_name = "calf suspension" + description = "An augment that reduces the damage from falling from heights." + path = /obj/item/organ/internal/augment/suspension + cost = 4 + +/datum/gear/augment/taste_boosters + display_name = "taste booster selection" + description = "A selection of augments that modify the user's taste sensitivity." + path = /obj/item/organ/internal/augment/taste_booster + cost = 3 + +/datum/gear/augment/taste_boosters/New() + ..() + var/augs = list() + augs["taste booster"] = /obj/item/organ/internal/augment/taste_booster + augs["taste duller"] = /obj/item/organ/internal/augment/taste_booster/dull + gear_tweaks += new /datum/gear_tweak/path(augs) + +/datum/gear/augment/fuel_cell + display_name = "integrated fuel cell" + description = "An augment that allows the user to synthetize welding fuel into nutrients." + path = /obj/item/organ/internal/augment/fuel_cell + cost = 3 diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno/tajara.dm b/code/modules/client/preference_setup/loadout/loadout_xeno/tajara.dm index 50719cf3997..f9cff3581bd 100644 --- a/code/modules/client/preference_setup/loadout/loadout_xeno/tajara.dm +++ b/code/modules/client/preference_setup/loadout/loadout_xeno/tajara.dm @@ -185,4 +185,12 @@ path = /obj/item/storage/belt/shumaila_buckle whitelisted = list("Tajara", "Zhan-Khazan Tajara", "M'sai Tajara") sort_category = "Xenowear - Tajara" - flags = GEAR_HAS_DESC_SELECTION \ No newline at end of file + flags = GEAR_HAS_DESC_SELECTION + +/datum/gear/augment/tesla_spine + display_name = "tesla spine" + description = "A People's Republic of Adhomai made tesla spine issued to disabled veterans and civilians." + path = /obj/item/organ/internal/augment/tesla + cost = 4 + whitelisted = list("Tajara", "Zhan-Khazan Tajara", "M'sai Tajara") + sort_category = "Xenowear - Tajara" diff --git a/code/modules/client/preference_setup/loadout/loadout_xeno/unathi.dm b/code/modules/client/preference_setup/loadout/loadout_xeno/unathi.dm index d8346addb06..f9f67fda06e 100644 --- a/code/modules/client/preference_setup/loadout/loadout_xeno/unathi.dm +++ b/code/modules/client/preference_setup/loadout/loadout_xeno/unathi.dm @@ -46,41 +46,41 @@ sort_category = "Xenowear - Unathi" flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION -/datum/gear/autakh_engineering +/datum/gear/augment/autakh_engineering display_name = "engineering grasper" description = "An Aut'akh augment limb, this one is outfitted with a limited toolkit." path = /obj/item/organ/external/hand/right/autakh/tool - whitelisted = list("Aut'akh Unathi") + whitelisted = list("Unathi", "Aut'akh Unathi") sort_category = "Xenowear - Unathi" cost = 3 allowed_roles = list("Station Engineer", "Chief Engineer", "Atmospheric Technician", "Engineering Apprentice", "Roboticist") flags = GEAR_NO_SELECTION -/datum/gear/autakh_mining +/datum/gear/augment/autakh_mining display_name = "mining grasper" description = "An Aut'akh augment limb, this one is outfitted with a mining drill." path = /obj/item/organ/external/hand/right/autakh/tool/mining - whitelisted = list("Aut'akh Unathi") + whitelisted = list("Unathi", "Aut'akh Unathi") sort_category = "Xenowear - Unathi" cost = 3 allowed_roles = list("Shaft Miner") flags = GEAR_NO_SELECTION -/datum/gear/autakh_medical +/datum/gear/augment/autakh_medical display_name = "medical grasper" description = "An Aut'akh augment limb, this one is outfitted with a health scanner." path = /obj/item/organ/external/hand/right/autakh/medical - whitelisted = list("Aut'akh Unathi") + whitelisted = list("Unathi", "Aut'akh Unathi") sort_category = "Xenowear - Unathi" cost = 3 allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Paramedic", "Medical Resident", "Psychiatrist", "Chemist") flags = GEAR_NO_SELECTION -/datum/gear/autakh_security +/datum/gear/augment/autakh_security display_name = "security grasper" description = "An Aut'akh augment limb, this one is outfitted with an electroshock weapon." path = /obj/item/organ/external/hand/right/autakh/security - whitelisted = list("Aut'akh Unathi") + whitelisted = list("Unathi", "Aut'akh Unathi") sort_category = "Xenowear - Unathi" cost = 3 allowed_roles = list("Security Officer", "Head of Security", "Warden") @@ -138,4 +138,12 @@ cost = 1 whitelisted = list("Unathi") sort_category = "Xenowear - Unathi" - flags = GEAR_HAS_DESC_SELECTION \ No newline at end of file + flags = GEAR_HAS_DESC_SELECTION + +/datum/gear/augment/anchor + display_name = "soul anchor" + description = "An implant that connects the Aut'akh to the Mesh." + path = /obj/item/organ/internal/anchor + cost = 1 + whitelisted = list("Unathi") + sort_category = "Xenowear - Unathi" \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/rig/suits/alien.dm b/code/modules/clothing/spacesuits/rig/suits/alien.dm index 14e5c53bf6e..b65ae6a1d52 100644 --- a/code/modules/clothing/spacesuits/rig/suits/alien.dm +++ b/code/modules/clothing/spacesuits/rig/suits/alien.dm @@ -96,3 +96,11 @@ /obj/item/rig_module/mounted/tesla) allowed_module_types = MODULE_GENERAL | MODULE_LIGHT_COMBAT | MODULE_HEAVY_COMBAT | MODULE_UTILITY + +/obj/item/rig/tesla/process() + ..() + if(wearer) + var/obj/item/organ/internal/augment/tesla/T = wearer.internal_organs_by_name[BP_AUG_TESLA] + if(T && !T.is_broken()) + if(cell) + cell.give(T.max_charges) diff --git a/code/modules/mob/abstract/new_player/new_player.dm b/code/modules/mob/abstract/new_player/new_player.dm index 520843cf979..a7ca37f4825 100644 --- a/code/modules/mob/abstract/new_player/new_player.dm +++ b/code/modules/mob/abstract/new_player/new_player.dm @@ -333,6 +333,7 @@ INITIALIZE_IMMEDIATE(/mob/abstract/new_player) var/mob/living/character = create_character() //creates the human and transfers vars and mind + SSjobs.EquipAugments(character, character.client.prefs) character = SSjobs.EquipPersonal(character, rank, 1,spawning_at) //equips the human // AIs don't need a spawnpoint, they must spawn at an empty core diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 41da71d9f0b..4a71a702119 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -509,6 +509,11 @@ if (shock_damage<1) return 0 + var/obj/item/organ/internal/augment/tesla/tesla = internal_organs_by_name[BP_AUG_TESLA] + if(tesla?.check_shock()) + tesla.actual_charges = min(tesla.actual_charges+1, tesla.max_charges) + return FALSE + if(!def_zone) //The way this works is by damaging multiple areas in an "Arc" if no def_zone is provided. should be pretty easy to add more arcs if it's needed. though I can't imangine a situation that can apply. switch ((h_style == "Floorlength Braid" || h_style == "Very Long Hair") ? rand(1, 7) : rand(1, 6)) @@ -1278,6 +1283,8 @@ //Fix husks mutations.Remove(HUSK) status_flags &= ~DISFIGURED //Fixes the unknown status + if(src.client) + SSjobs.EquipAugments(src, src.client.prefs) update_body(1) update_eyes() diff --git a/code/modules/mob/living/carbon/taste.dm b/code/modules/mob/living/carbon/taste.dm index e2337ac94e0..072d4a1144f 100644 --- a/code/modules/mob/living/carbon/taste.dm +++ b/code/modules/mob/living/carbon/taste.dm @@ -18,7 +18,15 @@ calculate text size per text. var/minimum_percent = 15 if(ishuman(taster)) var/mob/living/carbon/human/H = taster - minimum_percent = round(15/ (H.isSynthetic() ? TASTE_DULL : H.species.taste_sensitivity)) + var/total_taste_sensitivity + + var/obj/item/organ/internal/augment/taste_booster/booster = H.internal_organs_by_name[BP_AUG_TASTE_BOOSTER] + if(booster && !booster.is_broken()) + total_taste_sensitivity = booster.new_taste + else + total_taste_sensitivity = H.species.taste_sensitivity + + minimum_percent = round(15 / (H.isSynthetic() ? TASTE_DULL : total_taste_sensitivity)) var/list/out = list() var/list/tastes = list() //descriptor = strength @@ -91,4 +99,4 @@ calculate text size per text. return "[temp_text][temp_text ? " " : ""][english_list(out, "something indescribable")]." /mob/living/carbon/proc/get_fullness() - return nutrition + (reagents.get_reagent_amount("nutriment") * 25) \ No newline at end of file + return nutrition + (reagents.get_reagent_amount("nutriment") * 25) diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 80f9297da02..b19d0bc21dc 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -496,8 +496,14 @@ visible_message(span("notice", "\The [src] tucks into a roll as they hit \the [loc]!"), span("notice", "You tuck into a roll as you hit \the [loc], minimizing damage!")) + var/aug_mod = 1 + var/obj/item/organ/internal/augment/suspension/suspension = internal_organs_by_name[BP_AUG_SUSPENSION] + if(suspension && !suspension.is_broken()) + aug_mod = suspension.suspension_mod + suspension.take_damage(10) + var/z_velocity = 5*(levels_fallen**2) - var/damage = (((40 * species.fall_mod) + z_velocity) + rand(-20,20)) * combat_roll * damage_mod + var/damage = (((40 * species.fall_mod) + z_velocity) + rand(-20,20)) * combat_roll * damage_mod * aug_mod var/limb_damage = rand(0,damage/2) diff --git a/code/modules/organs/internal/_internal.dm b/code/modules/organs/internal/_internal.dm index 0cc122960ac..1f7a1b8edd7 100644 --- a/code/modules/organs/internal/_internal.dm +++ b/code/modules/organs/internal/_internal.dm @@ -6,6 +6,7 @@ var/damage_reduction = 0.5 //modifier for internal organ injury var/toxin_type = "undefined" var/relative_size = 25 //Used for size calcs + var/on_mob_icon min_broken_damage = 10 //Internal organs are frail, man. diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index f1d62d6e7da..13e59b3b9ae 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -11,6 +11,7 @@ var/status = 0 var/vital //Lose a vital limb, die immediately. var/rejecting // Is this organ already being rejected? + var/is_augment = FALSE //Organ damage stats. var/damage = 0 // amount of damage to the organ @@ -28,18 +29,19 @@ var/robotic_name var/robotic_sprite var/emp_coeff = 1 //coefficient for damages taken by EMP, if the organ is robotic. - + //Lists. var/list/transplant_data var/list/datum/autopsy_data/autopsy_data = list() var/list/organ_verbs //verb that are added when you gain the organ var/list/trace_chemicals = list() // traces of chemicals in the organ, // links chemical IDs to number of ticks for which they'll stay in the blood - + //DNA stuff. var/datum/dna/dna var/datum/species/species var/force_skintone = FALSE // If true, icon generation will skip is-robotic checks. Used for synthskin limbs. + var/list/species_restricted //used by augments and biomods to see what species can have this augment /obj/item/organ/New(loc, ...) ..() diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 523c6ffb6b1..418aa4b43a8 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -85,6 +85,8 @@ var/image/hud_damage_image + var/augment_limit //how many augments you can fit inside this limb + /obj/item/organ/external/proc/invalidate_marking_cache() cached_markings = null @@ -1042,6 +1044,8 @@ Note that amputating the affected organ does in fact remove the infection from t brute_mod = R.brute_mod burn_mod = R.burn_mod + robotize_type = company + augment_limit += 1 //robotic limbs get one extra augment capacity dislocated = -1 //TODO, make robotic limbs a separate type, remove snowflake limb_flags &= ~ORGAN_CAN_BREAK @@ -1085,7 +1089,14 @@ Note that amputating the affected organ does in fact remove the infection from t return ..() && !is_dislocated() && !(status & ORGAN_TENDON_CUT) && (!can_feel_pain() || get_pain() < pain_disability_threshold) && brute_ratio < 1 && burn_ratio < 1 /obj/item/organ/external/proc/is_malfunctioning() - return (BP_IS_ROBOTIC(src) && (brute_ratio + burn_ratio) >= 0.3 && prob(brute_dam + burn_dam)) + if(BP_IS_ROBOTIC(src) && (brute_ratio + burn_ratio) >= 0.3 && prob(brute_dam + burn_dam)) + return TRUE + if(robotize_type) + var/datum/robolimb/R = all_robolimbs[robotize_type] + if(R.malfunctioning_check(owner)) + return TRUE + else + return FALSE /obj/item/organ/external/proc/embed(var/obj/item/W, var/silent = 0, var/supplied_message) if(!owner || loc != owner) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index de5238e2c08..f130299ffdc 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -85,6 +85,8 @@ apply_markings() + get_internal_organs_overlay() + add_overlay(owner.generate_hair_icon()) compile_overlays() @@ -113,6 +115,19 @@ add_overlay(finished_icon) //So when it's not on your body, it has icons mob_icon.Blend(finished_icon, ICON_OVERLAY) //So when it's on your body, it has icons +/obj/item/organ/external/proc/get_internal_organs_overlay() + for(var/obj/item/organ/internal/O in internal_organs) + if(O.on_mob_icon) + var/cache_key = "[O.on_mob_icon]-[O.icon_state]" + + var/icon/organ_icon = SSicon_cache.internal_organ_cache[cache_key] + if (!organ_icon) + organ_icon = new /icon(O.on_mob_icon, O.icon_state) + SSicon_cache.internal_organ_cache[cache_key] = organ_icon + + add_overlay(organ_icon) + mob_icon.Blend(organ_icon, ICON_OVERLAY) + /obj/item/organ/external/var/icon_cache_key /obj/item/organ/external/proc/get_icon(var/skeletal) @@ -125,6 +140,7 @@ if(painted && skin_color) mob_icon.Blend(skin_color, ICON_ADD) apply_markings(restrict_to_robotic = TRUE) + get_internal_organs_overlay() else if(!dna) mob_icon = new /icon('icons/mob/human_races/human/r_human.dmi', "[icon_name][gendered_icon ? "_[gender]" : ""]") @@ -162,6 +178,7 @@ apply_markings() + get_internal_organs_overlay() if(body_hair) var/list/limb_icon_cache = SSicon_cache.limb_icons_cache @@ -212,6 +229,10 @@ for (var/marking in cached_markings) keyparts += "[marking][cached_markings[marking]["color"]]" + for(var/obj/item/organ/internal/O in internal_organs) + if(O.on_mob_icon) + keyparts += "[O.on_mob_icon]-[O.icon_state]" + . = keyparts.Join("_") /obj/item/organ/external/proc/update_marking_cache() @@ -252,4 +273,4 @@ var/list/robot_hud_colours = list("#ffffff","#cccccc","#aaaaaa","#888888","#6666 // Apply colour and return product. var/list/hud_colours = !BP_IS_ROBOTIC(src) ? flesh_hud_colours : robot_hud_colours hud_damage_image.color = hud_colours[max(1,min(Ceiling(dam_state*hud_colours.len),hud_colours.len))] - return hud_damage_image \ No newline at end of file + return hud_damage_image diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index 0777a72bec4..88135356dc3 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -1,5 +1,6 @@ var/global/list/all_robolimbs = list() var/global/list/chargen_robolimbs = list() +var/global/list/fabricator_robolimbs = list() var/global/datum/robolimb/basic_robolimb /proc/populate_robolimb_list() @@ -9,6 +10,8 @@ var/global/datum/robolimb/basic_robolimb all_robolimbs[R.company] = R if(!R.unavailable_at_chargen) chargen_robolimbs[R.company] = R + if(R.fabricator_available) + fabricator_robolimbs[R.company] = R /datum/robolimb var/company = "Unbranded" // Shown when selecting the limb. @@ -31,30 +34,38 @@ var/global/datum/robolimb/basic_robolimb var/linked_frame = "Unbranded Frame" //which machine species this limb will create var/brute_mod = 0.9 //how resistant is this mode to brute damage var/burn_mod = 1.1 //how resistant is this mode to burn damage + var/fabricator_available = FALSE //if you can print this limb in the robotics fabricator + +/datum/robolimb/proc/malfunctioning_check() + return FALSE /datum/robolimb/bishop company = PROSTHETIC_BC desc = "This limb is coated in a brilliant silver illuminated from the inside with blue status lights." icon = 'icons/mob/human_races/ipc/r_ind_bishop.dmi' linked_frame = "Bishop Accessory Frame" + fabricator_available = TRUE /datum/robolimb/hesphaistos company = PROSTHETIC_HI desc = "This limb is covered in thick plating coated with a militaristic olive drab." icon = 'icons/mob/human_races/ipc/r_ind_hephaestus.dmi' linked_frame = "Hephaestus G2 Industrial Frame" + fabricator_available = TRUE /datum/robolimb/zenghu company = PROSTHETIC_ZH desc = "This limb has sleek white plating over a graphene-based nanofiber weave." icon = 'icons/mob/human_races/ipc/r_ind_zenghu.dmi' linked_frame = "Zeng-Hu Mobility Frame" + fabricator_available = TRUE /datum/robolimb/xion company = PROSTHETIC_XMG desc = "This limb has a minimalist black and grey casing with exposed orange wiring channels." icon = 'icons/mob/human_races/ipc/r_ind_xion.dmi' linked_frame = "Xion Industrial Frame" + fabricator_available = TRUE /datum/robolimb/ipc company = PROSTHETIC_IPC @@ -63,6 +74,7 @@ var/global/datum/robolimb/basic_robolimb unavailable_at_chargen = 1 paintable = 1 linked_frame = "Baseline Frame" + fabricator_available = TRUE /datum/robolimb/industrial company = PROSTHETIC_IND @@ -70,6 +82,7 @@ var/global/datum/robolimb/basic_robolimb icon = 'icons/mob/human_races/ipc/r_industrial.dmi' unavailable_at_chargen = 1 linked_frame = "Hephaestus G1 Industrial Frame" + fabricator_available = TRUE /datum/robolimb/terminator company = PROSTHETIC_HK @@ -83,6 +96,7 @@ var/global/datum/robolimb/basic_robolimb icon = 'icons/mob/human_races/human/r_human.dmi' species_can_use = list("Human") linked_frame = "Shell Frame" + fabricator_available = TRUE /datum/robolimb/autakh company = PROSTHETIC_AUTAKH @@ -93,4 +107,17 @@ var/global/datum/robolimb/basic_robolimb unavailable_at_chargen = 1 paintable = 1 brute_mod = 1 - burn_mod = 1 \ No newline at end of file + burn_mod = 1 + +/datum/robolimb/tesla + company = PROSTHETIC_TESLA + desc = "A limb designed to be used by the People's Republic of Adhomai Tesla Brigade. This civilian version is issued to disabled veterans and civilians." + icon = 'icons/mob/human_races/tajara/tesla_limbs.dmi' + species_can_use = list("Tajara", "Zhan-Khazan Tajara", "M'sai Tajara") + +/datum/robolimb/tesla/malfunctioning_check(var/mob/living/carbon/human/H) + var/obj/item/organ/internal/augment/tesla/T = H.internal_organs_by_name[BP_AUG_TESLA] + if(T && !T.is_broken()) + return FALSE + else + return TRUE diff --git a/code/modules/organs/subtypes/augment.dm b/code/modules/organs/subtypes/augment.dm new file mode 100644 index 00000000000..ff985ead8d8 --- /dev/null +++ b/code/modules/organs/subtypes/augment.dm @@ -0,0 +1,294 @@ +/obj/item/organ/internal/augment + name = "augment" + icon_state = "augment" + parent_organ = BP_CHEST + organ_tag = "augment" + robotic = 2 + emp_coeff = 2 + is_augment = TRUE + species_restricted = list("Human","Off-Worlder Human", + "Tajara", "Zhan-Khazan Tajara", "M'sai Tajara", + "Unathi", "Aut'akh Unathi", "Skrell", + "Baseline Frame", "Hephaestus G1 Industrial Frame", + "Hephaestus G2 Industrial Frame", "Xion Industrial Frame", + "Zeng-Hu Mobility Frame", "Bishop Accessory Frame") + var/cooldown = 150 + var/action_button_icon = "augment" + var/activable = FALSE + +/obj/item/organ/internal/augment/Initialize() + robotize() + . = ..() + +/obj/item/organ/internal/augment/refresh_action_button() + . = ..() + if(.) + if(activable) + action.button_icon_state = action_button_icon + if(action.button) + action.button.UpdateIcon() + +/obj/item/organ/internal/augment/attack_self(var/mob/user) + . = ..() + + if(.) + + if(owner.last_special > world.time) + to_chat(owner, SPAN_WARNING("\The [src] is still recharging!")) + return FALSE + + if(use_check_and_message(owner)) + return FALSE + + if(is_bruised()) + if(do_bruised_act()) + return FALSE + + if(is_broken()) + if(do_broken_act()) + return FALSE + + owner.last_special = world.time + cooldown + return TRUE + + +/obj/item/organ/internal/augment/proc/do_broken_act() + spark(get_turf(owner), 3) + return TRUE + +/obj/item/organ/internal/augment/proc/do_bruised_act() + spark(get_turf(owner), 3) + return FALSE + +/obj/item/organ/internal/augment/timepiece + name = "integrated timepiece" + icon_state = "augment-clock" + parent_organ = BP_HEAD + action_button_name = "Activate Integrated Timepiece" + activable = TRUE + organ_tag = BP_AUG_TIMEPIECE + action_button_icon = "augment-clock" + cooldown = 10 + +/obj/item/organ/internal/augment/timepiece/attack_self(var/mob/user) + . = ..() + + if(!.) + return FALSE + + to_chat(owner, SPAN_NOTICE("Hello [user], it is currently: '[worldtime2text()]'. Today's date is '[time2text(world.time, "Month DD")]. [game_year]'. Have a lovely day.")) + if (emergency_shuttle.get_status_panel_eta()) + to_chat(owner, SPAN_WARNING("Notice: You have one (1) scheduled flight, ETA: [emergency_shuttle.get_status_panel_eta()].")) + +/obj/item/organ/internal/augment/tool + name = "retractable widget" + action_button_name = "Deploy Widget" + cooldown = 10 + activable = TRUE + var/obj/item/augment_type + + +/obj/item/organ/internal/augment/tool/attack_self(var/mob/user) + . = ..() + + if(!.) + return FALSE + + + if(!augment_type) + return FALSE + + if (locate(augment_type) in owner) + to_chat(owner, SPAN_WARNING("\The [src] is already enabled!")) + return + + if(owner.get_active_hand()) + to_chat(owner, SPAN_WARNING("You must empty your active hand before enabling your [src]!")) + return + + var/obj/item/M = new augment_type(owner) + owner.put_in_active_hand(M) + owner.visible_message(SPAN_NOTICE("\The [M] slides out of \the [owner]'s [src.loc]."), SPAN_NOTICE("You deploy \the [M]!")) + +/obj/item/organ/internal/augment/tool/combitool + name = "retractable combitool" + icon_state = "augment-tool" + action_button_name = "Deploy Combitool" + action_button_icon = "augment-tool" + parent_organ = BP_R_HAND + organ_tag = BP_AUG_TOOL + augment_type = /obj/item/combitool/robotic + +/obj/item/organ/internal/augment/tool/combitool/left + parent_organ = BP_L_HAND + +/obj/item/organ/internal/augment/health_scanner + name = "integrated health scanner" + action_button_name = "Activate Health Scanner" + action_button_icon = "health" + organ_tag = BP_AUG_HEALTHSCAN + activable = TRUE + cooldown = 8 + +/obj/item/organ/internal/augment/health_scanner/attack_self(var/mob/user) + . = ..() + if(!.) + return FALSE + + health_scan_mob(owner, owner) + +/obj/item/organ/internal/augment/tesla + name = "tesla spine" + icon_state = "tesla_spine" + organ_tag = BP_AUG_TESLA + on_mob_icon = 'icons/mob/human_races/augments_external.dmi' + species_restricted = list("Tajara", "Zhan-Khazan Tajara", "M'sai Tajara") + var/max_charges = 1 + var/actual_charges = 0 + var/recharge_time = 5 //this is in minutes + +/obj/item/organ/internal/augment/tesla/proc/check_shock() + if(is_broken()) + return FALSE + if(is_bruised()) + if(prob(50)) + return FALSE + if(actual_charges >= max_charges) + return FALSE + else + do_tesla_act() + return TRUE + +/obj/item/organ/internal/augment/tesla/proc/do_tesla_act() + if(owner) + to_chat(owner, FONT_LARGE(SPAN_DANGER("You feel your [src.name] surge with energy!"))) + spark(get_turf(owner), 3) + addtimer(CALLBACK(src, .proc/disarm), recharge_time MINUTES) + if(is_bruised() && prob(50)) + owner.electrocute_act(40, owner) + +/obj/item/organ/internal/augment/tesla/proc/disarm() + if(actual_charges <= 0) + return + actual_charges = min(actual_charges - 1, max_charges) + if(actual_charges > 0) + addtimer(CALLBACK(src, .proc/disarm), recharge_time MINUTES) + if(is_broken()) + visible_message(SPAN_DANGER("\The [owner] crackles with energy!")) + playsound(owner, 'sound/magic/LightningShock.ogg', 75, 1) + tesla_zap(owner, 7, 1500) + +/obj/item/organ/internal/augment/tesla/advanced + name = "advanced tesla spine" + max_charges = 15 + cooldown = 50 + emp_coeff = 1 + action_button_icon = "tesla_spine" + action_button_name = "Activate Tesla Coil" + activable = TRUE + +/obj/item/organ/internal/augment/tesla/advanced/attack_self(var/mob/user) + . = ..() + + if(!.) + return FALSE + + visible_message(SPAN_DANGER("\The [owner] crackles with energy!")) + playsound(owner, 'sound/magic/LightningShock.ogg', 75, 1) + tesla_zap(owner, 7, 1500) + +/obj/item/organ/internal/augment/eye_sensors + name = "integrated eye sensors" + icon_state = "augment_eyes" + cooldown = 25 + activable = TRUE + organ_tag = BP_AUG_EYE_SENSORS + action_button_name = "Toggle Eye Sensors" + + var/static/list/hud_types = list( + "Disabled", + "Security", + "Medical") + + var/selected_hud = "Disabled" + +/obj/item/organ/internal/augment/eye_sensors/attack_self(var/mob/user) + . = ..() + + if(!.) + return FALSE + + var/choice = input("Select the Sensor Type.", "Bionic Eyes Sensors") as null|anything in hud_types + + selected_hud = choice + +/obj/item/organ/internal/augment/eye_sensors/process() + ..() + + if(!owner) + return + + switch(selected_hud) + + if("Security") + req_access = list(access_security) + if(allowed(owner)) + process_sec_hud(owner, 1) + + if("Medical") + req_access = list(access_medical) + if(allowed(owner)) + process_med_hud(owner, 1) + +/obj/item/organ/internal/augment/eye_sensors/emp_act(severity) + ..() + var/obj/item/organ/internal/eyes/E = owner.get_eyes() + if(!E) + return + E.take_damage(5) + +/obj/item/organ/internal/augment/cyber_hair + name = "synthetic hair extensions" + cooldown = 20 + action_button_icon = "cyber_hair" + organ_tag = BP_AUG_HAIR + activable = TRUE + action_button_name = "Activate Synthetic Hair Extensions" + +/obj/item/organ/internal/augment/cyber_hair/attack_self(var/mob/user) + . = ..() + + if(!.) + return FALSE + + owner.visible_message(SPAN_NOTICE("\The [owner]'s hair begins to rapidly shift in shape and length.")) + owner.change_appearance(APPEARANCE_ALL_HAIR, owner.loc, owner, check_species_whitelist = 1) + +/obj/item/organ/internal/augment/suspension + name = "calf suspension" + icon_state = "suspension" + organ_tag = BP_AUG_SUSPENSION + parent_organ = BP_GROIN + min_broken_damage = 20 + max_damage = 20 + var/suspension_mod = 0.8 + +/obj/item/organ/internal/augment/suspension/advanced + name = "advanced calf suspension" + min_broken_damage = 50 + max_damage = 50 + suspension_mod = 0 + +/obj/item/organ/internal/augment/taste_booster + name = "taste booster" + organ_tag = BP_AUG_TASTE_BOOSTER + parent_organ = BP_HEAD + var/new_taste = TASTE_SENSITIVE //this will replace the species' taste var + +/obj/item/organ/internal/augment/taste_booster/dull + name = "taste duller" + new_taste = TASTE_DULL + +/obj/item/organ/internal/augment/fuel_cell + name = "integrated fuel cell" + organ_tag = BP_AUG_FUEL_CELL \ No newline at end of file diff --git a/code/modules/organs/subtypes/autakh.dm b/code/modules/organs/subtypes/autakh.dm index 771893df7d1..8dd7789c329 100644 --- a/code/modules/organs/subtypes/autakh.dm +++ b/code/modules/organs/subtypes/autakh.dm @@ -334,7 +334,8 @@ desc = "An integrated combitool module." icon_state = "digitool" item_state = "digitool" - + w_class = ITEMSIZE_LARGE + /obj/item/combitool/robotic/throw_at() usr.drop_from_inventory(src) diff --git a/code/modules/organs/subtypes/standard.dm b/code/modules/organs/subtypes/standard.dm index 77e2f7a8e90..e8dc90b0758 100644 --- a/code/modules/organs/subtypes/standard.dm +++ b/code/modules/organs/subtypes/standard.dm @@ -19,6 +19,7 @@ limb_flags = ORGAN_CAN_BREAK parent_organ = null encased = "ribcage" + augment_limit = 3 /obj/item/organ/external/groin name = "lower body" @@ -35,6 +36,7 @@ artery_name = "iliac artery" dislocated = -1 gendered_icon = 1 + augment_limit = 3 /obj/item/organ/external/arm limb_name = "l_arm" @@ -50,6 +52,7 @@ tendon_name = "palmaris longus tendon" artery_name = "basilic vein" amputation_point = "left shoulder" + augment_limit = 2 /obj/item/organ/external/arm/right limb_name = "r_arm" @@ -76,6 +79,7 @@ artery_name = "femoral artery" amputation_point = "left hip" limb_flags = ORGAN_CAN_AMPUTATE | ORGAN_CAN_BREAK | ORGAN_CAN_MAIM | ORGAN_HAS_TENDON + augment_limit = 2 /obj/item/organ/external/leg/right limb_name = "r_leg" @@ -100,6 +104,7 @@ amputation_point = "left ankle" limb_flags = ORGAN_CAN_AMPUTATE | ORGAN_CAN_BREAK | ORGAN_CAN_MAIM | ORGAN_CAN_STAND maim_bonus = 1 + augment_limit = 1 /obj/item/organ/external/foot/removed() if(owner) @@ -130,6 +135,7 @@ amputation_point = "left wrist" limb_flags = ORGAN_CAN_AMPUTATE | ORGAN_CAN_BREAK | ORGAN_CAN_MAIM | ORGAN_CAN_GRASP | ORGAN_HAS_TENDON maim_bonus = 1 + augment_limit = 1 /obj/item/organ/external/hand/removed() owner.drop_from_inventory(owner.gloves) @@ -163,6 +169,7 @@ amputation_point = "neck" gendered_icon = 1 encased = "skull" + augment_limit = 3 var/can_intake_reagents = 1 /obj/item/organ/external/head/removed() diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm index 8db132568ca..5bccb29c9e1 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm @@ -275,7 +275,11 @@ return /datum/reagent/fuel/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) - M.adjustToxLoss(2 * removed) + var/obj/item/organ/internal/augment/fuel_cell/aug = M.internal_organs_by_name[BP_AUG_FUEL_CELL] + if(aug && !aug.is_broken()) + M.adjustNutritionLoss(-8 * removed) + else + M.adjustToxLoss(2 * removed) /datum/reagent/fuel/touch_mob(var/mob/living/L, var/amount) . = ..() diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm index 8f04afa73d4..0e9e6850139 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Dispenser.dm @@ -160,7 +160,7 @@ if (halluci) M.hallucination = max(M.hallucination, halluci) - + if(caffeine) M.add_chemical_effect(CE_PULSE, caffeine*2) if(!caffeine_mod) @@ -269,7 +269,11 @@ fallback_specific_heat = 0.549 //Unknown /datum/reagent/hydrazine/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) - M.adjustToxLoss(4 * removed) + var/obj/item/organ/internal/augment/fuel_cell/aug = M.internal_organs_by_name[BP_AUG_FUEL_CELL] + if(aug && !aug.is_broken()) + M.adjustNutritionLoss(-12 * removed) + else + M.adjustToxLoss(4 * removed) /datum/reagent/hydrazine/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) // Hydrazine is both toxic and flammable. M.adjust_fire_stacks(removed / 12) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index bb3adc07e77..d31453bb85b 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -9,7 +9,12 @@ return 0 var/obj/item/organ/external/affected = target.get_organ(target_zone) - return affected && affected.open == (affected.encased ? 3 : 2) + if(affected.encased) + return affected && affected.open == (affected.encased ? 3 : 2) + if(BP_IS_ROBOTIC(affected)) + return affected.augment_limit && affected.open == 3 + else + return affected.augment_limit && affected.open == 2 ////////////////////////////////////////////////////////////////// // CHEST INTERNAL ORGAN SURGERY // @@ -148,6 +153,10 @@ if(I && istype(I)) I.status |= ORGAN_CUT_AWAY + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + /datum/surgery_step/internal/detach_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, slicing an artery inside [target]'s [affected.name] with \the [tool]!", \ @@ -205,6 +214,10 @@ else playsound(target.loc, 'sound/items/Ratchet.ogg', 50, 1) + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + /datum/surgery_step/internal/remove_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, damaging [target]'s [affected.name] with \the [tool]!", \ @@ -246,12 +259,30 @@ if(O.organ_tag == "limb") return 0 - else if(target.species.has_organ[O.organ_tag]) + else if(target.species.has_organ[O.organ_tag] || O.is_augment) if(O.damage > (O.max_damage * 0.75)) to_chat(user, "\The [O.organ_tag] [o_is] in no state to be transplanted.") return SURGERY_FAILURE + if(O.species_restricted) + if(!target.species.name in O.species_restricted) + to_chat(user, SPAN_WARNING("\The [O] is not compatible with \the [target]'s biology.")) + return SURGERY_FAILURE + + if(O.is_augment) + if(affected.augment_limit) + var/total_augments + for(var/obj/item/organ/internal/I in affected.internal_organs) + if(I.is_augment) + total_augments += 1 + if(total_augments >= affected.augment_limit) + to_chat(user, SPAN_WARNING("There is no space left in \the [affected] to implant \the [O].")) + return SURGERY_FAILURE + else + to_chat(user, SPAN_WARNING("There is no space in \the [affected] to implant \the [O].")) + return SURGERY_FAILURE + if(!target.internal_organs_by_name[O.organ_tag]) organ_missing = 1 else @@ -285,6 +316,10 @@ O.replaced(target,affected) playsound(target.loc, 'sound/effects/squelch1.ogg', 50, 1) + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + /datum/surgery_step/internal/replace_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) user.visible_message("[user]'s hand slips, damaging \the [tool]!", \ "Your hand slips, damaging \the [tool]!") @@ -334,6 +369,10 @@ if(I && istype(I)) I.status &= ~ORGAN_CUT_AWAY + target.update_body() + target.updatehealth() + target.UpdateDamageIcon() + /datum/surgery_step/internal/attach_organ/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("[user]'s hand slips, damaging the flesh in [target]'s [affected.name] with \the [tool]!", \ diff --git a/html/changelogs/alberyk-augs.yml b/html/changelogs/alberyk-augs.yml new file mode 100644 index 00000000000..f97286de98d --- /dev/null +++ b/html/changelogs/alberyk-augs.yml @@ -0,0 +1,7 @@ +author: Alberyk, Kyres1 + +delete-after: True + +changes: + - rscadd: "Added a couple of augments to the custom loadout." + - rscadd: "Added tesla limbs for the Tajara species." diff --git a/icons/mob/human_races/augments_external.dmi b/icons/mob/human_races/augments_external.dmi new file mode 100644 index 00000000000..74c345f5a7b Binary files /dev/null and b/icons/mob/human_races/augments_external.dmi differ diff --git a/icons/mob/human_races/tajara/tesla_limbs.dmi b/icons/mob/human_races/tajara/tesla_limbs.dmi new file mode 100644 index 00000000000..cb74cd7e705 Binary files /dev/null and b/icons/mob/human_races/tajara/tesla_limbs.dmi differ diff --git a/icons/obj/action_buttons/organs.dmi b/icons/obj/action_buttons/organs.dmi index 90dfa669594..0db0a83f09d 100644 Binary files a/icons/obj/action_buttons/organs.dmi and b/icons/obj/action_buttons/organs.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 6bb60a28888..bcafd8ae745 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ