diff --git a/code/datums/repositories/decls.dm b/code/datums/repositories/decls.dm new file mode 100644 index 0000000000..e87be74f53 --- /dev/null +++ b/code/datums/repositories/decls.dm @@ -0,0 +1,39 @@ +/var/repository/decls/decls_repository = new() + +/repository/decls + var/list/fetched_decls + var/list/fetched_decl_types + var/list/fetched_decl_subtypes + +/repository/decls/New() + ..() + fetched_decls = list() + fetched_decl_types = list() + fetched_decl_subtypes = list() + +/repository/decls/proc/decls_of_type(var/decl_prototype) + . = fetched_decl_types[decl_prototype] + if(!.) + . = get_decls(typesof(decl_prototype)) + fetched_decl_types[decl_prototype] = . + +/repository/decls/proc/decls_of_subtype(var/decl_prototype) + . = fetched_decl_subtypes[decl_prototype] + if(!.) + . = get_decls(subtypesof(decl_prototype)) + fetched_decl_subtypes[decl_prototype] = . + +/repository/decls/proc/get_decl(var/decl_type) + . = fetched_decls[decl_type] + if(!.) + . = new decl_type() + fetched_decls[decl_type] = . + +/repository/decls/proc/get_decls(var/list/decl_types) + . = list() + for(var/decl_type in decl_types) + .[decl_type] = get_decl(decl_type) + +/decls/Destroy() + crash_with("Prevented attempt to delete a decl instance: [log_info_line(src)]") + return 1 // Prevents Decl destruction \ No newline at end of file diff --git a/code/datums/repositories/repository.dm b/code/datums/repositories/repository.dm index 6267099c93..04eee50540 100644 --- a/code/datums/repositories/repository.dm +++ b/code/datums/repositories/repository.dm @@ -1,4 +1,19 @@ +/repository/New() + return + /datum/cache_entry var/timestamp var/data +/datum/cache_entry/New() + timestamp = world.time + +/datum/cache_entry/proc/is_valid() + return FALSE + +/datum/cache_entry/valid_until/New(var/valid_duration) + ..() + timestamp += valid_duration + +/datum/cache_entry/valid_until/is_valid() + return world.time < timestamp \ No newline at end of file diff --git a/code/modules/hydroponics/seed_controller.dm b/code/modules/hydroponics/seed_controller.dm index 89cb299f5f..fc2b6ea018 100644 --- a/code/modules/hydroponics/seed_controller.dm +++ b/code/modules/hydroponics/seed_controller.dm @@ -13,11 +13,11 @@ if(!holder) return if(!plant_controller || !plant_controller.gene_tag_masks) - usr << "Gene masks not set." + to_chat(usr, "Gene masks not set.") return for(var/mask in plant_controller.gene_tag_masks) - usr << "[mask]: [plant_controller.gene_tag_masks[mask]]" + to_chat(usr, "[mask]: [plant_controller.gene_tag_masks[mask]]") var/global/datum/controller/plants/plant_controller // Set in New(). @@ -33,6 +33,8 @@ var/global/datum/controller/plants/plant_controller // Set in New(). var/list/plant_sprites = list() // List of all harvested product sprites. var/list/plant_product_sprites = list() // List of all growth sprites plus number of growth stages. var/processing = 0 // Off/on. + var/list/gene_masked_list = list() // Stored gene masked list, rather than recreating it when needed. + var/list/plant_gene_datums = list() // Stored datum versions of the gene masked list. /datum/controller/plants/New() if(plant_controller && plant_controller != src) @@ -83,18 +85,29 @@ var/global/datum/controller/plants/plant_controller // Set in New(). S.update_seed() //Might as well mask the gene types while we're at it. + var/list/gene_datums = decls_repository.decls_of_subtype(/decl/plantgene) var/list/used_masks = list() var/list/plant_traits = ALL_GENES while(plant_traits && plant_traits.len) + world.log << "2" var/gene_tag = pick(plant_traits) var/gene_mask = "[uppertext(num2hex(rand(0,255)))]" while(gene_mask in used_masks) gene_mask = "[uppertext(num2hex(rand(0,255)))]" + var/decl/plantgene/G + + for(var/D in gene_datums) + var/decl/plantgene/P = gene_datums[D] + if(gene_tag == P.gene_tag) + G = P + gene_datums -= D used_masks += gene_mask plant_traits -= gene_tag gene_tag_masks[gene_tag] = gene_mask + plant_gene_datums[gene_mask] = G + gene_masked_list.Add(list(list("tag" = gene_tag, "mask" = gene_mask))) // Proc for creating a random seed type. /datum/controller/plants/proc/create_random_seed(var/survive_on_station) @@ -147,4 +160,4 @@ var/global/datum/controller/plants/plant_controller // Set in New(). plant_queue |= plant /datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant) - plant_queue -= plant + plant_queue -= plant \ No newline at end of file diff --git a/code/modules/hydroponics/seed_gene_mut.dm b/code/modules/hydroponics/seed_gene_mut.dm new file mode 100644 index 0000000000..cdb7048957 --- /dev/null +++ b/code/modules/hydroponics/seed_gene_mut.dm @@ -0,0 +1,135 @@ +/datum/seed/proc/diverge_mutate_gene(var/decl/plantgene/G, var/turf/T) + if(!istype(G)) + log_debug("Attempted to mutate [src] with a non-plantgene var.") + return src + + var/datum/seed/S = diverge() //Let's not modify all of the seeds. + T.visible_message("\The [S.display_name] quivers!") //Mimicks the normal mutation. + G.mutate(S, T) + + return S + +/decl/plantgene + var/gene_tag + +/decl/plantgene/biochem + gene_tag = GENE_BIOCHEMISTRY + +/decl/plantgene/hardiness + gene_tag = GENE_HARDINESS + +/decl/plantgene/environment + gene_tag = GENE_ENVIRONMENT + +/decl/plantgene/metabolism + gene_tag = GENE_METABOLISM + +/decl/plantgene/structure + gene_tag = GENE_STRUCTURE + +/decl/plantgene/diet + gene_tag = GENE_DIET + +/decl/plantgene/pigment + gene_tag = GENE_PIGMENT + +/decl/plantgene/output + gene_tag = GENE_OUTPUT + +/decl/plantgene/atmosphere + gene_tag = GENE_ATMOSPHERE + +/decl/plantgene/vigour + gene_tag = GENE_VIGOUR + +/decl/plantgene/fruit + gene_tag = GENE_FRUIT + +/decl/plantgene/special + gene_tag = GENE_SPECIAL + +/decl/plantgene/proc/mutate(var/datum/seed/S) + return + +/decl/plantgene/biochem/mutate(var/datum/seed/S) + S.set_trait(TRAIT_POTENCY, S.get_trait(TRAIT_POTENCY)+rand(-20,20),200, 0) + +/decl/plantgene/hardiness/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_PEST_TOLERANCE, S.get_trait(TRAIT_PEST_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) + +/decl/plantgene/environment/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_IDEAL_HEAT, S.get_trait(TRAIT_IDEAL_HEAT)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_IDEAL_LIGHT, S.get_trait(TRAIT_IDEAL_LIGHT)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_LIGHT_TOLERANCE, S.get_trait(TRAIT_LIGHT_TOLERANCE)+rand(-5,5),100,0) + +/decl/plantgene/metabolism/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_REQUIRES_NUTRIENTS, S.get_trait(TRAIT_REQUIRES_NUTRIENTS)+rand(-2,2),10,0) + if(prob(65)) + S.set_trait(TRAIT_REQUIRES_WATER, S.get_trait(TRAIT_REQUIRES_WATER)+rand(-2,2),10,0) + if(prob(40)) + S.set_trait(TRAIT_ALTER_TEMP, S.get_trait(TRAIT_ALTER_TEMP)+rand(-5,5),100,0) + +/decl/plantgene/diet/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_CARNIVOROUS, S.get_trait(TRAIT_CARNIVOROUS)+rand(-1,1),2,0) + if(prob(60)) + S.set_trait(TRAIT_PARASITE, !S.get_trait(TRAIT_PARASITE)) + if(prob(65)) + S.set_trait(TRAIT_NUTRIENT_CONSUMPTION, S.get_trait(TRAIT_NUTRIENT_CONSUMPTION)+rand(-0.1,0.1),5,0) + if(prob(65)) + S.set_trait(TRAIT_WATER_CONSUMPTION, S.get_trait(TRAIT_WATER_CONSUMPTION)+rand(-1,1),50,0) + +/decl/plantgene/output/mutate(var/datum/seed/S, var/turf/T) + if(prob(50)) + S.set_trait(TRAIT_BIOLUM, !S.get_trait(TRAIT_BIOLUM)) + if(S.get_trait(TRAIT_BIOLUM)) + T.visible_message("\The [S.display_name] begins to glow!") + if(prob(50)) + S.set_trait(TRAIT_BIOLUM_COLOUR,get_random_colour(0,75,190)) + T.visible_message("\The [S.display_name]'s glow changes colour!") + else + T.visible_message("\The [S.display_name]'s glow dims...") + if(prob(60)) + S.set_trait(TRAIT_PRODUCES_POWER, !S.get_trait(TRAIT_PRODUCES_POWER)) + +/decl/plantgene/atmosphere/mutate(var/datum/seed/S) + if(prob(60)) + S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_PEST_TOLERANCE, S.get_trait(TRAIT_PEST_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) + if(prob(60)) + S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) + +/decl/plantgene/vigour/mutate(var/datum/seed/S, var/turf/T) + if(prob(65)) + S.set_trait(TRAIT_PRODUCTION, S.get_trait(TRAIT_PRODUCTION)+rand(-1,1),10,0) + if(prob(65)) + S.set_trait(TRAIT_MATURATION, S.get_trait(TRAIT_MATURATION)+rand(-1,1),30,0) + if(prob(55)) + S.set_trait(TRAIT_SPREAD, S.get_trait(TRAIT_SPREAD)+rand(-1,1),2,0) + T.visible_message("\The [S.display_name] spasms visibly, shifting in the tray.") + +/decl/plantgene/fruit/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_STINGS, !S.get_trait(TRAIT_STINGS)) + if(prob(65)) + S.set_trait(TRAIT_EXPLOSIVE, !S.get_trait(TRAIT_EXPLOSIVE)) + if(prob(65)) + S.set_trait(TRAIT_JUICY, !S.get_trait(TRAIT_JUICY)) + +/decl/plantgene/special/mutate(var/datum/seed/S) + if(prob(65)) + S.set_trait(TRAIT_TELEPORTING, !S.get_trait(TRAIT_TELEPORTING)) diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm index 1479ffdc5c..bc96f064c9 100644 --- a/code/modules/hydroponics/seed_machines.dm +++ b/code/modules/hydroponics/seed_machines.dm @@ -137,9 +137,7 @@ var/list/data = list() - var/list/geneMasks[0] - for(var/gene_tag in plant_controller.gene_tag_masks) - geneMasks.Add(list(list("tag" = gene_tag, "mask" = plant_controller.gene_tag_masks[gene_tag]))) + var/list/geneMasks = plant_controller.gene_masked_list data["geneMasks"] = geneMasks data["activity"] = active diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index efdae46db7..e69c3eec8a 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -181,9 +181,14 @@ return //Override for somatoray projectiles. - if(istype(Proj ,/obj/item/projectile/energy/floramut) && prob(20)) - mutate(1) - return + if(istype(Proj ,/obj/item/projectile/energy/floramut)&& prob(20)) + if(istype(Proj, /obj/item/projectile/energy/floramut/gene)) + var/obj/item/projectile/energy/floramut/gene/G = Proj + if(seed) + seed = seed.diverge_mutate_gene(G.gene, get_turf(loc)) //get_turf just in case it's not in a turf. + else + mutate(1) + return else if(istype(Proj ,/obj/item/projectile/energy/florayield) && prob(20)) yield_mod = min(10,yield_mod+rand(1,2)) return diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 8fbfc0e657..46988c9934 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -44,10 +44,12 @@ origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3) modifystate = "floramut" self_recharge = 1 + var/decl/plantgene/gene = null firemodes = list( list(mode_name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"), list(mode_name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"), + list(mode_name="induce specific mutations", projectile_type=/obj/item/projectile/energy/floramut/gene, modifystate="floramut"), ) /obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag) @@ -58,6 +60,28 @@ return ..() +/obj/item/weapon/gun/energy/floragun/verb/select_gene() + set name = "Select Gene" + set category = "Object" + set src in view(1) + + var/genemask = input("Choose a gene to modify.") as null|anything in plant_controller.plant_gene_datums + + if(!genemask) + return + + gene = plant_controller.plant_gene_datums[genemask] + + to_chat(usr, "You set the [src]'s targeted genetic area to [genemask].") + + return + +/obj/item/weapon/gun/energy/floragun/consume_next_projectile() + . = ..() + var/obj/item/projectile/energy/floramut/gene/G = . + if(istype(G)) + G.gene = gene + /obj/item/weapon/gun/energy/meteorgun name = "meteor gun" desc = "For the love of god, make sure you're aiming this the right way!" diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index dd81d713fe..c8c26f5f39 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -121,6 +121,15 @@ else return 1 +/obj/item/projectile/energy/floramut/gene + name = "gamma somatoray" + icon_state = "energy2" + damage = 0 + damage_type = TOX + nodamage = 1 + check_armour = "energy" + var/decl/plantgene/gene = null + /obj/item/projectile/energy/florayield name = "beta somatoray" icon_state = "energy2" diff --git a/polaris.dme b/polaris.dme index 23fc2fc0c4..e758a5eb7f 100644 --- a/polaris.dme +++ b/polaris.dme @@ -212,6 +212,7 @@ #include "code\datums\observation\~cleanup.dm" #include "code\datums\repositories\cameras.dm" #include "code\datums\repositories\crew.dm" +#include "code\datums\repositories\decls.dm" #include "code\datums\repositories\repository.dm" #include "code\datums\supplypacks\atmospherics.dm" #include "code\datums\supplypacks\contraband.dm" @@ -1412,6 +1413,7 @@ #include "code\modules\hydroponics\seed.dm" #include "code\modules\hydroponics\seed_controller.dm" #include "code\modules\hydroponics\seed_datums.dm" +#include "code\modules\hydroponics\seed_gene_mut.dm" #include "code\modules\hydroponics\seed_machines.dm" #include "code\modules\hydroponics\seed_mobs.dm" #include "code\modules\hydroponics\seed_packets.dm"