diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index e8904f0bb1f86..6f6a9d209a10e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -84,6 +84,8 @@ #define BODYTYPE_ALIEN (1<<3) ///The limb is from a golem #define BODYTYPE_GOLEM (1<<4) +//The limb is a peg limb +#define BODYTYPE_PEG (1<<5) // Bodyshape defines for how things can be worn, i.e., what "shape" the mob sprite is ///The limb fits the human mold. This is not meant to be literal, if the sprite "fits" on a human, it is "humanoid", regardless of origin. @@ -95,7 +97,7 @@ ///The limb is snouted. #define BODYSHAPE_SNOUTED (1<<3) -#define BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE (BODYTYPE_ROBOTIC | BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_GOLEM) +#define BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE (BODYTYPE_ROBOTIC | BODYTYPE_LARVA_PLACEHOLDER | BODYTYPE_GOLEM | BODYTYPE_PEG) #define BODYTYPE_CAN_BE_BIOSCRAMBLED(bodytype) (!(bodytype & BODYTYPE_BIOSCRAMBLE_INCOMPATIBLE)) // Defines for Species IDs. Used to refer to the name of a species, for things like bodypart names or species preferences. @@ -135,6 +137,8 @@ #define BODYPART_ID_LARVA "larva" #define BODYPART_ID_PSYKER "psyker" #define BODYPART_ID_MEAT "meat" +#define BODYPART_ID_PEG "peg" + //See: datum/species/var/digitigrade_customization ///The species does not have digitigrade legs in generation. @@ -631,6 +635,7 @@ // Otherwise they are completely arbitrary #define MONKEY_HEIGHT_DWARF 2 #define MONKEY_HEIGHT_MEDIUM 4 +#define MONKEY_HEIGHT_TALL HUMAN_HEIGHT_DWARF #define HUMAN_HEIGHT_DWARF 6 #define HUMAN_HEIGHT_SHORTEST 8 #define HUMAN_HEIGHT_SHORT 10 diff --git a/code/__DEFINES/research.dm b/code/__DEFINES/research.dm index d3f99314f1d8f..cf35d553ec4dc 100644 --- a/code/__DEFINES/research.dm +++ b/code/__DEFINES/research.dm @@ -4,8 +4,15 @@ //! Techweb names for new point types. Can be used to define specific point values for specific types of research (science, security, engineering, etc.) #define TECHWEB_POINT_TYPE_GENERIC "General Research" +//! Amount of points required to unlock nodes of corresponding tiers +#define TECHWEB_TIER_1_POINTS 40 +#define TECHWEB_TIER_2_POINTS 80 +#define TECHWEB_TIER_3_POINTS 120 +#define TECHWEB_TIER_4_POINTS 160 +#define TECHWEB_TIER_5_POINTS 200 + //! Amount of points gained per second by a single R&D server, see: [research][code/controllers/subsystem/research.dm] -#define TECHWEB_SINGLE_SERVER_INCOME 52.3 +#define TECHWEB_SINGLE_SERVER_INCOME 1 //! Swab cell line types #define CELL_LINE_TABLE_SLUDGE "cell_line_sludge_table" diff --git a/code/__DEFINES/research/slimes.dm b/code/__DEFINES/research/slimes.dm index f54248a21a3ac..e03c6af8f581d 100644 --- a/code/__DEFINES/research/slimes.dm +++ b/code/__DEFINES/research/slimes.dm @@ -61,3 +61,6 @@ #define SLIME_TYPE_SEPIA "sepia" #define SLIME_TYPE_SILVER "silver" #define SLIME_TYPE_YELLOW "yellow" + +// The alpha value of transperent slime types +#define SLIME_TRANSPARENCY_ALPHA 180 diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm index 42e00045761e5..feddc24c6f858 100644 --- a/code/__DEFINES/surgery.dm +++ b/code/__DEFINES/surgery.dm @@ -33,6 +33,8 @@ #define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC) /// Helper to figure out if a limb is robotic #define IS_ROBOTIC_LIMB(limb) (limb.bodytype & BODYTYPE_ROBOTIC) +/// Helper to figure out if a limb is a peg limb +#define IS_PEG_LIMB(limb) (limb.bodytype & BODYTYPE_PEG) // Flags for the bodypart_flags var on /obj/item/bodypart /// Bodypart cannot be dismembered or amputated diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 17d9008a543b3..8f1c58bc96684 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -138,8 +138,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_AGENDER "agender" /// Species with this trait have a blood clan mechanic #define TRAIT_BLOOD_CLANS "blood_clans" -/// Species with this trait have markings (this SUCKS, remove this later in favor of bodypart overlays) -#define TRAIT_HAS_MARKINGS "has_markings" /// Species with this trait use skin tones for coloration #define TRAIT_USES_SKINTONES "uses_skintones" /// Species with this trait use mutant colors for coloration @@ -366,6 +364,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_GAMERGOD "gamer-god" #define TRAIT_GIANT "giant" #define TRAIT_DWARF "dwarf" +/// Makes you way too tall. Like just too much, dude, it's kind of creepy. Humanoid only. +#define TRAIT_TOO_TALL "too_tall" /// makes your footsteps completely silent #define TRAIT_SILENT_FOOTSTEPS "silent_footsteps" /// hnnnnnnnggggg..... you're pretty good.... @@ -1153,5 +1153,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// This item cannot be selected for or used by a theft objective (Spies, Traitors, etc.) #define TRAIT_ITEM_OBJECTIVE_BLOCKED "item_objective_blocked" +/// This trait lets you attach limbs to any player without surgery. +#define TRAIT_EASY_ATTACH "easy_attach" // END TRAIT DEFINES diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 67f33d0460e47..ead7b324cea13 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -390,6 +390,7 @@ DEFINE_BITFIELD(bodytype, list( "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, + "BODYTYPE_PEG" = BODYTYPE_PEG, )) DEFINE_BITFIELD(acceptable_bodytype, list( @@ -398,6 +399,7 @@ DEFINE_BITFIELD(acceptable_bodytype, list( "BODYTYPE_LARVA_PLACEHOLDER" = BODYTYPE_LARVA_PLACEHOLDER, "BODYTYPE_ALIEN" = BODYTYPE_ALIEN, "BODYTYPE_GOLEM" = BODYTYPE_GOLEM, + "BODYTYPE_PEG" = BODYTYPE_PEG, )) DEFINE_BITFIELD(bodyshape, list( diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 1fe465da39f0d..9175b86dc3589 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -248,7 +248,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HARDLY_WOUNDED" = TRAIT_HARDLY_WOUNDED, "TRAIT_HAS_BEEN_KIDNAPPED" = TRAIT_HAS_BEEN_KIDNAPPED, "TRAIT_HAS_CRANIAL_FISSURE" = TRAIT_HAS_CRANIAL_FISSURE, - "TRAIT_HAS_MARKINGS" = TRAIT_HAS_MARKINGS, "TRAIT_HATED_BY_DOGS" = TRAIT_HATED_BY_DOGS, "TRAIT_HEAD_INJURY_BLOCKED" = TRAIT_HEAD_INJURY_BLOCKED, "TRAIT_HEALS_FROM_CARP_RIFTS" = TRAIT_HEALS_FROM_CARP_RIFTS, @@ -465,6 +464,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_THINKING_IN_CHARACTER" = TRAIT_THINKING_IN_CHARACTER, "TRAIT_THROWINGARM" = TRAIT_THROWINGARM, "TRAIT_TIME_STOP_IMMUNE" = TRAIT_TIME_STOP_IMMUNE, + "TRAIT_TOO_TALL" = TRAIT_TOO_TALL, "TRAIT_TOWER_OF_BABEL" = TRAIT_TOWER_OF_BABEL, "TRAIT_TOXIMMUNE" = TRAIT_TOXIMMUNE, "TRAIT_TOXINLOVER" = TRAIT_TOXINLOVER, @@ -548,6 +548,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( /obj/item/bodypart = list( "TRAIT_PARALYSIS" = TRAIT_PARALYSIS, ), + /obj/item/bodypart = list( + "TRAIT_EASY_ATTACH" = TRAIT_EASY_ATTACH, + ), /obj/item/card/id = list( "TRAIT_JOB_FIRST_ID_CARD" = TRAIT_JOB_FIRST_ID_CARD, "TRAIT_MAGNETIC_ID_CARD" = TRAIT_MAGNETIC_ID_CARD, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index d9f6350a07480..150a10c108494 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -94,7 +94,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_GUNFLIP" = TRAIT_GUNFLIP, "TRAIT_HANDS_BLOCKED" = TRAIT_HANDS_BLOCKED, "TRAIT_HARDLY_WOUNDED" = TRAIT_HARDLY_WOUNDED, - "TRAIT_HAS_MARKINGS" = TRAIT_HAS_MARKINGS, "TRAIT_HEAVY_SLEEPER" = TRAIT_HEAVY_SLEEPER, "TRAIT_HIDE_EXTERNAL_ORGANS" = TRAIT_HIDE_EXTERNAL_ORGANS, "TRAIT_HOLY" = TRAIT_HOLY, diff --git a/code/controllers/subsystem/sprite_accessories.dm b/code/controllers/subsystem/sprite_accessories.dm index ec5934ac8e8d4..f381df80df6da 100644 --- a/code/controllers/subsystem/sprite_accessories.dm +++ b/code/controllers/subsystem/sprite_accessories.dm @@ -35,7 +35,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity var/list/socks_list //! stores /datum/sprite_accessory/socks indexed by name //Lizard Bits (all datum lists indexed by name) - var/list/body_markings_list + var/list/lizard_markings_list var/list/snouts_list var/list/horns_list var/list/frills_list @@ -87,7 +87,7 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity socks_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/socks)[DEFAULT_SPRITE_LIST] - body_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings)[DEFAULT_SPRITE_LIST] + lizard_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/lizard_markings)[DEFAULT_SPRITE_LIST] tails_list_human = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey, add_blank = TRUE)[DEFAULT_SPRITE_LIST] diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 468882f0e86ec..efca8dd19b5cc 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -697,6 +697,13 @@ SUBSYSTEM_DEF(ticker) to_chat(world, span_boldannounce("Rebooting World in [DisplayTimeText(delay)]. [reason]")) + var/statspage = CONFIG_GET(string/roundstatsurl) + var/gamelogloc = CONFIG_GET(string/gamelogurl) + if(statspage) + to_chat(world, span_info("Round statistics and logs can be viewed at this website!")) + else if(gamelogloc) + to_chat(world, span_info("Round logs can be located at this website!")) + var/start_wait = world.time UNTIL(round_end_sound_sent || (world.time - start_wait) > (delay * 2)) //don't wait forever sleep(delay - (world.time - start_wait)) @@ -707,13 +714,6 @@ SUBSYSTEM_DEF(ticker) if(end_string) end_state = end_string - var/statspage = CONFIG_GET(string/roundstatsurl) - var/gamelogloc = CONFIG_GET(string/gamelogurl) - if(statspage) - to_chat(world, span_info("Round statistics and logs can be viewed at this website!")) - else if(gamelogloc) - to_chat(world, span_info("Round logs can be located at this website!")) - log_game(span_boldannounce("Rebooting World. [reason]")) world.Reboot() diff --git a/code/datums/bodypart_overlays/markings_bodypart_overlay.dm b/code/datums/bodypart_overlays/markings_bodypart_overlay.dm new file mode 100644 index 0000000000000..c2c6f54d861d3 --- /dev/null +++ b/code/datums/bodypart_overlays/markings_bodypart_overlay.dm @@ -0,0 +1,31 @@ +/// For body markings applied on the species, which need some extra code +/datum/bodypart_overlay/simple/body_marking + layers = EXTERNAL_ADJACENT + /// Listen to the gendercode, if the limb is bimorphic + var/use_gender = FALSE + /// Which dna feature key to draw from + var/dna_feature_key + /// Which bodyparts do we apply ourselves to? + var/list/applies_to = list(/obj/item/bodypart/head, /obj/item/bodypart/chest, /obj/item/bodypart/arm/left, /obj/item/bodypart/arm/right, \ + /obj/item/bodypart/leg/left, /obj/item/bodypart/leg/right) + +/// Get the accessory list from SSaccessories. Used in species.dm to get the right sprite +/datum/bodypart_overlay/simple/body_marking/proc/get_accessory(name) + CRASH("get_accessories() not overriden on [type] !") + +/datum/bodypart_overlay/simple/body_marking/get_image(layer, obj/item/bodypart/limb) + var/gender_string = (use_gender && limb.is_dimorphic) ? (limb.gender == MALE ? MALE : FEMALE + "_") : "" //we only got male and female sprites + return image(icon, gender_string + icon_state + "_" + limb.body_zone, layer = layer) + +/datum/bodypart_overlay/simple/body_marking/moth + dna_feature_key = "moth_markings" + +/datum/bodypart_overlay/simple/body_marking/moth/get_accessory(name) + return SSaccessories.moth_markings_list[name] + +/datum/bodypart_overlay/simple/body_marking/lizard + dna_feature_key = "lizard_markings" + applies_to = list(/obj/item/bodypart/chest) + +/datum/bodypart_overlay/simple/body_marking/lizard/get_accessory(name) + return SSaccessories.lizard_markings_list[name] diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 75fb406e3371e..d5677dad7ca61 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -207,8 +207,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_MUTANT_COLOR_BLOCK] = sanitize_hexcolor(features["mcolor"], include_crunch = FALSE) if(features["ethcolor"]) L[DNA_ETHEREAL_COLOR_BLOCK] = sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE) - if(features["body_markings"]) - L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(SSaccessories.body_markings_list.Find(features["body_markings"]), length(SSaccessories.body_markings_list)) + if(features["lizard_markings"]) + L[DNA_LIZARD_MARKINGS_BLOCK] = construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list)) if(features["tail_cat"]) L[DNA_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human)) if(features["tail_lizard"]) @@ -354,7 +354,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) if(DNA_ETHEREAL_COLOR_BLOCK) set_uni_feature_block(blocknumber, sanitize_hexcolor(features["ethcolor"], include_crunch = FALSE)) if(DNA_LIZARD_MARKINGS_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.body_markings_list.Find(features["body_markings"]), length(SSaccessories.body_markings_list))) + set_uni_feature_block(blocknumber, construct_block(SSaccessories.lizard_markings_list.Find(features["lizard_markings"]), length(SSaccessories.lizard_markings_list))) if(DNA_TAIL_BLOCK) set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human))) if(DNA_LIZARD_TAIL_BLOCK) @@ -423,7 +423,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /datum/dna/proc/update_instability(alert=TRUE) stability = 100 for(var/datum/mutation/human/M in mutations) - if(M.class == MUT_EXTRA) + if(M.class == MUT_EXTRA || M.instability < 0) stability -= M.instability * GET_MUTATION_STABILIZER(M) if(holder) var/message @@ -649,8 +649,8 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["mcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_MUTANT_COLOR_BLOCK)) if(dna.features["ethcolor"]) dna.features["ethcolor"] = sanitize_hexcolor(get_uni_feature_block(features, DNA_ETHEREAL_COLOR_BLOCK)) - if(dna.features["body_markings"]) - dna.features["body_markings"] = SSaccessories.body_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_MARKINGS_BLOCK), length(SSaccessories.body_markings_list))] + if(dna.features["lizard_markings"]) + dna.features["lizard_markings"] = SSaccessories.lizard_markings_list[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_MARKINGS_BLOCK), length(SSaccessories.lizard_markings_list))] if(dna.features["snout"]) dna.features["snout"] = SSaccessories.snouts_list[deconstruct_block(get_uni_feature_block(features, DNA_SNOUT_BLOCK), length(SSaccessories.snouts_list))] if(dna.features["horns"]) @@ -686,14 +686,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) external_organ.mutate_feature(features, src) if(icon_update) - if(mutcolor_update) - update_body(is_creating = TRUE) - else - update_body() + update_body(is_creating = mutcolor_update) if(mutations_overlay_update) update_mutations_overlay() - /mob/proc/domutcheck() return diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm index 4913a057e011a..95f59ade38c39 100644 --- a/code/datums/mutations/_mutations.dm +++ b/code/datums/mutations/_mutations.dm @@ -1,3 +1,23 @@ + +/// Negatives that are virtually harmless and mostly just funny (language) +// Set to 0 because munchkinning via miscommunication = bad +#define NEGATIVE_STABILITY_MINI 0 +/// Negatives that are slightly annoying (unused) +#define NEGATIVE_STABILITY_MINOR -20 +/// Negatives that present an uncommon or weak, consistent hindrance to gameplay (cough, paranoia) +#define NEGATIVE_STABILITY_MODERATE -30 +/// Negatives that present a major consistent hindrance to gameplay (deaf, mute, acid flesh) +#define NEGATIVE_STABILITY_MAJOR -40 + +/// Positives that provide basically no benefit (glowy) +#define POSITIVE_INSTABILITY_MINI 5 +/// Positives that are niche in application or useful in rare circumstances (parlor tricks, geladikinesis, autotomy) +#define POSITIVE_INSTABILITY_MINOR 10 +/// Positives that provide a new ability that's roughly par with station equipment (insulated, cryokinesis) +#define POSITIVE_INSTABILITY_MODERATE 25 +/// Positives that are unique, very powerful, and noticeably change combat/gameplay (hulk, tk) +#define POSITIVE_INSTABILITY_MAJOR 35 + /datum/mutation var/name diff --git a/code/datums/mutations/adaptation.dm b/code/datums/mutations/adaptation.dm index 1c183f9367d3a..2cac87dd4b4c4 100644 --- a/code/datums/mutations/adaptation.dm +++ b/code/datums/mutations/adaptation.dm @@ -4,7 +4,7 @@ quality = POSITIVE difficulty = 16 text_gain_indication = "Your body feels warm!" - instability = 25 + instability = POSITIVE_INSTABILITY_MAJOR conflicts = list(/datum/mutation/human/pressure_adaptation) /datum/mutation/human/temperature_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut) @@ -31,7 +31,7 @@ quality = POSITIVE difficulty = 16 text_gain_indication = "Your body feels numb!" - instability = 25 + instability = POSITIVE_INSTABILITY_MAJOR conflicts = list(/datum/mutation/human/temperature_adaptation) /datum/mutation/human/pressure_adaptation/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut) diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm index 80edceea1e5ed..fc1a94276f702 100644 --- a/code/datums/mutations/antenna.dm +++ b/code/datums/mutations/antenna.dm @@ -4,7 +4,7 @@ quality = POSITIVE text_gain_indication = "You feel an antenna sprout from your forehead." text_lose_indication = "Your antenna shrinks back down." - instability = 5 + instability = POSITIVE_INSTABILITY_MINOR difficulty = 8 var/datum/weakref/radio_weakref @@ -47,7 +47,7 @@ text_gain_indication = "You hear distant voices at the corners of your mind." text_lose_indication = "The distant voices fade." power_path = /datum/action/cooldown/spell/pointed/mindread - instability = 40 + instability = POSITIVE_INSTABILITY_MINOR difficulty = 8 locked = TRUE diff --git a/code/datums/mutations/autotomy.dm b/code/datums/mutations/autotomy.dm index 5a70455db5fb8..bb78ceb08dcf7 100644 --- a/code/datums/mutations/autotomy.dm +++ b/code/datums/mutations/autotomy.dm @@ -3,7 +3,7 @@ desc = "Allows a creature to voluntary discard a random appendage." quality = POSITIVE text_gain_indication = span_notice("Your joints feel loose.") - instability = 30 + instability = POSITIVE_INSTABILITY_MINOR power_path = /datum/action/cooldown/spell/self_amputation energy_coeff = 1 diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index 896820746d61d..eaa1ba1f5cafa 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -4,6 +4,7 @@ /datum/mutation/human/epilepsy name = "Epilepsy" desc = "A genetic defect that sporadically causes seizures." + instability = NEGATIVE_STABILITY_MODERATE quality = NEGATIVE text_gain_indication = "You get a headache." synchronizer_coeff = 1 @@ -50,6 +51,7 @@ /datum/mutation/human/bad_dna name = "Unstable DNA" desc = "Strange mutation that causes the holder to randomly mutate." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "You feel strange." locked = TRUE @@ -79,6 +81,7 @@ /datum/mutation/human/cough name = "Cough" desc = "A chronic cough." + instability = NEGATIVE_STABILITY_MODERATE quality = MINOR_NEGATIVE text_gain_indication = "You start coughing." synchronizer_coeff = 1 @@ -96,6 +99,7 @@ /datum/mutation/human/paranoia name = "Paranoia" desc = "Subject is easily terrified, and may suffer from hallucinations." + instability = NEGATIVE_STABILITY_MODERATE quality = NEGATIVE text_gain_indication = "You feel screams echo through your mind..." text_lose_indication = "The screaming in your mind fades." @@ -112,8 +116,8 @@ desc = "A mutation believed to be the cause of dwarfism." quality = POSITIVE difficulty = 16 - instability = 5 - conflicts = list(/datum/mutation/human/gigantism) + instability = POSITIVE_INSTABILITY_MINOR + conflicts = list(/datum/mutation/human/gigantism, /datum/mutation/human/acromegaly) locked = TRUE // Default intert species for now, so locked from regular pool. /datum/mutation/human/dwarfism/on_acquiring(mob/living/carbon/human/owner) @@ -128,10 +132,71 @@ REMOVE_TRAIT(owner, TRAIT_DWARF, GENETIC_MUTATION) owner.visible_message(span_danger("[owner] suddenly grows!"), span_notice("Everything around you seems to shrink..")) +/datum/mutation/human/acromegaly + name = "Acromegaly" + desc = "A mutation believed to be the cause of acromegaly, or 'being unusually tall'." + quality = MINOR_NEGATIVE + difficulty = 16 + instability = NEGATIVE_STABILITY_MODERATE + synchronizer_coeff = 1 + conflicts = list(/datum/mutation/human/dwarfism) + +/datum/mutation/human/acromegaly/on_acquiring(mob/living/carbon/human/owner) + if(..()) + return + ADD_TRAIT(owner, TRAIT_TOO_TALL, GENETIC_MUTATION) + owner.visible_message(span_danger("[owner] suddenly grows tall!"), span_notice("You feel a small strange urge to fight small men with slingshots. Or maybe play some basketball.")) + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(head_bonk)) + owner.regenerate_icons() + +/datum/mutation/human/acromegaly/on_losing(mob/living/carbon/human/owner) + if(..()) + return + REMOVE_TRAIT(owner, TRAIT_TOO_TALL, GENETIC_MUTATION) + owner.visible_message(span_danger("[owner] suddenly shrinks!"), span_notice("You return to your usual height.")) + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(head_bonk)) + owner.regenerate_icons() + +// This is specifically happening because they're not used to their new height and are stumbling around into machinery made for normal humans +/datum/mutation/human/acromegaly/proc/head_bonk(mob/living/parent) + SIGNAL_HANDLER + var/turf/airlock_turf = get_turf(parent) + var/atom/movable/whacked_by = locate(/obj/machinery/door/airlock) in airlock_turf || locate(/obj/machinery/door/firedoor) in airlock_turf || locate(/obj/structure/mineral_door) in airlock_turf + if(!whacked_by || prob(100 - (8 * GET_MUTATION_SYNCHRONIZER(src)))) + return + to_chat(parent, span_danger("You hit your head on \the [whacked_by]'s header!")) + var/dmg = HAS_TRAIT(parent, TRAIT_HEAD_INJURY_BLOCKED) ? rand(1,4) : rand(2,9) + parent.apply_damage(dmg, BRUTE, BODY_ZONE_HEAD) + parent.do_attack_animation(whacked_by, ATTACK_EFFECT_PUNCH) + playsound(whacked_by, 'sound/effects/bang.ogg', 10, TRUE) + parent.adjust_staggered_up_to(STAGGERED_SLOWDOWN_LENGTH, 10 SECONDS) + +/datum/mutation/human/gigantism + name = "Gigantism" //negative version of dwarfism + desc = "The cells within the subject spread out to cover more area, making the subject appear larger." + quality = MINOR_NEGATIVE + difficulty = 12 + conflicts = list(/datum/mutation/human/dwarfism) + +/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner) + if(..()) + return + ADD_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) + owner.update_transform(1.25) + owner.visible_message(span_danger("[owner] suddenly grows!"), span_notice("Everything around you seems to shrink..")) + +/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner) + if(..()) + return + REMOVE_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) + owner.update_transform(0.8) + owner.visible_message(span_danger("[owner] suddenly shrinks!"), span_notice("Everything around you seems to grow..")) + //Clumsiness has a very large amount of small drawbacks depending on item. /datum/mutation/human/clumsy name = "Clumsiness" desc = "A genome that inhibits certain brain functions, causing the holder to appear clumsy. Honk!" + instability = NEGATIVE_STABILITY_MAJOR quality = MINOR_NEGATIVE text_gain_indication = "You feel lightheaded." @@ -151,6 +216,7 @@ name = "Tourette's Syndrome" desc = "A chronic twitch that forces the user to scream bad words." //definitely needs rewriting quality = NEGATIVE + instability = 0 text_gain_indication = "You twitch." synchronizer_coeff = 1 @@ -173,6 +239,7 @@ /datum/mutation/human/deaf name = "Deafness" desc = "The holder of this genome is completely deaf." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "You can't seem to hear anything." @@ -194,6 +261,7 @@ text_gain_indication = "You feel unusually monkey-like." text_lose_indication = "You feel like your old self." quality = NEGATIVE + instability = NEGATIVE_STABILITY_MAJOR // mmmonky remove_on_aheal = FALSE locked = TRUE //Species specific, keep out of actual gene pool mutadone_proof = TRUE @@ -219,7 +287,7 @@ desc = "You permanently emit a light with a random color and intensity." quality = POSITIVE text_gain_indication = "Your skin begins to glow softly." - instability = 5 + instability = POSITIVE_INSTABILITY_MINI power_coeff = 1 conflicts = list(/datum/mutation/human/glow/anti) var/glow_power = 2 @@ -257,6 +325,7 @@ desc = "Your skin seems to attract and absorb nearby light creating 'darkness' around you." text_gain_indication = "The light around you seems to disappear." conflicts = list(/datum/mutation/human/glow) + instability = POSITIVE_INSTABILITY_MINOR locked = TRUE glow_power = -1.5 @@ -265,10 +334,10 @@ /datum/mutation/human/strong name = "Strength" - desc = "The user's muscles slightly expand." + desc = "The user's muscles slightly expand. Commonly seen in top-ranking boxers." quality = POSITIVE text_gain_indication = "You feel strong." - instability = 5 + instability = POSITIVE_INSTABILITY_MINI difficulty = 16 /datum/mutation/human/strong/on_acquiring(mob/living/carbon/human/owner) @@ -286,10 +355,11 @@ /datum/mutation/human/stimmed name = "Stimmed" - desc = "The user's chemical balance is more robust." + desc = "The user's chemical balance is more robust. This mutation is known to slightly improve workout efficiency." quality = POSITIVE + instability = POSITIVE_INSTABILITY_MINI text_gain_indication = "You feel stimmed." - instability = 5 + instability = 15 difficulty = 16 /datum/mutation/human/stimmed/on_acquiring(mob/living/carbon/human/owner) @@ -311,7 +381,7 @@ text_gain_indication = "Your fingertips go numb." text_lose_indication = "Your fingertips regain feeling." difficulty = 16 - instability = 25 + instability = POSITIVE_INSTABILITY_MODERATE /datum/mutation/human/insulated/on_acquiring(mob/living/carbon/human/owner) if(..()) @@ -355,7 +425,7 @@ text_gain_indication = "The space around you twists sickeningly." text_lose_indication = "The space around you settles back to normal." difficulty = 18//high so it's hard to unlock and abuse - instability = 10 + instability = NEGATIVE_STABILITY_MODERATE synchronizer_coeff = 1 energy_coeff = 1 power_coeff = 1 @@ -381,6 +451,7 @@ /datum/mutation/human/acidflesh name = "Acidic Flesh" desc = "Subject has acidic chemicals building up underneath the skin. This is often lethal." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "A horrible burning sensation envelops you as your flesh turns to acid!" text_lose_indication = "A feeling of relief fills you as your flesh goes back to normal." @@ -398,30 +469,10 @@ owner.visible_message(span_warning("[owner]'s skin bubbles and pops."), span_userdanger("Your bubbling flesh pops! It burns!")) playsound(owner,'sound/weapons/sear.ogg', 50, TRUE) -/datum/mutation/human/gigantism - name = "Gigantism"//negative version of dwarfism - desc = "The cells within the subject spread out to cover more area, making the subject appear larger." - quality = MINOR_NEGATIVE - difficulty = 12 - conflicts = list(/datum/mutation/human/dwarfism) - -/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner) - if(..()) - return - ADD_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) - owner.update_transform(1.25) - owner.visible_message(span_danger("[owner] suddenly grows!"), span_notice("Everything around you seems to shrink..")) - -/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner) - if(..()) - return - REMOVE_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) - owner.update_transform(0.8) - owner.visible_message(span_danger("[owner] suddenly shrinks!"), span_notice("Everything around you seems to grow..")) - /datum/mutation/human/spastic name = "Spastic" desc = "Subject suffers from muscle spasms." + instability = NEGATIVE_STABILITY_MODERATE quality = NEGATIVE text_gain_indication = "You flinch." text_lose_indication = "Your flinching subsides." @@ -440,6 +491,7 @@ /datum/mutation/human/extrastun name = "Two Left Feet" desc = "A mutation that replaces the right foot with another left foot. Symptoms include kissing the floor when taking a step." + instability = NEGATIVE_STABILITY_MODERATE quality = NEGATIVE text_gain_indication = "Your right foot feels... left." text_lose_indication = "Your right foot feels alright." @@ -471,6 +523,7 @@ /datum/mutation/human/martyrdom name = "Internal Martyrdom" desc = "A mutation that makes the body destruct when near death. Not damaging, but very, VERY disorienting." + instability = NEGATIVE_STABILITY_MAJOR // free stability >:) locked = TRUE quality = POSITIVE //not that cloning will be an option a lot but generally lets keep this around i guess? text_gain_indication = "You get an intense feeling of heartburn." @@ -518,6 +571,7 @@ /datum/mutation/human/headless name = "H.A.R.S." desc = "A mutation that makes the body reject the head, the brain receding into the chest. Stands for Head Allergic Rejection Syndrome. Warning: Removing this mutation is very dangerous, though it will regenerate non-vital head organs." + instability = NEGATIVE_STABILITY_MAJOR difficulty = 12 //pretty good for traitors quality = NEGATIVE //holy shit no eyes or tongue or ears text_gain_indication = "Something feels off." diff --git a/code/datums/mutations/chameleon.dm b/code/datums/mutations/chameleon.dm index d5cbc36d20a1f..e3ce8826a9438 100644 --- a/code/datums/mutations/chameleon.dm +++ b/code/datums/mutations/chameleon.dm @@ -6,7 +6,7 @@ difficulty = 16 text_gain_indication = "You feel one with your surroundings." text_lose_indication = "You feel oddly exposed." - instability = 25 + instability = POSITIVE_INSTABILITY_MAJOR power_coeff = 1 /datum/mutation/human/chameleon/on_acquiring(mob/living/carbon/human/owner) diff --git a/code/datums/mutations/cold.dm b/code/datums/mutations/cold.dm index 57c4f854fc7a2..32e162bf7d3a0 100644 --- a/code/datums/mutations/cold.dm +++ b/code/datums/mutations/cold.dm @@ -3,7 +3,7 @@ desc = "Allows the user to concentrate moisture and sub-zero forces into snow." quality = POSITIVE text_gain_indication = "Your hand feels cold." - instability = 10 + instability = POSITIVE_INSTABILITY_MINOR difficulty = 10 synchronizer_coeff = 1 power_path = /datum/action/cooldown/spell/conjure_item/snow @@ -25,7 +25,7 @@ desc = "Draws negative energy from the sub-zero void to freeze surrounding temperatures at subject's will." quality = POSITIVE //upsides and downsides text_gain_indication = "Your hand feels cold." - instability = 30 + instability = POSITIVE_INSTABILITY_MODERATE difficulty = 12 synchronizer_coeff = 1 energy_coeff = 1 diff --git a/code/datums/mutations/fire_breath.dm b/code/datums/mutations/fire_breath.dm index f8631761ba202..5836997729456 100644 --- a/code/datums/mutations/fire_breath.dm +++ b/code/datums/mutations/fire_breath.dm @@ -7,7 +7,7 @@ text_gain_indication = "Your throat is burning!" text_lose_indication = "Your throat is cooling down." power_path = /datum/action/cooldown/spell/cone/staggered/fire_breath - instability = 30 + instability = POSITIVE_INSTABILITY_MODERATE energy_coeff = 1 power_coeff = 1 diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 63e0abc22a33f..3fdc5de52ce2b 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -8,7 +8,7 @@ text_gain_indication = "Your muscles hurt!" species_allowed = list(SPECIES_HUMAN) //no skeleton/lizard hulk health_req = 25 - instability = 40 + instability = POSITIVE_INSTABILITY_MAJOR var/scream_delay = 50 var/last_scream = 0 /// List of traits to add/remove when someone gets this mutation. diff --git a/code/datums/mutations/olfaction.dm b/code/datums/mutations/olfaction.dm index 305f6d16e8389..f487702a3c6c8 100644 --- a/code/datums/mutations/olfaction.dm +++ b/code/datums/mutations/olfaction.dm @@ -6,7 +6,7 @@ text_gain_indication = "Smells begin to make more sense..." text_lose_indication = "Your sense of smell goes back to normal." power_path = /datum/action/cooldown/spell/olfaction - instability = 30 + instability = POSITIVE_INSTABILITY_MODERATE synchronizer_coeff = 1 /datum/mutation/human/olfaction/modify() @@ -119,6 +119,9 @@ /// Actually go through and give the user a hint of the direction our target is. /datum/action/cooldown/spell/olfaction/proc/on_the_trail(mob/living/caster) var/mob/living/carbon/current_target = tracking_ref?.resolve() + //Using get_turf to deal with those pesky closets that put your x y z to 0 + var/turf/current_target_turf = get_turf(current_target) + var/turf/caster_turf = get_turf(caster) if(!current_target) to_chat(caster, span_warning("You're not tracking a scent, but the game thought you were. \ Something's gone wrong! Report this as a bug.")) @@ -130,14 +133,14 @@ to_chat(caster, span_warning("You smell out the trail to yourself. Yep, it's you.")) return - if(caster.z < current_target.z) + if(caster_turf.z < current_target_turf.z) to_chat(caster, span_warning("The trail leads... way up above you? Huh. They must be really, really far away.")) return - else if(caster.z > current_target.z) + else if(caster_turf.z > current_target_turf.z) to_chat(caster, span_warning("The trail leads... way down below you? Huh. They must be really, really far away.")) return - var/direction_text = span_bold("[dir2text(get_dir(caster, current_target))]") + var/direction_text = span_bold("[dir2text(get_dir(caster_turf, current_target_turf))]") if(direction_text) to_chat(caster, span_notice("You consider [current_target]'s scent. The trail leads [direction_text].")) diff --git a/code/datums/mutations/passive.dm b/code/datums/mutations/passive.dm index 9d694aaf1ebbb..14135fe426ea4 100644 --- a/code/datums/mutations/passive.dm +++ b/code/datums/mutations/passive.dm @@ -2,7 +2,7 @@ name = "Biotech Compatibility" desc = "Subject is more compatibile with biotechnology such as skillchips." quality = POSITIVE - instability = 5 + instability = POSITIVE_INSTABILITY_MINI /datum/mutation/human/biotechcompat/on_acquiring(mob/living/carbon/human/owner) . = ..() @@ -16,7 +16,7 @@ name = "Clever" desc = "Causes the subject to feel just a little bit smarter. Most effective in specimens with low levels of intelligence." quality = POSITIVE - instability = 20 + instability = POSITIVE_INSTABILITY_MODERATE // literally makes you on par with station equipment text_gain_indication = "You feel a little bit smarter." text_lose_indication = "Your mind feels a little bit foggy." diff --git a/code/datums/mutations/radioactive.dm b/code/datums/mutations/radioactive.dm index 8f710bfa497a4..8700e405662a6 100644 --- a/code/datums/mutations/radioactive.dm +++ b/code/datums/mutations/radioactive.dm @@ -3,7 +3,7 @@ desc = "A volatile mutation that causes the host to sent out deadly beta radiation. This affects both the hosts and their surroundings." quality = NEGATIVE text_gain_indication = "You can feel it in your bones!" - instability = 5 + instability = NEGATIVE_STABILITY_MAJOR difficulty = 8 power_coeff = 1 /// Weakref to our radiation emitter component diff --git a/code/datums/mutations/sight.dm b/code/datums/mutations/sight.dm index 8b26f6ca268f0..66e307c247846 100644 --- a/code/datums/mutations/sight.dm +++ b/code/datums/mutations/sight.dm @@ -2,6 +2,7 @@ /datum/mutation/human/nearsight name = "Near Sightness" desc = "The holder of this mutation has poor eyesight." + instability = NEGATIVE_STABILITY_MODERATE quality = MINOR_NEGATIVE text_gain_indication = "You can't see very well." @@ -19,6 +20,7 @@ /datum/mutation/human/blind name = "Blindness" desc = "Renders the subject completely blind." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "You can't seem to see anything." @@ -40,7 +42,7 @@ difficulty = 18 text_gain_indication = "You can see the heat rising off of your skin..." text_lose_indication = "You can no longer see the heat rising off of your skin..." - instability = 25 + instability = POSITIVE_INSTABILITY_MAJOR // thermals aren't station equipment synchronizer_coeff = 1 power_coeff = 1 energy_coeff = 1 @@ -110,7 +112,7 @@ name = "X Ray Vision" desc = "A strange genome that allows the user to see between the spaces of walls." //actual x-ray would mean you'd constantly be blasting rads, wich might be fun for later //hmb text_gain_indication = "The walls suddenly disappear!" - instability = 35 + instability = POSITIVE_INSTABILITY_MAJOR locked = TRUE /datum/mutation/human/xray/on_acquiring(mob/living/carbon/human/owner) @@ -182,6 +184,7 @@ /datum/mutation/human/illiterate name = "Illiterate" desc = "Causes a severe case of Aphasia that prevents reading or writing." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "You feel unable to read or write." text_lose_indication = "You feel able to read and write again." diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm index 4c78c19610439..1400503dfc45d 100644 --- a/code/datums/mutations/speech.dm +++ b/code/datums/mutations/speech.dm @@ -4,6 +4,7 @@ /datum/mutation/human/nervousness name = "Nervousness" desc = "Causes the holder to stutter." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = "You feel nervous." @@ -14,6 +15,7 @@ /datum/mutation/human/wacky name = "Wacky" desc = "You are not a clown. You are the entire circus." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = "You feel an off sensation in your voicebox." text_lose_indication = "The off sensation passes." @@ -36,6 +38,7 @@ /datum/mutation/human/mute name = "Mute" desc = "Completely inhibits the vocal section of the brain." + instability = NEGATIVE_STABILITY_MAJOR quality = NEGATIVE text_gain_indication = "You feel unable to express yourself at all." text_lose_indication = "You feel able to speak freely again." @@ -53,6 +56,7 @@ /datum/mutation/human/unintelligible name = "Unintelligible" desc = "Partially inhibits the vocal center of the brain, severely distorting speech." + instability = NEGATIVE_STABILITY_MODERATE quality = NEGATIVE text_gain_indication = "You can't seem to form any coherent thoughts!" text_lose_indication = "Your mind feels more clear." @@ -70,6 +74,7 @@ /datum/mutation/human/swedish name = "Swedish" desc = "A horrible mutation originating from the distant past. Thought to be eradicated after the incident in 2037." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = "You feel Swedish, however that works." text_lose_indication = "The feeling of Swedishness passes." @@ -101,6 +106,7 @@ /datum/mutation/human/chav name = "Chav" desc = "Unknown" + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = "Ye feel like a reet prat like, innit?" text_lose_indication = "You no longer feel like being rude and sassy." @@ -138,6 +144,7 @@ /datum/mutation/human/elvis name = "Elvis" desc = "A terrifying mutation named after its 'patient-zero'." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE locked = TRUE text_gain_indication = "You feel pretty good, honeydoll." @@ -203,6 +210,7 @@ /datum/mutation/human/medieval name = "Medieval" desc = "A horrible mutation originating from the distant past, thought to have once been a common gene in all of old world Europe." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = "You feel like seeking the holy grail!" text_lose_indication = "You no longer feel like seeking anything." @@ -243,6 +251,7 @@ /datum/mutation/human/piglatin name = "Pig Latin" desc = "Historians say back in the 2020's humanity spoke entirely in this mystical language." + instability = NEGATIVE_STABILITY_MINI quality = MINOR_NEGATIVE text_gain_indication = span_notice("Omethingsay eelsfay offyay.") text_lose_indication = span_notice("The off sensation passes.") diff --git a/code/datums/mutations/telekinesis.dm b/code/datums/mutations/telekinesis.dm index 53d8beb56ff50..bd6ba13070df3 100644 --- a/code/datums/mutations/telekinesis.dm +++ b/code/datums/mutations/telekinesis.dm @@ -6,7 +6,7 @@ difficulty = 18 text_gain_indication = "You feel smarter!" limb_req = BODY_ZONE_HEAD - instability = 30 + instability = POSITIVE_INSTABILITY_MAJOR ///Typecache of atoms that TK shouldn't interact with var/static/list/blacklisted_atoms = typecacheof(list(/atom/movable/screen)) diff --git a/code/datums/mutations/telepathy.dm b/code/datums/mutations/telepathy.dm index 8619c2bddc476..0e3dffb48b4a4 100644 --- a/code/datums/mutations/telepathy.dm +++ b/code/datums/mutations/telepathy.dm @@ -6,5 +6,5 @@ text_lose_indication = "You don't hear your mind echo anymore." difficulty = 12 power_path = /datum/action/cooldown/spell/list_target/telepathy - instability = 10 + instability = POSITIVE_INSTABILITY_MINOR // basically a mediocre PDA messager energy_coeff = 1 diff --git a/code/datums/mutations/tongue_spike.dm b/code/datums/mutations/tongue_spike.dm index e6249041250b8..9e25ad6f4f296 100644 --- a/code/datums/mutations/tongue_spike.dm +++ b/code/datums/mutations/tongue_spike.dm @@ -3,7 +3,7 @@ desc = "Allows a creature to voluntary shoot their tongue out as a deadly weapon." quality = POSITIVE text_gain_indication = span_notice("Your feel like you can throw your voice.") - instability = 15 + instability = POSITIVE_INSTABILITY_MINI // worthless. also serves as a bit of a hint that it's not good power_path = /datum/action/cooldown/spell/tongue_spike energy_coeff = 1 @@ -89,7 +89,7 @@ desc = "Allows a creature to voluntary shoot their tongue out as biomass, allowing a long range transfer of chemicals." quality = POSITIVE text_gain_indication = span_notice("Your feel like you can really connect with people by throwing your voice.") - instability = 15 + instability = POSITIVE_INSTABILITY_MINOR // slightly less worthless. slightly. locked = TRUE power_path = /datum/action/cooldown/spell/tongue_spike/chem energy_coeff = 1 diff --git a/code/datums/mutations/touch.dm b/code/datums/mutations/touch.dm index ca94f109ac664..eaa4909703525 100644 --- a/code/datums/mutations/touch.dm +++ b/code/datums/mutations/touch.dm @@ -7,7 +7,7 @@ text_gain_indication = "You feel power flow through your hands." text_lose_indication = "The energy in your hands subsides." power_path = /datum/action/cooldown/spell/touch/shock - instability = 35 + instability = POSITIVE_INSTABILITY_MODERATE // bad stun baton energy_coeff = 1 power_coeff = 1 diff --git a/code/datums/mutations/void_magnet.dm b/code/datums/mutations/void_magnet.dm index 48f04eda636a7..b5c893e32c547 100644 --- a/code/datums/mutations/void_magnet.dm +++ b/code/datums/mutations/void_magnet.dm @@ -3,7 +3,7 @@ desc = "A rare genome that attracts odd forces not usually observed." quality = MINOR_NEGATIVE //upsides and downsides text_gain_indication = span_notice("You feel a heavy, dull force just beyond the walls watching you.") - instability = 30 + instability = POSITIVE_INSTABILITY_MODERATE // useful, but has large drawbacks power_path = /datum/action/cooldown/spell/void/cursed energy_coeff = 1 synchronizer_coeff = 1 diff --git a/code/datums/mutations/webbing.dm b/code/datums/mutations/webbing.dm index 0fda118d0ed60..002687d55be0f 100644 --- a/code/datums/mutations/webbing.dm +++ b/code/datums/mutations/webbing.dm @@ -4,7 +4,7 @@ desc = "Allows the user to lay webbing, and travel through it." quality = POSITIVE text_gain_indication = "Your skin feels webby." - instability = 15 + instability = POSITIVE_INSTABILITY_MODERATE // useful until you're lynched power_path = /datum/action/cooldown/mob_cooldown/lay_web/genetic energy_coeff = 1 diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index e6e8b956e6568..e5cf49475e22e 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -1700,24 +1700,24 @@ // MutantParts Definitions // ///////////////////////////// -/datum/sprite_accessory/body_markings - icon = 'icons/mob/human/species/lizard/lizard_misc.dmi' +/datum/sprite_accessory/lizard_markings + icon = 'icons/mob/human/species/lizard/lizard_markings.dmi' -/datum/sprite_accessory/body_markings/none +/datum/sprite_accessory/lizard_markings/none name = "None" icon_state = "none" -/datum/sprite_accessory/body_markings/dtiger +/datum/sprite_accessory/lizard_markings/dtiger name = "Dark Tiger Body" icon_state = "dtiger" gender_specific = TRUE -/datum/sprite_accessory/body_markings/ltiger +/datum/sprite_accessory/lizard_markings/ltiger name = "Light Tiger Body" icon_state = "ltiger" gender_specific = TRUE -/datum/sprite_accessory/body_markings/lbelly +/datum/sprite_accessory/lizard_markings/lbelly name = "Light Belly" icon_state = "lbelly" gender_specific = TRUE diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index c9e94e0dd97f5..3d4bd7e93655c 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -31,7 +31,7 @@ SIGNAL_HANDLER if(istype(attacking_item, /obj/item/kinetic_crusher)) - total_damage += damage_dealt + total_damage += (-1 * damage_dealt) /datum/status_effect/syphon_mark id = "syphon_mark" diff --git a/code/game/machinery/civilian_bounties.dm b/code/game/machinery/civilian_bounties.dm index e5cd81cc965a1..fa0d28c999c88 100644 --- a/code/game/machinery/civilian_bounties.dm +++ b/code/game/machinery/civilian_bounties.dm @@ -168,7 +168,7 @@ return inserted_scan_id.registered_account.civilian_bounty = inserted_scan_id.registered_account.bounties[choice] inserted_scan_id.registered_account.bounties = null - SSblackbox.record_feedback("tally", "bounties_assigned", 1, choice.type) + SSblackbox.record_feedback("tally", "bounties_assigned", 1, inserted_scan_id.registered_account.civilian_bounty.type) return inserted_scan_id.registered_account.civilian_bounty /obj/machinery/computer/piratepad_control/civilian/click_alt(mob/user) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index f0d7b2e30eb52..9028d6d367d91 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -1,5 +1,20 @@ -/// Base timeout for creating mutation activators and other injectors -#define INJECTOR_TIMEOUT 100 +/// Base timeout for creating mutation activators +#define MIN_ACTIVATOR_TIMEOUT 5 SECONDS +/// Base cooldown multiplier for activator upgrades +#define ACTIVATOR_COOLDOWN_MULTIPLIER 0.25 +/// Base timeout for creating mutation injectors +#define MIN_INJECTOR_TIMEOUT 10 SECONDS +/// Base cooldown multiplier for injecotr upgrades +#define INJECTOR_COOLDOWN_MULTIPLIER 0.15 + +/// Base timeout for creating advanced injectors +#define MIN_ADVANCED_TIMEOUT 15 SECONDS +/// Base cooldown multiplier for advanced injector upgrades +#define ADVANCED_COOLDOWN_MULTIPLIER 0.1 + +/// Used for other things like UI/UE/Initial CD +#define MISC_INJECTOR_TIMEOUT 60 SECONDS + /// Maximum number of genetic makeup storage slots in DNA Console #define NUMBER_OF_BUFFERS 3 /// Timeout for DNA Scramble in DNA Consoles @@ -221,7 +236,7 @@ connect_to_scanner() // Set appropriate ready timers and limits for machines functions - injector_ready = world.time + INJECTOR_TIMEOUT + injector_ready = world.time + MISC_INJECTOR_TIMEOUT scramble_ready = world.time + SCRAMBLE_TIMEOUT joker_ready = world.time + JOKER_TIMEOUT COOLDOWN_START(src, enzyme_copy_timer, ENZYME_COPY_BASE_COOLDOWN) @@ -816,21 +831,33 @@ I.research = TRUE // If there's an operational connected scanner, we can use its upgrades // to improve our injector's genetic damage generation + var/cd_reduction_mult = 1 + ACTIVATOR_COOLDOWN_MULTIPLIER + var/base_cd_time = max(MIN_ACTIVATOR_TIMEOUT, abs(HM.instability) SECONDS) + if(scanner_operational()) I.damage_coeff = connected_scanner.damage_coeff*4 - injector_ready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected_scanner.precision_coeff) - else - injector_ready = world.time + INJECTOR_TIMEOUT + // T1: 1.25 - 0.25: 1: 100% + // T4: 1.25 - 1: 0.25 = 25% + // 25% reduction per tier + cd_reduction_mult -= ACTIVATOR_COOLDOWN_MULTIPLIER * (connected_scanner.precision_coeff) + + injector_ready = world.time + (base_cd_time * cd_reduction_mult) else I.name = "[HM.name] mutator" - I.doitanyway = TRUE + I.force_mutate = TRUE // If there's an operational connected scanner, we can use its upgrades // to improve our injector's genetic damage generation + var/cd_reduction_mult = 1 + INJECTOR_COOLDOWN_MULTIPLIER + var/base_cd_time = max(MIN_INJECTOR_TIMEOUT, abs(HM.instability) * 1 SECONDS) + if(scanner_operational()) - I.damage_coeff = connected_scanner.damage_coeff - injector_ready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected_scanner.precision_coeff) - else - injector_ready = world.time + INJECTOR_TIMEOUT * 5 + I.damage_coeff = connected_scanner.damage_coeff*4 + // T1: 1.15 - 0.15: 1: 100% + // T4: 1.15 - 0.60: 0.55: 55% + // 15% reduction per tier + cd_reduction_mult -= (INJECTOR_COOLDOWN_MULTIPLIER * connected_scanner.precision_coeff) + + injector_ready = world.time + (base_cd_time * cd_reduction_mult) if(connected_scanner) connected_scanner.use_energy(connected_scanner.active_power_usage) else @@ -1349,7 +1376,7 @@ // If we successfully created an injector, don't forget to set the new // ready timer. if(I) - injector_ready = world.time + INJECTOR_TIMEOUT + injector_ready = world.time + MISC_INJECTOR_TIMEOUT if(connected_scanner) connected_scanner.use_energy(connected_scanner.active_power_usage) else @@ -1538,22 +1565,29 @@ // Run through each mutation in our Advanced Injector and add them to a // new injector + var/total_stability for(var/A in injector) var/datum/mutation/human/HM = A I.add_mutations += new HM.type(copymut=HM) + total_stability += HM.instability // Force apply any mutations, this is functionality similar to mutators - I.doitanyway = TRUE + I.force_mutate = TRUE I.name = "Advanced [inj_name] injector" // If there's an operational connected scanner, we can use its upgrades // to improve our injector's genetic damage generation + var/cd_reduction_mult = 1 + ADVANCED_COOLDOWN_MULTIPLIER + var/base_cd_time = max(MIN_ADVANCED_TIMEOUT, abs(total_stability) SECONDS) + if(scanner_operational()) - I.damage_coeff = connected_scanner.damage_coeff - injector_ready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected_scanner.precision_coeff) - else - injector_ready = world.time + INJECTOR_TIMEOUT * 8 + I.damage_coeff = connected_scanner.damage_coeff*4 + // T1: 1.1 - 0.1: 1: 100% + // T4: 1.1 - 0.4: 0.7 = 70% + // 10% reduction per tier + cd_reduction_mult -= ADVANCED_COOLDOWN_MULTIPLIER * (connected_scanner.precision_coeff) + injector_ready = world.time + (base_cd_time * cd_reduction_mult) return // Adds a mutation to an advanced injector @@ -2299,11 +2333,20 @@ SIGNAL_HANDLER set_connected_scanner(null) +#undef MIN_ACTIVATOR_TIMEOUT +#undef ACTIVATOR_COOLDOWN_MULTIPLIER +#undef MIN_INJECTOR_TIMEOUT +#undef INJECTOR_COOLDOWN_MULTIPLIER + +#undef MIN_ADVANCED_TIMEOUT +#undef ADVANCED_COOLDOWN_MULTIPLIER + +#undef MISC_INJECTOR_TIMEOUT + #undef GENETIC_DAMAGE_PULSE_UNIQUE_IDENTITY #undef GENETIC_DAMAGE_PULSE_UNIQUE_FEATURES #undef ENZYME_COPY_BASE_COOLDOWN -#undef INJECTOR_TIMEOUT #undef NUMBER_OF_BUFFERS #undef SCRAMBLE_TIMEOUT #undef JOKER_TIMEOUT diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index 4775642881fcc..cb0ab9900d5cc 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -11,9 +11,9 @@ circuit = /obj/item/circuitboard/machine/dnascanner var/locked = FALSE - var/damage_coeff + var/damage_coeff = 1 var/scan_level - var/precision_coeff + var/precision_coeff = 1 var/message_cooldown var/breakout_time = 1200 var/obj/machinery/computer/scan_consolenew/linked_console = null diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index ae37691f1c1a1..37310e2aceb49 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -601,7 +601,11 @@ if(!machine_stat) update_icon(ALL, AIRLOCK_DENY) playsound(src,doorDeni,50,FALSE,3) - addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon), ALL, AIRLOCK_CLOSED), AIRLOCK_DENY_ANIMATION_TIME) + addtimer(CALLBACK(src, PROC_REF(handle_deny_end)), AIRLOCK_DENY_ANIMATION_TIME) + +/obj/machinery/door/airlock/proc/handle_deny_end() + if(airlock_state == AIRLOCK_DENY) + update_icon(ALL, AIRLOCK_CLOSED) /obj/machinery/door/airlock/examine(mob/user) . = ..() diff --git a/code/game/machinery/flatpacker.dm b/code/game/machinery/flatpacker.dm index 1eb8f6e2cc5cb..9468dacc24c56 100644 --- a/code/game/machinery/flatpacker.dm +++ b/code/game/machinery/flatpacker.dm @@ -231,6 +231,10 @@ materials.retrieve_sheets(amount, ejecting, drop_location()) return TRUE +/obj/machinery/flatpacker/screwdriver_act(mob/living/user, obj/item/tool) + . = ITEM_INTERACT_BLOCKING + if(default_deconstruction_screwdriver(user, icon_state, icon_state, tool)) + return ITEM_INTERACT_SUCCESS /obj/machinery/flatpacker/Destroy() QDEL_NULL(inserted_board) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index d977605b2436f..b99c8000c58a4 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -444,6 +444,7 @@ beauty = -50 clean_type = CLEAN_TYPE_BLOOD mouse_opacity = MOUSE_OPACITY_OPAQUE + resistance_flags = UNACIDABLE | ACID_PROOF | FIRE_PROOF | FLAMMABLE //gross way of doing this but would need to disassemble fire_act call stack otherwise /// Maximum amount of hotspots this pool can create before deleting itself var/burn_amount = 3 /// Is this fuel pool currently burning? @@ -453,6 +454,10 @@ /obj/effect/decal/cleanable/fuel_pool/Initialize(mapload, burn_stacks) . = ..() + var/static/list/ignition_trigger_connections = list( + COMSIG_TURF_MOVABLE_THROW_LANDED = PROC_REF(ignition_trigger), + ) + AddElement(/datum/element/connect_loc, ignition_trigger_connections) for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf if(pool == src) continue @@ -509,6 +514,26 @@ ignite() return ..() +/obj/effect/decal/cleanable/fuel_pool/on_entered(datum/source, atom/movable/entered_atom) + . = ..() + if(entered_atom.throwing) // don't light from things being thrown over us, we handle that somewhere else + return + ignition_trigger(source = src, enflammable_atom = entered_atom) + +/obj/effect/decal/cleanable/fuel_pool/proc/ignition_trigger(datum/source, atom/movable/enflammable_atom) + SIGNAL_HANDLER + + if(isitem(enflammable_atom)) + var/obj/item/enflamed_item = enflammable_atom + if(enflamed_item.get_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) + ignite() + return + else if(isliving(enflammable_atom)) + var/mob/living/enflamed_liver = enflammable_atom + if(enflamed_liver.on_fire) + ignite() + + /obj/effect/decal/cleanable/fuel_pool/hivis icon_state = "fuel_pool_hivis" diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 874c53fa83c7d..f9bb819fd42a1 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -26,24 +26,65 @@ return INITIALIZE_HINT_LATELOAD /obj/effect/particle_effect/sparks/LateInitialize() + RegisterSignals(src, list(COMSIG_MOVABLE_CROSS, COMSIG_MOVABLE_CROSS_OVER), PROC_REF(sparks_touched)) flick(icon_state, src) playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - var/turf/T = loc - if(isturf(T)) - T.hotspot_expose(1000,100) + var/turf/location = loc + if(isturf(location)) + affect_location(location, just_initialized = TRUE) QDEL_IN(src, 20) /obj/effect/particle_effect/sparks/Destroy() - var/turf/T = loc - if(isturf(T)) - T.hotspot_expose(1000,100) + var/turf/location = loc + if(isturf(location)) + affect_location(location) return ..() /obj/effect/particle_effect/sparks/Move() ..() - var/turf/T = loc - if(isturf(T)) - T.hotspot_expose(1000,100) + var/turf/location = loc + if(isturf(location)) + affect_location(location) + +/* +* Apply the effects of this spark to its location. +* +* When the spark is first created, Cross() and Crossed() don't get called, +* so for the first initialization, we make sure to specifically invoke the +* behavior of the spark on all the mobs and objects in the location. +* turf/location - The place the spark is affectiong +* just_initialized - If the spark is just being created, and we need to manually affect everything in the location +*/ +/obj/effect/particle_effect/sparks/proc/affect_location(turf/location, just_initialized = FALSE) + location.hotspot_expose(1000,100) + if(just_initialized) + for(var/atom/movable/singed in location) + sparks_touched(src, singed) + +/* +* This is called when anything passes through the same tiles as a spark, or when a spark passes through something's tile. +* +* This is invoked by the signals sent by every atom when they're crossed or crossing something. It +* signifies that something has been touched by sparks, and should be affected by possible pyrotechnic affects.. +* datum/source - Can either be the spark itself or an object that just walked into it +* mob/living/singed_mob - The mob that was touched by the spark +*/ +/obj/effect/particle_effect/sparks/proc/sparks_touched(datum/source, atom/movable/singed) + SIGNAL_HANDLER + + if(isobj(singed)) + var/obj/singed_obj = singed + if(singed_obj.resistance_flags & FLAMMABLE && !(singed_obj.resistance_flags & ON_FIRE)) //only fire_act flammable objects instead of burning EVERYTHING + singed_obj.fire_act(1,100) + if(singed_obj.reagents) + var/datum/reagents/reagents = singed_obj.reagents + reagents?.expose_temperature(1000) + return + if(isliving(singed)) + var/mob/living/singed_living = singed + if(singed_living.fire_stacks) + singed_living.ignite_mob(FALSE) //ignite the mob, silent = FALSE (You're set on fire!) + return /datum/effect_system/spark_spread effect_type = /obj/effect/particle_effect/sparks diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 174a8fde5f7c2..6ca951d262a67 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -282,7 +282,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM var/obj/item/reagent_containers/cup/glass = interacting_with if(!istype(glass)) //you can dip cigarettes into beakers return NONE - + if(istype(glass, /obj/item/reagent_containers/cup/mortar)) + return NONE if(glass.reagents.trans_to(src, chem_volume, transferred_by = user)) //if reagents were transferred, show the message to_chat(user, span_notice("You dip \the [src] into \the [glass].")) //if not, either the beaker was empty, or the cigarette was full diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index c3203a0ace7a9..598c16c9041a8 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -211,6 +211,7 @@ it explodes properly when it gets a signal (and it does). */ /obj/item/transfer_valve/proc/toggle_valve(obj/item/tank/target, change_volume = TRUE) + playsound(src, 'sound/effects/valve_opening.ogg', 50) if(!valve_open && tank_one && tank_two) var/turf/bombturf = get_turf(src) diff --git a/code/game/objects/items/dna_injector.dm b/code/game/objects/items/dna_injector.dm index 0dc20c6dbb4d9..8fee497a4f9ee 100644 --- a/code/game/objects/items/dna_injector.dm +++ b/code/game/objects/items/dna_injector.dm @@ -163,7 +163,7 @@ /obj/item/dnainjector/activator name = "\improper DNA activator" desc = "Activates the current mutation on injection, if the subject has it." - var/doitanyway = FALSE + var/force_mutate = FALSE var/research = FALSE //Set to true to get expended and filled injectors for chromosomes var/filled = FALSE var/crispr_charge = FALSE // Look for viruses, look at symptoms, if research and Dormant DNA Activator or Viral Evolutionary Acceleration, set to true @@ -176,7 +176,7 @@ if(istype(added_mutation, /datum/mutation/human)) mutation = added_mutation.type if(!target.dna.activate_mutation(added_mutation)) - if(doitanyway) + if(force_mutate) target.dna.add_mutation(added_mutation, MUT_EXTRA) else if(research && target.client) filled = TRUE @@ -184,7 +184,7 @@ for(var/datum/symptom/symp in disease.symptoms) if((symp.type == /datum/symptom/genetic_mutation) || (symp.type == /datum/symptom/viralevolution)) crispr_charge = TRUE - log_combat(user, target, "[!doitanyway ? "failed to inject" : "injected"]", "[src] ([mutation])[crispr_charge ? " with CRISPR charge" : ""]") + log_combat(user, target, "[!force_mutate ? "failed to inject" : "injected"]", "[src] ([mutation])[crispr_charge ? " with CRISPR charge" : ""]") return TRUE /// DNA INJECTORS diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index be47d7009053b..ac309e275d77c 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -32,7 +32,11 @@ /// Can we refill this at a water tank? var/refilling = FALSE /// What tank we need to refill this. - var/tanktype = /obj/structure/reagent_dispensers/watertank + var/tanktypes = list( + /obj/structure/reagent_dispensers/watertank, + /obj/structure/reagent_dispensers/plumbed, + /obj/structure/reagent_dispensers/water_cooler, + ) /// something that should be replaced with base_icon_state var/sprite_name = "fire_extinguisher" /// Maximum distance launched water will travel. @@ -131,7 +135,10 @@ tank_holder_icon_state = "holder_foam_extinguisher" dog_fashion = null chem = /datum/reagent/firefighting_foam - tanktype = /obj/structure/reagent_dispensers/foamtank + tanktypes = list( + /obj/structure/reagent_dispensers/foamtank, + /obj/structure/reagent_dispensers/plumbed, + ) sprite_name = "foam_extinguisher" precision = TRUE max_water = 100 @@ -178,10 +185,14 @@ . += span_notice("Alt-click to empty it.") /obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user) - if(istype(target, tanktype) && target.Adjacent(user)) + if(is_type_in_list(target, tanktypes) && target.Adjacent(user)) if(reagents.total_volume == reagents.maximum_volume) balloon_alert(user, "already full!") return TRUE + // Make sure we're refilling with the proper chem. + if(!(target.reagents.has_reagent(chem))) + balloon_alert(user, "can't refill with this liquid!") + return TRUE var/obj/structure/reagent_dispensers/W = target //will it work? var/transferred = W.reagents.trans_to(src, max_water, transferred_by = user) if(transferred > 0) @@ -305,5 +316,8 @@ name = "fire extender" desc = "A traditional red fire extinguisher. Made in Britain... wait, what?" chem = /datum/reagent/fuel - tanktype = /obj/structure/reagent_dispensers/fueltank + tanktypes = list( + /obj/structure/reagent_dispensers/fueltank, + /obj/structure/reagent_dispensers/plumbed + ) cooling_power = 0 diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index 5deb833b1f234..ec16b4c22fe95 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -16,7 +16,6 @@ flags_1 = PREVENT_CONTENTS_EXPLOSION_1 // We detonate upon being exploded. obj_flags = CONDUCTS_ELECTRICITY slot_flags = ITEM_SLOT_BELT - resistance_flags = FLAMMABLE max_integrity = 40 /// Bitfields which prevent the grenade from detonating if set. Includes ([GRENADE_DUD]|[GRENADE_USED]) var/dud_flags = NONE diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 2d886163a50ba..1a695442d8a76 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -425,6 +425,7 @@ . = ..() if(!.) return . + ADD_TRAIT(cyborg, TRAIT_FASTMED, REF(src)) for(var/obj/item/borg/cyborg_omnitool/medical/omnitool_upgrade in cyborg.model.modules) if(omnitool_upgrade.upgraded) to_chat(user, span_warning("This unit is already equipped with an omnitool upgrade!")) @@ -436,6 +437,7 @@ . = ..() if(!.) return . + REMOVE_TRAIT(cyborg, TRAIT_FASTMED, REF(src)) for(var/obj/item/borg/cyborg_omnitool/omnitool in cyborg.model.modules) omnitool.downgrade_omnitool() diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 7b6d4b6207340..662f94c61d5e1 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -347,6 +347,12 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new /datum/stack_recipe("pew (left)", /obj/structure/chair/pew/left, 3, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE), new /datum/stack_recipe("pew (right)", /obj/structure/chair/pew/right, 3, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_FURNITURE) )), + new/datum/stack_recipe_list("peg limbs", list( + new /datum/stack_recipe("peg arm (left)", /obj/item/bodypart/arm/left/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg arm (right)", /obj/item/bodypart/arm/right/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg leg (left)", /obj/item/bodypart/leg/left/ghetto, 2, crafting_flags = NONE, category = CAT_MISC), + new /datum/stack_recipe("peg leg (right)", /obj/item/bodypart/leg/right/ghetto, 2, crafting_flags = NONE, category = CAT_MISC) + )), null, \ )) @@ -377,6 +383,21 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ /obj/item/stack/sheet/mineral/wood/fifty amount = 50 +/obj/item/stack/sheet/mineral/wood/interact_with_atom(mob/living/carbon/human/target, mob/user) + if(!istype(target)) + return NONE + + var/obj/item/bodypart/affecting = target.get_bodypart(check_zone(user.zone_selected)) + if(affecting && IS_PEG_LIMB(affecting)) + if(user == target) + user.visible_message(span_notice("[user] starts to fix their [affecting.name]."), span_notice("You start fixing [target == user ? "your" : "[target]'s"] [affecting.name].")) + if(!do_after(user, 5 SECONDS, target)) + return ITEM_INTERACT_FAILURE + if(target.item_heal(user, brute_heal = 15, burn_heal = 15, heal_message_brute = "splintering", heal_message_burn = "charring", required_bodytype = BODYTYPE_PEG)) + use(1) + return ITEM_INTERACT_SUCCESS + else + return NONE /* * Bamboo */ diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 0e9b9743a4593..b2b0109c04c88 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -160,7 +160,7 @@ if(!use_tool(attacked_humanoid, user, use_delay, volume=50, amount=1)) return ITEM_INTERACT_BLOCKING - item_heal_robotic(attacked_humanoid, user, 15, 0) + attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC) return ITEM_INTERACT_SUCCESS /obj/item/weldingtool/afterattack(atom/target, mob/user, click_parameters) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm index 32f3eb7419ced..aeb14c9b5dd28 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/valve.dm @@ -25,6 +25,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off. normalize_cardinal_directions() if(animation) flick("[valve_type]valve_[on][!on]-[set_overlay_offset(piping_layer)]", src) + playsound(src, 'sound/effects/valve_opening.ogg', 50) icon_state = "[valve_type]valve_[on ? "on" : "off"]-[set_overlay_offset(piping_layer)]" /** @@ -37,6 +38,7 @@ It's like a regular ol' straight pipe, but you can turn it on and off. . = on on = to_open if(on) + playsound(src, 'sound/effects/gas_hissing.ogg', 50) update_icon_nopipes() update_parents() var/datum/pipeline/parent1 = parents[1] diff --git a/code/modules/bitrunning/designs.dm b/code/modules/bitrunning/designs.dm index 4e7bca1c1a8dd..96ae65d41e99b 100644 --- a/code/modules/bitrunning/designs.dm +++ b/code/modules/bitrunning/designs.dm @@ -72,16 +72,3 @@ RND_CATEGORY_COMPUTER + RND_SUBCATEGORY_COMPUTER_CARGO ) departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING - - -/datum/techweb_node/bitrunning - id = "bitrunning" - display_name = "Bitrunning Technology" - description = "Bluespace technology has led to the development of quantum-scale computing, which unlocks the means to materialize atomic structures while executing advanced programs." - prereq_ids = list("practical_bluespace") - design_ids = list( - "byteforge", - "quantum_console", - "netpod", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/buildmode/buildmode.dm b/code/modules/buildmode/buildmode.dm index 36a3db07f597e..80f5ae1ad27b0 100644 --- a/code/modules/buildmode/buildmode.dm +++ b/code/modules/buildmode/buildmode.dm @@ -50,6 +50,8 @@ holder.player_details.post_login_callbacks -= li_cb li_cb = null holder = null + modebutton = null + dirbutton = null QDEL_NULL(mode) QDEL_LIST(buttons) QDEL_LIST(modeswitch_buttons) diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index 6c62ed1d054c2..485276b4ade2a 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -112,6 +112,10 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /// will show the feature as selectable. var/relevant_mutant_bodypart = null + /// If the selected species has this in its /datum/species/body_markings, + /// will show the feature as selectable. + var/relevant_body_markings = null + /// If the selected species has this in its /datum/species/inherent_traits, /// will show the feature as selectable. var/relevant_inherent_trait = null @@ -333,6 +337,7 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) || !isnull(relevant_inherent_trait) \ || !isnull(relevant_external_organ) \ || !isnull(relevant_head_flag) \ + || !isnull(relevant_body_markings) \ ) var/species_type = preferences.read_preference(/datum/preference/choiced/species) diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm index bee57300ec4a4..38c83690b3b5e 100644 --- a/code/modules/client/preferences/species_features/lizard.dm +++ b/code/modules/client/preferences/species_features/lizard.dm @@ -29,20 +29,20 @@ category = PREFERENCE_CATEGORY_FEATURES main_feature_name = "Body markings" should_generate_icons = TRUE - relevant_mutant_bodypart = "body_markings" + relevant_body_markings = /datum/bodypart_overlay/simple/body_marking/lizard /datum/preference/choiced/lizard_body_markings/init_possible_values() - return assoc_to_keys_features(SSaccessories.body_markings_list) + return assoc_to_keys_features(SSaccessories.lizard_markings_list) /datum/preference/choiced/lizard_body_markings/icon_for(value) - var/datum/sprite_accessory/sprite_accessory = SSaccessories.body_markings_list[value] + var/datum/sprite_accessory/sprite_accessory = SSaccessories.lizard_markings_list[value] var/icon/final_icon = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_chest_m") if (sprite_accessory.icon_state != "none") var/icon/body_markings_icon = icon( 'icons/mob/human/species/lizard/lizard_misc.dmi', - "m_body_markings_[sprite_accessory.icon_state]_ADJ", + "male_[sprite_accessory.icon_state]_chest", ) final_icon.Blend(body_markings_icon, ICON_OVERLAY) @@ -55,7 +55,7 @@ return final_icon /datum/preference/choiced/lizard_body_markings/apply_to_human(mob/living/carbon/human/target, value) - target.dna.features["body_markings"] = value + target.dna.features["lizard_markings"] = value /datum/preference/choiced/lizard_frills savefile_key = "feature_lizard_frills" diff --git a/code/modules/client/preferences/species_features/moth.dm b/code/modules/client/preferences/species_features/moth.dm index 745e6fb917b8f..f697d857d4fc4 100644 --- a/code/modules/client/preferences/species_features/moth.dm +++ b/code/modules/client/preferences/species_features/moth.dm @@ -34,7 +34,7 @@ category = PREFERENCE_CATEGORY_FEATURES main_feature_name = "Body markings" should_generate_icons = TRUE - relevant_mutant_bodypart = "moth_markings" + relevant_body_markings = /datum/bodypart_overlay/simple/body_marking/moth /datum/preference/choiced/moth_markings/init_possible_values() return assoc_to_keys_features(SSaccessories.moth_markings_list) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index cd32002d0434b..98184b3fce25e 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -360,7 +360,7 @@ . = ..() if(href_list["list_armor"]) - var/list/readout = list("PROTECTION CLASSES") + var/list/readout = list() var/datum/armor/armor = get_armor() var/added_damage_header = FALSE @@ -369,9 +369,9 @@ if(!rating) continue if(!added_damage_header) - readout += "\nARMOR (I-X)" + readout += "ARMOR (I-X)" added_damage_header = TRUE - readout += "\n[armor_to_protection_name(damage_key)] [armor_to_protection_class(rating)]" + readout += "[armor_to_protection_name(damage_key)] [armor_to_protection_class(rating)]" var/added_durability_header = FALSE for(var/durability_key in ARMOR_LIST_DURABILITY()) @@ -379,9 +379,9 @@ if(!rating) continue if(!added_durability_header) - readout += "\nDURABILITY (I-X)" + readout += "DURABILITY (I-X)" added_damage_header = TRUE - readout += "\n[armor_to_protection_name(durability_key)] [armor_to_protection_class(rating)]" + readout += "[armor_to_protection_name(durability_key)] [armor_to_protection_class(rating)]" if(flags_cover & HEADCOVERSMOUTH || flags_cover & PEPPERPROOF) var/list/things_blocked = list() @@ -390,12 +390,15 @@ if(flags_cover & PEPPERPROOF) things_blocked += "pepperspray" if(length(things_blocked)) - readout += "\nCOVERAGE" - readout += "\nIt will block [english_list(things_blocked)]." + readout += "COVERAGE" + readout += "It will block [english_list(things_blocked)]." - readout += "" - to_chat(usr, "[readout.Join()]") + if(!length(readout)) + readout += "No armor or durability information available." + + var/formatted_readout = span_notice("PROTECTION CLASSES
[jointext(readout, "\n")]") + to_chat(usr, examine_block(formatted_readout)) /** * Rounds armor_value down to the nearest 10, divides it by 10 and then converts it to Roman numerals. diff --git a/code/modules/clothing/suits/reactive_armour.dm b/code/modules/clothing/suits/reactive_armour.dm index 155e4dbe42fb6..c1889cc77383d 100644 --- a/code/modules/clothing/suits/reactive_armour.dm +++ b/code/modules/clothing/suits/reactive_armour.dm @@ -5,8 +5,8 @@ icon = 'icons/obj/clothing/suits/armor.dmi' w_class = WEIGHT_CLASS_BULKY -/obj/item/reactive_armor_shell/attackby(obj/item/weapon, mob/user, params) - ..() +/obj/item/reactive_armor_shell/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + . = ..() var/static/list/anomaly_armour_types = list( /obj/effect/anomaly/grav = /obj/item/clothing/suit/armor/reactive/repulse, /obj/effect/anomaly/flux = /obj/item/clothing/suit/armor/reactive/tesla, @@ -17,15 +17,16 @@ /obj/effect/anomaly/ectoplasm = /obj/item/clothing/suit/armor/reactive/ectoplasm, ) - if(istype(weapon, /obj/item/assembly/signaler/anomaly)) - var/obj/item/assembly/signaler/anomaly/anomaly = weapon - var/armour_path = anomaly_armour_types[anomaly.anomaly_type] + if(istype(tool, /obj/item/assembly/signaler/anomaly)) + var/obj/item/assembly/signaler/anomaly/anomaly = tool + var/armour_path = is_path_in_list(anomaly.anomaly_type, anomaly_armour_types, TRUE) if(!armour_path) armour_path = /obj/item/clothing/suit/armor/reactive/stealth //Lets not cheat the player if an anomaly type doesnt have its own armour coded to_chat(user, span_notice("You insert [anomaly] into the chest plate, and the armour gently hums to life.")) new armour_path(get_turf(src)) qdel(src) qdel(anomaly) + return ITEM_INTERACT_SUCCESS //Reactive armor /obj/item/clothing/suit/armor/reactive diff --git a/code/modules/experisci/experiment/experiments.dm b/code/modules/experisci/experiment/experiments.dm index 3434fb6fdb1ed..f0915bdbf77cd 100644 --- a/code/modules/experisci/experiment/experiments.dm +++ b/code/modules/experisci/experiment/experiments.dm @@ -118,6 +118,14 @@ experiment_proper = TRUE required_gas = /datum/gas/nitrous_oxide +/datum/experiment/ordnance/gaseous/plasma + name = "Plasma Gas Shells" + description = "The delivery of Plasma gas into an area of operation might prove useful. Pack the specified gas into a tank and burst it using a Tank Compressor. Publish the data in a paper." + gain = list(10,40) + target_amount = list(200,600) + experiment_proper = TRUE + required_gas = /datum/gas/plasma + /datum/experiment/ordnance/gaseous/bz name = "BZ Gas Shells" description = "The delivery of BZ gas into an area of operation might prove useful. Pack the specified gas into a tank and burst it using a Tank Compressor. Publish the data in a paper." @@ -315,7 +323,7 @@ required_stock_part = /obj/item/stock_parts/micro_laser/ultra /datum/experiment/scanning/random/mecha_damage_scan - name = "Exosuit Materials 1: Stress Failure Test" + name = "Exosuit Materials: Stress Failure Test" description = "Your exosuit fabricators allow for rapid production on a small scale, but the structural integrity of created parts is inferior to more traditional means." exp_tag = "Scan" possible_types = list(/obj/vehicle/sealed/mecha) @@ -324,7 +332,7 @@ var/damage_percent /datum/experiment/scanning/random/mecha_equipped_scan - name = "Exosuit Materials 2: Load Strain Test" + name = "Exosuit Materials: Load Strain Test" description = "Exosuit equipment places unique strain upon the structure of the vehicle. Scan exosuits you have assembled from your exosuit fabricator and fully equipped to accelerate our structural stress simulations." possible_types = list(/obj/vehicle/sealed/mecha) total_requirement = 2 @@ -368,3 +376,80 @@ continue return TRUE return FALSE + +/// Scan for cybernetic organs +/datum/experiment/scanning/people/augmented_organs + name = "Human Field Research: Augmented Organs" + description = "We need to gather data on how cybernetic vital organs integrate with human biology. Conduct a scan on a human with these implants to help us understand their compatibility" + performance_hint = "Perform an organ manipulation surgery to replace one of the vital organs with a cybernetic variant." + required_traits_desc = "augmented vital organs" + +/datum/experiment/scanning/people/augmented_organs/is_valid_scan_target(mob/living/carbon/human/check) + . = ..() + if (!.) + return + var/static/list/vital_organ_slots = list( + ORGAN_SLOT_HEART, + ORGAN_SLOT_LUNGS, + ORGAN_SLOT_EYES, + ORGAN_SLOT_EARS, + ORGAN_SLOT_LIVER, + ORGAN_SLOT_STOMACH, + ) + + for (var/obj/item/organ/organ as anything in check.organs) + if (IS_ORGANIC_ORGAN(organ)) + continue + if (!(organ.slot in vital_organ_slots)) + continue + return TRUE + return FALSE + +/// Scan for skillchips +/datum/experiment/scanning/people/skillchip + name = "Human Field Research: Skill Chip Implants" + description = "Before sticking programmed circuits into human brain, we need to know how it handles simple ones. Scan a live person with a skill chip implant in their brain." + performance_hint = "Perform a skill chip implantation with a skill station." + required_traits_desc = "skill chip implant" + +/datum/experiment/scanning/people/skillchip/is_valid_scan_target(mob/living/carbon/human/check, datum/component/experiment_handler/experiment_handler) + . = ..() + if (!.) + return + var/obj/item/organ/internal/brain/scanned_brain = check.get_organ_slot(ORGAN_SLOT_BRAIN) + if (isnull(scanned_brain)) + experiment_handler.announce_message("Subject is brainless!") + return FALSE + if (scanned_brain.get_used_skillchip_slots() == 0) + experiment_handler.announce_message("No skill chips found!") + return FALSE + return TRUE + +/datum/experiment/scanning/reagent/cryostylane + name = "Pure Cryostylane Scan" + description = "It appears that the Cryostylane reagent can potentially halt all physiological processes in the human body. Produce Cryostylane with at least 99% purity and scan the beaker." + required_reagent = /datum/reagent/cryostylane + min_purity = 0.99 + +/datum/experiment/scanning/bluespace_crystal + name = "Bluespace Crystal Sampling" + description = "Investigate the properties of bluespace crystals by scanning either an artificial or naturally occurring variant. This will help us deepen our understanding of bluespace phenomena." + required_atoms = list(/obj/item/stack/ore/bluespace_crystal = 1) + +/datum/experiment/scanning/points/machinery_tiered_scan/tier2_any + name = "Upgraded Stock Parts Benchmark" + description = "Our newly-designed machinery components require practical application tests for hints at possible further advancements, as well as a general confirmation that we didn't actually design worse parts somehow. Scan any machinery with Upgraded Parts and report the results." + required_points = 8 + required_atoms = list( + /obj/machinery = 1 + ) + required_tier = 2 + +/datum/experiment/scanning/points/machinery_tiered_scan/tier3_any + name = "Advanced Stock Parts Benchmark" + description = "Our newly-designed machinery components require practical application tests for hints at possible further advancements, as well as a general confirmation that we didn't actually design worse parts somehow. Scan any machinery with Advanced Parts and report the results." + required_points = 8 + required_atoms = list( + /obj/machinery = 1 + ) + required_tier = 3 diff --git a/code/modules/experisci/experiment/types/scanning_people.dm b/code/modules/experisci/experiment/types/scanning_people.dm index 379d7e9089524..c3879e2a8d32c 100644 --- a/code/modules/experisci/experiment/types/scanning_people.dm +++ b/code/modules/experisci/experiment/types/scanning_people.dm @@ -18,15 +18,15 @@ return FALSE if(!ishuman(target)) return FALSE - return is_valid_scan_target(target) + return is_valid_scan_target(target, experiment_handler) /// Checks that the passed mob is valid human to scan -/datum/experiment/scanning/people/proc/is_valid_scan_target(mob/living/carbon/human/check) +/datum/experiment/scanning/people/proc/is_valid_scan_target(mob/living/carbon/human/check, datum/component/experiment_handler/experiment_handler) SHOULD_CALL_PARENT(TRUE) if(!mind_required || !isnull(check.mind)) return TRUE if(isliving(usr)) - check.balloon_alert(usr, "subject is mindless!") + experiment_handler.announce_message("Subject is mindless!") return FALSE /datum/experiment/scanning/people/serialize_progress_stage(atom/target, list/seen_instances) diff --git a/code/modules/experisci/experiment/types/scanning_reagent.dm b/code/modules/experisci/experiment/types/scanning_reagent.dm new file mode 100644 index 0000000000000..1a39e2941efeb --- /dev/null +++ b/code/modules/experisci/experiment/types/scanning_reagent.dm @@ -0,0 +1,35 @@ +/// An experiment where you scan a container with a specified reagent of certain purity +/datum/experiment/scanning/reagent + exp_tag = "Reagent Scan" + allowed_experimentors = list(/obj/item/experi_scanner, /obj/item/scanner_wand) + required_atoms = list(/obj/item/reagent_containers = 1) + /// The reagent required to present in the scanned container + var/datum/reagent/required_reagent = /datum/reagent/water + /// The minimum required purity of required_reagent + var/min_purity = 0 + +/datum/experiment/scanning/reagent/final_contributing_index_checks(datum/component/experiment_handler/experiment_handler, atom/target, typepath) + . = ..() + if(!.) + return FALSE + if(!is_reagent_container(target)) + return FALSE + return is_valid_scan_target(experiment_handler, target) + +/datum/experiment/scanning/reagent/proc/is_valid_scan_target(datum/component/experiment_handler/experiment_handler, obj/item/reagent_containers/container) + SHOULD_CALL_PARENT(TRUE) + if (container.reagents.total_volume == 0) + experiment_handler.announce_message("Container empty!") + return FALSE + var/datum/reagent/master_reagent = container.reagents.get_master_reagent() + if (master_reagent.type != required_reagent) + experiment_handler.announce_message("Reagent not found!") + return FALSE + if (master_reagent.purity < min_purity) + experiment_handler.announce_message("Purity too low!") + return FALSE + return TRUE + +/datum/experiment/scanning/reagent/serialize_progress_stage(atom/target, list/seen_instances) + return EXPERIMENT_PROG_INT("Scan a reagent container with [required_reagent::name] of at least [PERCENT(min_purity)] purity.", \ + seen_instances.len, required_atoms[target]) diff --git a/code/modules/experisci/experiment/types/scanning_vatgrown.dm b/code/modules/experisci/experiment/types/scanning_vatgrown.dm index f4578fdf41238..0a7ade381a4ea 100644 --- a/code/modules/experisci/experiment/types/scanning_vatgrown.dm +++ b/code/modules/experisci/experiment/types/scanning_vatgrown.dm @@ -3,7 +3,7 @@ description = "Base experiment for scanning atoms that were vatgrown" exp_tag = "Cytology Scan" total_requirement = 1 - possible_types = list(/mob/living/basic/cockroach) + possible_types = list(/mob/living/basic/slime) traits = EXPERIMENT_TRAIT_DESTRUCTIVE /datum/experiment/scanning/random/cytology/final_contributing_index_checks(datum/component/experiment_handler/experiment_handler, atom/target, typepath) diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index f4ae3548fa659..0bbf15352318d 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -755,7 +755,7 @@ "wings" = "None", "frills" = "None", "spines" = "Long", - "body_markings" = "Dark Tiger Body", + "lizard_markings" = "Dark Tiger Body", "legs" = DIGITIGRADE_LEGS, ) consumer.eye_color_left = "#FEE5A3" diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 556a959e4f8eb..3c02de4707317 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -984,8 +984,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp game.ui_interact(usr) /mob/dead/observer/CtrlShiftClickOn(atom/target) - if(check_rights(R_SPAWN)) - change_mob_type(/mob/living/carbon/human , null, null, TRUE) //always delmob, ghosts shouldn't be left lingering + if(isobserver(target) && check_rights(R_SPAWN)) + var/mob/dead/observer/target_ghost = target + + target_ghost.change_mob_type(/mob/living/carbon/human , null, null, TRUE) //always delmob, ghosts shouldn't be left lingering /mob/dead/observer/examine(mob/user) . = ..() diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm index b2aff7371a426..ce363af236465 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla.dm @@ -55,7 +55,7 @@ /mob/living/basic/gorilla/Initialize(mapload) . = ..() - add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT) + add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP, TRAIT_CHUNKYFINGERS), ROUNDSTART_TRAIT) AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE) AddElement(/datum/element/dextrous) AddElement(/datum/element/footstep, FOOTSTEP_MOB_BAREFOOT) diff --git a/code/modules/mob/living/basic/slime/slime.dm b/code/modules/mob/living/basic/slime/slime.dm index 4864cb82016a7..fa40ac28d816d 100644 --- a/code/modules/mob/living/basic/slime/slime.dm +++ b/code/modules/mob/living/basic/slime/slime.dm @@ -187,6 +187,8 @@ /mob/living/basic/slime/regenerate_icons() cut_overlays() + if(slime_type.transparent) + alpha = SLIME_TRANSPARENCY_ALPHA var/icon_text = "[slime_type.colour]-[life_stage]" icon_dead = "[icon_text]-dead" if(stat != DEAD) diff --git a/code/modules/mob/living/basic/slime/slime_type.dm b/code/modules/mob/living/basic/slime/slime_type.dm index 11f3798804017..048f861eeb08a 100644 --- a/code/modules/mob/living/basic/slime/slime_type.dm +++ b/code/modules/mob/living/basic/slime/slime_type.dm @@ -1,6 +1,8 @@ /datum/slime_type ///Our slime's colour as text. Used by both description, and icon var/colour + ///Whether the slime icons should be semi-transparent + var/transparent = FALSE ///The type our slime spawns var/core_type ///The possible mutations of our slime @@ -12,6 +14,7 @@ /datum/slime_type/grey colour = SLIME_TYPE_GREY + transparent = TRUE core_type = /obj/item/slime_extract/grey mutations = list( /datum/slime_type/blue = 1, @@ -21,11 +24,11 @@ ) rgb_code = COLOR_SLIME_GREY - //TIER 1 /datum/slime_type/blue colour = SLIME_TYPE_BLUE + transparent = TRUE core_type = /obj/item/slime_extract/blue mutations = list( /datum/slime_type/darkblue = 1, @@ -46,6 +49,7 @@ /datum/slime_type/purple colour = SLIME_TYPE_PURPLE + transparent = TRUE core_type = /obj/item/slime_extract/purple mutations = list( /datum/slime_type/darkblue = 1, @@ -56,6 +60,7 @@ /datum/slime_type/orange colour = SLIME_TYPE_ORANGE + transparent = TRUE core_type = /obj/item/slime_extract/orange mutations = list( /datum/slime_type/darkpurple = 1, @@ -68,6 +73,7 @@ /datum/slime_type/darkblue colour = SLIME_TYPE_DARK_BLUE + transparent = TRUE core_type = /obj/item/slime_extract/darkblue mutations = list( /datum/slime_type/blue = 1, @@ -98,6 +104,7 @@ /datum/slime_type/yellow colour = SLIME_TYPE_YELLOW + transparent = TRUE core_type = /obj/item/slime_extract/yellow mutations = list( /datum/slime_type/bluespace = 2, @@ -119,6 +126,7 @@ /datum/slime_type/cerulean colour = SLIME_TYPE_CERULEAN + transparent = TRUE core_type = /obj/item/slime_extract/cerulean mutations = list( /datum/slime_type/cerulean = 1, @@ -135,6 +143,7 @@ /datum/slime_type/sepia colour = SLIME_TYPE_SEPIA + transparent = TRUE core_type = /obj/item/slime_extract/sepia mutations = list( /datum/slime_type/sepia = 1, @@ -154,6 +163,7 @@ /datum/slime_type/green colour = SLIME_TYPE_GREEN + transparent = TRUE core_type = /obj/item/slime_extract/green mutations = list( /datum/slime_type/black = 1, @@ -163,6 +173,7 @@ /datum/slime_type/pink colour = SLIME_TYPE_PINK + transparent = TRUE core_type = /obj/item/slime_extract/pink mutations = list( /datum/slime_type/lightpink = 1, @@ -172,6 +183,7 @@ /datum/slime_type/red colour = SLIME_TYPE_RED + transparent = TRUE core_type = /obj/item/slime_extract/red mutations = list( /datum/slime_type/oil = 1, @@ -191,6 +203,7 @@ /datum/slime_type/black colour = SLIME_TYPE_BLACK + transparent = TRUE core_type = /obj/item/slime_extract/black mutations = list( /datum/slime_type/black = 1, @@ -199,6 +212,7 @@ /datum/slime_type/lightpink colour = SLIME_TYPE_LIGHT_PINK + transparent = TRUE core_type = /obj/item/slime_extract/lightpink mutations = list( /datum/slime_type/lightpink = 1, @@ -217,6 +231,7 @@ /datum/slime_type/rainbow colour = SLIME_TYPE_RAINBOW + transparent = TRUE core_type = /obj/item/slime_extract/rainbow mutations = list( /datum/slime_type/rainbow = 1, diff --git a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm index be31e121249a6..2286f65b79758 100644 --- a/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm +++ b/code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm @@ -77,6 +77,11 @@ buffet = new(src) buffet.Grant(src) +/mob/living/basic/space_dragon/Destroy() + fire_breath = null + buffet = null + return ..() + /mob/living/basic/space_dragon/Login() . = ..() if(!isnull(chosen_colour)) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index b9dca314b5189..d5d048a33f844 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -102,6 +102,9 @@ GLOBAL_LIST_EMPTY(features_by_species) ///Replaces default appendix with a different organ. var/obj/item/organ/internal/appendix/mutantappendix = /obj/item/organ/internal/appendix + /// Store body marking defines. See mobs.dm for bitflags + var/list/body_markings = list() + /// Flat modifier on all damage taken via [apply_damage][/mob/living/proc/apply_damage] (so being punched, shot, etc.) /// IE: 10 = 10% less damage taken. var/damage_modifier = 0 @@ -466,7 +469,7 @@ GLOBAL_LIST_EMPTY(features_by_species) var/obj/item/organ/external/new_organ = SSwardrobe.provide_type(organ_path) new_organ.Insert(human, special=TRUE, movement_flags = DELETE_IF_REPLACED) - + add_body_markings(human_who_gained_species) if(length(inherent_traits)) human_who_gained_species.add_traits(inherent_traits, SPECIES_TRAIT) @@ -526,6 +529,8 @@ GLOBAL_LIST_EMPTY(features_by_species) clear_tail_moodlets(C) + remove_body_markings(C) + // Removes all languages previously associated with [LANGUAGE_SPECIES], gaining our new species will add new ones back var/datum/language_holder/losing_holder = GLOB.prototype_language_holders[species_language_holder] for(var/language in losing_holder.understood_languages) @@ -560,42 +565,6 @@ GLOBAL_LIST_EMPTY(features_by_species) eye_organ.refresh(call_update = FALSE) standing += eye_organ.generate_body_overlay(species_human) - // organic body markings (oh my god this is terrible please rework this to be done on the limbs themselves i beg you) - if(HAS_TRAIT(species_human, TRAIT_HAS_MARKINGS)) - var/obj/item/bodypart/chest/chest = species_human.get_bodypart(BODY_ZONE_CHEST) - var/obj/item/bodypart/arm/right/right_arm = species_human.get_bodypart(BODY_ZONE_R_ARM) - var/obj/item/bodypart/arm/left/left_arm = species_human.get_bodypart(BODY_ZONE_L_ARM) - var/obj/item/bodypart/leg/right/right_leg = species_human.get_bodypart(BODY_ZONE_R_LEG) - var/obj/item/bodypart/leg/left/left_leg = species_human.get_bodypart(BODY_ZONE_L_LEG) - var/datum/sprite_accessory/markings = SSaccessories.moth_markings_list[species_human.dna.features["moth_markings"]] - var/mutable_appearance/marking = mutable_appearance(layer = -BODY_LAYER, appearance_flags = KEEP_TOGETHER) - - if(noggin && (IS_ORGANIC_LIMB(noggin))) - var/mutable_appearance/markings_head_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_head") - marking.overlays += markings_head_overlay - - if(chest && (IS_ORGANIC_LIMB(chest))) - var/mutable_appearance/markings_chest_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_chest") - marking.overlays += markings_chest_overlay - - if(right_arm && (IS_ORGANIC_LIMB(right_arm))) - var/mutable_appearance/markings_r_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_r_arm") - marking.overlays += markings_r_arm_overlay - - if(left_arm && (IS_ORGANIC_LIMB(left_arm))) - var/mutable_appearance/markings_l_arm_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_l_arm") - marking.overlays += markings_l_arm_overlay - - if(right_leg && (IS_ORGANIC_LIMB(right_leg))) - var/mutable_appearance/markings_r_leg_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_r_leg") - marking.overlays += markings_r_leg_overlay - - if(left_leg && (IS_ORGANIC_LIMB(left_leg))) - var/mutable_appearance/markings_l_leg_overlay = mutable_appearance(markings.icon, "[markings.icon_state]_l_leg") - marking.overlays += markings_l_leg_overlay - - standing += marking - //Underwear, Undershirts & Socks if(!HAS_TRAIT(species_human, TRAIT_NO_UNDERWEAR)) if(species_human.underwear) @@ -672,8 +641,6 @@ GLOBAL_LIST_EMPTY(features_by_species) switch(bodypart) if("ears") accessory = SSaccessories.ears_list[source.dna.features["ears"]] - if("body_markings") - accessory = SSaccessories.body_markings_list[source.dna.features["body_markings"]] if("legs") accessory = SSaccessories.legs_list[source.dna.features["legs"]] @@ -727,6 +694,8 @@ GLOBAL_LIST_EMPTY(features_by_species) source.apply_overlay(BODY_ADJ_LAYER) source.apply_overlay(BODY_FRONT_LAYER) + update_body_markings(source) + //This exists so sprite accessories can still be per-layer without having to include that layer's //number in their sprite name, which causes issues when those numbers change. /datum/species/proc/mutant_bodyparts_layertext(layer) @@ -1519,6 +1488,7 @@ GLOBAL_LIST_EMPTY(features_by_species) || (preference.relevant_inherent_trait in inherent_traits) \ || (preference.relevant_external_organ in external_organs) \ || (preference.relevant_head_flag && check_head_flags(preference.relevant_head_flag)) \ + || (preference.relevant_body_markings in body_markings) \ ) features += preference.savefile_key @@ -2110,3 +2080,48 @@ GLOBAL_LIST_EMPTY(features_by_species) return fixed_mut_color return null + +/// Add species appropriate body markings +/datum/species/proc/add_body_markings(mob/living/carbon/human/hooman) + for(var/markings_type in body_markings) //loop through possible species markings + var/datum/bodypart_overlay/simple/body_marking/markings = new markings_type() // made to die... mostly because we cant use initial on lists but its convenient and organized + var/accessory_name = hooman.dna.features[markings.dna_feature_key] //get the accessory name from dna + var/datum/sprite_accessory/moth_markings/accessory = markings.get_accessory(accessory_name) //get the actual datum + + if(isnull(accessory)) + CRASH("Value: [accessory_name] did not have a corresponding sprite accessory!") + + for(var/obj/item/bodypart/part as anything in markings.applies_to) //check through our limbs + var/obj/item/bodypart/people_part = hooman.get_bodypart(initial(part.body_zone)) // and see if we have a compatible marking for that limb + + if(!people_part) + continue + + var/datum/bodypart_overlay/simple/body_marking/overlay = new markings_type () + + // Tell the overlay what it should look like + overlay.icon = accessory.icon + overlay.icon_state = accessory.icon_state + overlay.use_gender = accessory.gender_specific + overlay.draw_color = accessory.color_src ? hooman.dna.features["mcolor"] : null + + people_part.add_bodypart_overlay(overlay) + +/// Remove body markings +/datum/species/proc/remove_body_markings(mob/living/carbon/human/hooman) + for(var/obj/item/bodypart/part as anything in hooman.bodyparts) + for(var/datum/bodypart_overlay/simple/body_marking/marking in part.bodypart_overlays) + part.remove_bodypart_overlay(marking) + +/// Update the overlays if necessary +/datum/species/proc/update_body_markings(mob/living/carbon/human/hooman) + var/needs_update = FALSE + for(var/datum/bodypart_overlay/simple/body_marking/marking as anything in body_markings) + if(initial(marking.dna_feature_key) == body_markings[marking]) // dna is same as our species (sort of mini-cache), so no update needed + continue + needs_update = TRUE + break + + if(needs_update) + remove_body_markings(hooman) + add_body_markings(hooman) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 627745cba929e..8d62ed5907948 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -103,7 +103,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) /proc/create_consistent_human_dna(mob/living/carbon/human/target) target.dna.features["mcolor"] = COLOR_VIBRANT_LIME target.dna.features["ethcolor"] = COLOR_WHITE - target.dna.features["body_markings"] = get_consistent_feature_entry(SSaccessories.body_markings_list) + target.dna.features["lizard_markings"] = get_consistent_feature_entry(SSaccessories.lizard_markings_list) target.dna.features["ears"] = get_consistent_feature_entry(SSaccessories.ears_list) target.dna.features["frills"] = get_consistent_feature_entry(SSaccessories.frills_list) target.dna.features["horns"] = get_consistent_feature_entry(SSaccessories.horns_list) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index da2c057d740bb..52ffe51bfe68b 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -293,6 +293,11 @@ return MONKEY_HEIGHT_DWARF else return HUMAN_HEIGHT_DWARF + if(HAS_TRAIT(src, TRAIT_TOO_TALL)) + if(ismonkey(src)) + return MONKEY_HEIGHT_TALL + else + return HUMAN_HEIGHT_TALLEST else if(ismonkey(src)) return MONKEY_HEIGHT_MEDIUM @@ -360,3 +365,30 @@ var/damage = ((min_damage / 4) + (max_damage / 4)) / 2 // We expect you to have 4 functional limbs- if you have fewer you're probably not going to be so good at lifting return ceil(damage * (ceil(athletics_level / 2)) * fitness_modifier * maxHealth) + +/mob/living/carbon/human/proc/item_heal(mob/user, brute_heal, burn_heal, heal_message_brute, heal_message_burn, required_bodytype) + var/obj/item/bodypart/affecting = src.get_bodypart(check_zone(user.zone_selected)) + if (!affecting || !(affecting.bodytype == required_bodytype)) + to_chat(user, span_warning("[affecting] is already in good condition!")) + return FALSE + + var/brute_damaged = affecting.brute_dam > 0 + var/burn_damaged = affecting.burn_dam > 0 + + var/nothing_to_heal = ((brute_heal <= 0 || !brute_damaged) && (burn_heal <= 0 || !burn_damaged)) + if (nothing_to_heal) + to_chat(user, span_notice("[affecting] is already in good condition!")) + return FALSE + + src.update_damage_overlays() + var/message + if ((brute_damaged && brute_heal > 0) && (burn_damaged && burn_heal > 0)) + message = "[heal_message_brute] and [heal_message_burn] on" + else if (brute_damaged && brute_heal > 0) + message = "[heal_message_brute] on" + else + message = "[heal_message_burn] on" + affecting.heal_damage(brute_heal, burn_heal, required_bodytype) + user.visible_message(span_notice("[user] fixes some of the [message] [src]'s [affecting.name]."), \ + span_notice("You fix some of the [message] [src == user ? "your" : "[src]'s"] [affecting.name].")) + return TRUE diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index bd320079b65d5..fe5817eab2780 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -864,20 +864,34 @@ generate/load female uniform sprites matching all previously decided variables "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 4), ), )) + if(HUMAN_HEIGHT_DWARF) // tall monkeys and dwarves use the same value + if(ismonkey(src)) + appearance.add_filters(list( + list( + "name" = "Monkey_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 1), + ), + list( + "name" = "Monkey_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 1), + ), + )) + else + appearance.add_filters(list( + list( + "name" = "Gnome_Cut_Torso", + "priority" = 1, + "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 2), + ), + list( + "name" = "Gnome_Cut_Legs", + "priority" = 1, + "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 3), + ), + )) // Don't set this one directly, use TRAIT_DWARF - if(HUMAN_HEIGHT_DWARF) - appearance.add_filters(list( - list( - "name" = "Gnome_Cut_Torso", - "priority" = 1, - "params" = displacement_map_filter(cut_torso_mask, x = 0, y = 0, size = 2), - ), - list( - "name" = "Gnome_Cut_Legs", - "priority" = 1, - "params" = displacement_map_filter(cut_legs_mask, x = 0, y = 0, size = 3), - ), - )) if(HUMAN_HEIGHT_SHORTEST) appearance.add_filters(list( list( diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index b2a036a9d6d71..ba813901b3e87 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -8,7 +8,8 @@ TRAIT_TACKLING_TAILED_DEFENDER, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE - mutant_bodyparts = list("body_markings" = "None", "legs" = "Normal Legs") + mutant_bodyparts = list("legs" = "Normal Legs") + body_markings = list(/datum/bodypart_overlay/simple/body_marking/lizard = "None") external_organs = list( /obj/item/organ/external/horns = "None", /obj/item/organ/external/frills = "None", @@ -49,7 +50,7 @@ /datum/species/lizard/randomize_features() var/list/features = ..() - features["body_markings"] = pick(SSaccessories.body_markings_list) + features["lizard_markings"] = pick(SSaccessories.lizard_markings_list) return features /datum/species/lizard/get_scream_sound(mob/living/carbon/human/lizard) diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index e2458563b038c..26efe358221fc 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -3,12 +3,11 @@ plural_form = "Mothmen" id = SPECIES_MOTH inherent_traits = list( - TRAIT_HAS_MARKINGS, TRAIT_TACKLING_WINGED_ATTACKER, TRAIT_ANTENNAE, ) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG - mutant_bodyparts = list("moth_markings" = "None") + body_markings = list(/datum/bodypart_overlay/simple/body_marking/moth = "None") external_organs = list(/obj/item/organ/external/wings/moth = "Plain", /obj/item/organ/external/antennae = "Plain") meat = /obj/item/food/meat/slab/human/mutant/moth mutanttongue = /obj/item/organ/internal/tongue/moth diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 51b2f3954973d..7a205da5c089f 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -486,7 +486,8 @@ . = ..() if(has_gravity()) for(var/mob/living/carbon/human/future_pancake in loc) - run_over(future_pancake) + if(future_pancake.body_position == LYING_DOWN) + run_over(future_pancake) diag_hud_set_mulebotcell() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9092efac428ca..a6a1c58c7eddf 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -331,19 +331,6 @@ toast.name = header toast.target_ref = WEAKREF(source) -/// Heals a robotic limb on a mob -/proc/item_heal_robotic(mob/living/carbon/human/human, mob/user, brute_heal, burn_heal) - var/obj/item/bodypart/affecting = human.get_bodypart(check_zone(user.zone_selected)) - if(!affecting || IS_ORGANIC_LIMB(affecting)) - to_chat(user, span_warning("[affecting] is already in good condition!")) - return FALSE - var/brute_damage = brute_heal > burn_heal //changes repair text based on how much brute/burn was supplied - if((brute_heal > 0 && affecting.brute_dam > 0) || (burn_heal > 0 && affecting.burn_dam > 0)) - if(affecting.heal_damage(brute_heal, burn_heal, required_bodytype = BODYTYPE_ROBOTIC)) - human.update_damage_overlays() - user.visible_message(span_notice("[user] fixes some of the [brute_damage ? "dents on" : "burnt wires in"] [human]'s [affecting.name]."), \ - span_notice("You fix some of the [brute_damage ? "dents on" : "burnt wires in"] [human == user ? "your" : "[human]'s"] [affecting.name].")) - return TRUE //successful heal ///Is the passed in mob a ghost with admin powers, doesn't check for AI interact like isAdminGhost() used to diff --git a/code/modules/power/apc/apc_malf.dm b/code/modules/power/apc/apc_malf.dm index f4c27e15a4067..1419e12c46be3 100644 --- a/code/modules/power/apc/apc_malf.dm +++ b/code/modules/power/apc/apc_malf.dm @@ -36,6 +36,12 @@ return if(!is_station_level(z)) return + INVOKE_ASYNC(src, PROC_REF(malfshunt), malf) + +/obj/machinery/power/apc/proc/malfshunt(mob/living/silicon/ai/malf) + var/confirm = tgui_alert(malf, "Are you sure that you want to shunt? This will take you out of your core!", "Shunt to [name]?", list("Yes", "No")) + if(confirm != "Yes") + return malf.ShutOffDoomsdayDevice() occupier = malf if (isturf(malf.loc)) // create a deactivated AI core if the AI isn't coming from an emergency mech shunt diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index e55442f31fd1f..a8e20cde8c7a0 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -575,7 +575,7 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri user.visible_message(span_notice("[user] starts to fix some of the wires in [H]'s [affecting.name]."), span_notice("You start fixing some of the wires in [H == user ? "your" : "[H]'s"] [affecting.name].")) if(!do_after(user, 5 SECONDS, H)) return - if(item_heal_robotic(H, user, 0, 15)) + if(H.item_heal(user, 0, 15, "dents", "burnt wires", BODYTYPE_ROBOTIC)) use(1) return else diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index c7fefc745f7e0..7237ee0e32747 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -254,6 +254,8 @@ require_model = TRUE model_type = list(/obj/item/robot_model/miner) model_flags = BORG_MODEL_MINER + //Most modkits are supposed to allow duplicates. The ones that don't should be blocked by PKA code anyways. + allow_duplicates = TRUE var/denied_type = null var/maximum_of_type = 1 var/cost = 30 diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index f7fc1b04ac8de..40305c9a8bc47 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -281,7 +281,7 @@ * * modifier - a flat additive numeric to the size of the explosion - set this if you want a minimum range * * strengthdiv - the divisional factor of the explosion, a larger number means a smaller range - This is the part that modifies an explosion's range with volume (i.e. it divides it by this number) */ -/datum/chemical_reaction/proc/default_explode(datum/reagents/holder, created_volume, modifier = 0, strengthdiv = 10) +/datum/chemical_reaction/proc/default_explode(datum/reagents/holder, created_volume, modifier = 0, strengthdiv = 10, clear_mob_reagents) var/power = modifier + round(created_volume/strengthdiv, 1) if(power > 0) var/turf/T = get_turf(holder.my_atom) @@ -300,8 +300,29 @@ var/datum/effect_system/reagents_explosion/e = new() e.set_up(power , T, 0, 0) e.start(holder.my_atom) - holder.clear_reagents() - + if (ismob(holder.my_atom)) + if(!clear_mob_reagents) + return + // Only clear reagents if they use a special explosive reaction to do it; it shouldn't apply + // to any explosion inside a person + holder.clear_reagents() + if(iscarbon(holder.my_atom)) + var/mob/living/carbon/victim = holder.my_atom + var/vomit_flags = MOB_VOMIT_MESSAGE | MOB_VOMIT_FORCE + // The vomiting here is for effect, not meant to help with purging + victim.vomit(vomit_flags, distance = 5) + // Not quite the same if the reaction is in their stomach; they'll throw up + // from any explosion, but it'll only make them puke up everything in their + // stomach + else if (istype(holder.my_atom, /obj/item/organ/internal/stomach)) + var/obj/item/organ/internal/stomach/indigestion = holder.my_atom + if(power < 1) + return + indigestion.owner?.vomit(MOB_VOMIT_MESSAGE | MOB_VOMIT_FORCE, lost_nutrition = 150, distance = 5, purge_ratio = 1) + holder.clear_reagents() + return + else + holder.clear_reagents() /* *Creates a flash effect only - less expensive than explode() * diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index d190a44aea063..f02aaa3ab2473 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -1,13 +1,48 @@ +#define PURGING_REAGENTS list( \ + /datum/reagent/medicine/c2/multiver, \ + /datum/reagent/medicine/pen_acid, \ + /datum/reagent/medicine/calomel, \ + /datum/reagent/medicine/ammoniated_mercury, \ + /datum/reagent/medicine/c2/syriniver, \ + /datum/reagent/medicine/c2/musiver \ +) + /datum/chemical_reaction/reagent_explosion var/strengthdiv = 10 var/modifier = 0 reaction_flags = REACTION_INSTANT reaction_tags = REACTION_TAG_EXPLOSIVE | REACTION_TAG_MODERATE | REACTION_TAG_DANGEROUS required_temp = 0 //Prevent impromptu RPGs - -/datum/chemical_reaction/reagent_explosion/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - default_explode(holder, created_volume, modifier, strengthdiv) - + // Only clear mob reagents in special cases + var/clear_mob_reagents = FALSE + +/datum/chemical_reaction/reagent_explosion/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume, clear_mob_reagents) + // If an explosive reaction clears mob reagents, it should always be a minimum power + if(ismob(holder.my_atom) && clear_mob_reagents) + if(round((created_volume / strengthdiv) + modifier, 1) < 1) + modifier += 1 - ((created_volume / strengthdiv) + modifier) + // If this particular explosion doesn't automatically clear mob reagents as an inherent quality, + // then we can still clear mob reagents with some mad science malpractice that shouldn't work but + // does because omnizine is magic and also it's the future or whatever + if(ismob(holder.my_atom) && !clear_mob_reagents) + // The explosion needs to be a minimum power to clear reagents: see above + var/purge_power = round((created_volume / strengthdiv) + modifier, 1) + if(purge_power >= 1) + var/has_purging_chemical = FALSE + // They need one of the purge reagents in them + for(var/purging_chem as anything in PURGING_REAGENTS) + if(holder.has_reagent(purging_chem)) + // We have a purging chemical + has_purging_chemical = TRUE + break + // Then we need omnizine! MAGIC! + var/has_omnizine = holder.has_reagent(/datum/reagent/medicine/omnizine) + if(has_purging_chemical && has_omnizine) + // With all this medical "science" combined, we can clear mob reagents + clear_mob_reagents = TRUE + default_explode(holder, created_volume, modifier, strengthdiv, clear_mob_reagents) + +#undef PURGING_REAGENTS /datum/chemical_reaction/reagent_explosion/nitroglycerin results = list(/datum/reagent/nitroglycerin = 2) required_reagents = list(/datum/reagent/glycerol = 1, /datum/reagent/toxin/acid/nitracid = 1, /datum/reagent/toxin/acid = 1) @@ -104,11 +139,18 @@ /datum/chemical_reaction/reagent_explosion/penthrite_explosion_epinephrine required_reagents = list(/datum/reagent/medicine/c2/penthrite = 1, /datum/reagent/medicine/epinephrine = 1) strengthdiv = 5 + // Penthrite is rare as hell, so this clears your reagents + // Will most likely be from miners accidentally penstacking + clear_mob_reagents = TRUE + /datum/chemical_reaction/reagent_explosion/penthrite_explosion_atropine required_reagents = list(/datum/reagent/medicine/c2/penthrite = 1, /datum/reagent/medicine/atropine = 1) strengthdiv = 5 modifier = 5 + // Rare reagents clear your reagents + // Probably not good for you because you'll need healing chems to survive this most likely + clear_mob_reagents = TRUE /datum/chemical_reaction/reagent_explosion/potassium_explosion required_reagents = list(/datum/reagent/water = 1, /datum/reagent/potassium = 1) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm deleted file mode 100644 index 1c6e6f2b9f7ee..0000000000000 --- a/code/modules/research/techweb/all_nodes.dm +++ /dev/null @@ -1,2498 +0,0 @@ - -//Current rate: 135000 research points in 90 minutes - -//Base Nodes -/datum/techweb_node/base - id = "base" - starting_node = TRUE - display_name = "Basic Research Technology" - description = "NT default research technologies." - // Default research tech, prevents bricking - design_ids = list( - "basic_capacitor", - "basic_cell", - "basic_matter_bin", - "basic_micro_laser", - "basic_scanning", - "blast", - "bounced_radio", - "bowl", - "bucket", - "c-reader", - "c38_rubber", - "camera_assembly", - "camera_film", - "camera", - "capbox", - "chisel", - "circuit_imprinter_offstation", - "circuit_imprinter", - "circuit", - "circuitgreen", - "circuitred", - "coffee_cartridge", - "coffeemaker", - "coffeepot", - "condenser", - "conveyor_belt", - "conveyor_switch", - "custom_vendor_refill", - "destructive_analyzer", - "destructive_scanner", - "desttagger", - "doppler_array", - "drinking_glass", - "earmuffs", - "electropack", - "experi_scanner", - "experimentor", - "extinguisher", - "fax", - "fish_case", - "fishing_rod", - "fishing_portal_generator", - "flashlight", - "fluid_ducts", - "foam_dart", - "fork", - "gas_filter", - "handcuffs_s", - "handlabel", - "health_sensor", - "holodisk", - "igniter", - "infrared_emitter", - "intercom_frame", - "kitchen_knife", - "laptop", - "light_bulb", - "light_replacer", - "light_tube", - "mechfab", - "micro_servo", - "miniature_power_cell", - "newscaster_frame", - "oven_tray", - "packagewrap", - "pet_carrier", - "plasmaglass", - "plasmaman_gas_filter", - "plasmareinforcedglass", - "plasteel", - "plastic_fork", - "plastic_knife", - "plastic_spoon", - "plastitanium", - "plastitaniumglass", - "plate", - "prox_sensor", - "radio_headset", - "rdconsole", - "rdserver", - "rdservercontrol", - "recorder", - "rglass", - "roll", - "sec_38", - "sec_beanbag_slug", - "sec_dart", - "sec_Islug", - "sec_rshot", - "sec_pen", - "servingtray", - "shaker", - "shot_glass", - "signaler", - "slime_scanner", - "solar_panel", - "solar_tracker", - "souppot", - "space_heater", - "spoon", - "status_display_frame", - "sticky_tape", - "syrup_bottle", - "tape", - "tech_disk", - "timer", - "titaniumglass", - "toner_large", - "toner", - "tongs", - "toy_armblade", - "toy_balloon", - "toygun", - "tram_floor_dark", - "tram_floor_light", - "trapdoor_electronics", - "turbine_part_compressor", - "turbine_part_rotor", - "turbine_part_stator", - "turret_control", - "universal_scanner", - "voice_analyzer", - "watering_can", - ) - experiments_to_unlock = list( - /datum/experiment/autopsy/nonhuman, - /datum/experiment/scanning/random/material/medium/one, - /datum/experiment/scanning/random/material/medium/three, - /datum/experiment/scanning/random/material/hard/one, - /datum/experiment/scanning/random/material/hard/two, - /datum/experiment/scanning/people/novel_organs, - ) - -/datum/techweb_node/mmi - id = "mmi" - starting_node = TRUE - display_name = "Man Machine Interface" - description = "A slightly Frankensteinian device that allows human brains to interface natively with software APIs." - design_ids = list( - "mmi", - ) - -/datum/techweb_node/cyborg - id = "cyborg" - starting_node = TRUE - display_name = "Cyborg Construction" - description = "Sapient robots with preloaded tool modules and programmable laws." - design_ids = list( - "borg_chest", - "borg_head", - "borg_l_arm", - "borg_l_leg", - "borg_r_arm", - "borg_r_leg", - "borg_suit", - "borg_upgrade_rename", - "borg_upgrade_restart", - "borgupload", - "cyborgrecharger", - "robocontrol", - "sflash", - ) - -/datum/techweb_node/mech - id = "mecha" - starting_node = TRUE - display_name = "Mechanical Exosuits" - description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human." - design_ids = list( - "mech_recharger", - "mecha_tracking", - "mechacontrol", - "mechapower", - "ripley_chassis", - "ripley_left_arm", - "ripley_left_leg", - "ripley_main", - "ripley_peri", - "ripley_right_arm", - "ripley_right_leg", - "ripley_torso", - "ripleyupgrade", - "mech_hydraulic_clamp", - "mech_radio", - "mech_air_tank", - "mech_thrusters", - ) - -/datum/techweb_node/mod_basic - id = "mod" - starting_node = TRUE - display_name = "Basic Modular Suits" - description = "Specialized back mounted power suits with various different modules." - design_ids = list( - "mod_boots", - "mod_chestplate", - "mod_gauntlets", - "mod_helmet", - "mod_paint_kit", - "mod_shell", - "mod_plating_standard", - "mod_storage", - "mod_welding", - "mod_safety", - "mod_mouthhole", - "mod_flashlight", - "mod_longfall", - "mod_thermal_regulator", - "mod_plasma", - "mod_sign_radio", - ) - -/datum/techweb_node/mech_tools - id = "mech_tools" - starting_node = TRUE - display_name = "Basic Exosuit Equipment" - description = "Various tools fit for basic mech units" - design_ids = list( - "mech_drill", - "mech_extinguisher", - "mech_mscanner", - ) - -/datum/techweb_node/basic_tools - id = "basic_tools" - starting_node = TRUE - display_name = "Basic Tools" - description = "Basic mechanical, electronic, surgical and botanical tools." - design_ids = list( - "airlock_painter", - "analyzer", - "boxcutter", - "cable_coil", - "cable_coil", - "crowbar", - "cultivator", - "decal_painter", - "hatchet", - "mop", - "multitool", - "normtrash", - "pipe_painter", - "plant_analyzer", - "plunger", - "pushbroom", - "rwd", - "razor", - "screwdriver", - "secateurs", - "shovel", - "spade", - "spraycan", - "tile_sprayer", - "tscanner", - "welding_helmet", - "welding_tool", - "wirebrush", - "wirecutters", - "wrench", - "pickaxe", - ) - -/datum/techweb_node/basic_medical - id = "basic_medical" - starting_node = TRUE - display_name = "Basic Medical Equipment" - description = "Basic medical tools and equipment." - design_ids = list( - "beaker", - "biopsy_tool", - "blood_filter", - "bonesetter", - "cautery", - "circular_saw", - "cybernetic_ears", - "cybernetic_eyes", - "cybernetic_eyes_moth", - "cybernetic_heart", - "cybernetic_liver", - "cybernetic_lungs", - "cybernetic_stomach", - "defibmountdefault", - "dropper", - "hemostat", - "large_beaker", - "medicalbed", - "mmi_m", - "operating", - "petri_dish", - "pillbottle", - "plumbing_rcd", - "plumbing_rcd_service", - "plumbing_rcd_sci", - "portable_chem_mixer", - "penlight", - "retractor", - "scalpel", - "stethoscope", - "surgical_drapes", - "surgical_tape", - "surgicaldrill", - "swab", - "syringe", - "xlarge_beaker", - ) - -/datum/techweb_node/basic_circuitry - id = "basic_circuitry" - starting_node = TRUE - display_name = "Basic Integrated Circuits" - description = "Research on how to fully exploit the power of integrated circuits" - design_ids = list( - "circuit_multitool", - "comp_access_checker", - "comp_arctan2", - "comp_arithmetic", - "comp_assoc_list_pick", - "comp_assoc_list_remove", - "comp_assoc_list_set", - "comp_binary_convert", - "comp_clock", - "comp_comparison", - "comp_concat", - "comp_concat_list", - "comp_decimal_convert", - "comp_delay", - "comp_direction", - "comp_element_find", - "comp_filter_list", - "comp_foreach", - "comp_format", - "comp_format_assoc", - "comp_get_column", - "comp_gps", - "comp_health", - "comp_health_state", - "comp_hear", - "comp_id_access_reader", - "comp_id_getter", - "comp_id_info_reader", - "comp_index", - "comp_index_assoc", - "comp_index_table", - "comp_laserpointer", - "comp_length", - "comp_light", - "comp_list_add", - "comp_list_assoc_literal", - "comp_list_clear", - "comp_list_literal", - "comp_list_pick", - "comp_list_remove", - "comp_logic", - "comp_matscanner", - "comp_mmi", - "comp_module", - "comp_multiplexer", - "comp_not", - "comp_ntnet_receive", - "comp_ntnet_send", - "comp_ntnet_send_list_literal", - "comp_pinpointer", - "comp_pressuresensor", - "comp_radio", - "comp_random", - "comp_reagents", - "comp_router", - "comp_select_query", - "comp_self", - "comp_set_variable_trigger", - "comp_soundemitter", - "comp_species", - "comp_speech", - "comp_speech", - "comp_split", - "comp_string_contains", - "comp_tempsensor", - "comp_textcase", - "comp_timepiece", - "comp_toggle", - "comp_tonumber", - "comp_tostring", - "comp_trigonometry", - "comp_typecast", - "comp_typecheck", - "comp_view_sensor", - "compact_remote_shell", - "component_printer", - "integrated_circuit", - "module_duplicator", - "usb_cable" - ) - -/////////////////////////Biotech///////////////////////// - -/datum/techweb_node/biotech - id = "biotech" - display_name = "Biological Technology" - description = "What makes us tick." //the MC, silly! - prereq_ids = list("base") - design_ids = list( - "beer_dispenser", - "blood_pack", - "chem_dispenser", - "chem_heater", - "chem_mass_spec", - "chem_master", - "chem_pack", - "defibmount", - "defibrillator", - "genescanner", - "healthanalyzer", - "med_spray_bottle", - "medical_kiosk", - "medigel", - "medipen_refiller", - "pandemic", - "penlight_paramedic", - "soda_dispenser", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - required_experiments = list(/datum/experiment/autopsy/human) - -/datum/techweb_node/adv_biotech - id = "adv_biotech" - display_name = "Advanced Biotechnology" - description = "Advanced Biotechnology" - prereq_ids = list("biotech") - design_ids = list( - "autopsyscanner", - "crewpinpointer", - "defibrillator_compact", - "harvester", - "healthanalyzer_advanced", - "holobarrier_med", - "limbgrower", - "meta_beaker", - "ph_meter", - "piercesyringe", - "plasmarefiller", - "smoke_machine", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - required_experiments = list(/datum/experiment/autopsy/nonhuman) - discount_experiments = list(/datum/experiment/scanning/random/material/meat = 4000) - -/datum/techweb_node/xenoorgan_biotech - id = "xenoorgan_bio" - display_name = "Xeno-organ Biology" - description = "Plasmaman, Ethereals, Lizardpeople... What makes our non-human crewmembers tick?" - prereq_ids = list("adv_biotech") - design_ids = list( - "limbdesign_ethereal", - "limbdesign_felinid", - "limbdesign_lizard", - "limbdesign_plasmaman", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 6500) - discount_experiments = list( - /datum/experiment/scanning/random/cytology/easy = 1000, - /datum/experiment/scanning/points/slime/hard = 5000, - /datum/experiment/autopsy/xenomorph = 5000, - ) - -/datum/techweb_node/morphological_theory - id = "morphological_theory" - display_name = "Anomalous Morphology" - description = "Use poorly understood energies to change your body." - prereq_ids = list("adv_biotech", "anomaly_research") - design_ids = list("polymorph_belt") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list( - /datum/experiment/scanning/people/novel_organs = 5000, - ) - -/datum/techweb_node/bio_process - id = "bio_process" - display_name = "Biological Processing" - description = "From slimes to kitchens." - prereq_ids = list("biotech") - design_ids = list( - "deepfryer", - "dish_drive", - "fat_sucker", - "gibber", - "griddle", - "microwave", - "microwave_engineering", - "monkey_recycler", - "oven", - "processor", - "range", // should be in a further node, probably - "reagentgrinder", - "smartfridge", - "stove", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - discount_experiments = list(/datum/experiment/scanning/random/cytology = 3000) //Big discount to reinforce doing it. - -/datum/techweb_node/marine_util - id = "marine_util" - display_name = "Marine Utility" - description = "Fish are nice to look at and all, but they can be put to use." - prereq_ids = list("bio_process") - design_ids = list( - "bioelec_gen", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - // only available if you've done the first fishing experiment (thus unlocking fishing tech), but not a strict requirement to get the tech - discount_experiments = list(/datum/experiment/scanning/fish/second = 3000) - -/////////////////////////Advanced Surgery///////////////////////// - -/datum/techweb_node/imp_wt_surgery - id = "imp_wt_surgery" - display_name = "Improved Wound-Tending Surgery" - description = "Who would have known being more gentle with a hemostat decreases patient pain?" - prereq_ids = list("biotech") - design_ids = list( - "surgery_heal_brute_upgrade", - "surgery_heal_burn_upgrade", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/oldstation_surgery - id = "oldstation_surgery" - display_name = "Experimental Dissection" - description = "Grants access to experimental dissections, which allows generation of research points." - design_ids = list( - "surgery_oldstation_dissection", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) - hidden = TRUE - show_on_wiki = FALSE - -/datum/techweb_node/adv_surgery - id = "adv_surgery" - display_name = "Advanced Surgery" - description = "When simple medicine doesn't cut it." - prereq_ids = list("imp_wt_surgery") - design_ids = list( - "surgery_heal_brute_upgrade_femto", - "surgery_heal_burn_upgrade_femto", - "surgery_heal_combo", - "surgery_lobotomy", - "surgery_wing_reconstruction", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/exp_surgery - id = "exp_surgery" - display_name = "Experimental Surgery" - description = "When evolution isn't fast enough." - prereq_ids = list("adv_surgery") - design_ids = list( - "surgery_cortex_folding", - "surgery_cortex_imprint", - "surgery_heal_combo_upgrade", - "surgery_ligament_hook", - "surgery_ligament_reinforcement", - "surgery_muscled_veins", - "surgery_nerve_ground", - "surgery_nerve_splice", - "surgery_pacify", - "surgery_vein_thread", - "surgery_viral_bond", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - discount_experiments = list(/datum/experiment/scanning/random/plants/traits = 4500) - -/datum/techweb_node/alien_surgery - id = "alien_surgery" - display_name = "Alien Surgery" - description = "Abductors did nothing wrong." - prereq_ids = list("exp_surgery", "alientech") - design_ids = list( - "surgery_brainwashing", - "surgery_heal_combo_upgrade_femto", - "surgery_zombie", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/////////////////////////data theory tech///////////////////////// - -/datum/techweb_node/datatheory //Computer science - id = "datatheory" - display_name = "Data Theory" - description = "Big Data, in space!" - prereq_ids = list("base") - design_ids = list( - "bounty_pad", - "bounty_pad_control", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - - -/////////////////////////engineering tech///////////////////////// - -/datum/techweb_node/engineering - id = "engineering" - display_name = "Industrial Engineering" - description = "A refresher course on modern engineering technology." - prereq_ids = list("base") - design_ids = list( - "adv_capacitor", - "adv_matter_bin", - "adv_scanning", - "airalarm_electronics", - "airlock_board", - "anomaly_refinery", - "apc_control", - "atmos_control", - "atmos_thermal", - "atmosalerts", - "autolathe", - "cell_charger", - "crystallizer", - "electrolyzer", - "emergency_oxygen_engi", - "emergency_oxygen", - "emitter", - "mass_driver", - "firealarm_electronics", - "firelock_board", - "generic_tank", - "grounding_rod", - "high_cell", - "high_micro_laser", - "mesons", - "nano_servo", - "oxygen_tank", - "pacman", - "plasma_tank", - "plasmaman_tank_belt", - "pneumatic_seal", - "power_control", - "powermonitor", - "recharger", - "recycler", - "rped", - "scanner_gate", - "solarcontrol", - "stack_console", - "stack_machine", - "suit_storage_unit", - "tank_compressor", - "tesla_coil", - "thermomachine", - "w-recycler", - "welding_goggles", - "flatpacker", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 12500) - discount_experiments = list(/datum/experiment/scanning/random/material/easy = 7500) - experiments_to_unlock = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier2_microlaser) - -/datum/techweb_node/adv_engi - id = "adv_engi" - display_name = "Advanced Engineering" - description = "Pushing the boundaries of physics, one chainsaw-fist at a time." - prereq_ids = list("engineering", "emp_basic") - design_ids = list( - "HFR_core", - "HFR_corner", - "HFR_fuel_input", - "HFR_interface", - "HFR_moderator_input", - "HFR_waste_output", - "engine_goggles", - "forcefield_projector", - "magboots", - "rcd_loaded", - "rcd_ammo", - "rpd_loaded", - "rtd_loaded", - "sheetifier", - "weldingmask", - "bolter_wrench", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 15000) - discount_experiments = list( - /datum/experiment/scanning/random/material/medium/one = 4000, - /datum/experiment/ordnance/gaseous/bz = 10000, - ) - -/datum/techweb_node/anomaly - id = "anomaly_research" - display_name = "Anomaly Research" - description = "Unlock the potential of the mysterious anomalies that appear on station." - prereq_ids = list("adv_engi", "practical_bluespace") - design_ids = list( - "anomaly_neutralizer", - "reactive_armour", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/high_efficiency - id = "high_efficiency" - display_name = "High Efficiency Parts" - description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels." - prereq_ids = list("engineering", "datatheory") - design_ids = list( - "pico_servo", - "super_matter_bin", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier2_lathes = 5000) - -/datum/techweb_node/adv_power - id = "adv_power" - display_name = "Advanced Power Manipulation" - description = "How to get more zap." - prereq_ids = list("engineering") - design_ids = list( - "hyper_cell", - "power_turbine_console", - "smes", - "super_capacitor", - "super_cell", - "turbine_compressor", - "turbine_rotor", - "turbine_stator", - "modular_shield_generator", - "modular_shield_node", - "modular_shield_relay", - "modular_shield_charger", - "modular_shield_well", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - discount_experiments = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier2_capacitors = 2500) - -/////////////////////////Bluespace tech///////////////////////// -/datum/techweb_node/bluespace_basic //Bluespace-memery - id = "bluespace_basic" - display_name = "Basic Bluespace Theory" - description = "Basic studies into the mysterious alternate dimension known as bluespace." - prereq_ids = list("base") - design_ids = list( - "beacon", - "bluespace_crystal", - "telesci_gps", - "xenobioconsole", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bluespace_travel - id = "bluespace_travel" - display_name = "Bluespace Travel" - description = "Application of Bluespace for static teleportation technology." - prereq_ids = list("practical_bluespace") - design_ids = list( - "bluespace_pod", - "launchpad", - "launchpad_console", - "quantumpad", - "tele_hub", - "tele_station", - "teleconsole", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_bluespacemachines = 4000) - -/datum/techweb_node/micro_bluespace - id = "micro_bluespace" - display_name = "Miniaturized Bluespace Research" - description = "Extreme reduction in space required for bluespace engines, leading to portable bluespace technology." - prereq_ids = list("bluespace_travel", "practical_bluespace", "high_efficiency") - design_ids = list( - "bluespace_matter_bin", - "bluespacebodybag", - "medicalbed_emergency", - "femto_servo", - "quantum_keycard", - "swapper", - "triphasic_scanning", - "wormholeprojector", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_variety = 5000) - /* /datum/experiment/exploration_scan/random/condition) this should have a point cost but im not even sure the experiment works properly lmao*/ - -/datum/techweb_node/advanced_bluespace - id = "bluespace_storage" - display_name = "Advanced Bluespace Storage" - description = "With the use of bluespace we can create even more advanced storage devices than we could have ever done" - prereq_ids = list("micro_bluespace", "janitor") - design_ids = list( - "bag_holding", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -/datum/techweb_node/practical_bluespace - id = "practical_bluespace" - display_name = "Applied Bluespace Research" - description = "Using bluespace to make things faster and better." - prereq_ids = list("bluespace_basic", "engineering") - design_ids = list( - "bluespacebeaker", - "bluespacesyringe", - "bluespace_coffeepot", - "bs_rped", - "minerbag_holding", - "ore_silo", - "phasic_scanning", - "plumbing_receiver", - "roastingstick", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier2_scanmodules = 3500) - -/datum/techweb_node/bluespace_power - id = "bluespace_power" - display_name = "Bluespace Power Technology" - description = "Even more powerful.. power!" - prereq_ids = list("adv_power", "practical_bluespace") - design_ids = list( - "bluespace_cell", - "quadratic_capacitor", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier3_cells = 3000) - -/datum/techweb_node/unregulated_bluespace - id = "unregulated_bluespace" - display_name = "Unregulated Bluespace Research" - description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." - prereq_ids = list("bluespace_travel", "syndicate_basic") - design_ids = list( - "desynchronizer", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - - -/////////////////////////plasma tech///////////////////////// -/datum/techweb_node/basic_plasma - id = "basic_plasma" - display_name = "Basic Plasma Research" - description = "Research into the mysterious and dangerous substance, plasma." - prereq_ids = list("engineering") - design_ids = list( - "mech_generator", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_plasma - id = "adv_plasma" - display_name = "Advanced Plasma Research" - description = "Research on how to fully exploit the power of plasma." - prereq_ids = list("basic_plasma") - design_ids = list( - "mech_plasma_cutter", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/////////////////////////integrated circuits tech///////////////////////// - -/datum/techweb_node/adv_shells - id = "adv_shells" - display_name = "Advanced Shell Research" - description = "Grants access to more complicated shell designs." - prereq_ids = list("basic_circuitry", "engineering") - design_ids = list( - "assembly_shell", - "bot_shell", - "comp_equip_action", - "controller_shell", - "dispenser_shell", - "door_shell", - "gun_shell", - "keyboard_shell", - "module_shell", - "money_bot_shell", - "scanner_gate_shell", - "scanner_shell", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/bci_shells - id = "bci_shells" - display_name = "Brain-Computer Interfaces" - description = "Grants access to biocompatable shell designs and components." - prereq_ids = list("adv_shells") - design_ids = list( - "bci_implanter", - "bci_shell", - "comp_bar_overlay", - "comp_camera_bci", - "comp_counter_overlay", - "comp_install_detector", - "comp_object_overlay", - "comp_reagent_injector", - "comp_target_intercept", - "comp_thought_listener", - "comp_vox", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) - -/datum/techweb_node/movable_shells_tech - id = "movable_shells" - display_name = "Movable Shell Research" - description = "Grants access to movable shells." - prereq_ids = list("adv_shells", "robotics") - design_ids = list( - "comp_pathfind", - "comp_pull", - "drone_shell", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/datum/techweb_node/server_shell_tech - id = "server_shell" - display_name = "Server Technology Research" - description = "Grants access to a server shell that has a very high capacity for components." - prereq_ids = list("adv_shells", "computer_data_disks") - design_ids = list( - "server_shell", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -/////////////////////////robotics tech///////////////////////// -/datum/techweb_node/robotics - id = "robotics" - display_name = "Basic Robotics Research" - description = "Programmable machines that make our lives lazier." - prereq_ids = list("base") - design_ids = list( - "paicard", - "mecha_camera", - "botnavbeacon", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_robotics - id = "adv_robotics" - display_name = "Advanced Robotics Research" - description = "Advanced synthetic neural networks and synaptic pathways allows for extraordinary leaps in cybernetic intelligence and interfacing." - prereq_ids = list("robotics") - design_ids = list( - "advanced_l_arm", - "advanced_r_arm", - "advanced_l_leg", - "advanced_r_leg", - "mmi_posi", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_bots - id = "adv_bots" - display_name = "Advanced Bots Research" - description = "Grants access to a special launchpad designed for bots." - prereq_ids = list("robotics") - design_ids = list( - "botpad", - "botpad_remote", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/exodrone_tech - id = "exodrone" - display_name = "Exploration Drone Research" - description = "Technology for exploring far away locations." - prereq_ids = list("robotics") - design_ids = list( - "exodrone_console", - "exodrone_launcher", - "exoscanner", - "exoscanner_console", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/neural_programming - id = "neural_programming" - display_name = "Neural Programming" - description = "Study into networks of processing units that mimic our brains." - prereq_ids = list("biotech", "datatheory") - design_ids = list( - "skill_station", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cyborg_upg_util - id = "cyborg_upg_util" - display_name = "Cyborg Upgrades: Utility" - description = "Utility upgrades for cyborgs." - prereq_ids = list("adv_robotics") - design_ids = list( - "borg_upgrade_advancedmop", - "borg_upgrade_broomer", - "borg_upgrade_expand", - "borg_upgrade_prt", - "borg_upgrade_selfrepair", - "borg_upgrade_thrusters", - "borg_upgrade_trashofholding", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cyborg_upg_util/New() - . = ..() - if(!CONFIG_GET(flag/disable_secborg)) - design_ids += "borg_upgrade_disablercooler" - -/datum/techweb_node/cyborg_upg_serv - id = "cyborg_upg_serv" - display_name = "Cyborg Upgrades: Service" - description = "Service upgrades for cyborgs." - prereq_ids = list("adv_robotics") - design_ids = list( - "borg_upgrade_rolling_table", - "borg_upgrade_condiment_synthesizer", - "borg_upgrade_silicon_knife", - "borg_upgrade_service_apparatus", - "borg_upgrade_drink_apparatus", - "borg_upgrade_service_cookbook", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cyborg_upg_engiminer - id = "cyborg_upg_engiminer" - display_name = "Cyborg Upgrades: Engineering & Mining" - description = "Engineering and Mining upgrades for cyborgs." - prereq_ids = list("adv_engi", "basic_mining") - design_ids = list( - "borg_upgrade_circuitapp", - "borg_upgrade_diamonddrill", - "borg_upgrade_holding", - "borg_upgrade_lavaproof", - "borg_upgrade_rped", - "borg_upgrade_hypermod", - "borg_upgrade_inducer", - "borg_upgrade_engineeringomnitool", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/cyborg_upg_med - id = "cyborg_upg_med" - display_name = "Cyborg Upgrades: Medical" - description = "Medical upgrades for cyborgs." - prereq_ids = list("adv_biotech") - design_ids = list( - "borg_upgrade_beakerapp", - "borg_upgrade_defibrillator", - "borg_upgrade_expandedsynthesiser", - "borg_upgrade_piercinghypospray", - "borg_upgrade_pinpointer", - "borg_upgrade_surgicalprocessor", - "borg_upgrade_surgicalomnitool", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/ai_basic - id = "ai_basic" - display_name = "Artificial Intelligence" - description = "AI unit research." - prereq_ids = list("adv_robotics") - design_ids = list( - "aicore", - "borg_ai_control", - "intellicard", - "mecha_tracking_ai_control", - "aifixer", - "aiupload", - "reset_module", - "asimov_module", - "default_module", - "nutimov_module", - "paladin_module", - "robocop_module", - "corporate_module", - "drone_module", - "oxygen_module", - "safeguard_module", - "protectstation_module", - "quarantine_module", - "freeform_module", - "remove_module", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/ai_basic/New() - . = ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_HUMAN_AI)) - design_ids -= list( - "aicore", - "borg_ai_control", - "intellicard", - "mecha_tracking_ai_control", - "aifixer", - "aiupload", - ) - -/datum/techweb_node/ai_adv - id = "ai_adv" - display_name = "Advanced Artificial Intelligence" - description = "State of the art lawsets to be used for AI research." - prereq_ids = list("ai_basic") - design_ids = list( - "asimovpp_module", - "paladin_devotion_module", - "dungeon_master_module", - "painter_module", - "ten_commandments_module", - "hippocratic_module", - "maintain_module", - "liveandletlive_module", - "reporter_module", - "yesman_module", - "hulkamania_module", - "peacekeeper_module", - "overlord_module", - "tyrant_module", - "antimov_module", - "balance_module", - "thermurderdynamic_module", - "damaged_module", - "freeformcore_module", - "onehuman_module", - "purge_module", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - -//Any kind of point adjustment needs to happen before SSresearch sets up the whole node tree, it gets cached -/datum/techweb_node/ai/New() - . = ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_UNIQUE_AI)) - research_costs[TECHWEB_POINT_TYPE_GENERIC] *= 3 - -/////////////////////////EMP tech///////////////////////// -/datum/techweb_node/emp_basic //EMP tech for some reason - id = "emp_basic" - display_name = "Electromagnetic Theory" - description = "Study into usage of frequencies in the electromagnetic spectrum." - prereq_ids = list("base") - design_ids = list( - "holosign", - "holosignsec", - "holosignengi", - "holosignatmos", - "holosignrestaurant", - "holosignbar", - "inducer", - "inducerengi", - "tray_goggles", - "holopad", - "vendatray", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/emp_adv - id = "emp_adv" - display_name = "Advanced Electromagnetic Theory" - description = "Determining whether reversing the polarity will actually help in a given situation." - prereq_ids = list("emp_basic") - design_ids = list( - "ultra_micro_laser", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier2_microlaser = 1500) - -/datum/techweb_node/emp_super - id = "emp_super" - display_name = "Quantum Electromagnetic Technology" //bs - description = "Even better electromagnetic technology." - prereq_ids = list("emp_adv") - design_ids = list( - "quadultra_micro_laser", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 15000) - discount_experiments = list( - /datum/experiment/scanning/points/machinery_pinpoint_scan/tier3_microlaser = 4000, - /datum/experiment/ordnance/gaseous/noblium = 10000, - ) - -/////////////////////////Clown tech///////////////////////// -/datum/techweb_node/clown - id = "clown" - display_name = "Clown Technology" - description = "Honk?!" - prereq_ids = list("base") - design_ids = list( - "air_horn", - "borg_transform_clown", - "honk_chassis", - "honk_head", - "honk_left_arm", - "honk_left_leg", - "honk_right_arm", - "honk_right_leg", - "honk_torso", - "honker_main", - "honker_peri", - "honker_targ", - "implant_trombone", - "mech_banana_mortar", - "mech_honker", - "mech_mousetrap_mortar", - "mech_punching_face", - "clown_firing_pin", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -////////////////////////Computer tech//////////////////////// -/datum/techweb_node/comptech - id = "comptech" - display_name = "Computer Consoles" - description = "Computers and how they work." - prereq_ids = list("datatheory") - design_ids = list( - "bankmachine", - "barcode_scanner", - "cargo", - "cargorequest", - "comconsole", - "crewconsole", - "idcard", - "libraryconsole", - "mining", - "photobooth", - "rdcamera", - "seccamera", - "security_photobooth", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/data_disks - id = "computer_data_disks" - display_name = "Computer Data Disks" - description = "Data disks used for storing modular computer stuff." - prereq_ids = list("comptech") - design_ids = list( - "portadrive_advanced", - "portadrive_basic", - "portadrive_super", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/computer_board_gaming - id = "computer_board_gaming" - display_name = "Arcade Games" - description = "For the slackers on the station." - prereq_ids = list("comptech") - design_ids = list( - "arcade_battle", - "arcade_orion", - "slotmachine", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3250) - discount_experiments = list(/datum/experiment/physical/arcade_winner = 3000) - -/datum/techweb_node/comp_recordkeeping - id = "comp_recordkeeping" - display_name = "Computerized Recordkeeping" - description = "Organized record databases and how they're used." - prereq_ids = list("comptech") - design_ids = list( - "account_console", - "automated_announcement", - "med_data", - "prisonmanage", - "secdata", - "vendor", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/telecomms - id = "telecomms" - display_name = "Telecommunications Technology" - description = "Subspace transmission technology for near-instant communications devices." - prereq_ids = list("comptech", "bluespace_basic") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - design_ids = list( - "comm_monitor", - "comm_server", - "gigabeacon", - "message_monitor", - "ntnet_relay", - "s_amplifier", - "s_analyzer", - "s_ansible", - "s_broadcaster", - "s_bus", - "s_crystal", - "s_filter", - "s_hub", - "s_messaging", - "s_processor", - "s_receiver", - "s_relay", - "s_server", - "s_transmitter", - "s_treatment", - ) - -/datum/techweb_node/tram - id = "tram" - display_name = "Tram Technology" - description = "Technology for linear induction transportation systems." - prereq_ids = list("telecomms") - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - design_ids = list( - "tram_controller", - "tram_display", - "crossing_signal", - "guideway_sensor", - ) - -/datum/techweb_node/integrated_hud - id = "integrated_HUDs" - display_name = "Integrated HUDs" - description = "The usefulness of computerized records, projected straight onto your eyepiece!" - prereq_ids = list("comp_recordkeeping", "emp_basic") - design_ids = list( - "diagnostic_hud", - "health_hud", - "scigoggles", - "security_hud", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/nvg_tech - id = "NVGtech" - display_name = "Night Vision Technology" - description = "Allows seeing in the dark without actual light!" - prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv") - design_ids = list( - "diagnostic_hud_night", - "health_hud_night", - "night_visision_goggles", - "nvgmesons", - "nv_scigoggles", - "security_hud_night", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - -////////////////////////Medical//////////////////////// -/datum/techweb_node/genetics - id = "genetics" - display_name = "Genetic Engineering" - description = "We have the technology to change him." - prereq_ids = list("biotech") - design_ids = list( - "dna_disk", - "dnainfuser", - "dnascanner", - "scan_console", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cryotech - id = "cryotech" - display_name = "Cryostasis Technology" - description = "Smart freezing of objects to preserve them!" - prereq_ids = list("adv_engi", "biotech") - design_ids = list( - "cryo_grenade", - "cryotube", - "splitbeaker", - "stasis", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - -/datum/techweb_node/subdermal_implants - id = "subdermal_implants" - display_name = "Subdermal Implants" - description = "Electronic implants buried beneath the skin." - prereq_ids = list("biotech") - design_ids = list( - "c38_trac", - "implant_chem", - "implant_tracking", - "implant_exile", - "implantcase", - "implanter", - "locator", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/advanced_implants - id = "adv_subdermal_implants" - display_name = "Advanced Subdermal Implants" - description = "Subdermal implants that leverage bluespace research to control their bluespace signature." - prereq_ids = list("subdermal_implants", "micro_bluespace") - design_ids = list( - "implant_beacon", - "implant_bluespace", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cyber_organs - id = "cyber_organs" - display_name = "Cybernetic Organs" - description = "We have the technology to rebuild him." - prereq_ids = list("biotech") - design_ids = list( - "cybernetic_ears_u", - "cybernetic_eyes_improved", - "cybernetic_eyes_improved_moth", - "cybernetic_heart_tier2", - "cybernetic_liver_tier2", - "cybernetic_lungs_tier2", - "cybernetic_stomach_tier2", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/cyber_organs/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) - -/datum/techweb_node/cyber_organs_upgraded - id = "cyber_organs_upgraded" - display_name = "Upgraded Cybernetic Organs" - description = "We have the technology to upgrade him." - prereq_ids = list("adv_biotech", "cyber_organs") - design_ids = list( - "cybernetic_ears_whisper", - "cybernetic_ears_xray", - "ci-gloweyes", - "ci-welding", - "ci-gloweyes-moth", - "ci-welding-moth", - "cybernetic_heart_tier3", - "cybernetic_liver_tier3", - "cybernetic_lungs_tier3", - "cybernetic_stomach_tier3", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/cyber_organs_upgraded/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/cyber_implants - id = "cyber_implants" - display_name = "Cybernetic Implants" - description = "Electronic implants that improve humans." - prereq_ids = list("adv_biotech", "datatheory") - design_ids = list( - "ci-breather", - "ci-diaghud", - "ci-medhud", - "ci-nutriment", - "ci-sechud", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/cyber_implants/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/adv_cyber_implants - id = "adv_cyber_implants" - display_name = "Advanced Cybernetic Implants" - description = "Upgraded and more powerful cybernetic implants." - prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs") - design_ids = list( - "ci-nutrimentplus", - "ci-reviver", - "ci-surgery", - "ci-toolset", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_cyber_implants/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -/datum/techweb_node/combat_cyber_implants - id = "combat_cyber_implants" - display_name = "Combat Cybernetic Implants" - description = "Military grade combat implants to improve performance." - prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency") - design_ids = list( - "ci-antidrop", - "ci-antistun", - "ci-thermals", - "ci-thrusters", - "ci-xray", - "ci-thermals-moth", - "ci-xray-moth", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/combat_cyber_implants/New() - ..() - if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1500) - -////////////////////////Tools//////////////////////// - -/datum/techweb_node/basic_mining - id = "basic_mining" - display_name = "Mining Technology" - description = "Better than Efficiency V." - prereq_ids = list("engineering", "basic_plasma") - design_ids = list( - "borg_upgrade_cooldownmod", - "borg_upgrade_damagemod", - "borg_upgrade_rangemod", - "cargoexpress", - "cooldownmod", - "damagemod", - "drill", - "mecha_kineticgun", - "mining_equipment_vendor", - "ore_redemption", - "plasmacutter", - "rangemod", - "superresonator", - "triggermod", - "mining_scanner", - "brm", - "b_smelter", - "b_refinery", - )//e a r l y g a m e) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_mining - id = "adv_mining" - display_name = "Advanced Mining Technology" - description = "Efficiency Level 127" //dumb mc references - prereq_ids = list("basic_mining", "adv_power", "adv_plasma") - design_ids = list( - "drill_diamond", - "hypermod", - "jackhammer", - "plasmacutter_adv", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - discount_experiments = list(/datum/experiment/scanning/random/material/hard/one = 5000) - -/datum/techweb_node/janitor - id = "janitor" - display_name = "Advanced Sanitation Technology" - description = "Clean things better, faster, stronger, and harder!" - prereq_ids = list("adv_engi") - design_ids = list( - "advmop", - "beartrap", - "blutrash", - "buffer", - "vacuum", - "holobarrier_jani", - "light_replacer_blue", - "paint_remover", - "spraybottle", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - discount_experiments = list(/datum/experiment/scanning/random/janitor_trash = 3000) //75% discount for scanning some trash, seems fair right? - -/datum/techweb_node/botany - id = "botany" - display_name = "Botanical Engineering" - description = "Botanical tools" - prereq_ids = list("biotech") - design_ids = list( - "biogenerator", - "flora_gun", - "gene_shears", - "hydro_tray", - "portaseeder", - "seed_extractor", - "adv_watering_can", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) - required_experiments = list(/datum/experiment/scanning/random/plants/wild) - discount_experiments = list(/datum/experiment/scanning/random/plants/traits = 3000) - -/datum/techweb_node/fishing - id = "fishing" - display_name = "Fishing Technology" - description = "Cutting edge fishing advancements." - prereq_ids = list("base") - design_ids = list( - "fishing_rod_tech", - "stabilized_hook", - "auto_reel", - "fish_analyzer", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000) - required_experiments = list(/datum/experiment/scanning/fish) - -/datum/techweb_node/exp_tools - id = "exp_tools" - display_name = "Experimental Tools" - description = "Highly advanced tools." - prereq_ids = list("adv_engi") - design_ids = list( - "exwelder", - "handdrill", - "jawsoflife", - "laserscalpel", - "mechanicalpinches", - "rangedanalyzer", - "searingtool", - "adv_fire_extinguisher", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - discount_experiments = list(/datum/experiment/scanning/random/material/hard/one = 5000) - -/datum/techweb_node/sec_basic - id = "sec_basic" - display_name = "Basic Security Equipment" - description = "Standard equipment used by security." - prereq_ids = list("base") - design_ids = list( - "bola_energy", - "evidencebag", - "pepperspray", - "seclite", - "zipties", - "inspector", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -/datum/techweb_node/rcd_upgrade - id = "rcd_upgrade" - display_name = "Rapid Device Upgrade Designs" - description = "Unlocks new designs that improve rapid devices." - prereq_ids = list("adv_engi") - design_ids = list( - "rcd_upgrade_anti_interrupt", - "rcd_upgrade_cooling", - "rcd_upgrade_frames", - "rcd_upgrade_furnishing", - "rcd_upgrade_simple_circuits", - "rpd_upgrade_unwrench", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_rcd_upgrade - id = "adv_rcd_upgrade" - display_name = "Advanced RCD Designs Upgrade" - description = "Unlocks new RCD designs." - design_ids = list( - "rcd_upgrade_silo_link", - ) - prereq_ids = list( - "bluespace_travel", - "rcd_upgrade", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - discount_experiments = list(/datum/experiment/scanning/random/material/hard/two = 5000) - -/////////////////////////weaponry tech///////////////////////// -/datum/techweb_node/weaponry - id = "weaponry" - display_name = "Weapon Development Technology" - description = "Our researchers have found new ways to weaponize just about everything now." - prereq_ids = list("engineering") - design_ids = list( - "ballistic_shield", - "pin_testing", - "tele_shield", - "lasershell", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 20000) - discount_experiments = list(/datum/experiment/ordnance/explosive/pressurebomb = 10000) - -/datum/techweb_node/adv_weaponry - id = "adv_weaponry" - display_name = "Advanced Weapon Development Technology" - description = "Our weapons are breaking the rules of reality by now." - prereq_ids = list("adv_engi", "weaponry") - design_ids = list( - "pin_loyalty", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/datum/techweb_node/electric_weapons - id = "electronic_weapons" - display_name = "Electric Weapons" - description = "Weapons using electric technology" - prereq_ids = list("weaponry", "adv_power" , "emp_basic") - design_ids = list( - "ioncarbine", - "stunrevolver", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/radioactive_weapons - id = "radioactive_weapons" - display_name = "Radioactive Weaponry" - description = "Weapons using radioactive technology." - prereq_ids = list("adv_engi", "adv_weaponry") - design_ids = list( - "nuclear_gun", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/beam_weapons - id = "beam_weapons" - display_name = "Beam Weaponry" - description = "Various basic beam weapons" - prereq_ids = list("adv_weaponry") - design_ids = list( - "temp_gun", - "xray_laser", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/adv_beam_weapons - id = "adv_beam_weapons" - display_name = "Advanced Beam Weaponry" - description = "Various advanced beam weapons" - prereq_ids = list("beam_weapons") - design_ids = list( - "beamrifle", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/explosive_weapons - id = "explosive_weapons" - display_name = "Explosive & Pyrotechnical Weaponry" - description = "If the light stuff just won't do it." - prereq_ids = list("adv_weaponry") - design_ids = list( - "adv_grenade", - "large_grenade", - "pyro_grenade", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/exotic_ammo - id = "exotic_ammo" - display_name = "Exotic Ammunition" - description = "They won't know what hit em." - prereq_ids = list("weaponry") - design_ids = list( - "c38_hotshot", - "c38_iceblox", - "techshotshell", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/gravity_gun - id = "gravity_gun" - display_name = "One-point Bluespace-gravitational Manipulator" - description = "Fancy wording for gravity gun." - prereq_ids = list("adv_weaponry", "bluespace_travel") - design_ids = list( - "gravitygun", - "mech_gravcatapult", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -//MODsuit tech - -/datum/techweb_node/mod_advanced - id = "mod_advanced" - display_name = "Advanced Modular Suits" - description = "More advanced modules, to improve modular suits." - prereq_ids = list("robotics") - design_ids = list( - "mod_visor_diaghud", - "mod_gps", - "mod_reagent_scanner", - "mod_clamp", - "mod_drill", - "mod_orebag", - "modlink_scryer", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_engineering - id = "mod_engineering" - display_name = "Engineering Modular Suits" - description = "Engineering suits, for powered engineers." - prereq_ids = list("mod_advanced", "engineering") - design_ids = list( - "mod_plating_engineering", - "mod_visor_meson", - "mod_t_ray", - "mod_magboot", - "mod_tether", - "mod_constructor", - "mod_mister_atmos", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_advanced_engineering - id = "mod_advanced_engineering" - display_name = "Advanced Engineering Modular Suits" - description = "Advanced Engineering suits, for advanced powered engineers." - prereq_ids = list("mod_engineering", "adv_engi") - design_ids = list( - "mod_plating_atmospheric", - "mod_jetpack", - "mod_rad_protection", - "mod_emp_shield", - "mod_storage_expanded", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - -/datum/techweb_node/mod_advanced_engineering/New() - if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA)) //we'll really need the rad protection modsuit module - starting_node = TRUE - - return ..() - -/datum/techweb_node/mod_medical - id = "mod_medical" - display_name = "Medical Modular Suits" - description = "Medical suits for quick rescue purposes." - prereq_ids = list("mod_advanced", "biotech") - design_ids = list( - "mod_plating_medical", - "mod_visor_medhud", - "mod_health_analyzer", - "mod_quick_carry", - "mod_injector", - "mod_organ_thrower", - "mod_dna_lock", - "mod_patienttransport", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_advanced_medical - id = "mod_advanced_medical" - display_name = "Advanced Medical Modular Suits" - description = "Advanced medical suits for quicker rescue purposes." - prereq_ids = list("mod_medical", "adv_biotech") - design_ids = list( - "mod_defib", - "mod_threadripper", - "mod_surgicalprocessor", - "mod_statusreadout", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - -/datum/techweb_node/mod_security - id = "mod_security" - display_name = "Security Modular Suits" - description = "Security suits for space crime handling." - prereq_ids = list("mod_advanced", "sec_basic") - design_ids = list( - "mod_plating_security", - "mod_visor_sechud", - "mod_stealth", - "mod_mag_harness", - "mod_pathfinder", - "mod_holster", - "mod_sonar", - "mod_projectile_dampener", - "mod_criminalcapture", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_entertainment - id = "mod_entertainment" - display_name = "Entertainment Modular Suits" - description = "Powered suits for protection against low-humor environments." - prereq_ids = list("mod_advanced", "clown") - design_ids = list( - "mod_plating_cosmohonk", - "mod_bikehorn", - "mod_microwave_beam", - "mod_waddle", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_anomaly - id = "mod_anomaly" - display_name = "Anomalock Modular Suits" - description = "Modules for modular suits that require anomaly cores to function." - prereq_ids = list("mod_advanced", "anomaly_research") - design_ids = list( - "mod_antigrav", - "mod_teleporter", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mod_anomaly_engi - id = "mod_anomaly_engi" - display_name = "Engineering Anomalock Modular Suits" - description = "Advanced modules for modular suits, using anomaly cores to become even better engineers." - prereq_ids = list("mod_advanced_engineering", "mod_anomaly") - design_ids = list( - "mod_kinesis", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) - -////////////////////////mech technology//////////////////////// -/datum/techweb_node/adv_mecha - id = "adv_mecha" - display_name = "Advanced Exosuits" - description = "For when you just aren't Gundam enough." - prereq_ids = list("adv_robotics") - design_ids = list( - "mech_repair_droid", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500) - discount_experiments = list(/datum/experiment/scanning/random/material/medium/three = 5000) - -/datum/techweb_node/odysseus - id = "mecha_odysseus" - display_name = "EXOSUIT: Odysseus" - description = "Odysseus exosuit designs" - prereq_ids = list("base") - design_ids = list( - "odysseus_chassis", - "odysseus_head", - "odysseus_left_arm", - "odysseus_left_leg", - "odysseus_main", - "odysseus_peri", - "odysseus_right_arm", - "odysseus_right_leg", - "odysseus_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/clarke - id = "mecha_clarke" - display_name = "EXOSUIT: Clarke" - description = "Clarke exosuit designs" - prereq_ids = list("engineering") - design_ids = list( - "clarke_chassis", - "clarke_head", - "clarke_left_arm", - "clarke_main", - "clarke_peri", - "clarke_right_arm", - "clarke_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/paddy - id = "mech_paddy" - display_name = "EXOSUIT: APLU \"Paddy\"" - description = "Paddy exosuit designs" - prereq_ids = list("adv_mecha", "adv_mecha_armor") - design_ids = list( - "paddyupgrade", - "mech_hydraulic_claw" - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 5000) - -/datum/techweb_node/gygax - id = "mech_gygax" - display_name = "EXOSUIT: Gygax" - description = "Gygax exosuit designs" - prereq_ids = list("adv_mecha", "adv_mecha_armor") - design_ids = list( - "gygax_armor", - "gygax_chassis", - "gygax_head", - "gygax_left_arm", - "gygax_left_leg", - "gygax_main", - "gygax_peri", - "gygax_right_arm", - "gygax_right_leg", - "gygax_targ", - "gygax_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 5000) - -/datum/techweb_node/durand - id = "mech_durand" - display_name = "EXOSUIT: Durand" - description = "Durand exosuit designs" - prereq_ids = list("adv_mecha", "adv_mecha_armor") - design_ids = list( - "durand_armor", - "durand_chassis", - "durand_head", - "durand_left_arm", - "durand_left_leg", - "durand_main", - "durand_peri", - "durand_right_arm", - "durand_right_leg", - "durand_targ", - "durand_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 3500) - -/datum/techweb_node/phazon - id = "mecha_phazon" - display_name = "EXOSUIT: Phazon" - description = "Phazon exosuit designs" - prereq_ids = list("adv_mecha", "adv_mecha_armor" , "micro_bluespace") - design_ids = list( - "phazon_armor", - "phazon_chassis", - "phazon_head", - "phazon_left_arm", - "phazon_left_leg", - "phazon_main", - "phazon_peri", - "phazon_right_arm", - "phazon_right_leg", - "phazon_targ", - "phazon_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 2500) - -/datum/techweb_node/savannah_ivanov - id = "mecha_savannah_ivanov" - display_name = "EXOSUIT: Savannah-Ivanov" - description = "Savannah-Ivanov exosuit designs" - prereq_ids = list("adv_mecha", "weaponry", "exp_tools") - design_ids = list( - "savannah_ivanov_armor", - "savannah_ivanov_chassis", - "savannah_ivanov_head", - "savannah_ivanov_left_arm", - "savannah_ivanov_left_leg", - "savannah_ivanov_main", - "savannah_ivanov_peri", - "savannah_ivanov_right_arm", - "savannah_ivanov_right_leg", - "savannah_ivanov_targ", - "savannah_ivanov_torso", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_mechbay = 3000) - -/datum/techweb_node/adv_mecha_tools - id = "adv_mecha_tools" - display_name = "Advanced Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_mecha") - design_ids = list( - "mech_rcd", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/med_mech_tools - id = "med_mech_tools" - display_name = "Medical Exosuit Equipment" - description = "Tools for high level mech suits" - prereq_ids = list("adv_biotech") - design_ids = list( - "mech_medi_beam", - "mech_sleeper", - "mech_syringe_gun", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_armor - id = "adv_mecha_armor" - display_name = "Exosuit Heavy Armor Research" - description = "Recreating heavy armor with new rapid fabrication techniques." - prereq_ids = list("adv_mecha", "bluespace_power") - design_ids = list( - "mech_ccw_armor", - "mech_proj_armor", - ) - required_experiments = list(/datum/experiment/scanning/random/mecha_damage_scan) - discount_experiments = list(/datum/experiment/scanning/random/mecha_equipped_scan = 5000) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - -/datum/techweb_node/mech_scattershot - id = "mecha_tools" - display_name = "Exosuit Weapon (LBX AC 10 \"Scattershot\")" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_mecha") - design_ids = list( - "mech_scattershot", - "mech_scattershot_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_carbine - id = "mech_carbine" - display_name = "Exosuit Weapon (FNX-99 \"Hades\" Carbine)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("exotic_ammo") - design_ids = list( - "mech_carbine", - "mech_carbine_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_ion - id = "mmech_ion" - display_name = "Exosuit Weapon (MKIV Ion Heavy Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "emp_adv") - design_ids = list( - "mech_ion", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_tesla - id = "mech_tesla" - display_name = "Exosuit Weapon (MKI Tesla Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("electronic_weapons", "adv_power") - design_ids = list( - "mech_tesla", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_laser - id = "mech_laser" - display_name = "Exosuit Weapon (CH-PS \"Immolator\" Laser)" - description = "A basic piece of mech weaponry" - prereq_ids = list("beam_weapons") - design_ids = list( - "mech_laser", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_laser_heavy - id = "mech_laser_heavy" - display_name = "Exosuit Weapon (CH-LC \"Solaris\" Laser Cannon)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_beam_weapons") - design_ids = list( - "mech_laser_heavy", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_disabler - id = "mech_disabler" - display_name = "Exosuit Weapon (CH-DS \"Peacemaker\" Mounted Disabler)" - description = "A basic piece of mech weaponry" - prereq_ids = list("adv_mecha") - design_ids = list( - "mech_disabler", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_grenade_launcher - id = "mech_grenade_launcher" - display_name = "Exosuit Weapon (SGL-6 Grenade Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list( - "mech_grenade_launcher", - "mech_grenade_launcher_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_missile_rack - id = "mech_missile_rack" - display_name = "Exosuit Weapon (BRM-6 Missile Rack)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list( - "mech_missile_rack", - "mech_missile_rack_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/clusterbang_launcher - id = "clusterbang_launcher" - display_name = "Exosuit Module (SOB-3 Clusterbang Launcher)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("explosive_weapons") - design_ids = list( - "clusterbang_launcher", - "clusterbang_launcher_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_teleporter - id = "mech_teleporter" - display_name = "Exosuit Module (Teleporter Module)" - description = "An advanced piece of mech Equipment" - prereq_ids = list("micro_bluespace") - design_ids = list( - "mech_teleporter", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_wormhole_gen - id = "mech_wormhole_gen" - display_name = "Exosuit Module (Localized Wormhole Generator)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("bluespace_travel") - design_ids = list( - "mech_wormhole_gen", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_lmg - id = "mech_lmg" - display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)" - description = "An advanced piece of mech weaponry" - prereq_ids = list("adv_mecha") - design_ids = list( - "mech_lmg", - "mech_lmg_ammo", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -/datum/techweb_node/mech_diamond_drill - id = "mech_diamond_drill" - display_name = "Exosuit Diamond Drill" - description = "A diamond drill fit for a large exosuit" - prereq_ids = list("adv_mining") - design_ids = list( - "mech_diamond_drill", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - -////////////////////////Alien technology//////////////////////// -/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech - id = "alientech" - display_name = "Alien Technology" - description = "Things used by the greys." - prereq_ids = list("biotech","engineering") - required_items_to_unlock = list( - /obj/item/stack/sheet/mineral/abductor, - /obj/item/abductor, - /obj/item/cautery/alien, - /obj/item/circuitboard/machine/abductor, - /obj/item/circular_saw/alien, - /obj/item/crowbar/abductor, - /obj/item/gun/energy/alien, - /obj/item/gun/energy/shrink_ray, - /obj/item/hemostat/alien, - /obj/item/melee/baton/abductor, - /obj/item/multitool/abductor, - /obj/item/retractor/alien, - /obj/item/scalpel/alien, - /obj/item/screwdriver/abductor, - /obj/item/surgicaldrill/alien, - /obj/item/weldingtool/abductor, - /obj/item/wirecutters/abductor, - /obj/item/wrench/abductor, - ) - design_ids = list( - "alienalloy", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) - hidden = TRUE - -/datum/techweb_node/alientech/on_station_research() - SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH] = TRUE - -/datum/techweb_node/alien_bio - id = "alien_bio" - display_name = "Alien Biological Tools" - description = "Advanced biological tools." - prereq_ids = list("alientech", "adv_biotech") - design_ids = list( - "alien_cautery", - "alien_drill", - "alien_hemostat", - "alien_retractor", - "alien_saw", - "alien_scalpel", - ) - - required_items_to_unlock = list( - /obj/item/abductor, - /obj/item/cautery/alien, - /obj/item/circuitboard/machine/abductor, - /obj/item/circular_saw/alien, - /obj/item/crowbar/abductor, - /obj/item/gun/energy/alien, - /obj/item/gun/energy/shrink_ray, - /obj/item/hemostat/alien, - /obj/item/melee/baton/abductor, - /obj/item/multitool/abductor, - /obj/item/retractor/alien, - /obj/item/scalpel/alien, - /obj/item/screwdriver/abductor, - /obj/item/surgicaldrill/alien, - /obj/item/weldingtool/abductor, - /obj/item/wirecutters/abductor, - /obj/item/wrench/abductor, - ) - - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 12500) - discount_experiments = list(/datum/experiment/scanning/points/slime/hard = 10000) - hidden = TRUE - -/datum/techweb_node/alien_engi - id = "alien_engi" - display_name = "Alien Engineering" - description = "Alien engineering tools" - prereq_ids = list("alientech", "adv_engi") - - design_ids = list( - "alien_crowbar", - "alien_multitool", - "alien_screwdriver", - "alien_welder", - "alien_wirecutters", - "alien_wrench", - ) - - required_items_to_unlock = list( - /obj/item/abductor, - /obj/item/circuitboard/machine/abductor, - /obj/item/crowbar/abductor, - /obj/item/gun/energy/shrink_ray, - /obj/item/melee/baton/abductor, - /obj/item/multitool/abductor, - /obj/item/screwdriver/abductor, - /obj/item/weldingtool/abductor, - /obj/item/wirecutters/abductor, - /obj/item/wrench/abductor, - ) - - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - -/datum/techweb_node/syndicate_basic - id = "syndicate_basic" - display_name = "Illegal Technology" - description = "Dangerous research used to create dangerous objects." - prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons") - design_ids = list( - "advanced_camera", - "ai_cam_upgrade", - "borg_syndicate_module", - "donksoft_refill", - "donksofttoyvendor", - "largecrossbow", - "mag_autorifle", - "mag_autorifle_ap", - "mag_autorifle_ic", - "rapidsyringe", - "suppressor", - "super_pointy_tape", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000) - hidden = TRUE - -/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. - . = ..() - if(!SSearly_assets.initialized) - RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(register_uplink_items)) - else - register_uplink_items() - -/** - * This needs some clarification: The uplink_items_by_type list is populated on datum/asset/json/uplink/generate. - * SStraitor doesn't actually initialize. I'm bamboozled. - */ -/datum/techweb_node/syndicate_basic/proc/register_uplink_items() - SIGNAL_HANDLER - UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE) - required_items_to_unlock = list() - for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) - var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] - if(!item.item || !item.illegal_tech) - continue - required_items_to_unlock |= item.item //allows deconning to unlock. - - -////////////////////////B.E.P.I.S. Locked Techs//////////////////////// -/datum/techweb_node/light_apps - id = "light_apps" - display_name = "Illumination Applications" - description = "Applications of lighting and vision technology not originally thought to be commercially viable." - prereq_ids = list("base") - design_ids = list( - "bright_helmet", - "rld_mini", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/extreme_office - id = "extreme_office" - display_name = "Advanced Office Applications" - description = "Some of our smartest lab guys got together on a Friday and improved our office efficiency by 350%. Here's how." - prereq_ids = list("base") - design_ids = list( - "mauna_mug", - "rolling_table", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/spec_eng - id = "spec_eng" - display_name = "Specialized Engineering" - description = "Conventional wisdom has deemed these engineering products 'technically' safe, but far too dangerous to traditionally condone." - prereq_ids = list("base") - design_ids = list( - "eng_gloves", - "lava_rods", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/aus_security - id = "aus_security" - display_name = "Australicus Security Protocols" - description = "It is said that security in the Australicus sector is tight, so we took some pointers from their equipment. Thankfully, our sector lacks any signs of these, 'dropbears'." - prereq_ids = list("base") - design_ids = list( - "pin_explorer", - "stun_boomerang", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/interrogation - id = "interrogation" - display_name = "Enhanced Interrogation Technology" - description = "By cross-referencing several declassified documents from past dictatorial regimes, we were able to develop an incredibly effective interrogation device. \ - Ethical concerns about loss of free will do not apply to criminals, according to galactic law." - prereq_ids = list("base") - design_ids = list( - "hypnochair", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/sticky_advanced - id = "sticky_advanced" - display_name = "Advanced Sticky Technology" - description = "Taking a good joke too far? Nonsense!" - design_ids = list( - "pointy_tape", - "super_sticky_tape", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/tackle_advanced - id = "tackle_advanced" - display_name = "Advanced Grapple Technology" - description = "Nanotrasen would like to remind its researching staff that it is never acceptable to \"glomp\" your coworkers, and further \"scientific trials\" on the subject \ - will no longer be accepted in its academic journals." - design_ids = list( - "tackle_dolphin", - "tackle_rocket", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/mod_experimental - id = "mod_experimental" - display_name = "Experimental Modular Suits" - description = "Applications of experimentality when creating MODsuits have created these..." - prereq_ids = list("base") - design_ids = list( - "mod_disposal", - "mod_joint_torsion", - "mod_recycler", - "mod_shooting", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/mod_experimental - id = "mod_experimental" - display_name = "Experimental Modular Suits" - description = "Applications of experimentality when creating MODsuits have created these..." - prereq_ids = list("base") - design_ids = list( - "mod_disposal", - "mod_joint_torsion", - "mod_recycler", - "mod_shooting", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE - -/datum/techweb_node/posisphere - id = "positronic_sphere" - display_name = "Experimental Spherical Positronic Brain" - description = "Recent developments on cost-cutting measures have allowed us to cut positronic brain cubes into twice-as-cheap spheres. Unfortunately, it also allows them to move around the lab via rolling maneuvers." - prereq_ids = list("base") - design_ids = list( - "posisphere", - ) - research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) - hidden = TRUE - experimental = TRUE diff --git a/code/modules/research/techweb/nodes/alien_nodes.dm b/code/modules/research/techweb/nodes/alien_nodes.dm new file mode 100644 index 0000000000000..bf19c0c54a47d --- /dev/null +++ b/code/modules/research/techweb/nodes/alien_nodes.dm @@ -0,0 +1,100 @@ +/datum/techweb_node/alientech //AYYYYYYYYLMAOO tech + id = "alientech" + display_name = "Alien Technology" + description = "Things used by the greys." + prereq_ids = list("bluespace_travel") + required_items_to_unlock = list( + /obj/item/stack/sheet/mineral/abductor, + /obj/item/abductor, + /obj/item/cautery/alien, + /obj/item/circuitboard/machine/abductor, + /obj/item/circular_saw/alien, + /obj/item/crowbar/abductor, + /obj/item/gun/energy/alien, + /obj/item/gun/energy/shrink_ray, + /obj/item/hemostat/alien, + /obj/item/melee/baton/abductor, + /obj/item/multitool/abductor, + /obj/item/retractor/alien, + /obj/item/scalpel/alien, + /obj/item/screwdriver/abductor, + /obj/item/surgicaldrill/alien, + /obj/item/weldingtool/abductor, + /obj/item/wirecutters/abductor, + /obj/item/wrench/abductor, + ) + design_ids = list( + "alienalloy", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + hidden = TRUE + +/datum/techweb_node/alientech/on_station_research() + SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH] = TRUE + +/datum/techweb_node/alien_engi + id = "alien_engi" + display_name = "Alien Engineering" + description = "Alien engineering tools" + prereq_ids = list("alientech", "exp_tools") + design_ids = list( + "alien_crowbar", + "alien_multitool", + "alien_screwdriver", + "alien_welder", + "alien_wirecutters", + "alien_wrench", + ) + required_items_to_unlock = list( + /obj/item/abductor, + /obj/item/circuitboard/machine/abductor, + /obj/item/crowbar/abductor, + /obj/item/gun/energy/shrink_ray, + /obj/item/melee/baton/abductor, + /obj/item/multitool/abductor, + /obj/item/screwdriver/abductor, + /obj/item/weldingtool/abductor, + /obj/item/wirecutters/abductor, + /obj/item/wrench/abductor, + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + hidden = TRUE + +/datum/techweb_node/alien_surgery + id = "alien_surgery" + display_name = "Alien Surgery" + description = "Abductors did nothing wrong." + prereq_ids = list("alientech", "surgery_tools") + design_ids = list( + "alien_cautery", + "alien_drill", + "alien_hemostat", + "alien_retractor", + "alien_saw", + "alien_scalpel", + "surgery_brainwashing", + "surgery_heal_combo_upgrade_femto", + "surgery_zombie", + ) + required_items_to_unlock = list( + /obj/item/abductor, + /obj/item/cautery/alien, + /obj/item/circuitboard/machine/abductor, + /obj/item/circular_saw/alien, + /obj/item/crowbar/abductor, + /obj/item/gun/energy/alien, + /obj/item/gun/energy/shrink_ray, + /obj/item/hemostat/alien, + /obj/item/melee/baton/abductor, + /obj/item/multitool/abductor, + /obj/item/retractor/alien, + /obj/item/scalpel/alien, + /obj/item/screwdriver/abductor, + /obj/item/surgicaldrill/alien, + /obj/item/weldingtool/abductor, + /obj/item/wirecutters/abductor, + /obj/item/wrench/abductor, + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + discount_experiments = list(/datum/experiment/scanning/points/slime/hard = TECHWEB_TIER_5_POINTS) + hidden = TRUE diff --git a/code/modules/research/techweb/nodes/atmos_nodes.dm b/code/modules/research/techweb/nodes/atmos_nodes.dm new file mode 100644 index 0000000000000..b97538070beba --- /dev/null +++ b/code/modules/research/techweb/nodes/atmos_nodes.dm @@ -0,0 +1,114 @@ +/datum/techweb_node/atmos + id = "atmos" + starting_node = TRUE + display_name = "Atmospherics" + description = "Maintaining station air and related life support systems." + design_ids = list( + "atmos_control", + "atmosalerts", + "thermomachine", + "space_heater", + "generic_tank", + "oxygen_tank", + "plasma_tank", + "plasmaman_tank_belt", + "plasmarefiller", + "extinguisher", + "gas_filter", + "plasmaman_gas_filter", + "analyzer", + "pipe_painter", + ) + +/datum/techweb_node/gas_compression + id = "gas_compression" + display_name = "Gas Compression" + description = "Highly pressurized gases hold potential for unlocking immense energy capabilities." + prereq_ids = list("atmos") + design_ids = list( + "tank_compressor", + "emergency_oxygen", + "emergency_oxygen_engi", + "power_turbine_console", + "turbine_part_compressor", + "turbine_part_rotor", + "turbine_part_stator", + "turbine_compressor", + "turbine_rotor", + "turbine_stator", + "atmos_thermal", + "pneumatic_seal", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/plasma_control + id = "plasma_control" + display_name = "Controlled Plasma" + description = "Experiments with high-pressure gases and electricity resulting in crystallization and controlled plasma reactions." + prereq_ids = list("gas_compression", "energy_manipulation") + design_ids = list( + "crystallizer", + "electrolyzer", + "pacman", + "mech_generator", + "plasmacutter", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + required_experiments = list(/datum/experiment/ordnance/gaseous/plasma) + +/datum/techweb_node/fusion + id = "fusion" + display_name = "Fusion" + description = "Investigating fusion reactor technology to achieve sustainable and efficient energy production through controlled plasma reactions involving noble gases." + prereq_ids = list("plasma_control") + design_ids = list( + "HFR_core", + "HFR_corner", + "HFR_fuel_input", + "HFR_interface", + "HFR_moderator_input", + "HFR_waste_output", + "bolter_wrench", + "rpd_loaded", + "engine_goggles", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/ordnance/gaseous/bz) + discount_experiments = list(/datum/experiment/ordnance/gaseous/nitrous_oxide = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/exp_tools + id = "exp_tools" + display_name = "Experimental Tools" + description = "Enhances the functionality and versatility of station tools." + prereq_ids = list("fusion") + design_ids = list( + "flatpacker", + "handdrill", + "exwelder", + "jawsoflife", + "rangedanalyzer", + "rtd_loaded", + "rcd_loaded", + "rcd_ammo", + "weldingmask", + "magboots", + "adv_fire_extinguisher", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + discount_experiments = list(/datum/experiment/ordnance/gaseous/noblium = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/rcd_upgrade + id = "rcd_upgrade" + display_name = "Rapid Device Upgrade Designs" + description = "New designs and enhancements for RCD and RPD." + prereq_ids = list("exp_tools", "parts_bluespace") + design_ids = list( + "rcd_upgrade_silo_link", + "rcd_upgrade_anti_interrupt", + "rcd_upgrade_cooling", + "rcd_upgrade_frames", + "rcd_upgrade_furnishing", + "rcd_upgrade_simple_circuits", + "rpd_upgrade_unwrench", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) diff --git a/code/modules/research/techweb/nodes/bepis_nodes.dm b/code/modules/research/techweb/nodes/bepis_nodes.dm new file mode 100644 index 0000000000000..c051aab526f81 --- /dev/null +++ b/code/modules/research/techweb/nodes/bepis_nodes.dm @@ -0,0 +1,123 @@ +/datum/techweb_node/light_apps + id = "light_apps" + display_name = "Illumination Applications" + description = "Applications of lighting and vision technology not originally thought to be commercially viable." + design_ids = list( + "bright_helmet", + "rld_mini", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/extreme_office + id = "extreme_office" + display_name = "Advanced Office Applications" + description = "Some of our smartest lab guys got together on a Friday and improved our office efficiency by 350%. Here's how." + design_ids = list( + "mauna_mug", + "rolling_table", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/spec_eng + id = "spec_eng" + display_name = "Specialized Engineering" + description = "Conventional wisdom has deemed these engineering products 'technically' safe, but far too dangerous to traditionally condone." + design_ids = list( + "eng_gloves", + "lava_rods", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/aus_security + id = "aus_security" + display_name = "Australicus Security Protocols" + description = "It is said that security in the Australicus sector is tight, so we took some pointers from their equipment. Thankfully, our sector lacks any signs of these, 'dropbears'." + design_ids = list( + "pin_explorer", + "stun_boomerang", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/interrogation + id = "interrogation" + display_name = "Enhanced Interrogation Technology" + description = "By cross-referencing several declassified documents from past dictatorial regimes, we were able to develop an incredibly effective interrogation device. \ + Ethical concerns about loss of free will do not apply to criminals, according to galactic law." + design_ids = list( + "hypnochair", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/sticky_advanced + id = "sticky_advanced" + display_name = "Advanced Sticky Technology" + description = "Taking a good joke too far? Nonsense!" + design_ids = list( + "pointy_tape", + "super_sticky_tape", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/tackle_advanced + id = "tackle_advanced" + display_name = "Advanced Grapple Technology" + description = "Nanotrasen would like to remind its researching staff that it is never acceptable to \"glomp\" your coworkers, and further \"scientific trials\" on the subject \ + will no longer be accepted in its academic journals." + design_ids = list( + "tackle_dolphin", + "tackle_rocket", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/mod_experimental + id = "mod_experimental" + display_name = "Experimental Modular Suits" + description = "Applications of experimentality when creating MODsuits have created these..." + design_ids = list( + "mod_disposal", + "mod_joint_torsion", + "mod_recycler", + "mod_shooting", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/mod_experimental + id = "mod_experimental" + display_name = "Experimental Modular Suits" + description = "Applications of experimentality when creating MODsuits have created these..." + design_ids = list( + "mod_disposal", + "mod_joint_torsion", + "mod_recycler", + "mod_shooting", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE + +/datum/techweb_node/posisphere + id = "positronic_sphere" + display_name = "Experimental Spherical Positronic Brain" + description = "Recent developments on cost-cutting measures have allowed us to cut positronic brain cubes into twice-as-cheap spheres. Unfortunately, it also allows them to move around the lab via rolling maneuvers." + design_ids = list( + "posisphere", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + experimental = TRUE diff --git a/code/modules/research/techweb/nodes/biology_nodes.dm b/code/modules/research/techweb/nodes/biology_nodes.dm new file mode 100644 index 0000000000000..6a14d7d517c8f --- /dev/null +++ b/code/modules/research/techweb/nodes/biology_nodes.dm @@ -0,0 +1,64 @@ +/datum/techweb_node/bio_scan + id = "bio_scan" + display_name = "Biological Scan" + description = "Advanced technology for analyzing patient health and reagent compositions, ensuring precise diagnostics and treatment in the medical bay." + prereq_ids = list("medbay_equip") + design_ids = list( + "healthanalyzer", + "autopsyscanner", + "medical_kiosk", + "chem_master", + "ph_meter", + "scigoggles", + "mod_reagent_scanner", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/cytology + id = "cytology" + display_name = "Cytology" + description = "Cellular biology research focused on cultivation of limbs and diverse organisms from cells." + prereq_ids = list("bio_scan") + design_ids = list( + "limbgrower", + "pandemic", + "petri_dish", + "swab", + "biopsy_tool", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/xenobiology + id = "xenobiology" + display_name = "Xenobiology" + description = "Exploration of non-human biology, unlocking the secrets of extraterrestrial lifeforms and their unique biological processes." + prereq_ids = list("cytology") + design_ids = list( + "xenobioconsole", + "slime_scanner", + "limbdesign_ethereal", + "limbdesign_felinid", + "limbdesign_lizard", + "limbdesign_plasmaman", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/scanning/random/cytology) + +/datum/techweb_node/gene_engineering + id = "gene_engineering" + display_name = "Gene Engineering" + description = "Research into sophisticated DNA manipulation techniques, enabling the modification of human genetic traits to unlock specific abilities and enhancements." + prereq_ids = list("selection", "xenobiology") + design_ids = list( + "dnascanner", + "scan_console", + "dna_disk", + "dnainfuser", + "genescanner", + "mod_dna_lock", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + discount_experiments = list( + /datum/experiment/scanning/random/plants/traits = TECHWEB_TIER_2_POINTS, + /datum/experiment/scanning/points/slime/hard = TECHWEB_TIER_2_POINTS, + ) diff --git a/code/modules/research/techweb/nodes/circuit_nodes.dm b/code/modules/research/techweb/nodes/circuit_nodes.dm new file mode 100644 index 0000000000000..81f6dad275f0d --- /dev/null +++ b/code/modules/research/techweb/nodes/circuit_nodes.dm @@ -0,0 +1,151 @@ +/datum/techweb_node/programming + id = "programming" + starting_node = TRUE + display_name = "Programming" + description = "Dedicate an entire shift to program a fridge to greet you when opened." + prereq_ids = list("robotics") + design_ids = list( + "component_printer", + "module_duplicator", + "circuit_multitool", + "compact_remote_shell", + "usb_cable", + "integrated_circuit", + "comp_access_checker", + "comp_arctan2", + "comp_arithmetic", + "comp_assoc_list_pick", + "comp_assoc_list_remove", + "comp_assoc_list_set", + "comp_binary_convert", + "comp_clock", + "comp_comparison", + "comp_concat", + "comp_concat_list", + "comp_decimal_convert", + "comp_delay", + "comp_direction", + "comp_element_find", + "comp_filter_list", + "comp_foreach", + "comp_format", + "comp_format_assoc", + "comp_get_column", + "comp_gps", + "comp_health", + "comp_health_state", + "comp_hear", + "comp_id_access_reader", + "comp_id_getter", + "comp_id_info_reader", + "comp_index", + "comp_index_assoc", + "comp_index_table", + "comp_laserpointer", + "comp_length", + "comp_light", + "comp_list_add", + "comp_list_assoc_literal", + "comp_list_clear", + "comp_list_literal", + "comp_list_pick", + "comp_list_remove", + "comp_logic", + "comp_matscanner", + "comp_mmi", + "comp_module", + "comp_multiplexer", + "comp_not", + "comp_ntnet_receive", + "comp_ntnet_send", + "comp_ntnet_send_list_literal", + "comp_pinpointer", + "comp_pressuresensor", + "comp_radio", + "comp_random", + "comp_reagents", + "comp_router", + "comp_select_query", + "comp_self", + "comp_set_variable_trigger", + "comp_soundemitter", + "comp_species", + "comp_speech", + "comp_speech", + "comp_split", + "comp_string_contains", + "comp_tempsensor", + "comp_textcase", + "comp_timepiece", + "comp_toggle", + "comp_tonumber", + "comp_tostring", + "comp_trigonometry", + "comp_typecast", + "comp_typecheck", + "comp_view_sensor", + ) + +/datum/techweb_node/circuit_shells + id = "circuit_shells" + display_name = "Advanced Circuit Shells" + description = "Adding brains to more things." + prereq_ids = list("programming") + design_ids = list( + "assembly_shell", + "bot_shell", + "controller_shell", + "dispenser_shell", + "door_shell", + "gun_shell", + "keyboard_shell", + "module_shell", + "money_bot_shell", + "scanner_gate_shell", + "scanner_shell", + "comp_equip_action", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/bci + id = "bci" + display_name = "Brain-Computer Interface" + description = "Embedded brain circuits. May occasionally stream Nanotrasen ads in dreams." + prereq_ids = list("circuit_shells", "passive_implants") + design_ids = list( + "bci_implanter", + "bci_shell", + "comp_bar_overlay", + "comp_camera_bci", + "comp_counter_overlay", + "comp_install_detector", + "comp_object_overlay", + "comp_reagent_injector", + "comp_target_intercept", + "comp_thought_listener", + "comp_vox", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + discount_experiments = list(/datum/experiment/scanning/people/skillchip = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/programmed_robot + id = "programmed_robot" + display_name = "Programmed Robot" + description = "Grants access to movable shells, allowing for remote operations and pranks." + prereq_ids = list("circuit_shells") + design_ids = list( + "drone_shell", + "comp_pathfind", + "comp_pull", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/programmed_server + id = "programmed_server" + display_name = "Programmed Server" + description = "Grants access to a server shell that has a very high capacity for components." + prereq_ids = list("bci") + design_ids = list( + "server_shell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) diff --git a/code/modules/research/techweb/nodes/cyborg_nodes.dm b/code/modules/research/techweb/nodes/cyborg_nodes.dm new file mode 100644 index 0000000000000..a4e0debd6ebb8 --- /dev/null +++ b/code/modules/research/techweb/nodes/cyborg_nodes.dm @@ -0,0 +1,231 @@ +/datum/techweb_node/augmentation + id = "augmentation" + starting_node = TRUE + display_name = "Augmentation" + description = "For those who prefer shiny metal over squishy flesh." + prereq_ids = list("robotics") + design_ids = list( + "borg_chest", + "borg_head", + "borg_l_arm", + "borg_l_leg", + "borg_r_arm", + "borg_r_leg", + "cybernetic_eyes", + "cybernetic_eyes_moth", + "cybernetic_ears", + "cybernetic_lungs", + "cybernetic_stomach", + "cybernetic_liver", + "cybernetic_heart", + ) + +/datum/techweb_node/cybernetics + id = "cybernetics" + display_name = "Cybernetics" + description = "Sapient robots with preloaded tool modules and programmable laws." + prereq_ids = list("augmentation") + design_ids = list( + "robocontrol", + "borgupload", + "cyborgrecharger", + "borg_suit", + "mmi_posi", + "mmi", + "mmi_m", + "advanced_l_arm", + "advanced_r_arm", + "advanced_l_leg", + "advanced_r_leg", + "borg_upgrade_rename", + "borg_upgrade_restart", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/borg_service + id = "borg_service" + display_name = "Service Cyborg Upgrades" + description = "Let them do the cookin' by the book." + prereq_ids = list("cybernetics") + design_ids = list( + "borg_upgrade_rolling_table", + "borg_upgrade_condiment_synthesizer", + "borg_upgrade_silicon_knife", + "borg_upgrade_service_apparatus", + "borg_upgrade_drink_apparatus", + "borg_upgrade_service_cookbook", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/borg_mining + id = "borg_mining" + display_name = "Mining Cyborg Upgrades" + description = "To mine places too dangerous for humans." + prereq_ids = list("cybernetics") + design_ids = list( + "borg_upgrade_lavaproof", + "borg_upgrade_holding", + "borg_upgrade_diamonddrill", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/borg_medical + id = "borg_medical" + display_name = "Medical Cyborg Upgrades" + description = "Let them follow Asimov's First Law." + prereq_ids = list("borg_service", "surgery_adv") + design_ids = list( + "borg_upgrade_pinpointer", + "borg_upgrade_beakerapp", + "borg_upgrade_defibrillator", + "borg_upgrade_expandedsynthesiser", + "borg_upgrade_piercinghypospray", + "borg_upgrade_surgicalprocessor", + "borg_upgrade_surgicalomnitool", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/borg_utility + id = "borg_utility" + display_name = "Untility Cyborg Upgrades" + description = "Let them wipe our floors for us." + prereq_ids = list("borg_service", "sanitation") + design_ids = list( + "borg_upgrade_advancedmop", + "borg_upgrade_broomer", + "borg_upgrade_expand", + "borg_upgrade_prt", + "borg_upgrade_selfrepair", + "borg_upgrade_thrusters", + "borg_upgrade_trashofholding", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/borg_utility/New() + . = ..() + if(!CONFIG_GET(flag/disable_secborg)) + design_ids += "borg_upgrade_disablercooler" + +/datum/techweb_node/borg_engi + id = "borg_engi" + display_name = "Engineering Cyborg Upgrades" + description = "To slack even more." + prereq_ids = list("borg_mining", "parts_upg") + design_ids = list( + "borg_upgrade_rped", + "borg_upgrade_engineeringomnitool", + "borg_upgrade_circuitapp", + "borg_upgrade_inducer", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +// Implants root node +/datum/techweb_node/passive_implants + id = "passive_implants" + display_name = "Passive Implants" + description = "Implants designed to operate seamlessly without active user input, enhancing various physiological functions or providing continuous benefits." + prereq_ids = list("augmentation") + design_ids = list( + "skill_station", + "implant_trombone", + "implant_chem", + "implant_tracking", + "implant_exile", + "implant_beacon", + "implant_bluespace", + "implantcase", + "implanter", + "locator", + "c38_trac", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/cyber/cyber_implants + id = "cyber_implants" + display_name = "Cybernetic Implants" + description = "Advanced technological enhancements integrated into the body, offering improved physical capabilities." + prereq_ids = list("passive_implants", "cybernetics") + design_ids = list( + "ci-breather", + "ci-nutriment", + "ci-thrusters", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/cyber/New() + ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_CYBERNETIC_REVOLUTION)) + research_costs[TECHWEB_POINT_TYPE_GENERIC] /= 2 + +/datum/techweb_node/cyber/combat_implants + id = "combat_implants" + display_name = "Combat Implants" + description = "To make sure that you can wake the f*** up, samurai." + prereq_ids = list("cyber_implants") + design_ids = list( + "ci-reviver", + "ci-antidrop", + "ci-antistun", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/cyber/integrated_toolsets + id = "integrated_toolsets" + display_name = "Integrated Toolsets" + description = "Decades of contraband smuggling by assistants have led to the development of a full toolbox that fits seamlessly into your arm." + prereq_ids = list("combat_implants", "exp_tools") + design_ids = list( + "ci-nutrimentplus", + "ci-toolset", + "ci-surgery", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + +/datum/techweb_node/cyber/cyber_organs + id = "cyber_organs" + display_name = "Cybernetic Organs" + description = "We have the technology to rebuild him." + prereq_ids = list("cybernetics") + design_ids = list( + "cybernetic_eyes_improved", + "cybernetic_eyes_improved_moth", + "cybernetic_ears_u", + "cybernetic_lungs_tier2", + "cybernetic_stomach_tier2", + "cybernetic_liver_tier2", + "cybernetic_heart_tier2", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/cyber/cyber_organs_upgraded + id = "cyber_organs_upgraded" + display_name = "Upgraded Cybernetic Organs" + description = "We have the technology to upgrade him." + prereq_ids = list("cyber_organs") + design_ids = list( + "ci-gloweyes", + "ci-welding", + "ci-gloweyes-moth", + "ci-welding-moth", + "cybernetic_ears_whisper", + "cybernetic_lungs_tier3", + "cybernetic_stomach_tier3", + "cybernetic_liver_tier3", + "cybernetic_heart_tier3", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + required_experiments = list(/datum/experiment/scanning/people/augmented_organs) + +/datum/techweb_node/cyber/cyber_organs_adv + id = "cyber_organs_adv" + display_name = "Advanced Cybernetic Organs" + description = "Cutting-edge cybernetic organs offering enhanced sensory capabilities, making it easier than ever to detect ERP." + prereq_ids = list("cyber_organs_upgraded", "night_vision") + design_ids = list( + "cybernetic_ears_xray", + "ci-thermals", + "ci-xray", + "ci-thermals-moth", + "ci-xray-moth", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) diff --git a/code/modules/research/techweb/nodes/engi_nodes.dm b/code/modules/research/techweb/nodes/engi_nodes.dm new file mode 100644 index 0000000000000..182f689c372cd --- /dev/null +++ b/code/modules/research/techweb/nodes/engi_nodes.dm @@ -0,0 +1,232 @@ +// Parts root node +/datum/techweb_node/parts + id = "parts" + starting_node = TRUE + display_name = "Essential Stock Parts" + description = "Foundational components that form the backbone of station operations, encompassing a range of essential equipment necessary for day-to-day functionality." + design_ids = list( + "micro_servo", + "basic_capacitor", + "basic_matter_bin", + "basic_micro_laser", + "basic_scanning", + "high_cell", + "basic_cell", + "miniature_power_cell", + "condenser", + "igniter", + "infrared_emitter", + "prox_sensor", + "signaler", + "timer", + "voice_analyzer", + "health_sensor", + "sflash", + ) + +/datum/techweb_node/parts_upg + id = "parts_upg" + display_name = "Upgraded Parts" + description = "Offering enhanced capabilities beyond their basic counterparts." + prereq_ids = list("parts", "energy_manipulation") + design_ids = list( + "rped", + "high_micro_laser", + "adv_capacitor", + "nano_servo", + "adv_matter_bin", + "adv_scanning", + "super_cell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/parts_adv + id = "parts_adv" + display_name = "Advanced Parts" + description = "The most finely tuned and accurate stock parts." + prereq_ids = list("parts_upg") + design_ids = list( + "ultra_micro_laser", + "super_capacitor", + "pico_servo", + "super_matter_bin", + "phasic_scanning", + "hyper_cell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier2_any) + + +/datum/techweb_node/parts_bluespace + id = "parts_bluespace" + display_name = "Bluespace Parts" + description = "Integrating the latest in bluespace technology, these advanced components not only enhance functionality but also open up new possibilities for the station's technological capabilities." + prereq_ids = list("parts_adv", "bluespace_travel") + design_ids = list( + "bs_rped", + "quadultra_micro_laser", + "quadratic_capacitor", + "femto_servo", + "bluespace_matter_bin", + "triphasic_scanning", + "bluespace_cell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + discount_experiments = list(/datum/experiment/scanning/points/machinery_tiered_scan/tier3_any = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/telecomms + id = "telecomms" + display_name = "Telecommunications Technology" + description = "A comprehensive suite of machinery for station-wide communication setups, ensuring seamless connectivity and operational coordination." + prereq_ids = list("parts_bluespace") + design_ids = list( + "comm_monitor", + "comm_server", + "message_monitor", + "s_hub", + "s_messaging", + "s_server", + "s_processor", + "s_relay", + "s_bus", + "s_broadcaster", + "s_receiver", + "s_amplifier", + "s_analyzer", + "s_ansible", + "s_crystal", + "s_filter", + "s_transmitter", + "s_treatment", + "gigabeacon", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + +// Engineering root node +/datum/techweb_node/construction + id = "construction" + starting_node = TRUE + display_name = "Construction" + description = "Tools and essential machinery used for station maintenance and expansion." + design_ids = list( + "circuit_imprinter_offstation", + "circuit_imprinter", + "solarcontrol", + "solar_panel", + "solar_tracker", + "power_control", + "airalarm_electronics", + "airlock_board", + "firealarm_electronics", + "firelock_board", + "trapdoor_electronics", + "blast", + "tile_sprayer", + "airlock_painter", + "decal_painter", + "rwd", + "cable_coil", + "welding_helmet", + "welding_tool", + "tscanner", + "analyzer", + "multitool", + "wrench", + "crowbar", + "screwdriver", + "wirecutters", + "light_bulb", + "light_tube", + "intercom_frame", + "newscaster_frame", + "status_display_frame", + "circuit", + "circuitgreen", + "circuitred", + "tram_floor_dark", + "tram_floor_light", + "tram_controller", + "tram_display", + "crossing_signal", + "guideway_sensor", + ) + +/datum/techweb_node/energy_manipulation + id = "energy_manipulation" + display_name = "Energy Manipulation" + description = "Harnessing the raw power of lightning arcs through sophisticated energy control methods." + prereq_ids = list("construction") + design_ids = list( + "apc_control", + "powermonitor", + "smes", + "emitter", + "grounding_rod", + "tesla_coil", + "cell_charger", + "recharger", + "inducer", + "inducerengi", + "welding_goggles", + "tray_goggles", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/holographics + id = "holographics" + display_name = "Holographics" + description = "Use of holographic technology for signage and barriers." + prereq_ids = list("energy_manipulation") + design_ids = list( + "forcefield_projector", + "holosign", + "holosignsec", + "holosignengi", + "holosignatmos", + "holosignrestaurant", + "holosignbar", + "holobarrier_jani", + "holobarrier_med", + "holopad", + "vendatray", + "holodisk", + "modular_shield_generator", + "modular_shield_node", + "modular_shield_relay", + "modular_shield_charger", + "modular_shield_well", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/hud + id = "hud" + display_name = "Integrated HUDs" + description = "Initially developed for assistants to learn the nuances of different professions through augmented reality." + prereq_ids = list("holographics", "cyber_implants") + design_ids = list( + "health_hud", + "diagnostic_hud", + "security_hud", + "mod_visor_medhud", + "mod_visor_diaghud", + "mod_visor_sechud", + "ci-medhud", + "ci-diaghud", + "ci-sechud", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/night_vision + id = "night_vision" + display_name = "Night Vision Technology" + description = "There are whispers that Nanotrasen pushed for this technology to extend shift durations, ensuring productivity around the clock." + prereq_ids = list("hud") + design_ids = list( + "diagnostic_hud_night", + "health_hud_night", + "night_visision_goggles", + "nvgmesons", + "nv_scigoggles", + "security_hud_night", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/mech_nodes.dm b/code/modules/research/techweb/nodes/mech_nodes.dm new file mode 100644 index 0000000000000..4f58ed25c8955 --- /dev/null +++ b/code/modules/research/techweb/nodes/mech_nodes.dm @@ -0,0 +1,251 @@ +/datum/techweb_node/mech_assembly + id = "mech_assembly" + starting_node = TRUE + display_name = "Mech Assembly" + description = "Development of mech designed to contend with artificial gravity while transporting cargo." + prereq_ids = list("robotics") + design_ids = list( + "mechapower", + "mech_recharger", + "ripley_chassis", + "ripley_torso", + "ripley_left_arm", + "ripley_right_arm", + "ripley_left_leg", + "ripley_right_leg", + "ripley_main", + "ripley_peri", + "mech_hydraulic_clamp", + ) + +/datum/techweb_node/mech_equipment + id = "mech_equipment" + display_name = "Expedition Equipment" + description = "Specialized mech gear tailored for navigating space and celestial bodies, ensuring durability and functionality in the harshest conditions." + prereq_ids = list("mech_assembly") + design_ids = list( + "mechacontrol", + "botpad", + "botpad_remote", + "ripleyupgrade", + "mech_air_tank", + "mech_thrusters", + "mech_extinguisher", + "mecha_camera", + "mecha_tracking", + "mech_radio", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/mech_clown + id = "mech_clown" + display_name = "Funny Robots" + description = "Fueled by laughter." + prereq_ids = list("mech_assembly") + design_ids = list( + "honk_chassis", + "honk_torso", + "honk_head", + "honk_left_arm", + "honk_right_arm", + "honk_left_leg", + "honk_right_leg", + "honker_main", + "honker_peri", + "honker_targ", + "mech_banana_mortar", + "mech_honker", + "mech_mousetrap_mortar", + "mech_punching_face", + "borg_transform_clown", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/mech_medical + id = "mech_medical" + display_name = "Medical Mech" + description = "Advanced robotic unit equipped with syringe guns and healing beams, revolutionizing medical assistance in hazardous environments." + prereq_ids = list("mech_assembly", "chem_synthesis") + design_ids = list( + "odysseus_chassis", + "odysseus_torso", + "odysseus_head", + "odysseus_left_arm", + "odysseus_right_arm", + "odysseus_left_leg", + "odysseus_right_leg", + "odysseus_main", + "odysseus_peri", + "mech_medi_beam", + "mech_syringe_gun", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mech_mining + id = "mech_mining" + display_name = "Mining Mech" + description = "Robust mech engineered to withstand lava and storms for continuous off-station mining operations." + prereq_ids = list("mech_equipment", "mining") + design_ids = list( + "clarke_chassis", + "clarke_torso", + "clarke_head", + "clarke_left_arm", + "clarke_right_arm", + "clarke_main", + "clarke_peri", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mech_combat + id = "mech_combat" + display_name = "Combat Mechs" + description = "Modular armor upgrades and specialized equipment for security mechs." + prereq_ids = list("mech_equipment") + design_ids = list( + "mech_ccw_armor", + "mech_proj_armor", + "paddyupgrade", + "mech_hydraulic_claw", + "mech_disabler", + "mech_repair_droid", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + required_experiments = list(/datum/experiment/scanning/random/mecha_equipped_scan) + discount_experiments = list(/datum/experiment/scanning/random/mecha_damage_scan = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mech_assault + id = "mech_assault" + display_name = "Assault Mech" + description = "Heavy battle mech boasting robust armor but sacrificing speed for enhanced durability." + prereq_ids = list("mech_combat") + design_ids = list( + "durand_armor", + "durand_chassis", + "durand_torso", + "durand_head", + "durand_left_arm", + "durand_right_arm", + "durand_left_leg", + "durand_right_leg", + "durand_main", + "durand_peri", + "durand_targ", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/mech_light + id = "mech_light" + display_name = "Light Combat Mech" + description = "Agile combat mech equipped with overclocking capabilities for temporary speed boosts, prioritizing speed over durability on the battlefield." + prereq_ids = list("mech_combat") + design_ids = list( + "gygax_armor", + "gygax_chassis", + "gygax_torso", + "gygax_head", + "gygax_left_arm", + "gygax_right_arm", + "gygax_left_leg", + "gygax_right_leg", + "gygax_main", + "gygax_peri", + "gygax_targ", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/mech_heavy + id = "mech_heavy" + display_name = "Heavy Mech" + description = "Advanced heavy mechanized unit with dual pilot capability, designed for robust battlefield performance and increased tactical versatility." + prereq_ids = list("mech_assault") + design_ids = list( + "savannah_ivanov_armor", + "savannah_ivanov_chassis", + "savannah_ivanov_torso", + "savannah_ivanov_head", + "savannah_ivanov_left_arm", + "savannah_ivanov_right_arm", + "savannah_ivanov_left_leg", + "savannah_ivanov_right_leg", + "savannah_ivanov_main", + "savannah_ivanov_peri", + "savannah_ivanov_targ", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/mech_infiltrator + id = "mech_infiltrator" + display_name = "Infiltration Mech" + description = "Advanced mech with phasing capabilities, allowing it to move through walls and obstacles, ideal for covert and special operations." + prereq_ids = list("mech_light", "anomaly_research") + design_ids = list( + "phazon_armor", + "phazon_chassis", + "phazon_torso", + "phazon_head", + "phazon_left_arm", + "phazon_right_arm", + "phazon_left_leg", + "phazon_right_leg", + "phazon_main", + "phazon_peri", + "phazon_targ", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/mech_energy_guns + id = "mech_energy_guns" + display_name = "Mech Energy Guns" + description = "Scaled-up versions of electric weapons optimized for mech deployment." + prereq_ids = list("mech_combat", "electric_weapons") + design_ids = list( + "mech_laser", + "mech_laser_heavy", + "mech_ion", + "mech_tesla", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/mech_firearms + id = "mech_firearms" + display_name = "Mech Firearms" + description = "Mounted ballistic weaponry, enhancing combat capabilities for mechanized units." + prereq_ids = list("mech_energy_guns", "exotic_ammo") + design_ids = list( + "mech_lmg", + "mech_lmg_ammo", + "mech_scattershot", + "mech_scattershot_ammo", + "mech_carbine", + "mech_carbine_ammo", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + +/datum/techweb_node/mech_heavy_arms + id = "mech_heavy_arms" + display_name = "Heavy Mech Firearms" + description = "High-impact weaponry integrated into mechs, optimized for maximum firepower." + prereq_ids = list("mech_heavy", "exotic_ammo") + design_ids = list( + "clusterbang_launcher", + "clusterbang_launcher_ammo", + "mech_grenade_launcher", + "mech_grenade_launcher_ammo", + "mech_missile_rack", + "mech_missile_rack_ammo", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + +/datum/techweb_node/mech_equip_bluespace + id = "mech_equip_bluespace" + display_name = "Bluespace Mech Equipment" + description = "An array of equipment empowered by bluespace, providing unmatched mobility and utility." + prereq_ids = list("mech_infiltrator", "bluespace_travel") + design_ids = list( + "mech_gravcatapult", + "mech_teleporter", + "mech_wormhole_gen", + "mech_rcd", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) diff --git a/code/modules/research/techweb/nodes/medbay_nodes.dm b/code/modules/research/techweb/nodes/medbay_nodes.dm new file mode 100644 index 0000000000000..ce4ef103eda2d --- /dev/null +++ b/code/modules/research/techweb/nodes/medbay_nodes.dm @@ -0,0 +1,97 @@ +/datum/techweb_node/medbay_equip + id = "medbay_equip" + starting_node = TRUE + display_name = "Medbay Equipment" + description = "Essential medical tools to patch you up while medbay is still intact." + design_ids = list( + "operating", + "medicalbed", + "defibmountdefault", + "defibrillator", + "surgical_drapes", + "scalpel", + "retractor", + "hemostat", + "cautery", + "circular_saw", + "surgicaldrill", + "bonesetter", + "blood_filter", + "surgical_tape", + "penlight", + "penlight_paramedic", + "stethoscope", + "beaker", + "large_beaker", + "syringe", + "dropper", + "pillbottle", + ) + +/datum/techweb_node/chem_synthesis + id = "chem_synthesis" + display_name = "Chemical Synthesis" + description = "Synthesizing complex chemicals from electricity and thin air... Don't ask how..." + prereq_ids = list("medbay_equip") + design_ids = list( + "xlarge_beaker", + "blood_pack", + "chem_pack", + "med_spray_bottle", + "medigel", + "medipen_refiller", + "soda_dispenser", + "beer_dispenser", + "chem_dispenser", + "portable_chem_mixer", + "chem_heater", + "w-recycler", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/plumbing + id = "plumbing" + display_name = "Plumbing" + description = "Essential infrastructure for building chemical factories. To scale up the production of happy pills to an industrial level." + prereq_ids = list("chem_synthesis") + design_ids = list( + "plumbing_rcd", + "plumbing_rcd_service", + "plumbing_rcd_sci", + "plunger", + "fluid_ducts", + "meta_beaker", + "piercesyringe", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/cryostasis + id = "cryostasis" + display_name = "Cryostasis" + description = "The result of clown accidentally drinking a chemical, now repurposed for safely preserving crew members in suspended animation." + prereq_ids = list("plumbing", "plasma_control") + design_ids = list( + "cryotube", + "mech_sleeper", + "stasis", + "cryo_grenade", + "splitbeaker", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/scanning/reagent/cryostylane) + +/datum/techweb_node/medbay_equip_adv + id = "medbay_equip_adv" + display_name = "Advanced Medbay Equipment" + description = "State-of-the-art medical gear for keeping the crew in one piece — mostly." + prereq_ids = list("cryostasis") + design_ids = list( + "chem_mass_spec", + "healthanalyzer_advanced", + "mod_health_analyzer", + "crewpinpointer", + "defibrillator_compact", + "defibmount", + "medicalbed_emergency", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/mining_nodes.dm b/code/modules/research/techweb/nodes/mining_nodes.dm new file mode 100644 index 0000000000000..e1caaf57902e2 --- /dev/null +++ b/code/modules/research/techweb/nodes/mining_nodes.dm @@ -0,0 +1,104 @@ +/datum/techweb_node/material_processing + id = "material_proc" + starting_node = TRUE + display_name = "Material Processing" + description = "Refinement and processing of alloys and ores to enhance their utility and value." + design_ids = list( + "pickaxe", + "shovel", + "conveyor_switch", + "conveyor_belt", + "mass_driver", + "recycler", + "stack_machine", + "stack_console", + "autolathe", + "rglass", + "plasmaglass", + "plasmareinforcedglass", + "plasteel", + "titaniumglass", + "plastitanium", + "plastitaniumglass", + ) + +/datum/techweb_node/mining + id = "mining" + display_name = "Mining Technology" + description = "Development of tools meant to optimize mining operations and resource extraction." + prereq_ids = list("material_proc") + design_ids = list( + "cargoexpress", + "brm", + "b_smelter", + "b_refinery", + "ore_redemption", + "mining_equipment_vendor", + "mining_scanner", + "mech_mscanner", + "superresonator", + "mech_drill", + "mod_drill", + "drill", + "mod_orebag", + "beacon", + "telesci_gps", + "mod_gps", + "mod_visor_meson", + "mesons", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/low_pressure_excavation + id = "low_pressure_excavation" + display_name = "Low-Pressure Excavation" + description = "Research of Proto-Kinetic Accelerators (PKAs), pneumatic guns renowned for their exceptional performance in low-pressure environments." + prereq_ids = list("mining", "gas_compression") + design_ids = list( + "mecha_kineticgun", + "damagemod", + "rangemod", + "cooldownmod", + "triggermod", + "hypermod", + "borg_upgrade_damagemod", + "borg_upgrade_rangemod", + "borg_upgrade_cooldownmod", + "borg_upgrade_hypermod", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/plasma_mining + id = "plasma_mining" + display_name = "Plasma Beam Mining" + description = "Engineers' plasma welders have proven highly effective in mining operations. This led to the development of a mech-mounted variant and an enhanced handheld cutter for miners." + prereq_ids = list("low_pressure_excavation", "plasma_control") + design_ids = list( + "mech_plasma_cutter", + "plasmacutter_adv", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/bitrunning + id = "bitrunning" + display_name = "Bitrunning Technology" + description = "Bluespace technology has led to the development of quantum-scale computing, which unlocks the means to materialize atomic structures while executing advanced programs." + prereq_ids = list("gaming", "applied_bluespace") + design_ids = list( + "byteforge", + "quantum_console", + "netpod", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/mining_adv + id = "mining_adv" + display_name = "Advanced Mining Technology" + description = "High-level mining equipment, pushing the boundaries of efficiency and effectiveness in resource extraction." + prereq_ids = list("plasma_mining") + design_ids = list( + "jackhammer", + "drill_diamond", + "mech_diamond_drill", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/modsuit_nodes.dm b/code/modules/research/techweb/nodes/modsuit_nodes.dm new file mode 100644 index 0000000000000..a5005a66ee794 --- /dev/null +++ b/code/modules/research/techweb/nodes/modsuit_nodes.dm @@ -0,0 +1,139 @@ +/datum/techweb_node/mod_suit + id = "mod_suit" + starting_node = TRUE + display_name = "Modular Exosuit" + description = "Specialized back mounted power suits with various different modules." + prereq_ids = list("robotics") + design_ids = list( + "suit_storage_unit", + "mod_shell", + "mod_chestplate", + "mod_helmet", + "mod_gauntlets", + "mod_boots", + "mod_plating_standard", + "mod_paint_kit", + "mod_storage", + "mod_plasma", + "mod_flashlight", + ) + +/datum/techweb_node/mod_equip + id = "mod_equip" + display_name = "Modular Suit Equipment" + description = "More advanced modules, to improve modular suits." + prereq_ids = list("mod_suit") + design_ids = list( + "modlink_scryer", + "mod_clamp", + "mod_tether", + "mod_welding", + "mod_safety", + "mod_mouthhole", + "mod_longfall", + "mod_thermal_regulator", + "mod_sign_radio", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/mod_entertainment + id = "mod_entertainment" + display_name = "Entertainment Modular Suit" + description = "Powered suits for protection against low-humor environments." + prereq_ids = list("mod_suit") + design_ids = list( + "mod_plating_cosmohonk", + "mod_bikehorn", + "mod_microwave_beam", + "mod_waddle", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/mod_medical + id = "mod_medical" + display_name = "Medical Modular Suit" + description = "Medical exosuits for quick rescue purposes." + prereq_ids = list("mod_suit", "chem_synthesis") + design_ids = list( + "mod_plating_medical", + "mod_quick_carry", + "mod_injector", + "mod_organ_thrower", + "mod_patienttransport", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mod_engi + id = "mod_engi" + display_name = "Engineering Modular Suits" + description = "Engineering suits, for powered engineers." + prereq_ids = list("mod_equip") + design_ids = list( + "mod_plating_engineering", + "mod_t_ray", + "mod_magboot", + "mod_constructor", + "mod_mister_atmos", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mod_security + id = "mod_security" + display_name = "Security Modular Suits" + description = "Security suits for space crime handling." + prereq_ids = list("mod_equip") + design_ids = list( + "mod_plating_security", + "mod_stealth", + "mod_mag_harness", + "mod_pathfinder", + "mod_holster", + "mod_sonar", + "mod_projectile_dampener", + "mod_criminalcapture", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/mod_medical_adv + id = "mod_medical_adv" + display_name = "Field Surgery Modules" + description = "Medical exosuit equipment designed for conducting surgical operations in field conditions." + prereq_ids = list("mod_medical", "surgery_adv") + design_ids = list( + "mod_defib", + "mod_threadripper", + "mod_surgicalprocessor", + "mod_statusreadout", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/mod_engi_adv + id = "mod_engi_adv" + display_name = "Advanced Engineering Modular Suit" + description = "Advanced Engineering suits, for advanced powered engineers." + prereq_ids = list("mod_engi") + design_ids = list( + "mod_plating_atmospheric", + "mod_jetpack", + "mod_rad_protection", + "mod_emp_shield", + "mod_storage_expanded", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/mod_engi_adv/New() + if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA)) //we'll really need the rad protection modsuit module + starting_node = TRUE + return ..() + +/datum/techweb_node/mod_anomaly + id = "mod_anomaly" + display_name = "Anomalock Modular Suit" + description = "Modules for exosuits that require anomaly cores to function." + prereq_ids = list("mod_engi_adv", "anomaly_research") + design_ids = list( + "mod_antigrav", + "mod_teleporter", + "mod_kinesis", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/research_nodes.dm b/code/modules/research/techweb/nodes/research_nodes.dm new file mode 100644 index 0000000000000..b3af62c72e994 --- /dev/null +++ b/code/modules/research/techweb/nodes/research_nodes.dm @@ -0,0 +1,94 @@ +/datum/techweb_node/fundamental_sci + id = "fundamental_sci" + starting_node = TRUE + display_name = "Fundamental Science" + description = "Establishing the bedrock of scientific understanding, paving the way for deeper exploration and theoretical inquiry." + design_ids = list( + "rdserver", + "rdservercontrol", + "rdconsole", + "tech_disk", + "doppler_array", + "experimentor", + "destructive_analyzer", + "destructive_scanner", + "experi_scanner", + "ntnet_relay", + "laptop", + "portadrive_basic", + "portadrive_advanced", + "portadrive_super", + ) + +/datum/techweb_node/bluespace_theory + id = "bluespace_theory" + display_name = "Bluespace Theory" + description = "Basic studies into the mysterious alternate dimension known as bluespace." + prereq_ids = list("fundamental_sci") + design_ids = list( + "bluespace_crystal", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/applied_bluespace + id = "applied_bluespace" + display_name = "Applied Bluespace Research" + description = "With a heightened grasp of bluespace dynamics, sophisticated applications and technologies can be devised using data from bluespace crystal analyses." + prereq_ids = list("bluespace_theory") + design_ids = list( + "ore_silo", + "minerbag_holding", + "plumbing_receiver", + "bluespacebeaker", + "adv_watering_can", + "bluespace_coffeepot", + "bluespacesyringe", + "blutrash", + "light_replacer_blue", + "bluespacebodybag", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + required_experiments = list(/datum/experiment/scanning/bluespace_crystal) + +/datum/techweb_node/bluespace_travel + id = "bluespace_travel" + display_name = "Bluespace Travel" + description = "Facilitate teleportation methods based on bluespace principles to revolutionize logistical efficiency." + prereq_ids = list("applied_bluespace") + design_ids = list( + "teleconsole", + "tele_station", + "tele_hub", + "launchpad_console", + "quantumpad", + "launchpad", + "bluespace_pod", + "quantum_keycard", + "swapper", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/anomaly_research + id = "anomaly_research" + display_name = "Anomaly Research" + description = "Delving into the study of mysterious anomalies to investigate methods to refine and harness their unpredictable energies." + prereq_ids = list("applied_bluespace") + design_ids = list( + "anomaly_refinery", + "anomaly_neutralizer", + "reactive_armour", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/anomaly_shells + id = "anomaly_shells" + display_name = "Advanced Anomaly Shells" + description = "New shells designed to utilize anomaly cores, maximizing their potential in innovative ways." + prereq_ids = list("anomaly_research") + design_ids = list( + "bag_holding", + "wormholeprojector", + "gravitygun", + "polymorph_belt" + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/robo_nodes.dm b/code/modules/research/techweb/nodes/robo_nodes.dm new file mode 100644 index 0000000000000..556fa560daf6b --- /dev/null +++ b/code/modules/research/techweb/nodes/robo_nodes.dm @@ -0,0 +1,97 @@ +/datum/techweb_node/robotics + id = "robotics" + starting_node = TRUE + display_name = "Robotics" + description = "Programmable machines that make our lives lazier." + design_ids = list( + "mechfab", + "botnavbeacon", + "paicard", + ) + +/datum/techweb_node/exodrone + id = "exodrone" + display_name = "Exploration Drones" + description = "Adapted arcade machines to covertly harness gamers' skills in controlling real drones for practical purposes." + prereq_ids = list("robotics") + design_ids = list( + "exoscanner_console", + "exoscanner", + "exodrone_console", + "exodrone_launcher", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +// AI root node +/datum/techweb_node/ai + id = "ai" + display_name = "Artificial Intelligence" + description = "Exploration of AI systems, more intelligent than the entire crew put together." + prereq_ids = list("robotics") + design_ids = list( + "aiupload", + "aifixer", + "intellicard", + "mecha_tracking_ai_control", + "borg_ai_control", + "aicore", + "reset_module", + "asimov_module", + "default_module", + "nutimov_module", + "paladin_module", + "robocop_module", + "corporate_module", + "drone_module", + "oxygen_module", + "safeguard_module", + "protectstation_module", + "quarantine_module", + "freeform_module", + "remove_module", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/ai/New() + . = ..() + if(HAS_TRAIT(SSstation, STATION_TRAIT_HUMAN_AI)) + design_ids -= list( + "aicore", + "borg_ai_control", + "intellicard", + "mecha_tracking_ai_control", + "aifixer", + "aiupload", + ) + else if(HAS_TRAIT(SSstation, STATION_TRAIT_UNIQUE_AI)) + research_costs[TECHWEB_POINT_TYPE_GENERIC] *= 3 + +/datum/techweb_node/ai_laws + id = "ai_laws" + display_name = "Advanced AI Laws" + description = "Delving into sophisticated AI directives, with hopes that they won't lead to humanity's extinction." + prereq_ids = list("ai") + design_ids = list( + "asimovpp_module", + "paladin_devotion_module", + "dungeon_master_module", + "painter_module", + "ten_commandments_module", + "hippocratic_module", + "maintain_module", + "liveandletlive_module", + "reporter_module", + "yesman_module", + "hulkamania_module", + "peacekeeper_module", + "overlord_module", + "tyrant_module", + "antimov_module", + "balance_module", + "thermurderdynamic_module", + "damaged_module", + "freeformcore_module", + "onehuman_module", + "purge_module", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) diff --git a/code/modules/research/techweb/nodes/security_nodes.dm b/code/modules/research/techweb/nodes/security_nodes.dm new file mode 100644 index 0000000000000..97092f2682a63 --- /dev/null +++ b/code/modules/research/techweb/nodes/security_nodes.dm @@ -0,0 +1,107 @@ +/datum/techweb_node/basic_arms + id = "basic_arms" + starting_node = TRUE + display_name = "Basic Arms" + description = "Ballistics can be unpredictable in space." + design_ids = list( + "toygun", + "c38_rubber", + "sec_38", + "capbox", + "foam_dart", + "sec_beanbag_slug", + "sec_dart", + "sec_Islug", + "sec_rshot", + ) + +/datum/techweb_node/sec_equip + id = "sec_equip" + display_name = "Security Equipment" + description = "All the essentials to subdue a mime." + prereq_ids = list("basic_arms") + design_ids = list( + "camera_assembly", + "secdata", + "mining", + "prisonmanage", + "rdcamera", + "seccamera", + "security_photobooth", + "photobooth", + "scanner_gate", + "turret_control", + "pepperspray", + "inspector", + "evidencebag", + "handcuffs_s", + "zipties", + "seclite", + "electropack", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/riot_supression + id = "riot_supression" + display_name = "Riot Supression" + description = "When you are on the opposing side of a revolutionary movement." + prereq_ids = list("sec_equip") + design_ids = list( + "pin_testing", + "pin_loyalty", + "tele_shield", + "ballistic_shield", + "bola_energy", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/explosives + id = "explosives" + display_name = "Explosives" + description = "For once, intentional explosions." + prereq_ids = list("riot_supression") + design_ids = list( + "large_grenade", + "adv_grenade", + "pyro_grenade", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/ordnance/explosive/lowyieldbomb) + discount_experiments = list(/datum/experiment/ordnance/explosive/highyieldbomb = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/exotic_ammo + id = "exotic_ammo" + display_name = "Exotic Ammunition" + description = "Specialized bullets designed to ignite, freeze, and inflict various other effects on targets, expanding combat capabilities." + prereq_ids = list("explosives") + design_ids = list( + "c38_hotshot", + "c38_iceblox", + "techshotshell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + +/datum/techweb_node/electric_weapons + id = "electric_weapons" + display_name = "Electric Weaponry" + description = "Energy-based weaponry designed for both lethal and non-lethal applications." + prereq_ids = list("riot_supression") + design_ids = list( + "stunrevolver", + "ioncarbine", + "temp_gun", + "lasershell", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + +/datum/techweb_node/beam_weapons + id = "beam_weapons" + display_name = "Advanced Beam Weaponry" + description = "So advanced, even engineers are baffled by its operational principles." + prereq_ids = list("electric_weapons") + design_ids = list( + "beamrifle", + "xray_laser", + "nuclear_gun", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/service_nodes.dm b/code/modules/research/techweb/nodes/service_nodes.dm new file mode 100644 index 0000000000000..ff56afc115eb5 --- /dev/null +++ b/code/modules/research/techweb/nodes/service_nodes.dm @@ -0,0 +1,236 @@ +/datum/techweb_node/office_equip + id = "office_equip" + starting_node = TRUE + display_name = "Office Equipment" + description = "Nanotrasen's finest in ergonomic office tech, ensuring station admin stays productive and compliant with corporate policies — because even in space, paperwork never stops." + design_ids = list( + "fax", + "sec_pen", + "handlabel", + "roll", + "universal_scanner", + "desttagger", + "packagewrap", + "sticky_tape", + "toner_large", + "toner", + "boxcutter", + "bounced_radio", + "radio_headset", + "earmuffs", + "recorder", + "tape", + "toy_balloon", + "pet_carrier", + "chisel", + "spraycan", + "camera_film", + "camera", + "razor", + "bucket", + "mop", + "pushbroom", + "normtrash", + "wirebrush", + "flashlight", + ) + +/datum/techweb_node/sanitation + id = "sanitation" + display_name = "Advanced Sanitation Technology" + description = "Nanotrasen's latest in janitorial tech, making sure the station stays spotless and bear-free." + prereq_ids = list("office_equip") + design_ids = list( + "advmop", + "light_replacer", + "spraybottle", + "paint_remover", + "beartrap", + "buffer", + "vacuum", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + discount_experiments = list(/datum/experiment/scanning/random/janitor_trash = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/toys + id = "toys" + display_name = "New Toys" + description = "For new pranks." + prereq_ids = list("office_equip") + design_ids = list( + "smoke_machine", + "toy_armblade", + "air_horn", + "clown_firing_pin", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/consoles + id = "consoles" + display_name = "Civilian Consoles" + description = "User-friendly consoles for non-technical crew members, enhancing communication and access to essential station information." + prereq_ids = list("office_equip") + design_ids = list( + "comconsole", + "automated_announcement", + "cargo", + "cargorequest", + "med_data", + "crewconsole", + "bankmachine", + "account_console", + "idcard", + "c-reader", + "libraryconsole", + "barcode_scanner", + "vendor", + "custom_vendor_refill", + "bounty_pad_control", + "bounty_pad", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/gaming + id = "gaming" + display_name = "Gaming" + description = "For the slackers on the station." + prereq_ids = list("toys", "consoles") + design_ids = list( + "arcade_battle", + "arcade_orion", + "slotmachine", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + discount_experiments = list(/datum/experiment/physical/arcade_winner = TECHWEB_TIER_2_POINTS) + +// Kitchen root node +/datum/techweb_node/cafeteria_equip + id = "cafeteria_equip" + starting_node = TRUE + display_name = "Cafeteria Equipment" + description = "When standard-issue tubed food no longer satisfies the station crew's appetite..." + design_ids = list( + "griddle", + "microwave", + "bowl", + "plate", + "oven_tray", + "servingtray", + "tongs", + "spoon", + "fork", + "kitchen_knife", + "plastic_spoon", + "plastic_fork", + "plastic_knife", + "shaker", + "drinking_glass", + "shot_glass", + "coffee_cartridge", + "coffeemaker", + "coffeepot", + "syrup_bottle", + ) + +/datum/techweb_node/food_proc + id = "food_proc" + display_name = "Food Processing" + description = "Top-tier kitchen appliances from Nanotrasen, designed to keep the crew well-fed and happy." + prereq_ids = list("cafeteria_equip") + design_ids = list( + "deepfryer", + "oven", + "stove", + "range", + "souppot", + "processor", + "gibber", + "monkey_recycler", + "reagentgrinder", + "microwave_engineering", + "smartfridge", + "sheetifier", + "fat_sucker", + "dish_drive", + "roastingstick", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +// Fishing root node +/datum/techweb_node/fishing_equip + id = "fishing_equip" + starting_node = TRUE + display_name = "Fishing Equipment" + description = "Basic fishing gear tailored for space station environments, perfect for extraterrestrial aquatic pursuits." + design_ids = list( + "fishing_portal_generator", + "fishing_rod", + "fish_case", + ) + +/datum/techweb_node/fishing_equip_adv + id = "fishing_equip_adv" + display_name = "Advanced Fishing Tools" + description = "Continuing advancements in fishing technology, incorporating cutting-edge features in space fishing operations. Just don't try this on space carps..." + prereq_ids = list("fishing_equip") + design_ids = list( + "fishing_rod_tech", + "stabilized_hook", + "auto_reel", + "fish_analyzer", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + required_experiments = list(/datum/experiment/scanning/fish) + +/datum/techweb_node/marine_util + id = "marine_util" + display_name = "Marine Utility" + description = "Fish are nice to look at and all, but they can be put to use." + prereq_ids = list("fishing_equip_adv") + design_ids = list( + "bioelec_gen", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + // only available if you've done the first fishing experiment (thus unlocking fishing tech), but not a strict requirement to get the tech + discount_experiments = list(/datum/experiment/scanning/fish/second = TECHWEB_TIER_3_POINTS) + +// Botany root node +/datum/techweb_node/botany_equip + id = "botany_equip" + starting_node = TRUE + display_name = "Botany Equipment" + description = "Essential tools for maintaining onboard gardens, supporting plant growth in the unique environment of the space station." + design_ids = list( + "seed_extractor", + "plant_analyzer", + "watering_can", + "spade", + "cultivator", + "secateurs", + "hatchet", + ) + +/datum/techweb_node/hydroponics + id = "hydroponics" + display_name = "Hydroponics" + description = "Research into advanced hydroponic systems for efficient and sustainable plant cultivation." + prereq_ids = list("botany_equip", "chem_synthesis") + design_ids = list( + "biogenerator", + "hydro_tray", + "portaseeder", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + +/datum/techweb_node/selection + id = "selection" + display_name = "Artificial Selection" + description = "Advancement in plant cultivation techniques through artificial selection, enabling precise manipulation of plant DNA." + prereq_ids = list("hydroponics") + design_ids = list( + "flora_gun", + "gene_shears", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/scanning/random/plants/wild) + discount_experiments = list(/datum/experiment/scanning/random/plants/traits = TECHWEB_TIER_3_POINTS) diff --git a/code/modules/research/techweb/nodes/surgery_nodes.dm b/code/modules/research/techweb/nodes/surgery_nodes.dm new file mode 100644 index 0000000000000..3cd3d373c0599 --- /dev/null +++ b/code/modules/research/techweb/nodes/surgery_nodes.dm @@ -0,0 +1,72 @@ +/datum/techweb_node/oldstation_surgery + id = "oldstation_surgery" + display_name = "Experimental Dissection" + description = "Grants access to experimental dissections, which allows generation of research points." + prereq_ids = list("medbay_equip") + design_ids = list( + "surgery_oldstation_dissection", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + hidden = TRUE + show_on_wiki = FALSE + +/datum/techweb_node/surgery + id = "surgery" + display_name = "Improved Wound-Tending" + description = "Who would have known being more gentle with a hemostat decreases patient pain?" + prereq_ids = list("medbay_equip") + design_ids = list( + "surgery_heal_brute_upgrade", + "surgery_heal_burn_upgrade", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) + +/datum/techweb_node/surgery_adv + id = "surgery_adv" + display_name = "Advanced Surgery" + description = "When simple medicine doesn't cut it." + prereq_ids = list("surgery") + design_ids = list( + "harvester", + "surgery_heal_brute_upgrade_femto", + "surgery_heal_burn_upgrade_femto", + "surgery_heal_combo", + "surgery_lobotomy", + "surgery_wing_reconstruction", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_2_POINTS) + required_experiments = list(/datum/experiment/autopsy/human) + +/datum/techweb_node/surgery_exp + id = "surgery_exp" + display_name = "Experimental Surgery" + description = "When evolution isn't fast enough." + prereq_ids = list("surgery_adv") + design_ids = list( + "surgery_cortex_folding", + "surgery_cortex_imprint", + "surgery_heal_combo_upgrade", + "surgery_ligament_hook", + "surgery_ligament_reinforcement", + "surgery_muscled_veins", + "surgery_nerve_ground", + "surgery_nerve_splice", + "surgery_pacify", + "surgery_vein_thread", + "surgery_viral_bond", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS) + required_experiments = list(/datum/experiment/autopsy/nonhuman) + +/datum/techweb_node/surgery_tools + id = "surgery_tools" + display_name = "Advanced Surgery Tools" + description = "Surgical instruments of dual purpose for quick operations." + prereq_ids = list("surgery_exp") + design_ids = list( + "laserscalpel", + "searingtool", + "mechanicalpinches", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_4_POINTS) + discount_experiments = list(/datum/experiment/autopsy/xenomorph = TECHWEB_TIER_4_POINTS) diff --git a/code/modules/research/techweb/nodes/syndicate_nodes.dm b/code/modules/research/techweb/nodes/syndicate_nodes.dm new file mode 100644 index 0000000000000..c571551877099 --- /dev/null +++ b/code/modules/research/techweb/nodes/syndicate_nodes.dm @@ -0,0 +1,48 @@ +/datum/techweb_node/syndicate_basic + id = "syndicate_basic" + display_name = "Illegal Technology" + description = "Dangerous research used to create dangerous objects." + prereq_ids = list("exp_tools", "exotic_ammo") + design_ids = list( + "advanced_camera", + "ai_cam_upgrade", + "borg_syndicate_module", + "donksoft_refill", + "donksofttoyvendor", + "largecrossbow", + "mag_autorifle", + "mag_autorifle_ap", + "mag_autorifle_ic", + "rapidsyringe", + "suppressor", + "super_pointy_tape", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_5_POINTS) + hidden = TRUE + +/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way. + . = ..() + if(!SSearly_assets.initialized) + RegisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(register_uplink_items)) + else + register_uplink_items() + +/datum/techweb_node/syndicate_basic/proc/register_uplink_items() + SIGNAL_HANDLER + UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE) + required_items_to_unlock = list() + for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type) + var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path] + if(!item.item || !item.illegal_tech) + continue + required_items_to_unlock |= item.item //allows deconning to unlock. + +/datum/techweb_node/unregulated_bluespace + id = "unregulated_bluespace" + display_name = "Unregulated Bluespace Research" + description = "Bluespace technology using unstable or unbalanced procedures, prone to damaging the fabric of bluespace. Outlawed by galactic conventions." + prereq_ids = list("parts_bluespace", "syndicate_basic") + design_ids = list( + "desynchronizer", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_1_POINTS) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 318926465ae08..c03a930395ab9 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -362,7 +362,7 @@ if(ishuman(victim)) var/mob/living/carbon/human/human_victim = victim - if(HAS_TRAIT(victim, TRAIT_LIMBATTACHMENT)) + if(HAS_TRAIT(victim, TRAIT_LIMBATTACHMENT) || HAS_TRAIT(src, TRAIT_EASY_ATTACH)) if(!human_victim.get_bodypart(body_zone)) user.temporarilyRemoveItemFromInventory(src, TRUE) if(!try_attach_limb(victim)) diff --git a/code/modules/surgery/bodyparts/ghetto_parts.dm b/code/modules/surgery/bodyparts/ghetto_parts.dm new file mode 100644 index 0000000000000..36c0310dead76 --- /dev/null +++ b/code/modules/surgery/bodyparts/ghetto_parts.dm @@ -0,0 +1,79 @@ +/obj/item/bodypart/arm/left/ghetto + name = "left peg arm" + desc = "A roughly hewn wooden peg replaces where a forearm should be. It's simple and sturdy, clearly made in a hurry with whatever materials were at hand. Despite its crude appearance, it gets the job done." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_l_arm" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + attack_verb_simple = list("bashed", "slashed") + unarmed_damage_low = 3 + unarmed_damage_high = 9 + unarmed_effectiveness = 5 + brute_modifier = 1.2 + burn_modifier = 1.5 + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/left/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/arm/right/ghetto + name = "right peg arm" + desc = "A roughly hewn wooden peg replaces where a forearm should be. It's simple and sturdy, clearly made in a hurry with whatever materials were at hand. Despite its crude appearance, it gets the job done." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_r_arm" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + attack_verb_simple = list("bashed", "slashed") + unarmed_damage_low = 3 + unarmed_damage_high = 9 + unarmed_effectiveness = 5 + brute_modifier = 1.2 + burn_modifier = 1.5 + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/right/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/leg/left/ghetto + name = "left peg leg" + desc = "Fashioned from what looks suspiciously like a table leg, this peg leg brings a whole new meaning to 'dining on the go.' It's a bit wobbly and creaks ominously with every step, but at least you can claim to have the most well-balanced diet on the seven seas." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_l_leg" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + unarmed_damage_low = 2 + unarmed_damage_high = 5 + unarmed_effectiveness = 10 + brute_modifier = 1.2 + burn_modifier = 1.5 + +/obj/item/bodypart/leg/left/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) + +/obj/item/bodypart/leg/right/ghetto + name = "right peg leg" + desc = "Fashioned from what looks suspiciously like a table leg, this peg leg brings a whole new meaning to 'dining on the go.' It's a bit wobbly and creaks ominously with every step, but at least you can claim to have the most well-balanced diet on the seven seas." + icon = 'icons/mob/human/species/ghetto.dmi' + icon_static = 'icons/mob/human/species/ghetto.dmi' + limb_id = BODYPART_ID_PEG + icon_state = "peg_r_leg" + bodytype = BODYTYPE_PEG + should_draw_greyscale = FALSE + unarmed_damage_low = 2 + unarmed_damage_high = 5 + unarmed_effectiveness = 10 + brute_modifier = 1.2 + burn_modifier = 1.5 + +/obj/item/bodypart/leg/right/ghetto/Initialize(mapload, ...) + . = ..() + ADD_TRAIT(src, TRAIT_EASY_ATTACH, INNATE_TRAIT) diff --git a/code/modules/unit_tests/changeling.dm b/code/modules/unit_tests/changeling.dm index 9749d760ea91c..7f86510fd62d1 100644 --- a/code/modules/unit_tests/changeling.dm +++ b/code/modules/unit_tests/changeling.dm @@ -80,7 +80,7 @@ ling.dna.features["horns"] = "Curled" ling.dna.features["frills"] = "Short" ling.dna.features["spines"] = "Long + Membrane" - ling.dna.features["body_markings"] = "Light Belly" + ling.dna.features["lizard_markings"] = "Light Belly" ling.dna.features["legs"] = DIGITIGRADE_LEGS ling.eye_color_left = COLOR_WHITE ling.eye_color_right = COLOR_WHITE diff --git a/html/changelogs/AutoChangeLog-pr-83439.yml b/html/changelogs/AutoChangeLog-pr-83439.yml new file mode 100644 index 0000000000000..9e721ae4ba0a4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83439.yml @@ -0,0 +1,8 @@ +author: "carlarctg" +delete-after: True +changes: + - balance: "Negative mutations now allow you to have more positive mutations, via reducing your instability!" + - code_imp: "All mutations have been overall standardized via defines on their instability values. Many mediocre positive mutations have had their cost reduced significantly!" + - rscadd: "Added a new height mutation: Acromegaly! It's the opposite of Dwarfism and makes you uncannily tall. It also makes you hit your head 8% or 4% (with synch) of the time you pass through airlocks. Wear a helmet!" + - rscadd: "Gigantism is now a recipe mutation, mix Acromegaly with Strength to get it." + - qol: "Injectors and activators' duration is now dependent on the in/stability (absolute value) of the mutations to be injected! With a minimum of 5-10-15 seconds for each type of injector. Also changed up a bit how part upgrade cooldowns work, by making each tier reduce cooldowns by 25-15-10% for each injector type." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83673.yml b/html/changelogs/AutoChangeLog-pr-83673.yml new file mode 100644 index 0000000000000..0211d4508cf97 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83673.yml @@ -0,0 +1,5 @@ +author: "Bisar" +delete-after: True +changes: + - rscadd: "Sparks now ignite flammable things. Including you. Keep a fire extinguisher handy or stop dousing yourself in welding fuel!" + - bugfix: "Fixed a few oversights with welding fuel pools not igniting when you throw lit/hot things into them or when you walk into them while on fire." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83744.yml b/html/changelogs/AutoChangeLog-pr-83744.yml new file mode 100644 index 0000000000000..8425dfbfccd62 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83744.yml @@ -0,0 +1,4 @@ +author: "Time-Green" +delete-after: True +changes: + - refactor: "Lizard and moth markings now use the bodypart overlay system" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83792.yml b/html/changelogs/AutoChangeLog-pr-83792.yml new file mode 100644 index 0000000000000..c856d7586a8ce --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83792.yml @@ -0,0 +1,4 @@ +author: "TheRyeGuyWhoWillNowDie" +delete-after: True +changes: + - rscadd: "the advanced omnitool upgrade now hastens the mediborg's syringe too" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83840.yml b/html/changelogs/AutoChangeLog-pr-83840.yml deleted file mode 100644 index 5d879aece5df2..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-83840.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TheBoondock" -delete-after: True -changes: - - sound: "added compressed air sound for when air tanks are inserted into machinery" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83895.yml b/html/changelogs/AutoChangeLog-pr-83895.yml deleted file mode 100644 index 6b66da81feef3..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-83895.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Hacks-The-Doors" -delete-after: True -changes: - - balance: "dental pills can now be used in crit." - - balance: "dental pills now give off a message when you start using them" - - balance: "dental pills have a 2.5 second delay when in soft crit" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83949.yml b/html/changelogs/AutoChangeLog-pr-83949.yml deleted file mode 100644 index 62584dcc7c0fc..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-83949.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "grungussuss" -delete-after: True -changes: - - rscadd: "Added Misha the bear to the HoS office on icebox." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83952.yml b/html/changelogs/AutoChangeLog-pr-83952.yml new file mode 100644 index 0000000000000..431aaa759582e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83952.yml @@ -0,0 +1,4 @@ +author: "GPeckman" +delete-after: True +changes: + - bugfix: "Airlocks should no longer appear closed sometimes when fireman carrying someone into them." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83953.yml b/html/changelogs/AutoChangeLog-pr-83953.yml deleted file mode 100644 index fe5f444909fe3..0000000000000 --- a/html/changelogs/AutoChangeLog-pr-83953.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "JackEnoff" -delete-after: True -changes: - - balance: "Certain changeling abilities won't work while on fire." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-83999.yml b/html/changelogs/AutoChangeLog-pr-83999.yml new file mode 100644 index 0000000000000..a04af9580bdf3 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-83999.yml @@ -0,0 +1,4 @@ +author: "Jacquerel" +delete-after: True +changes: + - balance: "Gorillas have big fingers, which mostly just prevents them from using laser pointers and stun batons" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-84053.yml b/html/changelogs/AutoChangeLog-pr-84053.yml new file mode 100644 index 0000000000000..6aebdbc471f5f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-84053.yml @@ -0,0 +1,4 @@ +author: "jlsnow301" +delete-after: True +changes: + - bugfix: "TGUI say will no longer spill your /me contents when you get attacked" \ No newline at end of file diff --git a/html/changelogs/archive/2024-06.yml b/html/changelogs/archive/2024-06.yml index c0da4690e635b..9f757c45df58b 100644 --- a/html/changelogs/archive/2024-06.yml +++ b/html/changelogs/archive/2024-06.yml @@ -742,3 +742,61 @@ carlarctg: - bugfix: Cosmos spells will no longer star mark your steed - qol: Baby plushies are now smaller than their parents +2024-06-17: + Hacks-The-Doors: + - balance: dental pills can now be used in crit. + - balance: dental pills now give off a message when you start using them + - balance: dental pills have a 2.5 second delay when in soft crit + JackEnoff: + - balance: Certain changeling abilities won't work while on fire. + TheBoondock: + - sound: added compressed air sound for when air tanks are inserted into machinery + grungussuss: + - rscadd: Added Misha the bear to the HoS office on icebox. +2024-06-18: + Bisar: + - balance: Replaced the free reagent purging with actually purging by exploding + someone in the blood while they have omnizine and a purgative in their bloodstream. + Let's go practice medicine! + - bugfix: Fixed the free reagent purging mechanic from causing an explosion so weak + that it doesn't cause any damage. + GPeckman: + - bugfix: Mining borgs can get multiple modkits of the same type installed again. + Goat: + - qol: fire extinguishers can now be filled via stationary tanks. (and water coolers) + GoblinBackwards: + - bugfix: Fixed mulebots being able to run over people who are leaning against a + wall. + - bugfix: Fixed anomaly cores from the high-intensity grav anomaly event creating + the wrong type of reactive armour. + Kaostico: + - bugfix: Transcendent Olfaction mutation now works properly + LucyGrind: + - bugfix: allows cigarette grinding in mortar + MTandi: + - bugfix: Non-metallic slime types are semi-transparent + - balance: Reshuffled tech tree, making nodes more specialized + - qol: Research points devided by the amount generated per second, so now research + points correspond to seconds + - rscadd: Introduced reagent purity scan experiments (required for Cryostasis node) + - rscadd: Introduced synthetic organ scan experiment (required for top tier cyber + organs) + - rscadd: Added a variant of machinery scan experiment that accepts any machines + with upgraded parts (required for tier 3 parts) + - rscdel: Removed material scanning experiments from the tech tree + Melbert: + - qol: Block'd out armor readout, should be more readable now + - bugfix: Crusher Fix For Real + SyncIt21: + - bugfix: ctrl+shift clicking on a ghost will only quick spawn that clicked target + and not you + TheBoondock: + - sound: added squeaky turn and gas hissing sound to gas valve + TheRyeGuyWhoWillNowDie: + - qol: adds a confirmation to malf AI shunting into APCs + mc-oofert: + - bugfix: build mode and space dragons dont harddel on destroy + - bugfix: you may now open the panel of a flatpacker with a screwdriver + san7890: + - qol: A message with a link to publicly accessible logs (if enabled by your server + operators) should now be visible far earlier when a world is about to reboot. diff --git a/icons/mob/human/bodyparts.dmi b/icons/mob/human/bodyparts.dmi index d6e4472973a32..78be880423c1e 100644 Binary files a/icons/mob/human/bodyparts.dmi and b/icons/mob/human/bodyparts.dmi differ diff --git a/icons/mob/human/species/ghetto.dmi b/icons/mob/human/species/ghetto.dmi new file mode 100644 index 0000000000000..e11701428ebcb Binary files /dev/null and b/icons/mob/human/species/ghetto.dmi differ diff --git a/icons/mob/human/species/lizard/lizard_markings.dmi b/icons/mob/human/species/lizard/lizard_markings.dmi new file mode 100644 index 0000000000000..7cc8f2fa1b8a5 Binary files /dev/null and b/icons/mob/human/species/lizard/lizard_markings.dmi differ diff --git a/icons/mob/human/species/lizard/lizard_misc.dmi b/icons/mob/human/species/lizard/lizard_misc.dmi index ab228f29076f0..346581978e4b7 100644 Binary files a/icons/mob/human/species/lizard/lizard_misc.dmi and b/icons/mob/human/species/lizard/lizard_misc.dmi differ diff --git a/sound/attributions.txt b/sound/attributions.txt index bcd6f41edf278..29c86945dd1a1 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -188,3 +188,7 @@ https://freesound.org/people/BinaryMonkFlint/sounds/333296/ tank_remove_thunk.ogg was made by mixing two sound tracks from Freesound: https://freesound.org/people/lowdjinn/sounds/533885/ and; https://freesound.org/people/BMacZero/sounds/96137/ + +valve_opening.ogg was made by mixing water flowing samples from: +https://freesound.org/people/scriotxstudios/sounds/349111/?attribution=1 and squeaky scrape sound from: +https://freesound.org/people/Department64/sounds/669028/ which was modified with lower pitch diff --git a/sound/effects/gas_hissing.ogg b/sound/effects/gas_hissing.ogg new file mode 100644 index 0000000000000..58df62ef0842f Binary files /dev/null and b/sound/effects/gas_hissing.ogg differ diff --git a/sound/effects/valve_opening.ogg b/sound/effects/valve_opening.ogg new file mode 100644 index 0000000000000..9e71912041467 Binary files /dev/null and b/sound/effects/valve_opening.ogg differ diff --git a/tgstation.dme b/tgstation.dme index dd55b451101ef..5c2702885460a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -989,6 +989,7 @@ #include "code\datums\atmosphere\planetary.dm" #include "code\datums\bodypart_overlays\bodypart_overlay.dm" #include "code\datums\bodypart_overlays\emote_bodypart_overlay.dm" +#include "code\datums\bodypart_overlays\markings_bodypart_overlay.dm" #include "code\datums\bodypart_overlays\mutant_bodypart_overlay.dm" #include "code\datums\bodypart_overlays\simple_bodypart_overlay.dm" #include "code\datums\brain_damage\brain_trauma.dm" @@ -4048,6 +4049,7 @@ #include "code\modules\experisci\experiment\types\scanning_people.dm" #include "code\modules\experisci\experiment\types\scanning_plants.dm" #include "code\modules\experisci\experiment\types\scanning_points.dm" +#include "code\modules\experisci\experiment\types\scanning_reagent.dm" #include "code\modules\experisci\experiment\types\scanning_vatgrown.dm" #include "code\modules\explorer_drone\adventure.dm" #include "code\modules\explorer_drone\control_console.dm" @@ -5678,8 +5680,24 @@ #include "code\modules\research\techweb\__techweb_helpers.dm" #include "code\modules\research\techweb\_techweb.dm" #include "code\modules\research\techweb\_techweb_node.dm" -#include "code\modules\research\techweb\all_nodes.dm" #include "code\modules\research\techweb\techweb_types.dm" +#include "code\modules\research\techweb\nodes\alien_nodes.dm" +#include "code\modules\research\techweb\nodes\atmos_nodes.dm" +#include "code\modules\research\techweb\nodes\bepis_nodes.dm" +#include "code\modules\research\techweb\nodes\biology_nodes.dm" +#include "code\modules\research\techweb\nodes\circuit_nodes.dm" +#include "code\modules\research\techweb\nodes\cyborg_nodes.dm" +#include "code\modules\research\techweb\nodes\engi_nodes.dm" +#include "code\modules\research\techweb\nodes\mech_nodes.dm" +#include "code\modules\research\techweb\nodes\medbay_nodes.dm" +#include "code\modules\research\techweb\nodes\mining_nodes.dm" +#include "code\modules\research\techweb\nodes\modsuit_nodes.dm" +#include "code\modules\research\techweb\nodes\research_nodes.dm" +#include "code\modules\research\techweb\nodes\robo_nodes.dm" +#include "code\modules\research\techweb\nodes\security_nodes.dm" +#include "code\modules\research\techweb\nodes\service_nodes.dm" +#include "code\modules\research\techweb\nodes\surgery_nodes.dm" +#include "code\modules\research\techweb\nodes\syndicate_nodes.dm" #include "code\modules\research\xenobiology\xenobio_camera.dm" #include "code\modules\research\xenobiology\xenobiology.dm" #include "code\modules\research\xenobiology\crossbreeding\__corecross.dm" @@ -5879,6 +5897,7 @@ #include "code\modules\surgery\advanced\bioware\vein_threading.dm" #include "code\modules\surgery\bodyparts\_bodyparts.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" +#include "code\modules\surgery\bodyparts\ghetto_parts.dm" #include "code\modules\surgery\bodyparts\head.dm" #include "code\modules\surgery\bodyparts\head_hair_and_lips.dm" #include "code\modules\surgery\bodyparts\helpers.dm" diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx index 7bc459c7f2e84..fbee44f00f9e2 100644 --- a/tgui/packages/tgui-say/TguiSay.tsx +++ b/tgui/packages/tgui-say/TguiSay.tsx @@ -162,7 +162,7 @@ export class TguiSay extends Component<{}, State> { ? prefix + currentValue : currentValue; - this.messages.forceSayMsg(grunt); + this.messages.forceSayMsg(grunt, this.channelIterator.current()); this.reset(); } @@ -274,6 +274,7 @@ export class TguiSay extends Component<{}, State> { }; reset() { + this.currentPrefix = null; this.setValue(''); this.setSize(); this.setState({ diff --git a/tgui/packages/tgui-say/timers.ts b/tgui/packages/tgui-say/timers.ts index 85c58f7424ae9..d1388487c07c6 100644 --- a/tgui/packages/tgui-say/timers.ts +++ b/tgui/packages/tgui-say/timers.ts @@ -1,5 +1,7 @@ import { debounce, throttle } from 'common/timer'; +import { Channel } from './ChannelIterator'; + const SECONDS = 1000; /** Timers: Prevents overloading the server, throttles messages */ @@ -10,7 +12,8 @@ export const byondMessages = { 0.4 * SECONDS, ), forceSayMsg: debounce( - (entry: string) => Byond.sendMessage('force', { entry, channel: 'Say' }), + (entry: string, channel: Channel) => + Byond.sendMessage('force', { entry, channel }), 1 * SECONDS, true, ),